diff options
Diffstat (limited to 'net/base/x509_certificate_mac.cc')
-rw-r--r-- | net/base/x509_certificate_mac.cc | 73 |
1 files changed, 48 insertions, 25 deletions
diff --git a/net/base/x509_certificate_mac.cc b/net/base/x509_certificate_mac.cc index 9487410..36fc65a 100644 --- a/net/base/x509_certificate_mac.cc +++ b/net/base/x509_certificate_mac.cc @@ -10,6 +10,7 @@ #include "base/scoped_cftyperef.h" #include "base/logging.h" #include "base/pickle.h" +#include "base/sys_string_conversions.h" #include "net/base/cert_status_flags.h" #include "net/base/cert_verify_result.h" #include "net/base/net_errors.h" @@ -356,27 +357,6 @@ void GetCertDateForOID(X509Certificate::OSCertHandle cert_handle, } } -// Returns true if this cert supports a given extended key usage. -bool CertSupportsUsage(SecCertificateRef cert, const CSSM_OID& usage_oid) { - CSSMFields fields; - if (GetCertFields(cert, &fields) != noErr) - return false; - for (unsigned f = 0; f < fields.num_of_fields; ++f) { - const CSSM_FIELD &field = fields.fields[f]; - if (CSSMOIDEqual(&field.FieldOid, &CSSMOID_ExtendedKeyUsage)) { - const CSSM_X509_EXTENSION* ext = - reinterpret_cast<const CSSM_X509_EXTENSION*>(field.FieldValue.Data); - const CE_ExtendedKeyUsage* usage = - reinterpret_cast<const CE_ExtendedKeyUsage*>(ext->value.parsedValue); - for (unsigned p = 0; p < usage->numPurposes; ++p) { - if (CSSMOIDEqual(&usage->purposes[p], &usage_oid)) - return true; - } - } - } - return false; -} - // Creates a SecPolicyRef for the given OID, with optional value. OSStatus CreatePolicy(const CSSM_OID* policy_OID, void* option_data, @@ -732,6 +712,31 @@ X509Certificate::Fingerprint X509Certificate::CalculateFingerprint( return sha1; } +bool X509Certificate::SupportsSSLClientAuth() const { + CSSMFields fields; + if (GetCertFields(cert_handle_, &fields) != noErr) + return false; + 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 = + 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; +} + // static OSStatus X509Certificate::CreateSSLClientPolicy(SecPolicyRef* out_policy) { CSSM_APPLE_TP_SSL_OPTIONS tp_ssl_options = { @@ -748,7 +753,21 @@ OSStatus X509Certificate::CreateSSLClientPolicy(SecPolicyRef* out_policy) { // static bool X509Certificate::GetSSLClientCertificates ( + const std::string& server_domain, std::vector<scoped_refptr<X509Certificate> >* certs) { + scoped_cftyperef<SecIdentityRef> preferred_identity; + if (!server_domain.empty()) { + // See if there's an identity preference for this domain: + scoped_cftyperef<CFStringRef> domain_str( + base::SysUTF8ToCFStringRef("https://" + server_domain)); + SecIdentityRef identity = NULL; + if (SecIdentityCopyPreference(domain_str, + 0, + NULL, + &identity) == noErr) + preferred_identity.reset(identity); + } + SecIdentitySearchRef search = nil; OSStatus err = SecIdentitySearchCreate(NULL, CSSM_KEYUSE_SIGN, &search); fprintf(stderr,"====Created SecIdentitySearch %p\n",search);//TEMP @@ -768,8 +787,7 @@ bool X509Certificate::GetSSLClientCertificates ( scoped_refptr<X509Certificate> cert( CreateFromHandle(cert_handle, SOURCE_LONE_CERT_IMPORT)); // cert_handle is adoped by cert, so I don't need to release it myself. - if (cert->HasExpired() || - !CertSupportsUsage(cert_handle, CSSMOID_ClientAuth)) + if (cert->HasExpired() || !cert->SupportsSSLClientAuth()) continue; // Skip duplicates (a cert may be in multiple keychains). @@ -783,7 +801,12 @@ bool X509Certificate::GetSSLClientCertificates ( continue; // The cert passes, so add it to the vector. - certs->push_back(cert); + // If it's the preferred identity, add it at the start (so it'll be + // selected by default in the UI.) + if (preferred_identity && CFEqual(preferred_identity, identity)) + certs->insert(certs->begin(), cert); + else + certs->push_back(cert); } if (err != errSecItemNotFound) { @@ -793,7 +816,7 @@ bool X509Certificate::GetSSLClientCertificates ( return true; } -CFArrayRef X509Certificate::CreateClientCertificateChain() { +CFArrayRef X509Certificate::CreateClientCertificateChain() const { // Initialize the result array with just the IdentityRef of the receiver: OSStatus result; SecIdentityRef identity; |