Skip to content

Commit e7f95b3

Browse files
mastercactapusbradfitz
authored andcommitted
crypto/x509: load all trusted certs on darwin (cgo)
The current implementation ignores certs wherein the Subject does not match the Issuer. An example of where this causes issue is an enterprise environment with intermediate CAs. In this case, the issuer is separate (and may be loaded) but the intermediate is ignored. A TLS handshake that does not include the intermediate cert would then fail with an untrusted error in Go. On other platforms (darwin-nocgo included), all trusted certs are loaded and accepted reguardless of Subject/Issuer names. This change removes the Subject/Issuer name-matching restriction of certificates when trustAsRoot is set, allowing all trusted certs to be loaded on darwin (cgo). Refs #16532 Change-Id: I451e929588f8911892be6bdc2143d0799363c5f8 Reviewed-on: https://go-review.googlesource.com/36942 Run-TryBot: Brad Fitzpatrick <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Brad Fitzpatrick <[email protected]>
1 parent 26ec05c commit e7f95b3

File tree

1 file changed

+32
-18
lines changed

1 file changed

+32
-18
lines changed

src/crypto/x509/root_cgo_darwin.go

+32-18
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,11 @@ int FetchPEMRoots(CFDataRef *pemRoots, CFDataRef *untrustedPemRoots) {
119119
}
120120
// We only want trusted certs.
121121
int untrusted = 0;
122-
if (i != 0) {
122+
int trustAsRoot = 0;
123+
int trustRoot = 0;
124+
if (i == 0) {
125+
trustAsRoot = 1;
126+
} else {
123127
// Certs found in the system domain are always trusted. If the user
124128
// configures "Never Trust" on such a cert, it will also be found in the
125129
// admin or user domain, causing it to be added to untrustedPemRoots. The
@@ -129,7 +133,7 @@ int FetchPEMRoots(CFDataRef *pemRoots, CFDataRef *untrustedPemRoots) {
129133
// SecTrustServer.c, "user trust settings overrule admin trust settings",
130134
// so take the last trust settings array we find.
131135
// Skip the system domain since it is always trusted.
132-
for (int k = 1; k < numDomains; k++) {
136+
for (int k = i; k < numDomains; k++) {
133137
CFArrayRef domainTrustSettings = NULL;
134138
err = SecTrustSettingsCopyTrustSettings(cert, domains[k], &domainTrustSettings);
135139
if (err == errSecSuccess && domainTrustSettings != NULL) {
@@ -152,28 +156,35 @@ int FetchPEMRoots(CFDataRef *pemRoots, CFDataRef *untrustedPemRoots) {
152156
// TODO: The rest of the dictionary specifies conditions for evaluation.
153157
if (result == kSecTrustSettingsResultDeny) {
154158
untrusted = 1;
159+
} else if (result == kSecTrustSettingsResultTrustAsRoot) {
160+
trustAsRoot = 1;
161+
} else if (result == kSecTrustSettingsResultTrustRoot) {
162+
trustRoot = 1;
155163
}
156164
}
157165
}
158166
CFRelease(trustSettings);
159167
}
160-
// We only want to add Root CAs, so make sure Subject and Issuer Name match
161-
CFDataRef subjectName = SecCertificateCopyNormalizedSubjectContent(cert, &errRef);
162-
if (errRef != NULL) {
163-
CFRelease(errRef);
164-
continue;
165-
}
166-
CFDataRef issuerName = SecCertificateCopyNormalizedIssuerContent(cert, &errRef);
167-
if (errRef != NULL) {
168+
169+
if (trustRoot) {
170+
// We only want to add Root CAs, so make sure Subject and Issuer Name match
171+
CFDataRef subjectName = SecCertificateCopyNormalizedSubjectContent(cert, &errRef);
172+
if (errRef != NULL) {
173+
CFRelease(errRef);
174+
continue;
175+
}
176+
CFDataRef issuerName = SecCertificateCopyNormalizedIssuerContent(cert, &errRef);
177+
if (errRef != NULL) {
178+
CFRelease(subjectName);
179+
CFRelease(errRef);
180+
continue;
181+
}
182+
Boolean equal = CFEqual(subjectName, issuerName);
168183
CFRelease(subjectName);
169-
CFRelease(errRef);
170-
continue;
171-
}
172-
Boolean equal = CFEqual(subjectName, issuerName);
173-
CFRelease(subjectName);
174-
CFRelease(issuerName);
175-
if (!equal) {
176-
continue;
184+
CFRelease(issuerName);
185+
if (!equal) {
186+
continue;
187+
}
177188
}
178189
179190
// Note: SecKeychainItemExport is deprecated as of 10.7 in favor of SecItemExport.
@@ -185,6 +196,9 @@ int FetchPEMRoots(CFDataRef *pemRoots, CFDataRef *untrustedPemRoots) {
185196
}
186197
187198
if (data != NULL) {
199+
if (!trustRoot && !trustAsRoot) {
200+
untrusted = 1;
201+
}
188202
CFMutableDataRef appendTo = untrusted ? combinedUntrustedData : combinedData;
189203
CFDataAppendBytes(appendTo, CFDataGetBytePtr(data), CFDataGetLength(data));
190204
CFRelease(data);

0 commit comments

Comments
 (0)