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

Side by Side Diff: net/ssl/client_cert_store_mac.cc

Issue 2753143002: move X509Certificate::SupportsSSLClientAuth to client_cert_store_mac.cc (Closed)
Patch Set: . Created 3 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
« no previous file with comments | « net/cert/x509_certificate_mac.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/ssl/client_cert_store_mac.h" 5 #include "net/ssl/client_cert_store_mac.h"
6 6
7 #include <CommonCrypto/CommonDigest.h> 7 #include <CommonCrypto/CommonDigest.h>
8 #include <CoreFoundation/CFArray.h> 8 #include <CoreFoundation/CFArray.h>
9 #include <CoreServices/CoreServices.h> 9 #include <CoreServices/CoreServices.h>
10 #include <Security/SecBase.h> 10 #include <Security/SecBase.h>
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
114 cert_handle, intermediates)); 114 cert_handle, intermediates));
115 CFRelease(cert_chain); // Also frees |intermediates|. 115 CFRelease(cert_chain); // Also frees |intermediates|.
116 116
117 if (!new_cert->IsIssuedByEncoded(valid_issuers)) 117 if (!new_cert->IsIssuedByEncoded(valid_issuers))
118 return false; 118 return false;
119 119
120 cert->swap(new_cert); 120 cert->swap(new_cert);
121 return true; 121 return true;
122 } 122 }
123 123
124 // Returns true if |purpose| is listed as allowed in |usage|. This
125 // function also considers the "Any" purpose. If the attribute is
126 // present and empty, we return false.
127 bool ExtendedKeyUsageAllows(const CE_ExtendedKeyUsage* usage,
128 const CSSM_OID* purpose) {
129 for (unsigned p = 0; p < usage->numPurposes; ++p) {
130 if (CSSMOIDEqual(&usage->purposes[p], purpose))
131 return true;
132 if (CSSMOIDEqual(&usage->purposes[p], &CSSMOID_ExtendedKeyUsageAny))
133 return true;
134 }
135 return false;
136 }
137
138 // Does |cert|'s usage allow SSL client authentication?
139 bool SupportsSSLClientAuth(SecCertificateRef cert) {
140 x509_util::CSSMCachedCertificate cached_cert;
141 OSStatus status = cached_cert.Init(cert);
142 if (status)
143 return false;
144
145 // RFC5280 says to take the intersection of the two extensions.
146 //
147 // Our underlying crypto libraries don't expose
148 // ClientCertificateType, so for now we will not support fixed
149 // Diffie-Hellman mechanisms. For rsa_sign, we need the
150 // digitalSignature bit.
151 //
152 // In particular, if a key has the nonRepudiation bit and not the
153 // digitalSignature one, we will not offer it to the user.
154 x509_util::CSSMFieldValue key_usage;
155 status = cached_cert.GetField(&CSSMOID_KeyUsage, &key_usage);
156 if (status == CSSM_OK && key_usage.field()) {
157 const CSSM_X509_EXTENSION* ext = key_usage.GetAs<CSSM_X509_EXTENSION>();
158 const CE_KeyUsage* key_usage_value =
159 reinterpret_cast<const CE_KeyUsage*>(ext->value.parsedValue);
160 if (!((*key_usage_value) & CE_KU_DigitalSignature))
161 return false;
162 }
163
164 status = cached_cert.GetField(&CSSMOID_ExtendedKeyUsage, &key_usage);
165 if (status == CSSM_OK && key_usage.field()) {
166 const CSSM_X509_EXTENSION* ext = key_usage.GetAs<CSSM_X509_EXTENSION>();
167 const CE_ExtendedKeyUsage* ext_key_usage =
168 reinterpret_cast<const CE_ExtendedKeyUsage*>(ext->value.parsedValue);
169 if (!ExtendedKeyUsageAllows(ext_key_usage, &CSSMOID_ClientAuth))
170 return false;
171 }
172 return true;
173 }
174
124 // Examines the certificates in |preferred_cert| and |regular_certs| to find 175 // Examines the certificates in |preferred_cert| and |regular_certs| to find
125 // all certificates that match the client certificate request in |request|, 176 // all certificates that match the client certificate request in |request|,
126 // storing the matching certificates in |selected_certs|. 177 // storing the matching certificates in |selected_certs|.
127 // If |query_keychain| is true, Keychain Services will be queried to construct 178 // If |query_keychain| is true, Keychain Services will be queried to construct
128 // full certificate chains. If it is false, only the the certificates and their 179 // full certificate chains. If it is false, only the the certificates and their
129 // intermediates (available via X509Certificate::GetIntermediateCertificates()) 180 // intermediates (available via X509Certificate::GetIntermediateCertificates())
130 // will be considered. 181 // will be considered.
131 void GetClientCertsImpl(const scoped_refptr<X509Certificate>& preferred_cert, 182 void GetClientCertsImpl(const scoped_refptr<X509Certificate>& preferred_cert,
132 const CertificateList& regular_certs, 183 const CertificateList& regular_certs,
133 const SSLCertRequestInfo& request, 184 const SSLCertRequestInfo& request,
134 bool query_keychain, 185 bool query_keychain,
135 CertificateList* selected_certs) { 186 CertificateList* selected_certs) {
136 CertificateList preliminary_list; 187 CertificateList preliminary_list;
137 if (preferred_cert.get()) 188 if (preferred_cert.get())
138 preliminary_list.push_back(preferred_cert); 189 preliminary_list.push_back(preferred_cert);
139 preliminary_list.insert(preliminary_list.end(), regular_certs.begin(), 190 preliminary_list.insert(preliminary_list.end(), regular_certs.begin(),
140 regular_certs.end()); 191 regular_certs.end());
141 192
142 selected_certs->clear(); 193 selected_certs->clear();
143 for (size_t i = 0; i < preliminary_list.size(); ++i) { 194 for (size_t i = 0; i < preliminary_list.size(); ++i) {
144 scoped_refptr<X509Certificate>& cert = preliminary_list[i]; 195 scoped_refptr<X509Certificate>& cert = preliminary_list[i];
145 if (cert->HasExpired() || !cert->SupportsSSLClientAuth()) 196 if (cert->HasExpired() || !SupportsSSLClientAuth(cert->os_cert_handle()))
146 continue; 197 continue;
147 198
148 // Skip duplicates (a cert may be in multiple keychains). 199 // Skip duplicates (a cert may be in multiple keychains).
149 auto cert_iter = std::find_if( 200 auto cert_iter = std::find_if(
150 selected_certs->begin(), selected_certs->end(), 201 selected_certs->begin(), selected_certs->end(),
151 [&cert](const scoped_refptr<X509Certificate>& other_cert) { 202 [&cert](const scoped_refptr<X509Certificate>& other_cert) {
152 return X509Certificate::IsSameOSCert(cert->os_cert_handle(), 203 return X509Certificate::IsSameOSCert(cert->os_cert_handle(),
153 other_cert->os_cert_handle()); 204 other_cert->os_cert_handle());
154 }); 205 });
155 if (cert_iter != selected_certs->end()) 206 if (cert_iter != selected_certs->end())
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
275 const SSLCertRequestInfo& request, 326 const SSLCertRequestInfo& request,
276 CertificateList* selected_certs) { 327 CertificateList* selected_certs) {
277 GetClientCertsImpl( 328 GetClientCertsImpl(
278 preferred_cert, regular_certs, request, false, selected_certs); 329 preferred_cert, regular_certs, request, false, selected_certs);
279 return true; 330 return true;
280 } 331 }
281 332
282 #pragma clang diagnostic pop // "-Wdeprecated-declarations" 333 #pragma clang diagnostic pop // "-Wdeprecated-declarations"
283 334
284 } // namespace net 335 } // namespace net
OLDNEW
« no previous file with comments | « net/cert/x509_certificate_mac.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698