#include <CoreFoundation/CoreFoundation.h>
#include <Security/Security.h>
-// FetchPEMRoots_MountainLion is the version of FetchPEMRoots from Go 1.6
-// which still works on OS X 10.8 (Mountain Lion).
-// It lacks support for admin & user cert domains.
-// See golang.org/issue/16473
-int FetchPEMRoots_MountainLion(CFDataRef *pemRoots) {
- if (pemRoots == NULL) {
- return -1;
- }
- CFArrayRef certs = NULL;
- OSStatus err = SecTrustCopyAnchorCertificates(&certs);
- if (err != noErr) {
- return -1;
- }
- CFMutableDataRef combinedData = CFDataCreateMutable(kCFAllocatorDefault, 0);
- int i, ncerts = CFArrayGetCount(certs);
- for (i = 0; i < ncerts; i++) {
- CFDataRef data = NULL;
- SecCertificateRef cert = (SecCertificateRef)CFArrayGetValueAtIndex(certs, i);
- if (cert == NULL) {
- continue;
- }
- // Note: SecKeychainItemExport is deprecated as of 10.7 in favor of SecItemExport.
- // Once we support weak imports via cgo we should prefer that, and fall back to this
- // for older systems.
- err = SecKeychainItemExport(cert, kSecFormatX509Cert, kSecItemPemArmour, NULL, &data);
- if (err != noErr) {
- continue;
- }
- if (data != NULL) {
- CFDataAppendBytes(combinedData, CFDataGetBytePtr(data), CFDataGetLength(data));
- CFRelease(data);
- }
- }
- CFRelease(certs);
- *pemRoots = combinedData;
- return 0;
-}
-
-// useOldCode reports whether the running machine is OS X 10.8 Mountain Lion
-// or older. We only support Mountain Lion and higher, but we'll at least try our
-// best on older machines and continue to use the old code path.
-//
-// See golang.org/issue/16473
-int useOldCode() {
- char str[256];
- size_t size = sizeof(str);
- memset(str, 0, size);
- sysctlbyname("kern.osrelease", str, &size, NULL, 0);
- // OS X 10.8 is osrelease "12.*", 10.7 is 11.*, 10.6 is 10.*.
- // We never supported things before that.
- return memcmp(str, "12.", 3) == 0 || memcmp(str, "11.", 3) == 0 || memcmp(str, "10.", 3) == 0;
-}
-
// FetchPEMRoots fetches the system's list of trusted X.509 root certificates.
//
// On success it returns 0 and fills pemRoots with a CFDataRef that contains the extracted root
int FetchPEMRoots(CFDataRef *pemRoots, CFDataRef *untrustedPemRoots) {
int i;
- if (useOldCode()) {
- return FetchPEMRoots_MountainLion(pemRoots);
- }
-
// Get certificates from all domains, not just System, this lets
// the user add CAs to their "login" keychain, and Admins to add
// to the "System" keychain
func dupCloseOnExec(fd int) (newfd int, err error) {
if atomic.LoadInt32(&tryDupCloexec) == 1 {
r0, _, e1 := syscall.Syscall(syscall.SYS_FCNTL, uintptr(fd), syscall.F_DUPFD_CLOEXEC, 0)
- if runtime.GOOS == "darwin" && e1 == syscall.EBADF {
- // On OS X 10.6 and below (but we only support
- // >= 10.6), F_DUPFD_CLOEXEC is unsupported
- // and fcntl there falls back (undocumented)
- // to doing an ioctl instead, returning EBADF
- // in this case because fd is not of the
- // expected device fd type. Treat it as
- // EINVAL instead, so we fall back to the
- // normal dup path.
- // TODO: only do this on 10.6 if we can detect 10.6
- // cheaply.
- e1 = syscall.EINVAL
- }
switch e1 {
case 0:
return int(r0), nil
switch runtime.GOOS {
case "plan9", "windows":
t.Skipf("no pthreads on %s", runtime.GOOS)
- case "darwin":
- if runtime.GOARCH != "arm" && runtime.GOARCH != "arm64" {
- // static constructor needs external linking, but we don't support
- // external linking on OS X 10.6.
- out, err := exec.Command("uname", "-r").Output()
- if err != nil {
- t.Fatalf("uname -r failed: %v", err)
- }
- // OS X 10.6 == Darwin 10.x
- if strings.HasPrefix(string(out), "10.") {
- t.Skipf("no external linking on OS X 10.6")
- }
- }
}
if runtime.GOARCH == "ppc64" {
// TODO(austin) External linking not implemented on