| Index: net/ssl/client_cert_store_mac.cc
|
| diff --git a/net/ssl/client_cert_store_mac.cc b/net/ssl/client_cert_store_mac.cc
|
| deleted file mode 100644
|
| index 06d7d0613c88560e00116bd86541565da31f4a7a..0000000000000000000000000000000000000000
|
| --- a/net/ssl/client_cert_store_mac.cc
|
| +++ /dev/null
|
| @@ -1,277 +0,0 @@
|
| -// Copyright 2013 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "net/ssl/client_cert_store_mac.h"
|
| -
|
| -#include <CommonCrypto/CommonDigest.h>
|
| -#include <CoreFoundation/CFArray.h>
|
| -#include <CoreServices/CoreServices.h>
|
| -#include <Security/SecBase.h>
|
| -#include <Security/Security.h>
|
| -
|
| -#include <algorithm>
|
| -#include <string>
|
| -
|
| -#include "base/callback.h"
|
| -#include "base/logging.h"
|
| -#include "base/mac/mac_logging.h"
|
| -#include "base/mac/scoped_cftyperef.h"
|
| -#include "base/strings/sys_string_conversions.h"
|
| -#include "base/synchronization/lock.h"
|
| -#include "crypto/mac_security_services_lock.h"
|
| -#include "net/base/host_port_pair.h"
|
| -#include "net/cert/x509_util.h"
|
| -#include "net/cert/x509_util_mac.h"
|
| -
|
| -using base::ScopedCFTypeRef;
|
| -
|
| -namespace net {
|
| -
|
| -namespace {
|
| -
|
| -// 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
|
| -// result: it shouldn't be used to determine trust, just to traverse the chain.
|
| -// Caller is responsible for releasing the value stored into *out_cert_chain.
|
| -OSStatus CopyCertChain(SecCertificateRef cert_handle,
|
| - CFArrayRef* out_cert_chain) {
|
| - DCHECK(cert_handle);
|
| - DCHECK(out_cert_chain);
|
| -
|
| - // Create an SSL policy ref configured for client cert evaluation.
|
| - SecPolicyRef ssl_policy;
|
| - OSStatus result = x509_util::CreateSSLClientPolicy(&ssl_policy);
|
| - if (result)
|
| - return result;
|
| - ScopedCFTypeRef<SecPolicyRef> scoped_ssl_policy(ssl_policy);
|
| -
|
| - // Create a SecTrustRef.
|
| - ScopedCFTypeRef<CFArrayRef> input_certs(CFArrayCreate(
|
| - NULL, const_cast<const void**>(reinterpret_cast<void**>(&cert_handle)),
|
| - 1, &kCFTypeArrayCallBacks));
|
| - SecTrustRef trust_ref = NULL;
|
| - {
|
| - base::AutoLock lock(crypto::GetMacSecurityServicesLock());
|
| - result = SecTrustCreateWithCertificates(input_certs, ssl_policy,
|
| - &trust_ref);
|
| - }
|
| - if (result)
|
| - return result;
|
| - ScopedCFTypeRef<SecTrustRef> trust(trust_ref);
|
| -
|
| - // Evaluate trust, which creates the cert chain.
|
| - SecTrustResultType status;
|
| - CSSM_TP_APPLE_EVIDENCE_INFO* status_chain;
|
| - {
|
| - base::AutoLock lock(crypto::GetMacSecurityServicesLock());
|
| - result = SecTrustEvaluate(trust, &status);
|
| - }
|
| - if (result)
|
| - return result;
|
| - {
|
| - base::AutoLock lock(crypto::GetMacSecurityServicesLock());
|
| - result = SecTrustGetResult(trust, &status, out_cert_chain, &status_chain);
|
| - }
|
| - return result;
|
| -}
|
| -
|
| -// Returns true if |*cert| is issued by an authority in |valid_issuers|
|
| -// according to Keychain Services, rather than using |cert|'s intermediate
|
| -// certificates. If it is, |*cert| is updated to point to the completed
|
| -// certificate
|
| -bool IsIssuedByInKeychain(const std::vector<std::string>& valid_issuers,
|
| - scoped_refptr<X509Certificate>* cert) {
|
| - DCHECK(cert);
|
| - DCHECK(cert->get());
|
| -
|
| - X509Certificate::OSCertHandle cert_handle = (*cert)->os_cert_handle();
|
| - CFArrayRef cert_chain = NULL;
|
| - OSStatus result = CopyCertChain(cert_handle, &cert_chain);
|
| - if (result) {
|
| - OSSTATUS_LOG(ERROR, result) << "CopyCertChain error";
|
| - return false;
|
| - }
|
| -
|
| - if (!cert_chain)
|
| - return false;
|
| -
|
| - X509Certificate::OSCertHandles intermediates;
|
| - for (CFIndex i = 1, chain_count = CFArrayGetCount(cert_chain);
|
| - i < chain_count; ++i) {
|
| - SecCertificateRef cert = reinterpret_cast<SecCertificateRef>(
|
| - const_cast<void*>(CFArrayGetValueAtIndex(cert_chain, i)));
|
| - intermediates.push_back(cert);
|
| - }
|
| -
|
| - scoped_refptr<X509Certificate> new_cert(X509Certificate::CreateFromHandle(
|
| - cert_handle, intermediates));
|
| - CFRelease(cert_chain); // Also frees |intermediates|.
|
| -
|
| - if (!new_cert->IsIssuedByEncoded(valid_issuers))
|
| - return false;
|
| -
|
| - cert->swap(new_cert);
|
| - return true;
|
| -}
|
| -
|
| -// Examines the certificates in |preferred_cert| and |regular_certs| to find
|
| -// all certificates that match the client certificate request in |request|,
|
| -// storing the matching certificates in |selected_certs|.
|
| -// If |query_keychain| is true, Keychain Services will be queried to construct
|
| -// full certificate chains. If it is false, only the the certificates and their
|
| -// intermediates (available via X509Certificate::GetIntermediateCertificates())
|
| -// will be considered.
|
| -void GetClientCertsImpl(const scoped_refptr<X509Certificate>& preferred_cert,
|
| - const CertificateList& regular_certs,
|
| - const SSLCertRequestInfo& request,
|
| - bool query_keychain,
|
| - CertificateList* selected_certs) {
|
| - CertificateList preliminary_list;
|
| - if (preferred_cert.get())
|
| - preliminary_list.push_back(preferred_cert);
|
| - preliminary_list.insert(preliminary_list.end(), regular_certs.begin(),
|
| - regular_certs.end());
|
| -
|
| - selected_certs->clear();
|
| - for (size_t i = 0; i < preliminary_list.size(); ++i) {
|
| - scoped_refptr<X509Certificate>& cert = preliminary_list[i];
|
| - if (cert->HasExpired() || !cert->SupportsSSLClientAuth())
|
| - continue;
|
| -
|
| - // Skip duplicates (a cert may be in multiple keychains).
|
| - const SHA1HashValue& fingerprint = cert->fingerprint();
|
| - size_t pos;
|
| - for (pos = 0; pos < selected_certs->size(); ++pos) {
|
| - if ((*selected_certs)[pos]->fingerprint().Equals(fingerprint))
|
| - break;
|
| - }
|
| - if (pos < selected_certs->size())
|
| - continue;
|
| -
|
| - // Check if the certificate issuer is allowed by the server.
|
| - if (request.cert_authorities.empty() ||
|
| - cert->IsIssuedByEncoded(request.cert_authorities) ||
|
| - (query_keychain &&
|
| - IsIssuedByInKeychain(request.cert_authorities, &cert))) {
|
| - selected_certs->push_back(cert);
|
| - }
|
| - }
|
| -
|
| - // Preferred cert should appear first in the ui, so exclude it from the
|
| - // sorting.
|
| - CertificateList::iterator sort_begin = selected_certs->begin();
|
| - CertificateList::iterator sort_end = selected_certs->end();
|
| - if (preferred_cert.get() && sort_begin != sort_end &&
|
| - sort_begin->get() == preferred_cert.get()) {
|
| - ++sort_begin;
|
| - }
|
| - sort(sort_begin, sort_end, x509_util::ClientCertSorter());
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| -ClientCertStoreMac::ClientCertStoreMac() {}
|
| -
|
| -ClientCertStoreMac::~ClientCertStoreMac() {}
|
| -
|
| -void ClientCertStoreMac::GetClientCerts(const SSLCertRequestInfo& request,
|
| - CertificateList* selected_certs,
|
| - const base::Closure& callback) {
|
| - std::string server_domain = request.host_and_port.host();
|
| -
|
| - ScopedCFTypeRef<SecIdentityRef> preferred_identity;
|
| - if (!server_domain.empty()) {
|
| - // See if there's an identity preference for this domain:
|
| - ScopedCFTypeRef<CFStringRef> domain_str(
|
| - base::SysUTF8ToCFStringRef("https://" + server_domain));
|
| - SecIdentityRef identity = NULL;
|
| - // While SecIdentityCopyPreferences appears to take a list of CA issuers
|
| - // to restrict the identity search to, within Security.framework the
|
| - // argument is ignored and filtering unimplemented. See
|
| - // SecIdentity.cpp in libsecurity_keychain, specifically
|
| - // _SecIdentityCopyPreferenceMatchingName().
|
| - {
|
| - base::AutoLock lock(crypto::GetMacSecurityServicesLock());
|
| - if (SecIdentityCopyPreference(domain_str, 0, NULL, &identity) == noErr)
|
| - preferred_identity.reset(identity);
|
| - }
|
| - }
|
| -
|
| - // Now enumerate the identities in the available keychains.
|
| - scoped_refptr<X509Certificate> preferred_cert = NULL;
|
| - CertificateList regular_certs;
|
| -
|
| - SecIdentitySearchRef search = NULL;
|
| - OSStatus err;
|
| - {
|
| - base::AutoLock lock(crypto::GetMacSecurityServicesLock());
|
| - err = SecIdentitySearchCreate(NULL, CSSM_KEYUSE_SIGN, &search);
|
| - }
|
| - if (err) {
|
| - selected_certs->clear();
|
| - callback.Run();
|
| - return;
|
| - }
|
| - ScopedCFTypeRef<SecIdentitySearchRef> scoped_search(search);
|
| - while (!err) {
|
| - SecIdentityRef identity = NULL;
|
| - {
|
| - base::AutoLock lock(crypto::GetMacSecurityServicesLock());
|
| - err = SecIdentitySearchCopyNext(search, &identity);
|
| - }
|
| - if (err)
|
| - break;
|
| - ScopedCFTypeRef<SecIdentityRef> scoped_identity(identity);
|
| -
|
| - SecCertificateRef cert_handle;
|
| - err = SecIdentityCopyCertificate(identity, &cert_handle);
|
| - if (err != noErr)
|
| - continue;
|
| - ScopedCFTypeRef<SecCertificateRef> scoped_cert_handle(cert_handle);
|
| -
|
| - scoped_refptr<X509Certificate> cert(
|
| - X509Certificate::CreateFromHandle(cert_handle,
|
| - X509Certificate::OSCertHandles()));
|
| -
|
| - if (preferred_identity && CFEqual(preferred_identity, identity)) {
|
| - // Only one certificate should match.
|
| - DCHECK(!preferred_cert.get());
|
| - preferred_cert = cert;
|
| - } else {
|
| - regular_certs.push_back(cert);
|
| - }
|
| - }
|
| -
|
| - if (err != errSecItemNotFound) {
|
| - OSSTATUS_LOG(ERROR, err) << "SecIdentitySearch error";
|
| - selected_certs->clear();
|
| - callback.Run();
|
| - return;
|
| - }
|
| -
|
| - GetClientCertsImpl(preferred_cert, regular_certs, request, true,
|
| - selected_certs);
|
| - callback.Run();
|
| -}
|
| -
|
| -bool ClientCertStoreMac::SelectClientCertsForTesting(
|
| - const CertificateList& input_certs,
|
| - const SSLCertRequestInfo& request,
|
| - CertificateList* selected_certs) {
|
| - GetClientCertsImpl(NULL, input_certs, request, false, selected_certs);
|
| - return true;
|
| -}
|
| -
|
| -bool ClientCertStoreMac::SelectClientCertsGivenPreferredForTesting(
|
| - const scoped_refptr<X509Certificate>& preferred_cert,
|
| - const CertificateList& regular_certs,
|
| - const SSLCertRequestInfo& request,
|
| - CertificateList* selected_certs) {
|
| - GetClientCertsImpl(
|
| - preferred_cert, regular_certs, request, false, selected_certs);
|
| - return true;
|
| -}
|
| -
|
| -} // namespace net
|
|
|