| OLD | NEW |
| 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 <CommonCrypto/CommonDigest.h> | 7 #include <CommonCrypto/CommonDigest.h> |
| 8 #include <map> | |
| 9 #include <time.h> | 8 #include <time.h> |
| 10 | 9 |
| 11 #include "base/histogram.h" | 10 #include "base/histogram.h" |
| 12 #include "base/lock.h" | 11 #include "base/logging.h" |
| 13 #include "base/pickle.h" | 12 #include "base/pickle.h" |
| 14 #include "base/singleton.h" | |
| 15 #include "base/string_tokenizer.h" | |
| 16 #include "base/string_util.h" | |
| 17 #include "net/base/cert_status_flags.h" | 13 #include "net/base/cert_status_flags.h" |
| 18 #include "net/base/ev_root_ca_metadata.h" | 14 #include "net/base/ev_root_ca_metadata.h" |
| 19 | 15 |
| 20 namespace net { | 16 namespace net { |
| 21 | 17 |
| 22 namespace { | 18 namespace { |
| 23 | 19 |
| 24 // Returns true if this cert fingerprint is the null (all zero) fingerprint. | |
| 25 // We use this as a bogus fingerprint value. | |
| 26 bool IsNullFingerprint(const X509Certificate::Fingerprint& fingerprint) { | |
| 27 for (size_t i = 0; i < arraysize(fingerprint.data); ++i) { | |
| 28 if (fingerprint.data[i] != 0) | |
| 29 return false; | |
| 30 } | |
| 31 return true; | |
| 32 } | |
| 33 | |
| 34 // Calculates the SHA-1 fingerprint of the certificate. Returns an empty | 20 // Calculates the SHA-1 fingerprint of the certificate. Returns an empty |
| 35 // (all zero) fingerprint on failure. | 21 // (all zero) fingerprint on failure. |
| 36 X509Certificate::Fingerprint CalculateFingerprint( | 22 X509Certificate::Fingerprint CalculateFingerprint( |
| 37 X509Certificate::OSCertHandle cert) { | 23 X509Certificate::OSCertHandle cert) { |
| 38 X509Certificate::Fingerprint sha1; | 24 X509Certificate::Fingerprint sha1; |
| 39 memset(sha1.data, 0, sizeof(sha1.data)); | 25 memset(sha1.data, 0, sizeof(sha1.data)); |
| 40 | 26 |
| 41 CSSM_DATA cert_data; | 27 CSSM_DATA cert_data; |
| 42 OSStatus status = SecCertificateGetData(cert, &cert_data); | 28 OSStatus status = SecCertificateGetData(cert, &cert_data); |
| 43 if (status) | 29 if (status) |
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 211 exploded.second = time.tm_sec; | 197 exploded.second = time.tm_sec; |
| 212 exploded.millisecond = 0; | 198 exploded.millisecond = 0; |
| 213 | 199 |
| 214 *result = Time::FromUTCExploded(exploded); | 200 *result = Time::FromUTCExploded(exploded); |
| 215 } | 201 } |
| 216 } | 202 } |
| 217 } | 203 } |
| 218 | 204 |
| 219 } // namespace | 205 } // namespace |
| 220 | 206 |
| 221 bool X509Certificate::FingerprintLessThan::operator()( | |
| 222 const Fingerprint& lhs, | |
| 223 const Fingerprint& rhs) const { | |
| 224 for (size_t i = 0; i < sizeof(lhs.data); ++i) { | |
| 225 if (lhs.data[i] < rhs.data[i]) | |
| 226 return true; | |
| 227 if (lhs.data[i] > rhs.data[i]) | |
| 228 return false; | |
| 229 } | |
| 230 return false; | |
| 231 } | |
| 232 | |
| 233 bool X509Certificate::LessThan::operator()(X509Certificate* lhs, | |
| 234 X509Certificate* rhs) const { | |
| 235 if (lhs == rhs) | |
| 236 return false; | |
| 237 | |
| 238 X509Certificate::FingerprintLessThan fingerprint_functor; | |
| 239 return fingerprint_functor(lhs->fingerprint_, rhs->fingerprint_); | |
| 240 } | |
| 241 | |
| 242 // A thread-safe cache for X509Certificate objects. | |
| 243 // | |
| 244 // The cache does not hold a reference to the certificate objects. The objects | |
| 245 // must |Remove| themselves from the cache upon destruction (or else the cache | |
| 246 // will be holding dead pointers to the objects). | |
| 247 class X509Certificate::Cache { | |
| 248 public: | |
| 249 // Get the singleton object for the cache. | |
| 250 static X509Certificate::Cache* GetInstance() { | |
| 251 return Singleton<X509Certificate::Cache>::get(); | |
| 252 } | |
| 253 | |
| 254 // Insert |cert| into the cache. The cache does NOT AddRef |cert|. The cache | |
| 255 // must not already contain a certificate with the same fingerprint. | |
| 256 void Insert(X509Certificate* cert) { | |
| 257 AutoLock lock(lock_); | |
| 258 | |
| 259 DCHECK(!IsNullFingerprint(cert->fingerprint())) << | |
| 260 "Only insert certs with real fingerprints."; | |
| 261 DCHECK(cache_.find(cert->fingerprint()) == cache_.end()); | |
| 262 cache_[cert->fingerprint()] = cert; | |
| 263 }; | |
| 264 | |
| 265 // Remove |cert| from the cache. The cache does not assume that |cert| is | |
| 266 // already in the cache. | |
| 267 void Remove(X509Certificate* cert) { | |
| 268 AutoLock lock(lock_); | |
| 269 | |
| 270 CertMap::iterator pos(cache_.find(cert->fingerprint())); | |
| 271 if (pos == cache_.end()) | |
| 272 return; // It is not an error to remove a cert that is not in the cache. | |
| 273 cache_.erase(pos); | |
| 274 }; | |
| 275 | |
| 276 // Find a certificate in the cache with the given fingerprint. If one does | |
| 277 // not exist, this method returns NULL. | |
| 278 X509Certificate* Find(const Fingerprint& fingerprint) { | |
| 279 AutoLock lock(lock_); | |
| 280 | |
| 281 CertMap::iterator pos(cache_.find(fingerprint)); | |
| 282 if (pos == cache_.end()) | |
| 283 return NULL; | |
| 284 | |
| 285 return pos->second; | |
| 286 }; | |
| 287 | |
| 288 private: | |
| 289 typedef std::map<Fingerprint, X509Certificate*, FingerprintLessThan> CertMap; | |
| 290 | |
| 291 // Obtain an instance of X509Certificate::Cache via GetInstance(). | |
| 292 Cache() { } | |
| 293 friend struct DefaultSingletonTraits<X509Certificate::Cache>; | |
| 294 | |
| 295 // You must acquire this lock before using any private data of this object. | |
| 296 // You must not block while holding this lock. | |
| 297 Lock lock_; | |
| 298 | |
| 299 // The certificate cache. You must acquire |lock_| before using |cache_|. | |
| 300 CertMap cache_; | |
| 301 | |
| 302 DISALLOW_COPY_AND_ASSIGN(Cache); | |
| 303 }; | |
| 304 | |
| 305 void X509Certificate::Initialize() { | 207 void X509Certificate::Initialize() { |
| 306 const CSSM_X509_NAME* name; | 208 const CSSM_X509_NAME* name; |
| 307 OSStatus status = SecCertificateGetSubject(cert_handle_, &name); | 209 OSStatus status = SecCertificateGetSubject(cert_handle_, &name); |
| 308 if (!status) { | 210 if (!status) { |
| 309 ParsePrincipal(name, &subject_); | 211 ParsePrincipal(name, &subject_); |
| 310 } | 212 } |
| 311 status = SecCertificateGetIssuer(cert_handle_, &name); | 213 status = SecCertificateGetIssuer(cert_handle_, &name); |
| 312 if (!status) { | 214 if (!status) { |
| 313 ParsePrincipal(name, &issuer_); | 215 ParsePrincipal(name, &issuer_); |
| 314 } | 216 } |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 421 // additional checks of the certificatePolicies extensions of the certificates | 323 // additional checks of the certificatePolicies extensions of the certificates |
| 422 // in the certificate chain according to Section 7 (pp. 11-12) of the EV | 324 // in the certificate chain according to Section 7 (pp. 11-12) of the EV |
| 423 // Certificate Guidelines Version 1.0 at | 325 // Certificate Guidelines Version 1.0 at |
| 424 // http://cabforum.org/EV_Certificate_Guidelines.pdf. | 326 // http://cabforum.org/EV_Certificate_Guidelines.pdf. |
| 425 bool X509Certificate::IsEV(int cert_status) const { | 327 bool X509Certificate::IsEV(int cert_status) const { |
| 426 // TODO(avi): implement this | 328 // TODO(avi): implement this |
| 427 NOTIMPLEMENTED(); | 329 NOTIMPLEMENTED(); |
| 428 return false; | 330 return false; |
| 429 } | 331 } |
| 430 | 332 |
| 431 X509Certificate::Policy::Judgment X509Certificate::Policy::Check( | |
| 432 X509Certificate* cert) const { | |
| 433 // It shouldn't matter which set we check first, but we check denied first | |
| 434 // in case something strange has happened. | |
| 435 | |
| 436 if (denied_.find(cert->fingerprint()) != denied_.end()) { | |
| 437 // DCHECK that the order didn't matter. | |
| 438 DCHECK(allowed_.find(cert->fingerprint()) == allowed_.end()); | |
| 439 return DENIED; | |
| 440 } | |
| 441 | |
| 442 if (allowed_.find(cert->fingerprint()) != allowed_.end()) { | |
| 443 // DCHECK that the order didn't matter. | |
| 444 DCHECK(denied_.find(cert->fingerprint()) == denied_.end()); | |
| 445 return ALLOWED; | |
| 446 } | |
| 447 | |
| 448 // We don't have a policy for this cert. | |
| 449 return UNKNOWN; | |
| 450 } | |
| 451 | |
| 452 void X509Certificate::Policy::Allow(X509Certificate* cert) { | |
| 453 // Put the cert in the allowed set and (maybe) remove it from the denied set. | |
| 454 denied_.erase(cert->fingerprint()); | |
| 455 allowed_.insert(cert->fingerprint()); | |
| 456 } | |
| 457 | |
| 458 void X509Certificate::Policy::Deny(X509Certificate* cert) { | |
| 459 // Put the cert in the denied set and (maybe) remove it from the allowed set. | |
| 460 allowed_.erase(cert->fingerprint()); | |
| 461 denied_.insert(cert->fingerprint()); | |
| 462 } | |
| 463 | |
| 464 } // namespace net | 333 } // namespace net |
| OLD | NEW |