Index: net/base/x509_certificate_mac.cc |
diff --git a/net/base/x509_certificate_mac.cc b/net/base/x509_certificate_mac.cc |
index 4bb9adf66b58371d8d2d1b94b5a2a2a8163142cc..f7dfc66f51893ecfd1be50147864ad97b9d8e0cc 100644 |
--- a/net/base/x509_certificate_mac.cc |
+++ b/net/base/x509_certificate_mac.cc |
@@ -289,13 +289,18 @@ OSStatus CreatePolicy(const CSSM_OID* policy_OID, |
} |
// Creates a series of SecPolicyRefs to be added to a SecTrustRef used to |
-// validate a certificate for an SSL peer. |hostname| contains the name of |
-// the SSL peer that the certificate should be verified against. |flags| is |
+// validate a certificate for an SSL server. |hostname| contains the name of |
+// the SSL server that the certificate should be verified against. |flags| is |
// a bitwise-OR of VerifyFlags that can further alter how trust is |
// validated, such as how revocation is checked. If successful, returns |
// noErr, and stores the resultant array of SecPolicyRefs in |policies|. |
OSStatus CreateTrustPolicies(const std::string& hostname, int flags, |
ScopedCFTypeRef<CFArrayRef>* policies) { |
+ ScopedCFTypeRef<CFMutableArrayRef> local_policies( |
+ CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks)); |
+ if (!local_policies) |
+ return memFullErr; |
+ |
// Create an SSL SecPolicyRef, and configure it to perform hostname |
// validation. The hostname check does 99% of what we want, with the |
// exception of dotted IPv4 addreses, which we handle ourselves below. |
@@ -310,35 +315,38 @@ OSStatus CreateTrustPolicies(const std::string& hostname, int flags, |
sizeof(tp_ssl_options), &ssl_policy); |
if (status) |
return status; |
- ScopedCFTypeRef<SecPolicyRef> scoped_ssl_policy(ssl_policy); |
- |
- // Manually add OCSP and CRL policies. If neither an OCSP or CRL policy is |
- // specified, the Apple TP module will add whatever the system settings |
- // are, which is not desirable here. |
- // |
- // Note that this causes any locally configured OCSP responder URL to be |
- // ignored. |
+ CFArrayAppendValue(local_policies, ssl_policy); |
+ CFRelease(ssl_policy); |
+ |
+ // Manually add revocation policies. In order to actually disable revocation |
+ // checking, the SecTrustRef must have at least one revocation policy |
+ // associated with it. If none are present, the Apple TP will add policies |
+ // according to the system preferences, which will enable revocation |
+ // checking even if the caller explicitly disabled it. An OCSP policy is |
+ // used, rather than a CRL policy, because the Apple TP will force an OCSP |
+ // policy to be present and enabled if it believes the certificate may chain |
+ // to an EV root. By explicitly disabling network and OCSP cache access, |
+ // then even if the Apple TP enables OCSP checking, no revocation checking |
+ // will actually succeed. |
CSSM_APPLE_TP_OCSP_OPTIONS tp_ocsp_options; |
memset(&tp_ocsp_options, 0, sizeof(tp_ocsp_options)); |
tp_ocsp_options.Version = CSSM_APPLE_TP_OCSP_OPTS_VERSION; |
- CSSM_APPLE_TP_CRL_OPTIONS tp_crl_options; |
- memset(&tp_crl_options, 0, sizeof(tp_crl_options)); |
- tp_crl_options.Version = CSSM_APPLE_TP_CRL_OPTS_VERSION; |
- |
if (flags & X509Certificate::VERIFY_REV_CHECKING_ENABLED) { |
- // If an OCSP responder is available, use it, and avoid fetching any |
- // CRLs for that certificate if possible, as they may be much larger. |
+ // The default for the OCSP policy is to fetch responses via the network, |
+ // unlike the CRL policy default. The policy is further modified to |
+ // prefer OCSP over CRLs, if both are specified on the certificate. This |
+ // is because an OCSP response is both sufficient and typically |
+ // significantly smaller than the CRL counterpart. |
tp_ocsp_options.Flags = CSSM_TP_ACTION_OCSP_SUFFICIENT; |
- // Ensure that CRLs can be fetched if a crlDistributionPoint extension |
- // is found. Otherwise, only the local CRL cache will be consulted. |
- tp_crl_options.CrlFlags |= CSSM_TP_ACTION_FETCH_CRL_FROM_NET; |
} else { |
- // Disable OCSP network fetching, but still permit cached OCSP responses |
- // to be used. This is equivalent to the Windows code's usage of |
- // CERT_CHAIN_REVOCATION_CHECK_CACHE_ONLY. |
- tp_ocsp_options.Flags = CSSM_TP_ACTION_OCSP_DISABLE_NET; |
- // The default CrlFlags will ensure only cached CRLs are used. |
+ // Effectively disable OCSP checking by making it impossible to get an |
+ // OCSP response. Even if the Apple TP forces OCSP, no checking will |
+ // be able to succeed. If this happens, the Apple TP will report an error |
+ // that OCSP was unavailable, but this will be handled and suppressed in |
+ // X509Certificate::Verify(). |
+ tp_ocsp_options.Flags = CSSM_TP_ACTION_OCSP_DISABLE_NET | |
+ CSSM_TP_ACTION_OCSP_CACHE_READ_DISABLE; |
} |
SecPolicyRef ocsp_policy; |
@@ -346,23 +354,25 @@ OSStatus CreateTrustPolicies(const std::string& hostname, int flags, |
sizeof(tp_ocsp_options), &ocsp_policy); |
if (status) |
return status; |
- ScopedCFTypeRef<SecPolicyRef> scoped_ocsp_policy(ocsp_policy); |
+ CFArrayAppendValue(local_policies, ocsp_policy); |
+ CFRelease(ocsp_policy); |
- SecPolicyRef crl_policy; |
- status = CreatePolicy(&CSSMOID_APPLE_TP_REVOCATION_CRL, &tp_crl_options, |
- sizeof(tp_crl_options), &crl_policy); |
- if (status) |
- return status; |
- ScopedCFTypeRef<SecPolicyRef> scoped_crl_policy(crl_policy); |
- |
- CFTypeRef local_policies[] = { ssl_policy, ocsp_policy, crl_policy }; |
- CFArrayRef policy_array = CFArrayCreate(kCFAllocatorDefault, local_policies, |
- arraysize(local_policies), |
- &kCFTypeArrayCallBacks); |
- if (!policy_array) |
- return memFullErr; |
+ if (flags & X509Certificate::VERIFY_REV_CHECKING_ENABLED) { |
+ CSSM_APPLE_TP_CRL_OPTIONS tp_crl_options; |
+ memset(&tp_crl_options, 0, sizeof(tp_crl_options)); |
+ tp_crl_options.Version = CSSM_APPLE_TP_CRL_OPTS_VERSION; |
+ tp_crl_options.CrlFlags = CSSM_TP_ACTION_FETCH_CRL_FROM_NET; |
+ |
+ SecPolicyRef crl_policy; |
+ status = CreatePolicy(&CSSMOID_APPLE_TP_REVOCATION_CRL, &tp_crl_options, |
+ sizeof(tp_crl_options), &crl_policy); |
+ if (status) |
+ return status; |
+ CFArrayAppendValue(local_policies, crl_policy); |
+ CFRelease(crl_policy); |
+ } |
- policies->reset(policy_array); |
+ policies->reset(local_policies.release()); |
return noErr; |
} |
@@ -856,7 +866,7 @@ int X509Certificate::Verify(const std::string& hostname, int flags, |
} else { |
// EV requires revocation checking. |
// Note, under the hood, SecTrustEvaluate() will modify the OCSP options |
- // so as to attempt OCSP fetching if it believes a certificate may chain |
+ // so as to attempt OCSP checking if it believes a certificate may chain |
// to an EV root. However, because network fetches are disabled in |
// CreateTrustPolicies() when revocation checking is disabled, these |
// will only go against the local cache. |