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/cert/x509_cert_types.h" 6 7 #include <cstdlib> 8 #include <cstring> 9 10 #include "base/logging.h" 11 #include "base/strings/string_number_conversions.h" 12 #include "base/strings/string_piece.h" 13 #include "base/time/time.h" 14 #include "net/cert/x509_certificate.h" 15 16 namespace net { 17 18 namespace { 19 20 // Helper for ParseCertificateDate. |*field| must contain at least 21 // |field_len| characters. |*field| will be advanced by |field_len| on exit. 22 // |*ok| is set to false if there is an error in parsing the number, but left 23 // untouched otherwise. Returns the parsed integer. 24 int ParseIntAndAdvance(const char** field, size_t field_len, bool* ok) { 25 int result = 0; 26 *ok &= base::StringToInt(base::StringPiece(*field, field_len), &result); 27 *field += field_len; 28 return result; 29 } 30 31 } 32 33 CertPrincipal::CertPrincipal() { 34 } 35 36 CertPrincipal::CertPrincipal(const std::string& name) : common_name(name) {} 37 38 CertPrincipal::~CertPrincipal() { 39 } 40 41 std::string CertPrincipal::GetDisplayName() const { 42 if (!common_name.empty()) 43 return common_name; 44 if (!organization_names.empty()) 45 return organization_names[0]; 46 if (!organization_unit_names.empty()) 47 return organization_unit_names[0]; 48 49 return std::string(); 50 } 51 52 CertPolicy::CertPolicy() { 53 } 54 55 CertPolicy::~CertPolicy() { 56 } 57 58 // For a denial, we consider a given |cert| to be a match to a saved denied 59 // cert if the |error| intersects with the saved error status. For an 60 // allowance, we consider a given |cert| to be a match to a saved allowed 61 // cert if the |error| is an exact match to or subset of the errors in the 62 // saved CertStatus. 63 CertPolicy::Judgment CertPolicy::Check( 64 X509Certificate* cert, CertStatus error) const { 65 // It shouldn't matter which set we check first, but we check denied first 66 // in case something strange has happened. 67 bool denied = false; 68 std::map<SHA1HashValue, CertStatus, SHA1HashValueLessThan>::const_iterator 69 denied_iter = denied_.find(cert->fingerprint()); 70 if ((denied_iter != denied_.end()) && (denied_iter->second & error)) 71 denied = true; 72 73 std::map<SHA1HashValue, CertStatus, SHA1HashValueLessThan>::const_iterator 74 allowed_iter = allowed_.find(cert->fingerprint()); 75 if ((allowed_iter != allowed_.end()) && 76 (allowed_iter->second & error) && 77 !(~(allowed_iter->second & error) ^ ~error)) { 78 DCHECK(!denied); 79 return ALLOWED; 80 } 81 82 if (denied) 83 return DENIED; 84 return UNKNOWN; // We don't have a policy for this cert. 85 } 86 87 void CertPolicy::Allow(X509Certificate* cert, CertStatus error) { 88 // Put the cert in the allowed set and (maybe) remove it from the denied set. 89 denied_.erase(cert->fingerprint()); 90 // If this same cert had already been saved with a different error status, 91 // this will replace it with the new error status. 92 allowed_[cert->fingerprint()] = error; 93 } 94 95 void CertPolicy::Deny(X509Certificate* cert, CertStatus error) { 96 // Put the cert in the denied set and (maybe) remove it from the allowed set. 97 std::map<SHA1HashValue, CertStatus, SHA1HashValueLessThan>::const_iterator 98 allowed_iter = allowed_.find(cert->fingerprint()); 99 if ((allowed_iter != allowed_.end()) && (allowed_iter->second & error)) 100 allowed_.erase(cert->fingerprint()); 101 denied_[cert->fingerprint()] |= error; 102 } 103 104 bool CertPolicy::HasAllowedCert() const { 105 return !allowed_.empty(); 106 } 107 108 bool CertPolicy::HasDeniedCert() const { 109 return !denied_.empty(); 110 } 111 112 bool ParseCertificateDate(const base::StringPiece& raw_date, 113 CertDateFormat format, 114 base::Time* time) { 115 size_t year_length = format == CERT_DATE_FORMAT_UTC_TIME ? 2 : 4; 116 117 if (raw_date.length() < 11 + year_length) 118 return false; 119 120 const char* field = raw_date.data(); 121 bool valid = true; 122 base::Time::Exploded exploded = {0}; 123 124 exploded.year = ParseIntAndAdvance(&field, year_length, &valid); 125 exploded.month = ParseIntAndAdvance(&field, 2, &valid); 126 exploded.day_of_month = ParseIntAndAdvance(&field, 2, &valid); 127 exploded.hour = ParseIntAndAdvance(&field, 2, &valid); 128 exploded.minute = ParseIntAndAdvance(&field, 2, &valid); 129 exploded.second = ParseIntAndAdvance(&field, 2, &valid); 130 if (valid && year_length == 2) 131 exploded.year += exploded.year < 50 ? 2000 : 1900; 132 133 valid &= exploded.HasValidValues(); 134 135 if (!valid) 136 return false; 137 138 *time = base::Time::FromUTCExploded(exploded); 139 return true; 140 } 141 142 } // namespace net 143