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

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

Issue 4040: Refactoring out common code in the X.509 cert handling (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 12 years, 3 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
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2006-2008 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/base/x509_certificate.h" 5 #include "net/base/x509_certificate.h"
6 6
7 #include <map> 7 #include "base/logging.h"
8
9 #include "base/histogram.h"
10 #include "base/lock.h"
11 #include "base/pickle.h"
12 #include "base/singleton.h"
13 #include "base/string_tokenizer.h"
14 #include "base/string_util.h"
15 #include "net/base/cert_status_flags.h"
16 #include "net/base/ev_root_ca_metadata.h"
17
18 #pragma comment(lib, "crypt32.lib")
19 8
20 namespace net { 9 namespace net {
21 10
22 namespace { 11 namespace {
23 12
24 // Returns true if this cert fingerprint is the null (all zero) fingerprint. 13 // Returns true if this cert fingerprint is the null (all zero) fingerprint.
25 // We use this as a bogus fingerprint value. 14 // We use this as a bogus fingerprint value.
26 bool IsNullFingerprint(const X509Certificate::Fingerprint& fingerprint) { 15 bool IsNullFingerprint(const X509Certificate::Fingerprint& fingerprint) {
27 for (size_t i = 0; i < arraysize(fingerprint.data); ++i) { 16 for (size_t i = 0; i < arraysize(fingerprint.data); ++i) {
28 if (fingerprint.data[i] != 0) 17 if (fingerprint.data[i] != 0)
29 return false; 18 return false;
30 } 19 }
31 return true; 20 return true;
32 } 21 }
33 22
34 // Calculates the SHA-1 fingerprint of the certificate. Returns an empty
35 // (all zero) fingerprint on failure.
36 X509Certificate::Fingerprint CalculateFingerprint(PCCERT_CONTEXT cert) {
37 DCHECK(NULL != cert->pbCertEncoded);
38 DCHECK(0 != cert->cbCertEncoded);
39
40 BOOL rv;
41 X509Certificate::Fingerprint sha1;
42 DWORD sha1_size = sizeof(sha1.data);
43 rv = CryptHashCertificate(NULL, CALG_SHA1, 0, cert->pbCertEncoded,
44 cert->cbCertEncoded, sha1.data, &sha1_size);
45 DCHECK(rv && sha1_size == sizeof(sha1.data));
46 if (!rv)
47 memset(sha1.data, 0, sizeof(sha1.data));
48 return sha1;
49 }
50
51 // Wrappers of malloc and free for CRYPT_DECODE_PARA, which requires the
52 // WINAPI calling convention.
53 void* WINAPI MyCryptAlloc(size_t size) {
54 return malloc(size);
55 }
56
57 void WINAPI MyCryptFree(void* p) {
58 free(p);
59 }
60
61 // Decodes the cert's subjectAltName extension into a CERT_ALT_NAME_INFO
62 // structure and stores it in *output.
63 void GetCertSubjectAltName(PCCERT_CONTEXT cert,
64 scoped_ptr_malloc<CERT_ALT_NAME_INFO>* output) {
65 PCERT_EXTENSION extension = CertFindExtension(szOID_SUBJECT_ALT_NAME2,
66 cert->pCertInfo->cExtension,
67 cert->pCertInfo->rgExtension);
68 if (!extension)
69 return;
70
71 CRYPT_DECODE_PARA decode_para;
72 decode_para.cbSize = sizeof(decode_para);
73 decode_para.pfnAlloc = MyCryptAlloc;
74 decode_para.pfnFree = MyCryptFree;
75 CERT_ALT_NAME_INFO* alt_name_info = NULL;
76 DWORD alt_name_info_size = 0;
77 BOOL rv;
78 rv = CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
79 szOID_SUBJECT_ALT_NAME2,
80 extension->Value.pbData,
81 extension->Value.cbData,
82 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG,
83 &decode_para,
84 &alt_name_info,
85 &alt_name_info_size);
86 if (rv)
87 output->reset(alt_name_info);
88 }
89
90 ///////////////////////////////////////////////////////////////////////////
91 //
92 // Functions used by X509Certificate::IsEV
93 //
94 ///////////////////////////////////////////////////////////////////////////
95
96 // Constructs a certificate chain starting from the end certificate
97 // 'cert_context', matching any of the certificate policies.
98 //
99 // Returns the certificate chain context on success, or NULL on failure.
100 // The caller is responsible for freeing the certificate chain context with
101 // CertFreeCertificateChain.
102 PCCERT_CHAIN_CONTEXT ConstructCertChain(
103 PCCERT_CONTEXT cert_context,
104 const char* const* policies,
105 int num_policies) {
106 CERT_CHAIN_PARA chain_para;
107 memset(&chain_para, 0, sizeof(chain_para));
108 chain_para.cbSize = sizeof(chain_para);
109 chain_para.RequestedUsage.dwType = USAGE_MATCH_TYPE_AND;
110 chain_para.RequestedUsage.Usage.cUsageIdentifier = 0;
111 chain_para.RequestedUsage.Usage.rgpszUsageIdentifier = NULL; // LPSTR*
112 chain_para.RequestedIssuancePolicy.dwType = USAGE_MATCH_TYPE_OR;
113 chain_para.RequestedIssuancePolicy.Usage.cUsageIdentifier = num_policies;
114 chain_para.RequestedIssuancePolicy.Usage.rgpszUsageIdentifier =
115 const_cast<char**>(policies);
116 PCCERT_CHAIN_CONTEXT chain_context;
117 if (!CertGetCertificateChain(
118 NULL, // default chain engine, HCCE_CURRENT_USER
119 cert_context,
120 NULL, // current system time
121 cert_context->hCertStore, // search this store
122 &chain_para,
123 CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT |
124 CERT_CHAIN_CACHE_END_CERT,
125 NULL, // reserved
126 &chain_context)) {
127 return NULL;
128 }
129 return chain_context;
130 }
131
132 // Decodes the cert's certificatePolicies extension into a CERT_POLICIES_INFO
133 // structure and stores it in *output.
134 void GetCertPoliciesInfo(PCCERT_CONTEXT cert,
135 scoped_ptr_malloc<CERT_POLICIES_INFO>* output) {
136 PCERT_EXTENSION extension = CertFindExtension(szOID_CERT_POLICIES,
137 cert->pCertInfo->cExtension,
138 cert->pCertInfo->rgExtension);
139 if (!extension)
140 return;
141
142 CRYPT_DECODE_PARA decode_para;
143 decode_para.cbSize = sizeof(decode_para);
144 decode_para.pfnAlloc = MyCryptAlloc;
145 decode_para.pfnFree = MyCryptFree;
146 CERT_POLICIES_INFO* policies_info = NULL;
147 DWORD policies_info_size = 0;
148 BOOL rv;
149 rv = CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
150 szOID_CERT_POLICIES,
151 extension->Value.pbData,
152 extension->Value.cbData,
153 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG,
154 &decode_para,
155 &policies_info,
156 &policies_info_size);
157 if (rv)
158 output->reset(policies_info);
159 }
160
161 // Returns true if the policy is in the array of CERT_POLICY_INFO in
162 // the CERT_POLICIES_INFO structure.
163 bool ContainsPolicy(const CERT_POLICIES_INFO* policies_info,
164 const char* policy) {
165 int num_policies = policies_info->cPolicyInfo;
166 for (int i = 0; i < num_policies; i++) {
167 if (!strcmp(policies_info->rgPolicyInfo[i].pszPolicyIdentifier, policy))
168 return true;
169 }
170 return false;
171 }
172
173 // This class wraps the CertFreeCertificateChain function in a class that can
174 // be passed as a template argument to scoped_ptr_malloc.
175 class ScopedPtrMallocFreeCertChain {
176 public:
177 void operator()(const CERT_CHAIN_CONTEXT* x) const {
178 CertFreeCertificateChain(x);
179 }
180 };
181
182 typedef scoped_ptr_malloc<const CERT_CHAIN_CONTEXT,
183 ScopedPtrMallocFreeCertChain> ScopedCertChainContext;
184
185 } // namespace 23 } // namespace
186 24
187 bool X509Certificate::FingerprintLessThan::operator()( 25 bool X509Certificate::FingerprintLessThan::operator()(
188 const Fingerprint& lhs, 26 const Fingerprint& lhs,
189 const Fingerprint& rhs) const { 27 const Fingerprint& rhs) const {
190 for (size_t i = 0; i < sizeof(lhs.data); ++i) { 28 for (size_t i = 0; i < sizeof(lhs.data); ++i) {
191 if (lhs.data[i] < rhs.data[i]) 29 if (lhs.data[i] < rhs.data[i])
192 return true; 30 return true;
193 if (lhs.data[i] > rhs.data[i]) 31 if (lhs.data[i] > rhs.data[i])
194 return false; 32 return false;
195 } 33 }
196 return false; 34 return false;
197 } 35 }
198 36
199 bool X509Certificate::LessThan::operator()(X509Certificate* lhs, 37 bool X509Certificate::LessThan::operator()(X509Certificate* lhs,
200 X509Certificate* rhs) const { 38 X509Certificate* rhs) const {
201 if (lhs == rhs) 39 if (lhs == rhs)
202 return false; 40 return false;
203 41
204 X509Certificate::FingerprintLessThan fingerprint_functor; 42 X509Certificate::FingerprintLessThan fingerprint_functor;
205 return fingerprint_functor(lhs->fingerprint_, rhs->fingerprint_); 43 return fingerprint_functor(lhs->fingerprint_, rhs->fingerprint_);
206 } 44 }
207 45
208 // A thread-safe cache for X509Certificate objects. 46 // A thread-safe cache for X509Certificate objects.
209 // 47 //
210 // The cache does not hold a reference to the certificate objects. The objects 48 // The cache does not hold a reference to the certificate objects. The objects
211 // must |Remove| themselves from the cache upon destruction (or else the cache 49 // must |Remove| themselves from the cache upon destruction (or else the cache
212 // will be holding dead pointers to the objects). 50 // will be holding dead pointers to the objects).
213 class X509Certificate::Cache {
214 public:
215 // Get the singleton object for the cache.
216 static X509Certificate::Cache* GetInstance() {
217 return Singleton<X509Certificate::Cache>::get();
218 }
219 51
220 // Insert |cert| into the cache. The cache does NOT AddRef |cert|. The cache 52 // Get the singleton object for the cache.
221 // must not already contain a certificate with the same fingerprint. 53 // static
222 void Insert(X509Certificate* cert) { 54 X509Certificate::Cache* X509Certificate::Cache::GetInstance() {
223 AutoLock lock(lock_); 55 return Singleton<X509Certificate::Cache>::get();
56 }
224 57
225 DCHECK(!IsNullFingerprint(cert->fingerprint())) << 58 // Insert |cert| into the cache. The cache does NOT AddRef |cert|. The cache
226 "Only insert certs with real fingerprints."; 59 // must not already contain a certificate with the same fingerprint.
227 DCHECK(cache_.find(cert->fingerprint()) == cache_.end()); 60 void X509Certificate::Cache::Insert(X509Certificate* cert) {
228 cache_[cert->fingerprint()] = cert; 61 AutoLock lock(lock_);
229 };
230 62
231 // Remove |cert| from the cache. The cache does not assume that |cert| is 63 DCHECK(!IsNullFingerprint(cert->fingerprint())) <<
232 // already in the cache. 64 "Only insert certs with real fingerprints.";
233 void Remove(X509Certificate* cert) { 65 DCHECK(cache_.find(cert->fingerprint()) == cache_.end());
234 AutoLock lock(lock_); 66 cache_[cert->fingerprint()] = cert;
235
236 CertMap::iterator pos(cache_.find(cert->fingerprint()));
237 if (pos == cache_.end())
238 return; // It is not an error to remove a cert that is not in the cache.
239 cache_.erase(pos);
240 };
241
242 // Find a certificate in the cache with the given fingerprint. If one does
243 // not exist, this method returns NULL.
244 X509Certificate* Find(const Fingerprint& fingerprint) {
245 AutoLock lock(lock_);
246
247 CertMap::iterator pos(cache_.find(fingerprint));
248 if (pos == cache_.end())
249 return NULL;
250
251 return pos->second;
252 };
253
254 private:
255 typedef std::map<Fingerprint, X509Certificate*, FingerprintLessThan> CertMap;
256
257 // Obtain an instance of X509Certificate::Cache via GetInstance().
258 Cache() { }
259 friend struct DefaultSingletonTraits<X509Certificate::Cache>;
260
261 // You must acquire this lock before using any private data of this object.
262 // You must not block while holding this lock.
263 Lock lock_;
264
265 // The certificate cache. You must acquire |lock_| before using |cache_|.
266 CertMap cache_;
267
268 DISALLOW_COPY_AND_ASSIGN(X509Certificate::Cache);
269 }; 67 };
270 68
271 void X509Certificate::Initialize() { 69 // Remove |cert| from the cache. The cache does not assume that |cert| is
272 std::wstring subject_info; 70 // already in the cache.
273 std::wstring issuer_info; 71 void X509Certificate::Cache::Remove(X509Certificate* cert) {
274 DWORD name_size; 72 AutoLock lock(lock_);
275 name_size = CertNameToStr(cert_handle_->dwCertEncodingType,
276 &cert_handle_->pCertInfo->Subject,
277 CERT_X500_NAME_STR | CERT_NAME_STR_CRLF_FLAG,
278 NULL, 0);
279 name_size = CertNameToStr(cert_handle_->dwCertEncodingType,
280 &cert_handle_->pCertInfo->Subject,
281 CERT_X500_NAME_STR | CERT_NAME_STR_CRLF_FLAG,
282 WriteInto(&subject_info, name_size), name_size);
283 name_size = CertNameToStr(cert_handle_->dwCertEncodingType,
284 &cert_handle_->pCertInfo->Issuer,
285 CERT_X500_NAME_STR | CERT_NAME_STR_CRLF_FLAG,
286 NULL, 0);
287 name_size = CertNameToStr(cert_handle_->dwCertEncodingType,
288 &cert_handle_->pCertInfo->Issuer,
289 CERT_X500_NAME_STR | CERT_NAME_STR_CRLF_FLAG,
290 WriteInto(&issuer_info, name_size), name_size);
291 ParsePrincipal(WideToUTF8(subject_info), &subject_);
292 ParsePrincipal(WideToUTF8(issuer_info), &issuer_);
293 73
294 valid_start_ = Time::FromFileTime(cert_handle_->pCertInfo->NotBefore); 74 CertMap::iterator pos(cache_.find(cert->fingerprint()));
295 valid_expiry_ = Time::FromFileTime(cert_handle_->pCertInfo->NotAfter); 75 if (pos == cache_.end())
76 return; // It is not an error to remove a cert that is not in the cache.
77 cache_.erase(pos);
78 };
296 79
297 fingerprint_ = CalculateFingerprint(cert_handle_); 80 // Find a certificate in the cache with the given fingerprint. If one does
81 // not exist, this method returns NULL.
82 X509Certificate* X509Certificate::Cache::Find(const Fingerprint& fingerprint) {
83 AutoLock lock(lock_);
298 84
299 // Store the certificate in the cache in case we need it later. 85 CertMap::iterator pos(cache_.find(fingerprint));
300 X509Certificate::Cache::GetInstance()->Insert(this); 86 if (pos == cache_.end())
301 }
302
303 // static
304 X509Certificate* X509Certificate::CreateFromHandle(OSCertHandle cert_handle) {
305 DCHECK(cert_handle);
306
307 // Check if we already have this certificate in memory.
308 X509Certificate::Cache* cache = X509Certificate::Cache::GetInstance();
309 X509Certificate* cert = cache->Find(CalculateFingerprint(cert_handle));
310 if (cert) {
311 // We've found a certificate with the same fingerprint in our cache. We own
312 // the |cert_handle|, which makes it our job to free it.
313 CertFreeCertificateContext(cert_handle);
314 DHISTOGRAM_COUNTS(L"X509CertificateReuseCount", 1);
315 return cert;
316 }
317 // Otherwise, allocate a new object.
318 return new X509Certificate(cert_handle);
319 }
320
321 // static
322 X509Certificate* X509Certificate::CreateFromBytes(const char* data, int length) {
323 OSCertHandle cert_handle = NULL;
324 if (!CertAddEncodedCertificateToStore(
325 NULL, // the cert won't be persisted in any cert store
326 X509_ASN_ENCODING,
327 reinterpret_cast<const BYTE*>(data), length,
328 CERT_STORE_ADD_USE_EXISTING,
329 &cert_handle))
330 return NULL; 87 return NULL;
331 88
332 return CreateFromHandle(cert_handle); 89 return pos->second;
333 } 90 };
334
335 // static
336 X509Certificate* X509Certificate::CreateFromPickle(const Pickle& pickle,
337 void** pickle_iter) {
338 const char* data;
339 int length;
340 if (!pickle.ReadData(pickle_iter, &data, &length))
341 return NULL;
342
343 OSCertHandle cert_handle = NULL;
344 if (!CertAddSerializedElementToStore(
345 NULL, // the cert won't be persisted in any cert store
346 reinterpret_cast<const BYTE*>(data), length,
347 CERT_STORE_ADD_USE_EXISTING, 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG,
348 NULL, reinterpret_cast<const void **>(&cert_handle)))
349 return NULL;
350
351 return CreateFromHandle(cert_handle);
352 }
353
354 X509Certificate::X509Certificate(OSCertHandle cert_handle)
355 : cert_handle_(cert_handle) {
356 Initialize();
357 }
358
359 X509Certificate::X509Certificate(std::string subject, std::string issuer,
360 Time start_date, Time expiration_date)
361 : subject_(subject),
362 issuer_(issuer),
363 valid_start_(start_date),
364 valid_expiry_(expiration_date),
365 cert_handle_(NULL) {
366 memset(fingerprint_.data, 0, sizeof(fingerprint_.data));
367 }
368
369 void X509Certificate::Persist(Pickle* pickle) {
370 DWORD length;
371 if (!CertSerializeCertificateStoreElement(cert_handle_, 0,
372 NULL, &length)) {
373 NOTREACHED();
374 return;
375 }
376 BYTE* data = reinterpret_cast<BYTE*>(pickle->BeginWriteData(length));
377 if (!CertSerializeCertificateStoreElement(cert_handle_, 0,
378 data, &length)) {
379 NOTREACHED();
380 length = 0;
381 }
382 pickle->TrimWriteData(length);
383 }
384
385 X509Certificate::~X509Certificate() {
386 // We might not be in the cache, but it is safe to remove ourselves anyway.
387 X509Certificate::Cache::GetInstance()->Remove(this);
388 if (cert_handle_)
389 CertFreeCertificateContext(cert_handle_);
390 }
391
392 void X509Certificate::GetDNSNames(std::vector<std::string>* dns_names) const {
393 dns_names->clear();
394 scoped_ptr_malloc<CERT_ALT_NAME_INFO> alt_name_info;
395 GetCertSubjectAltName(cert_handle_, &alt_name_info);
396 CERT_ALT_NAME_INFO* alt_name = alt_name_info.get();
397 if (alt_name) {
398 int num_entries = alt_name->cAltEntry;
399 for (int i = 0; i < num_entries; i++) {
400 // dNSName is an ASN.1 IA5String representing a string of ASCII
401 // characters, so we can use WideToASCII here.
402 if (alt_name->rgAltEntry[i].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME)
403 dns_names->push_back(WideToASCII(alt_name->rgAltEntry[i].pwszDNSName));
404 }
405 }
406 if (dns_names->empty())
407 dns_names->push_back(subject_.common_name);
408 }
409
410 bool X509Certificate::HasExpired() const {
411 return Time::Now() > valid_expiry();
412 }
413
414 // Returns true if the certificate is an extended-validation certificate.
415 //
416 // The certificate has already been verified by the HTTP library. cert_status
417 // represents the result of that verification. This function performs
418 // additional checks of the certificatePolicies extensions of the certificates
419 // in the certificate chain according to Section 7 (pp. 11-12) of the EV
420 // Certificate Guidelines Version 1.0 at
421 // http://cabforum.org/EV_Certificate_Guidelines.pdf.
422 bool X509Certificate::IsEV(int cert_status) const {
423 if (net::IsCertStatusError(cert_status) ||
424 (cert_status & net::CERT_STATUS_REV_CHECKING_ENABLED) == 0)
425 return false;
426
427 net::EVRootCAMetadata* metadata = net::EVRootCAMetadata::GetInstance();
428
429 PCCERT_CHAIN_CONTEXT chain_context = ConstructCertChain(cert_handle_,
430 metadata->GetPolicyOIDs(), metadata->NumPolicyOIDs());
431 if (!chain_context)
432 return false;
433 ScopedCertChainContext scoped_chain_context(chain_context);
434
435 DCHECK(chain_context->cChain != 0);
436 // If the cert doesn't match any of the policies, the
437 // CERT_TRUST_IS_NOT_VALID_FOR_USAGE bit (0x10) in
438 // chain_context->TrustStatus.dwErrorStatus is set.
439 DWORD error_status = chain_context->TrustStatus.dwErrorStatus;
440 DWORD info_status = chain_context->TrustStatus.dwInfoStatus;
441 if (!chain_context->cChain || error_status != CERT_TRUST_NO_ERROR)
442 return false;
443
444 // Check the end certificate simple chain (chain_context->rgpChain[0]).
445 // If the end certificate's certificatePolicies extension contains the
446 // EV policy OID of the root CA, return true.
447 PCERT_CHAIN_ELEMENT* element = chain_context->rgpChain[0]->rgpElement;
448 int num_elements = chain_context->rgpChain[0]->cElement;
449 if (num_elements < 2)
450 return false;
451
452 // Look up the EV policy OID of the root CA.
453 PCCERT_CONTEXT root_cert = element[num_elements - 1]->pCertContext;
454 X509Certificate::Fingerprint fingerprint = CalculateFingerprint(root_cert);
455 std::string ev_policy_oid;
456 if (!metadata->GetPolicyOID(fingerprint, &ev_policy_oid))
457 return false;
458 DCHECK(!ev_policy_oid.empty());
459
460 // Get the certificatePolicies extension of the end certificate.
461 PCCERT_CONTEXT end_cert = element[0]->pCertContext;
462 scoped_ptr_malloc<CERT_POLICIES_INFO> policies_info;
463 GetCertPoliciesInfo(end_cert, &policies_info);
464 if (!policies_info.get())
465 return false;
466
467 return ContainsPolicy(policies_info.get(), ev_policy_oid.c_str());
468 }
469
470 // static
471 void X509Certificate::ParsePrincipal(const std::string& description,
472 Principal* principal) {
473 // The description of the principal is a string with each LDAP value on
474 // a separate line.
475 const std::string kDelimiters("\r\n");
476
477 std::vector<std::string> common_names, locality_names, state_names,
478 country_names;
479
480 // TODO(jcampan): add business_category and serial_number.
481 const std::string kPrefixes[] = { std::string("CN="),
482 std::string("L="),
483 std::string("S="),
484 std::string("C="),
485 std::string("STREET="),
486 std::string("O="),
487 std::string("OU="),
488 std::string("DC=") };
489
490 std::vector<std::string>* values[] = {
491 &common_names, &locality_names,
492 &state_names, &country_names,
493 &(principal->street_addresses),
494 &(principal->organization_names),
495 &(principal->organization_unit_names),
496 &(principal->domain_components) };
497 DCHECK(arraysize(kPrefixes) == arraysize(values));
498
499 StringTokenizer str_tok(description, kDelimiters);
500 while (str_tok.GetNext()) {
501 std::string entry = str_tok.token();
502 for (int i = 0; i < arraysize(kPrefixes); i++) {
503 if (!entry.compare(0, kPrefixes[i].length(), kPrefixes[i])) {
504 std::string value = entry.substr(kPrefixes[i].length());
505 // Remove enclosing double-quotes if any.
506 if (value.size() >= 2 &&
507 value[0] == '"' && value[value.size() - 1] == '"')
508 value = value.substr(1, value.size() - 2);
509 values[i]->push_back(value);
510 break;
511 }
512 }
513 }
514
515 // We don't expect to have more than one CN, L, S, and C.
516 std::vector<std::string>* single_value_lists[4] = {
517 &common_names, &locality_names, &state_names, &country_names };
518 std::string* single_values[4] = {
519 &principal->common_name, &principal->locality_name,
520 &principal->state_or_province_name, &principal->country_name };
521 for (int i = 0; i < arraysize(single_value_lists); ++i) {
522 int length = static_cast<int>(single_value_lists[i]->size());
523 DCHECK(single_value_lists[i]->size() <= 1);
524 if (single_value_lists[i]->size() > 0)
525 *(single_values[i]) = (*(single_value_lists[i]))[0];
526 }
527 }
528 91
529 X509Certificate::Policy::Judgment X509Certificate::Policy::Check( 92 X509Certificate::Policy::Judgment X509Certificate::Policy::Check(
530 X509Certificate* cert) const { 93 X509Certificate* cert) const {
531 // It shouldn't matter which set we check first, but we check denied first 94 // It shouldn't matter which set we check first, but we check denied first
532 // in case something strange has happened. 95 // in case something strange has happened.
533 96
534 if (denied_.find(cert->fingerprint()) != denied_.end()) { 97 if (denied_.find(cert->fingerprint()) != denied_.end()) {
535 // DCHECK that the order didn't matter. 98 // DCHECK that the order didn't matter.
536 DCHECK(allowed_.find(cert->fingerprint()) == allowed_.end()); 99 DCHECK(allowed_.find(cert->fingerprint()) == allowed_.end());
537 return DENIED; 100 return DENIED;
(...skipping 16 matching lines...) Expand all
554 } 117 }
555 118
556 void X509Certificate::Policy::Deny(X509Certificate* cert) { 119 void X509Certificate::Policy::Deny(X509Certificate* cert) {
557 // Put the cert in the denied set and (maybe) remove it from the allowed set. 120 // Put the cert in the denied set and (maybe) remove it from the allowed set.
558 allowed_.erase(cert->fingerprint()); 121 allowed_.erase(cert->fingerprint());
559 denied_.insert(cert->fingerprint()); 122 denied_.insert(cert->fingerprint());
560 } 123 }
561 124
562 } // namespace net 125 } // namespace net
563 126
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698