Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(708)

Side by Side Diff: net/base/client_cert_store_impl_mac.cc

Issue 12680003: net: split net/ssl out of net/base (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/base/client_cert_store_impl.h"
6
7 #include <CommonCrypto/CommonDigest.h>
8 #include <CoreFoundation/CFArray.h>
9 #include <CoreServices/CoreServices.h>
10 #include <Security/SecBase.h>
11 #include <Security/Security.h>
12
13 #include <algorithm>
14 #include <string>
15
16 #include "base/logging.h"
17 #include "base/mac/mac_logging.h"
18 #include "base/mac/scoped_cftyperef.h"
19 #include "base/synchronization/lock.h"
20 #include "base/sys_string_conversions.h"
21 #include "crypto/mac_security_services_lock.h"
22 #include "net/base/host_port_pair.h"
23 #include "net/base/x509_util.h"
24
25 using base::mac::ScopedCFTypeRef;
26
27 namespace net {
28
29 namespace {
30
31 bool GetClientCertsImpl(const scoped_refptr<X509Certificate>& preferred_cert,
32 const CertificateList& regular_certs,
33 const SSLCertRequestInfo& request,
34 CertificateList* selected_certs) {
35 CertificateList preliminary_list;
36 if (preferred_cert)
37 preliminary_list.push_back(preferred_cert);
38 preliminary_list.insert(preliminary_list.end(), regular_certs.begin(),
39 regular_certs.end());
40
41 selected_certs->clear();
42 for (size_t i = 0; i < preliminary_list.size(); ++i) {
43 scoped_refptr<X509Certificate>& cert = preliminary_list[i];
44 if (cert->HasExpired() || !cert->SupportsSSLClientAuth())
45 continue;
46
47 // Skip duplicates (a cert may be in multiple keychains).
48 const SHA1HashValue& fingerprint = cert->fingerprint();
49 size_t pos;
50 for (pos = 0; pos < selected_certs->size(); ++pos) {
51 if ((*selected_certs)[pos]->fingerprint().Equals(fingerprint))
52 break;
53 }
54 if (pos < selected_certs->size())
55 continue;
56
57 // Check if the certificate issuer is allowed by the server.
58 if (!request.cert_authorities.empty() &&
59 !cert->IsIssuedByEncoded(request.cert_authorities)) {
60 continue;
61 }
62 selected_certs->push_back(cert);
63 }
64
65 // Preferred cert should appear first in the ui, so exclude it from the
66 // sorting.
67 CertificateList::iterator sort_begin = selected_certs->begin();
68 CertificateList::iterator sort_end = selected_certs->end();
69 if (preferred_cert &&
70 sort_begin != sort_end &&
71 *sort_begin == preferred_cert) {
72 ++sort_begin;
73 }
74 sort(sort_begin, sort_end, x509_util::ClientCertSorter());
75 return true;
76 }
77
78 } // namespace
79
80 bool ClientCertStoreImpl::GetClientCerts(const SSLCertRequestInfo& request,
81 CertificateList* selected_certs) {
82 std::string server_domain =
83 HostPortPair::FromString(request.host_and_port).host();
84
85 ScopedCFTypeRef<SecIdentityRef> preferred_identity;
86 if (!server_domain.empty()) {
87 // See if there's an identity preference for this domain:
88 ScopedCFTypeRef<CFStringRef> domain_str(
89 base::SysUTF8ToCFStringRef("https://" + server_domain));
90 SecIdentityRef identity = NULL;
91 // While SecIdentityCopyPreferences appears to take a list of CA issuers
92 // to restrict the identity search to, within Security.framework the
93 // argument is ignored and filtering unimplemented. See
94 // SecIdentity.cpp in libsecurity_keychain, specifically
95 // _SecIdentityCopyPreferenceMatchingName().
96 {
97 base::AutoLock lock(crypto::GetMacSecurityServicesLock());
98 if (SecIdentityCopyPreference(domain_str, 0, NULL, &identity) == noErr)
99 preferred_identity.reset(identity);
100 }
101 }
102
103 // Now enumerate the identities in the available keychains.
104 scoped_refptr<X509Certificate> preferred_cert = NULL;
105 CertificateList regular_certs;
106
107 SecIdentitySearchRef search = NULL;
108 OSStatus err;
109 {
110 base::AutoLock lock(crypto::GetMacSecurityServicesLock());
111 err = SecIdentitySearchCreate(NULL, CSSM_KEYUSE_SIGN, &search);
112 }
113 if (err)
114 return false;
115 ScopedCFTypeRef<SecIdentitySearchRef> scoped_search(search);
116 while (!err) {
117 SecIdentityRef identity = NULL;
118 {
119 base::AutoLock lock(crypto::GetMacSecurityServicesLock());
120 err = SecIdentitySearchCopyNext(search, &identity);
121 }
122 if (err)
123 break;
124 ScopedCFTypeRef<SecIdentityRef> scoped_identity(identity);
125
126 SecCertificateRef cert_handle;
127 err = SecIdentityCopyCertificate(identity, &cert_handle);
128 if (err != noErr)
129 continue;
130 ScopedCFTypeRef<SecCertificateRef> scoped_cert_handle(cert_handle);
131
132 scoped_refptr<X509Certificate> cert(
133 X509Certificate::CreateFromHandle(cert_handle,
134 X509Certificate::OSCertHandles()));
135
136 if (preferred_identity && CFEqual(preferred_identity, identity)) {
137 // Only one certificate should match.
138 DCHECK(!preferred_cert);
139 preferred_cert = cert;
140 } else {
141 regular_certs.push_back(cert);
142 }
143 }
144
145 if (err != errSecItemNotFound) {
146 OSSTATUS_LOG(ERROR, err) << "SecIdentitySearch error";
147 return false;
148 }
149
150 return GetClientCertsImpl(preferred_cert, regular_certs, request,
151 selected_certs);
152 }
153
154 bool ClientCertStoreImpl::SelectClientCerts(const CertificateList& input_certs,
155 const SSLCertRequestInfo& request,
156 CertificateList* selected_certs) {
157 return GetClientCertsImpl(NULL, input_certs, request,
158 selected_certs);
159 }
160
161 #if defined(OS_MACOSX) && !defined(OS_IOS)
162 bool ClientCertStoreImpl::SelectClientCertsGivenPreferred(
163 const scoped_refptr<X509Certificate>& preferred_cert,
164 const CertificateList& regular_certs,
165 const SSLCertRequestInfo& request,
166 CertificateList* selected_certs) {
167 return GetClientCertsImpl(preferred_cert, regular_certs, request,
168 selected_certs);
169 }
170 #endif
171
172 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698