Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 <stdlib.h> | 7 #include <stdlib.h> |
| 8 | 8 |
| 9 #include <map> | 9 #include <map> |
| 10 #include <string> | 10 #include <string> |
| 11 #include <vector> | 11 #include <vector> |
| 12 | 12 |
| 13 #include "base/lazy_instance.h" | 13 #include "base/lazy_instance.h" |
| 14 #include "base/logging.h" | 14 #include "base/logging.h" |
| 15 #include "base/memory/singleton.h" | 15 #include "base/memory/singleton.h" |
| 16 #include "base/metrics/histogram.h" | 16 #include "base/metrics/histogram.h" |
| 17 #include "base/pickle.h" | |
| 17 #include "base/sha1.h" | 18 #include "base/sha1.h" |
| 18 #include "base/string_piece.h" | 19 #include "base/string_piece.h" |
| 19 #include "base/string_util.h" | 20 #include "base/string_util.h" |
| 20 #include "base/time.h" | 21 #include "base/time.h" |
| 21 #include "net/base/pem_tokenizer.h" | 22 #include "net/base/pem_tokenizer.h" |
| 22 | 23 |
| 23 namespace net { | 24 namespace net { |
| 24 | 25 |
| 25 namespace { | 26 namespace { |
| 26 | 27 |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 224 if (!cert_handle) | 225 if (!cert_handle) |
| 225 return NULL; | 226 return NULL; |
| 226 | 227 |
| 227 X509Certificate* cert = CreateFromHandle(cert_handle, | 228 X509Certificate* cert = CreateFromHandle(cert_handle, |
| 228 SOURCE_LONE_CERT_IMPORT, | 229 SOURCE_LONE_CERT_IMPORT, |
| 229 OSCertHandles()); | 230 OSCertHandles()); |
| 230 FreeOSCertHandle(cert_handle); | 231 FreeOSCertHandle(cert_handle); |
| 231 return cert; | 232 return cert; |
| 232 } | 233 } |
| 233 | 234 |
| 235 // static | |
| 236 X509Certificate* X509Certificate::CreateFromPickle(const Pickle& pickle, | |
| 237 void** pickle_iter, | |
| 238 PickleType type) { | |
| 239 OSCertHandle cert_handle = ReadCertHandleFromPickle(pickle, pickle_iter); | |
| 240 OSCertHandles intermediates; | |
| 241 | |
| 242 // Even if a certificate fails to parse, whether the server certificate in | |
| 243 // |cert_handle| or one of the optional intermediates, continue reading | |
| 244 // the data from |pickle| so that |pickle_iter| is kept in sync for any | |
| 245 // other reads the caller may perform after this method returns. | |
|
wtc
2011/04/20 23:07:58
If a certificate fails to parse, the subsequent da
Ryan Sleevi
2011/04/20 23:59:10
There are two reasons for why parsing may fail, an
| |
| 246 if (type == PICKLETYPE_CERTIFICATE_CHAIN) { | |
| 247 size_t num_intermediates; | |
| 248 if (!pickle.ReadSize(pickle_iter, &num_intermediates)) { | |
| 249 FreeOSCertHandle(cert_handle); | |
| 250 return NULL; | |
| 251 } | |
| 252 | |
| 253 bool ok = !!cert_handle; | |
|
wtc
2011/04/20 23:07:58
Nit: say
bool ok = (cert_handle != NULL);
| |
| 254 for (size_t i = 0; i < num_intermediates; ++i) { | |
| 255 OSCertHandle intermediate = ReadCertHandleFromPickle(pickle, | |
| 256 pickle_iter); | |
| 257 // If an intermediate fails to load, it and any certificates after it | |
| 258 // will not be added. However, any intermediates that were successfully | |
| 259 // parsed before the failure can be safely returned. | |
| 260 ok &= !!intermediate; | |
| 261 if (ok) { | |
| 262 intermediates.push_back(intermediate); | |
| 263 } else if (intermediate) { | |
| 264 FreeOSCertHandle(intermediate); | |
| 265 } | |
| 266 } | |
| 267 } | |
| 268 | |
| 269 if (!cert_handle) | |
| 270 return NULL; | |
|
wtc
2011/04/20 23:07:58
We should also return NULL if |ok| is false.
Ryan Sleevi
2011/04/20 23:59:10
This contradicts the behaviour documented in line
| |
| 271 X509Certificate* cert = CreateFromHandle(cert_handle, SOURCE_FROM_CACHE, | |
| 272 intermediates); | |
| 273 FreeOSCertHandle(cert_handle); | |
| 274 for (size_t i = 0; i < intermediates.size(); ++i) | |
| 275 FreeOSCertHandle(intermediates[i]); | |
| 276 | |
| 277 return cert; | |
| 278 } | |
| 279 | |
| 280 // static | |
| 234 CertificateList X509Certificate::CreateCertificateListFromBytes( | 281 CertificateList X509Certificate::CreateCertificateListFromBytes( |
| 235 const char* data, int length, int format) { | 282 const char* data, int length, int format) { |
| 236 OSCertHandles certificates; | 283 OSCertHandles certificates; |
| 237 | 284 |
| 238 // Check to see if it is in a PEM-encoded form. This check is performed | 285 // Check to see if it is in a PEM-encoded form. This check is performed |
| 239 // first, as both OS X and NSS will both try to convert if they detect | 286 // first, as both OS X and NSS will both try to convert if they detect |
| 240 // PEM encoding, except they don't do it consistently between the two. | 287 // PEM encoding, except they don't do it consistently between the two. |
| 241 base::StringPiece data_string(data, length); | 288 base::StringPiece data_string(data, length); |
| 242 std::vector<std::string> pem_headers; | 289 std::vector<std::string> pem_headers; |
| 243 | 290 |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 301 it != certificates.end(); ++it) { | 348 it != certificates.end(); ++it) { |
| 302 X509Certificate* result = CreateFromHandle(*it, SOURCE_LONE_CERT_IMPORT, | 349 X509Certificate* result = CreateFromHandle(*it, SOURCE_LONE_CERT_IMPORT, |
| 303 OSCertHandles()); | 350 OSCertHandles()); |
| 304 results.push_back(scoped_refptr<X509Certificate>(result)); | 351 results.push_back(scoped_refptr<X509Certificate>(result)); |
| 305 FreeOSCertHandle(*it); | 352 FreeOSCertHandle(*it); |
| 306 } | 353 } |
| 307 | 354 |
| 308 return results; | 355 return results; |
| 309 } | 356 } |
| 310 | 357 |
| 358 void X509Certificate::Persist(Pickle* pickle) { | |
| 359 DCHECK(cert_handle_); | |
| 360 if (!WriteCertHandleToPickle(cert_handle_, pickle)) { | |
| 361 NOTREACHED(); | |
| 362 return; | |
| 363 } | |
| 364 | |
| 365 if (!pickle->WriteSize(intermediate_ca_certs_.size())) { | |
| 366 NOTREACHED(); | |
| 367 return; | |
| 368 } | |
| 369 | |
| 370 for (size_t i = 0; i < intermediate_ca_certs_.size(); ++i) { | |
| 371 if (!WriteCertHandleToPickle(intermediate_ca_certs_[i], pickle)) { | |
| 372 NOTREACHED(); | |
| 373 return; | |
| 374 } | |
| 375 } | |
| 376 } | |
| 377 | |
| 311 bool X509Certificate::HasExpired() const { | 378 bool X509Certificate::HasExpired() const { |
| 312 return base::Time::Now() > valid_expiry(); | 379 return base::Time::Now() > valid_expiry(); |
| 313 } | 380 } |
| 314 | 381 |
| 315 bool X509Certificate::Equals(const X509Certificate* other) const { | 382 bool X509Certificate::Equals(const X509Certificate* other) const { |
| 316 return IsSameOSCert(cert_handle_, other->cert_handle_); | 383 return IsSameOSCert(cert_handle_, other->cert_handle_); |
| 317 } | 384 } |
| 318 | 385 |
| 319 bool X509Certificate::HasIntermediateCertificate(OSCertHandle cert) { | 386 bool X509Certificate::HasIntermediateCertificate(OSCertHandle cert) { |
| 320 #if defined(OS_MACOSX) || defined(OS_WIN) || defined(USE_OPENSSL) | |
| 321 for (size_t i = 0; i < intermediate_ca_certs_.size(); ++i) { | 387 for (size_t i = 0; i < intermediate_ca_certs_.size(); ++i) { |
| 322 if (IsSameOSCert(cert, intermediate_ca_certs_[i])) | 388 if (IsSameOSCert(cert, intermediate_ca_certs_[i])) |
| 323 return true; | 389 return true; |
| 324 } | 390 } |
| 325 return false; | 391 return false; |
| 326 #else | |
| 327 return true; | |
| 328 #endif | |
| 329 } | 392 } |
| 330 | 393 |
| 331 bool X509Certificate::HasIntermediateCertificates(const OSCertHandles& certs) { | 394 bool X509Certificate::HasIntermediateCertificates(const OSCertHandles& certs) { |
| 332 for (size_t i = 0; i < certs.size(); ++i) { | 395 for (size_t i = 0; i < certs.size(); ++i) { |
| 333 if (!HasIntermediateCertificate(certs[i])) | 396 if (!HasIntermediateCertificate(certs[i])) |
| 334 return false; | 397 return false; |
| 335 } | 398 } |
| 336 return true; | 399 return true; |
| 337 } | 400 } |
| 338 | 401 |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 541 bool X509Certificate::IsSHA1HashInSortedArray(const SHA1Fingerprint& hash, | 604 bool X509Certificate::IsSHA1HashInSortedArray(const SHA1Fingerprint& hash, |
| 542 const uint8* array, | 605 const uint8* array, |
| 543 size_t array_byte_len) { | 606 size_t array_byte_len) { |
| 544 DCHECK_EQ(0u, array_byte_len % base::SHA1_LENGTH); | 607 DCHECK_EQ(0u, array_byte_len % base::SHA1_LENGTH); |
| 545 const unsigned arraylen = array_byte_len / base::SHA1_LENGTH; | 608 const unsigned arraylen = array_byte_len / base::SHA1_LENGTH; |
| 546 return NULL != bsearch(hash.data, array, arraylen, base::SHA1_LENGTH, | 609 return NULL != bsearch(hash.data, array, arraylen, base::SHA1_LENGTH, |
| 547 CompareSHA1Hashes); | 610 CompareSHA1Hashes); |
| 548 } | 611 } |
| 549 | 612 |
| 550 } // namespace net | 613 } // namespace net |
| OLD | NEW |