Skip to content

fix root_cgo_darwin omits some trusty intermediate ca certificate #30673

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 63 additions & 2 deletions src/crypto/x509/root_cgo_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,62 @@ static bool isSSLPolicy(SecPolicyRef policyRef) {
return false;
}

static bool verifyUnspecifiedCert(SecCertificateRef cert) {
SecTrustRef trustRef = NULL;
CFMutableArrayRef certs = NULL;
CFMutableArrayRef policies = NULL;
SecPolicyRef policyRef = NULL;
OSStatus ortn;
bool isOk = true;

policyRef = SecPolicyCreateSSL(true, NULL);

certs = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
CFArrayAppendValue(certs, cert);

// create policies array
policies = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
CFArrayAppendValue(policies, policyRef);

// create trust reference from certs and policies
ortn = SecTrustCreateWithCertificates(certs, policies, &trustRef);
if (ortn) {
isOk = false;
goto errOut;
}

// Leaf cert (which being verified) is a CA
ortn = SecTrustSetOptions(trustRef, kSecTrustOptionLeafIsCA);
if (ortn) {
isOk = false;
goto errOut;
}

SecTrustResultType resultType;
ortn = SecTrustEvaluate(trustRef, &resultType);
if (ortn) {
isOk = false;
goto errOut;
}
switch(resultType) {
case kSecTrustResultUnspecified:
// cert chain valid, no special UserTrust assignments
case kSecTrustResultProceed:
// cert chain valid AND user explicitly trusts this
isOk = true;
break;
default:
isOk = false;
}

errOut:
CFRelease(trustRef);
CFRelease(certs);
CFRelease(policyRef);
CFRelease(policies);
return isOk;
}

// sslTrustSettingsResult obtains the final kSecTrustSettingsResult value
// for a certificate in the user or admin domain, combining usage constraints
// for the SSL SecTrustSettingsPolicy, ignoring SecTrustSettingsKeyUsage and
Expand Down Expand Up @@ -86,7 +142,8 @@ static SInt32 sslTrustSettingsResult(SecCertificateRef cert) {
continue;
}
} else {
continue;
// empty policy also means trusty
// continue;
}

if (CFDictionaryContainsKey(tSetting, _kSecTrustSettingsPolicyString)) {
Expand Down Expand Up @@ -246,7 +303,11 @@ int FetchPEMRoots(CFDataRef *pemRoots, CFDataRef *untrustedPemRoots, bool debugD
} else if (result == kSecTrustSettingsResultDeny) {
appendTo = combinedUntrustedData;
} else if (result == kSecTrustSettingsResultUnspecified) {
continue;
if (verifyUnspecifiedCert(cert)) {
appendTo = combinedData;
} else {
continue;
}
} else {
continue;
}
Expand Down