Home | History | Annotate | Download | only in x509
      1 // Copyright 2011 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 // +build cgo,!arm,!arm64,!ios
      6 
      7 package x509
      8 
      9 /*
     10 #cgo CFLAGS: -mmacosx-version-min=10.6 -D__MAC_OS_X_VERSION_MAX_ALLOWED=1060
     11 #cgo LDFLAGS: -framework CoreFoundation -framework Security
     12 
     13 #include <CoreFoundation/CoreFoundation.h>
     14 #include <Security/Security.h>
     15 
     16 // FetchPEMRoots fetches the system's list of trusted X.509 root certificates.
     17 //
     18 // On success it returns 0 and fills pemRoots with a CFDataRef that contains the extracted root
     19 // certificates of the system. On failure, the function returns -1.
     20 //
     21 // Note: The CFDataRef returned in pemRoots must be released (using CFRelease) after
     22 // we've consumed its content.
     23 int FetchPEMRoots(CFDataRef *pemRoots) {
     24 	if (pemRoots == NULL) {
     25 		return -1;
     26 	}
     27 
     28 	CFArrayRef certs = NULL;
     29 	OSStatus err = SecTrustCopyAnchorCertificates(&certs);
     30 	if (err != noErr) {
     31 		return -1;
     32 	}
     33 
     34 	CFMutableDataRef combinedData = CFDataCreateMutable(kCFAllocatorDefault, 0);
     35 	int i, ncerts = CFArrayGetCount(certs);
     36 	for (i = 0; i < ncerts; i++) {
     37 		CFDataRef data = NULL;
     38 		SecCertificateRef cert = (SecCertificateRef)CFArrayGetValueAtIndex(certs, i);
     39 		if (cert == NULL) {
     40 			continue;
     41 		}
     42 
     43 		// Note: SecKeychainItemExport is deprecated as of 10.7 in favor of SecItemExport.
     44 		// Once we support weak imports via cgo we should prefer that, and fall back to this
     45 		// for older systems.
     46 		err = SecKeychainItemExport(cert, kSecFormatX509Cert, kSecItemPemArmour, NULL, &data);
     47 		if (err != noErr) {
     48 			continue;
     49 		}
     50 
     51 		if (data != NULL) {
     52 			CFDataAppendBytes(combinedData, CFDataGetBytePtr(data), CFDataGetLength(data));
     53 			CFRelease(data);
     54 		}
     55 	}
     56 
     57 	CFRelease(certs);
     58 
     59 	*pemRoots = combinedData;
     60 	return 0;
     61 }
     62 */
     63 import "C"
     64 import "unsafe"
     65 
     66 func initSystemRoots() {
     67 	roots := NewCertPool()
     68 
     69 	var data C.CFDataRef = nil
     70 	err := C.FetchPEMRoots(&data)
     71 	if err == -1 {
     72 		return
     73 	}
     74 
     75 	defer C.CFRelease(C.CFTypeRef(data))
     76 	buf := C.GoBytes(unsafe.Pointer(C.CFDataGetBytePtr(data)), C.int(C.CFDataGetLength(data)))
     77 	roots.AppendCertsFromPEM(buf)
     78 	systemRoots = roots
     79 }
     80