summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorrsleevi@chromium.org <rsleevi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-04-15 05:02:27 +0000
committerrsleevi@chromium.org <rsleevi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-04-15 05:02:27 +0000
commit84bfe14746393de3041b7a906aa69c5ac298d04b (patch)
tree9094d62e1c1e2da2dc8d9439d6ee867ab20647b6 /net
parent52d3effc94111150965c9b386ab564e5c04e862b (diff)
downloadchromium_src-84bfe14746393de3041b7a906aa69c5ac298d04b.zip
chromium_src-84bfe14746393de3041b7a906aa69c5ac298d04b.tar.gz
chromium_src-84bfe14746393de3041b7a906aa69c5ac298d04b.tar.bz2
Allow certificate revocation checking to be enabled/disabled independent of the OS settings on OS X.
R=agl BUG=78523, 79533 TEST=See bug for test case Review URL: http://codereview.chromium.org/6824069 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@81702 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r--net/DEPS1
-rw-r--r--net/base/x509_certificate_mac.cc163
2 files changed, 125 insertions, 39 deletions
diff --git a/net/DEPS b/net/DEPS
index daa967e..2674d33 100644
--- a/net/DEPS
+++ b/net/DEPS
@@ -1,5 +1,6 @@
include_rules = [
"+crypto",
+ "+third_party/apple_apsl",
"+third_party/libevent",
"+third_party/nss",
"+third_party/zlib",
diff --git a/net/base/x509_certificate_mac.cc b/net/base/x509_certificate_mac.cc
index a60b240..033ddbf 100644
--- a/net/base/x509_certificate_mac.cc
+++ b/net/base/x509_certificate_mac.cc
@@ -5,6 +5,7 @@
#include "net/base/x509_certificate.h"
#include <CommonCrypto/CommonDigest.h>
+#include <CoreServices/CoreServices.h>
#include <Security/Security.h>
#include <time.h>
@@ -26,6 +27,7 @@
#include "net/base/net_errors.h"
#include "net/base/test_root_certs.h"
#include "net/base/x509_certificate_known_roots_mac.h"
+#include "third_party/apple_apsl/cssmapplePriv.h"
#include "third_party/nss/mozilla/security/nss/lib/certdb/cert.h"
using base::mac::ScopedCFTypeRef;
@@ -286,6 +288,84 @@ OSStatus CreatePolicy(const CSSM_OID* policy_OID,
return noErr;
}
+// 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
+// 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) {
+ // 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.
+ CSSM_APPLE_TP_SSL_OPTIONS tp_ssl_options = {
+ CSSM_APPLE_TP_SSL_OPTS_VERSION,
+ hostname.size(),
+ hostname.data(),
+ 0
+ };
+ SecPolicyRef ssl_policy;
+ OSStatus status = CreatePolicy(&CSSMOID_APPLE_TP_SSL, &tp_ssl_options,
+ 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.
+ 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.
+ 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.
+ }
+
+ SecPolicyRef ocsp_policy;
+ status = CreatePolicy(&CSSMOID_APPLE_TP_REVOCATION_OCSP, &tp_ocsp_options,
+ sizeof(tp_ocsp_options), &ocsp_policy);
+ if (status)
+ return status;
+ ScopedCFTypeRef<SecPolicyRef> scoped_ocsp_policy(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;
+
+ policies->reset(policy_array);
+ return noErr;
+}
+
// Gets the issuer for a given cert, starting with the cert itself and
// including the intermediate and finally root certificates (if any).
// This function calls SecTrust but doesn't actually pay attention to the trust
@@ -734,23 +814,10 @@ int X509Certificate::Verify(const std::string& hostname, int flags,
return ERR_CERT_REVOKED;
}
- // 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.
- CSSM_APPLE_TP_SSL_OPTIONS tp_ssl_options = {
- CSSM_APPLE_TP_SSL_OPTS_VERSION,
- hostname.size(),
- hostname.data(),
- 0
- };
- SecPolicyRef ssl_policy;
- OSStatus status = CreatePolicy(&CSSMOID_APPLE_TP_SSL,
- &tp_ssl_options,
- sizeof(tp_ssl_options),
- &ssl_policy);
+ ScopedCFTypeRef<CFArrayRef> trust_policies;
+ OSStatus status = CreateTrustPolicies(hostname, flags, &trust_policies);
if (status)
return NetErrorFromOSStatus(status);
- ScopedCFTypeRef<SecPolicyRef> scoped_ssl_policy(ssl_policy);
// Create and configure a SecTrustRef, which takes our certificate(s)
// and our SSL SecPolicyRef. SecTrustCreateWithCertificates() takes an
@@ -773,7 +840,8 @@ int X509Certificate::Verify(const std::string& hostname, int flags,
base::AutoLock lock(verification_lock_);
SecTrustRef trust_ref = NULL;
- status = SecTrustCreateWithCertificates(cert_array, ssl_policy, &trust_ref);
+ status = SecTrustCreateWithCertificates(cert_array, trust_policies,
+ &trust_ref);
if (status)
return NetErrorFromOSStatus(status);
ScopedCFTypeRef<SecTrustRef> scoped_trust_ref(trust_ref);
@@ -784,34 +852,51 @@ int X509Certificate::Verify(const std::string& hostname, int flags,
return NetErrorFromOSStatus(status);
}
+ CSSM_APPLE_TP_ACTION_DATA tp_action_data;
+ memset(&tp_action_data, 0, sizeof(tp_action_data));
+ tp_action_data.Version = CSSM_APPLE_TP_ACTION_VERSION;
+ // Allow CSSM to download any missing intermediate certificates if an
+ // authorityInfoAccess extension or issuerAltName extension is present.
+ tp_action_data.ActionFlags = CSSM_TP_ACTION_FETCH_CERT_FROM_NET;
+
if (flags & VERIFY_REV_CHECKING_ENABLED) {
- // When called with VERIFY_REV_CHECKING_ENABLED, we ask SecTrustEvaluate()
- // to apply OCSP and CRL checking, but we're still subject to the global
- // settings, which are configured in the Keychain Access application (in
- // the Certificates tab of the Preferences dialog). If the user has
- // revocation disabled (which is the default), then we will get
- // kSecTrustResultRecoverableTrustFailure back from SecTrustEvaluate()
- // with one of a number of sub error codes indicating that revocation
- // checking did not occur. In that case, we'll set our own result to include
+ // Require a positive result from an OCSP responder or a CRL (or both)
+ // for every certificate in the chain. The Apple TP automatically
+ // excludes the self-signed root from this requirement. If a certificate
+ // is missing both a crlDistributionPoints extension and an
+ // authorityInfoAccess extension with an OCSP responder URL, then we
+ // will get a kSecTrustResultRecoverableTrustFailure back from
+ // SecTrustEvaluate(), with a
+ // CSSMERR_APPLETP_INCOMPLETE_REVOCATION_CHECK error code. In that case,
+ // we'll set our own result to include
+ // CERT_STATUS_NO_REVOCATION_MECHANISM. If one or both extensions are
+ // present, and a check fails (server unavailable, OCSP retry later,
+ // signature mismatch), then we'll set our own result to include
// CERT_STATUS_UNABLE_TO_CHECK_REVOCATION.
- //
- // NOTE: This does not apply to EV certificates, which always get
- // revocation checks regardless of the global settings.
+ tp_action_data.ActionFlags |= CSSM_TP_ACTION_REQUIRE_REV_PER_CERT;
verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED;
- CSSM_APPLE_TP_ACTION_DATA tp_action_data = { CSSM_APPLE_TP_ACTION_VERSION };
- tp_action_data.ActionFlags = CSSM_TP_ACTION_REQUIRE_REV_PER_CERT;
- CFDataRef action_data_ref =
- CFDataCreate(NULL, reinterpret_cast<UInt8*>(&tp_action_data),
- sizeof(tp_action_data));
- if (!action_data_ref)
- return ERR_OUT_OF_MEMORY;
- ScopedCFTypeRef<CFDataRef> scoped_action_data_ref(action_data_ref);
- status = SecTrustSetParameters(trust_ref, CSSM_TP_ACTION_DEFAULT,
- action_data_ref);
- if (status)
- return NetErrorFromOSStatus(status);
+ } 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
+ // 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.
+ flags &= ~VERIFY_EV_CERT;
}
+ CFDataRef action_data_ref =
+ CFDataCreateWithBytesNoCopy(kCFAllocatorDefault,
+ reinterpret_cast<UInt8*>(&tp_action_data),
+ sizeof(tp_action_data), kCFAllocatorNull);
+ if (!action_data_ref)
+ return ERR_OUT_OF_MEMORY;
+ ScopedCFTypeRef<CFDataRef> scoped_action_data_ref(action_data_ref);
+ status = SecTrustSetParameters(trust_ref, CSSM_TP_ACTION_DEFAULT,
+ action_data_ref);
+ if (status)
+ return NetErrorFromOSStatus(status);
+
// Verify the certificate. A non-zero result from SecTrustGetResult()
// indicates that some fatal error occurred and the chain couldn't be
// processed, not that the chain contains no errors. We need to examine the