diff options
author | davidben@chromium.org <davidben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-13 18:11:01 +0000 |
---|---|---|
committer | davidben@chromium.org <davidben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-13 18:11:01 +0000 |
commit | dca06c1d45b69f70b376adfa8992cae448ae5633 (patch) | |
tree | 3a948e1ffe5b91c82c805956a6b4095d765fb42a | |
parent | 1caeb9996ad2e9581d6da4bf52030650945682ea (diff) | |
download | chromium_src-dca06c1d45b69f70b376adfa8992cae448ae5633.zip chromium_src-dca06c1d45b69f70b376adfa8992cae448ae5633.tar.gz chromium_src-dca06c1d45b69f70b376adfa8992cae448ae5633.tar.bz2 |
Rewrite X509Certificate::SupportsSSLClientAuth to be more accurate
We take the intersection of key usage and extended key usage and treat as an
allow if missing. Also, support the "Any" purpose. Removed support for the
Netscape-specific ns-cert-type extension. Internet Explorer doesn't seem to
support it anyway.
BUG=45353
TEST=SSL client auth displays correct certificates on Mac (e.g. on foaf.me)
Review URL: http://codereview.chromium.org/2899005
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@52189 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | net/base/x509_certificate_mac.cc | 51 |
1 files changed, 39 insertions, 12 deletions
diff --git a/net/base/x509_certificate_mac.cc b/net/base/x509_certificate_mac.cc index 8d7970a..08da804 100644 --- a/net/base/x509_certificate_mac.cc +++ b/net/base/x509_certificate_mac.cc @@ -358,6 +358,20 @@ OSStatus CopyCertChain(SecCertificateRef cert_handle, return SecTrustGetResult(trust, &status, out_cert_chain, &status_chain); } +// Returns true if |purpose| is listed as allowed in |usage|. This +// function also considers the "Any" purpose. If the attribute is +// present and empty, we return false. +bool ExtendedKeyUsageAllows(const CE_ExtendedKeyUsage* usage, + const CSSM_OID* purpose) { + for (unsigned p = 0; p < usage->numPurposes; ++p) { + if (CSSMOIDEqual(&usage->purposes[p], purpose)) + return true; + if (CSSMOIDEqual(&usage->purposes[p], &CSSMOID_ExtendedKeyUsageAny)) + return true; + } + return false; +} + } // namespace void X509Certificate::Initialize() { @@ -699,25 +713,38 @@ bool X509Certificate::SupportsSSLClientAuth() const { CSSMFields fields; if (GetCertFields(cert_handle_, &fields) != noErr) return false; + + // Gather the extensions we care about. We do not support + // CSSMOID_NetscapeCertType on OS X. + const CE_ExtendedKeyUsage* ext_key_usage = NULL; + const CE_KeyUsage* key_usage = NULL; for (unsigned f = 0; f < fields.num_of_fields; ++f) { const CSSM_FIELD& field = fields.fields[f]; const CSSM_X509_EXTENSION* ext = reinterpret_cast<const CSSM_X509_EXTENSION*>(field.FieldValue.Data); - if (CSSMOIDEqual(&field.FieldOid, &CSSMOID_ExtendedKeyUsage)) { - const CE_ExtendedKeyUsage* usage = + if (CSSMOIDEqual(&field.FieldOid, &CSSMOID_KeyUsage)) { + key_usage = reinterpret_cast<const CE_KeyUsage*>(ext->value.parsedValue); + } else if (CSSMOIDEqual(&field.FieldOid, &CSSMOID_ExtendedKeyUsage)) { + ext_key_usage = reinterpret_cast<const CE_ExtendedKeyUsage*>(ext->value.parsedValue); - for (unsigned p = 0; p < usage->numPurposes; ++p) { - if (CSSMOIDEqual(&usage->purposes[p], &CSSMOID_ClientAuth)) - return true; - } - } else if (CSSMOIDEqual(&field.FieldOid, &CSSMOID_NetscapeCertType)) { - uint16_t flags = - *reinterpret_cast<const uint16_t*>(ext->value.parsedValue); - if (flags & CE_NCT_SSL_Client) - return true; } } - return false; + + // RFC5280 says to take the intersection of the two extensions. + // + // Our underlying crypto libraries don't expose + // ClientCertificateType, so for now we will not support fixed + // Diffie-Hellman mechanisms. For rsa_sign, we need the + // digitalSignature bit. + // + // In particular, if a key has the nonRepudiation bit and not the + // digitalSignature one, we will not offer it to the user. + if (key_usage && !((*key_usage) & CE_KU_DigitalSignature)) + return false; + if (ext_key_usage && !ExtendedKeyUsageAllows(ext_key_usage, + &CSSMOID_ClientAuth)) + return false; + return true; } bool X509Certificate::IsIssuedBy( |