@@ -13,6 +13,48 @@ package x509
1313#include <CoreFoundation/CoreFoundation.h>
1414#include <Security/Security.h>
1515
16+ // FetchPEMRoots_MountainLion is the version of FetchPEMRoots from Go 1.6
17+ // which still works on OS X 10.8 (Mountain Lion).
18+ // It lacks support for admin & user cert domains.
19+ // See golang.org/issue/16473
20+ int FetchPEMRoots_MountainLion(CFDataRef *pemRoots) {
21+ if (pemRoots == NULL) {
22+ return -1;
23+ }
24+ CFArrayRef certs = NULL;
25+ OSStatus err = SecTrustCopyAnchorCertificates(&certs);
26+ if (err != noErr) {
27+ return -1;
28+ }
29+ CFMutableDataRef combinedData = CFDataCreateMutable(kCFAllocatorDefault, 0);
30+ int i, ncerts = CFArrayGetCount(certs);
31+ for (i = 0; i < ncerts; i++) {
32+ CFDataRef data = NULL;
33+ SecCertificateRef cert = (SecCertificateRef)CFArrayGetValueAtIndex(certs, i);
34+ if (cert == NULL) {
35+ continue;
36+ }
37+ // Note: SecKeychainItemExport is deprecated as of 10.7 in favor of SecItemExport.
38+ // Once we support weak imports via cgo we should prefer that, and fall back to this
39+ // for older systems.
40+ err = SecKeychainItemExport(cert, kSecFormatX509Cert, kSecItemPemArmour, NULL, &data);
41+ if (err != noErr) {
42+ continue;
43+ }
44+ if (data != NULL) {
45+ CFDataAppendBytes(combinedData, CFDataGetBytePtr(data), CFDataGetLength(data));
46+ CFRelease(data);
47+ }
48+ }
49+ CFRelease(certs);
50+ *pemRoots = combinedData;
51+ return 0;
52+ }
53+
54+ #ifndef kCFCoreFoundationVersionNumber10_9
55+ #define kCFCoreFoundationVersionNumber10_9 855.11
56+ #endif
57+
1658// FetchPEMRoots fetches the system's list of trusted X.509 root certificates.
1759//
1860// On success it returns 0 and fills pemRoots with a CFDataRef that contains the extracted root
@@ -21,6 +63,10 @@ package x509
2163// Note: The CFDataRef returned in pemRoots must be released (using CFRelease) after
2264// we've consumed its content.
2365int FetchPEMRoots(CFDataRef *pemRoots) {
66+ if (kCFCoreFoundationVersionNumber < kCFCoreFoundationVersionNumber10_9) {
67+ return FetchPEMRoots_MountainLion(pemRoots);
68+ }
69+
2470 // Get certificates from all domains, not just System, this lets
2571 // the user add CAs to their "login" keychain, and Admins to add
2672 // to the "System" keychain
0 commit comments