Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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/cert/x509_certificate.h" | 5 #include "net/cert/x509_certificate.h" |
| 6 | 6 |
| 7 #include "base/macros.h" | 7 #include "base/macros.h" |
| 8 #include "base/memory/singleton.h" | 8 #include "base/memory/singleton.h" |
| 9 #include "base/numerics/safe_conversions.h" | 9 #include "base/numerics/safe_conversions.h" |
| 10 #include "base/pickle.h" | 10 #include "base/pickle.h" |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 86 x509_util::ParsePrincipalValueByNID(x509_name, NID_commonName, | 86 x509_util::ParsePrincipalValueByNID(x509_name, NID_commonName, |
| 87 &principal->common_name); | 87 &principal->common_name); |
| 88 x509_util::ParsePrincipalValueByNID(x509_name, NID_localityName, | 88 x509_util::ParsePrincipalValueByNID(x509_name, NID_localityName, |
| 89 &principal->locality_name); | 89 &principal->locality_name); |
| 90 x509_util::ParsePrincipalValueByNID(x509_name, NID_stateOrProvinceName, | 90 x509_util::ParsePrincipalValueByNID(x509_name, NID_stateOrProvinceName, |
| 91 &principal->state_or_province_name); | 91 &principal->state_or_province_name); |
| 92 x509_util::ParsePrincipalValueByNID(x509_name, NID_countryName, | 92 x509_util::ParsePrincipalValueByNID(x509_name, NID_countryName, |
| 93 &principal->country_name); | 93 &principal->country_name); |
| 94 } | 94 } |
| 95 | 95 |
| 96 void ParseSubjectAltName(X509Certificate::OSCertHandle cert, | 96 bool ParseSubjectAltName(X509Certificate::OSCertHandle cert, |
| 97 std::vector<std::string>* dns_names, | 97 std::vector<std::string>* dns_names, |
| 98 std::vector<std::string>* ip_addresses) { | 98 std::vector<std::string>* ip_addresses) { |
| 99 DCHECK(dns_names || ip_addresses); | |
| 100 int index = X509_get_ext_by_NID(cert, NID_subject_alt_name, -1); | 99 int index = X509_get_ext_by_NID(cert, NID_subject_alt_name, -1); |
| 101 X509_EXTENSION* alt_name_ext = X509_get_ext(cert, index); | 100 X509_EXTENSION* alt_name_ext = X509_get_ext(cert, index); |
| 102 if (!alt_name_ext) | 101 if (!alt_name_ext) |
| 103 return; | 102 return false; |
| 104 | 103 |
| 105 bssl::UniquePtr<GENERAL_NAMES> alt_names( | 104 bssl::UniquePtr<GENERAL_NAMES> alt_names( |
| 106 reinterpret_cast<GENERAL_NAMES*>(X509V3_EXT_d2i(alt_name_ext))); | 105 reinterpret_cast<GENERAL_NAMES*>(X509V3_EXT_d2i(alt_name_ext))); |
| 107 if (!alt_names.get()) | 106 if (!alt_names.get()) |
| 108 return; | 107 return false; |
| 109 | 108 |
| 109 bool has_san = false; | |
| 110 for (size_t i = 0; i < sk_GENERAL_NAME_num(alt_names.get()); ++i) { | 110 for (size_t i = 0; i < sk_GENERAL_NAME_num(alt_names.get()); ++i) { |
| 111 const GENERAL_NAME* name = sk_GENERAL_NAME_value(alt_names.get(), i); | 111 const GENERAL_NAME* name = sk_GENERAL_NAME_value(alt_names.get(), i); |
| 112 if (name->type == GEN_DNS && dns_names) { | 112 if (name->type == GEN_DNS) { |
| 113 const unsigned char* dns_name = ASN1_STRING_data(name->d.dNSName); | 113 has_san = true; |
| 114 if (!dns_name) | 114 if (dns_names) { |
| 115 continue; | 115 const unsigned char* dns_name = ASN1_STRING_data(name->d.dNSName); |
| 116 int dns_name_len = ASN1_STRING_length(name->d.dNSName); | 116 if (!dns_name) |
| 117 dns_names->push_back( | 117 continue; |
|
eroman
2017/03/21 21:09:54
Same comments as with the ios one (which this vers
| |
| 118 std::string(reinterpret_cast<const char*>(dns_name), dns_name_len)); | 118 int dns_name_len = ASN1_STRING_length(name->d.dNSName); |
| 119 } else if (name->type == GEN_IPADD && ip_addresses) { | 119 dns_names->push_back( |
| 120 const unsigned char* ip_addr = name->d.iPAddress->data; | 120 std::string(reinterpret_cast<const char*>(dns_name), dns_name_len)); |
| 121 if (!ip_addr) | |
| 122 continue; | |
| 123 int ip_addr_len = name->d.iPAddress->length; | |
| 124 if (ip_addr_len != static_cast<int>(IPAddress::kIPv4AddressSize) && | |
| 125 ip_addr_len != static_cast<int>(IPAddress::kIPv6AddressSize)) { | |
| 126 // http://www.ietf.org/rfc/rfc3280.txt requires subjectAltName iPAddress | |
| 127 // to have 4 or 16 bytes, whereas in a name constraint it includes a | |
| 128 // net mask hence 8 or 32 bytes. Logging to help diagnose any mixup. | |
| 129 LOG(WARNING) << "Bad sized IP Address in cert: " << ip_addr_len; | |
| 130 continue; | |
| 131 } | 121 } |
| 132 ip_addresses->push_back( | 122 } else if (name->type == GEN_IPADD) { |
| 133 std::string(reinterpret_cast<const char*>(ip_addr), ip_addr_len)); | 123 has_san = true; |
| 124 if (ip_addresses) { | |
| 125 const unsigned char* ip_addr = name->d.iPAddress->data; | |
| 126 if (!ip_addr) | |
| 127 continue; | |
| 128 int ip_addr_len = name->d.iPAddress->length; | |
| 129 if (ip_addr_len != static_cast<int>(IPAddress::kIPv4AddressSize) && | |
| 130 ip_addr_len != static_cast<int>(IPAddress::kIPv6AddressSize)) { | |
| 131 // http://www.ietf.org/rfc/rfc3280.txt requires subjectAltName | |
| 132 // iPAddress to have 4 or 16 bytes, whereas in a name constraint it | |
| 133 // includes a net mask hence 8 or 32 bytes. Logging to help diagnose | |
| 134 // any mixup. | |
| 135 LOG(WARNING) << "Bad sized IP Address in cert: " << ip_addr_len; | |
| 136 continue; | |
| 137 } | |
| 138 ip_addresses->push_back( | |
| 139 std::string(reinterpret_cast<const char*>(ip_addr), ip_addr_len)); | |
| 140 } | |
| 134 } | 141 } |
| 142 // Fast path: Found at least one subjectAltName and the caller doesn't | |
| 143 // need the actual values. | |
| 144 if (has_san && !ip_addresses && !dns_names) | |
| 145 return true; | |
| 135 } | 146 } |
| 147 return has_san; | |
| 136 } | 148 } |
| 137 | 149 |
| 138 class X509InitSingleton { | 150 class X509InitSingleton { |
| 139 public: | 151 public: |
| 140 static X509InitSingleton* GetInstance() { | 152 static X509InitSingleton* GetInstance() { |
| 141 // We allow the X509 store to leak, because it is used from a non-joinable | 153 // We allow the X509 store to leak, because it is used from a non-joinable |
| 142 // worker that is not stopped on shutdown, hence may still be using | 154 // worker that is not stopped on shutdown, hence may still be using |
| 143 // OpenSSL library after the AtExit runner has completed. | 155 // OpenSSL library after the AtExit runner has completed. |
| 144 return base::Singleton<X509InitSingleton, base::LeakySingletonTraits< | 156 return base::Singleton<X509InitSingleton, base::LeakySingletonTraits< |
| 145 X509InitSingleton>>::get(); | 157 X509InitSingleton>>::get(); |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 279 } | 291 } |
| 280 | 292 |
| 281 void X509Certificate::GetSubjectAltName( | 293 void X509Certificate::GetSubjectAltName( |
| 282 std::vector<std::string>* dns_names, | 294 std::vector<std::string>* dns_names, |
| 283 std::vector<std::string>* ip_addrs) const { | 295 std::vector<std::string>* ip_addrs) const { |
| 284 if (dns_names) | 296 if (dns_names) |
| 285 dns_names->clear(); | 297 dns_names->clear(); |
| 286 if (ip_addrs) | 298 if (ip_addrs) |
| 287 ip_addrs->clear(); | 299 ip_addrs->clear(); |
| 288 | 300 |
| 289 ParseSubjectAltName(cert_handle_, dns_names, ip_addrs); | 301 return ParseSubjectAltName(cert_handle_, dns_names, ip_addrs); |
| 290 } | 302 } |
| 291 | 303 |
| 292 // static | 304 // static |
| 293 X509_STORE* X509Certificate::cert_store() { | 305 X509_STORE* X509Certificate::cert_store() { |
| 294 return X509InitSingleton::GetInstance()->store(); | 306 return X509InitSingleton::GetInstance()->store(); |
| 295 } | 307 } |
| 296 | 308 |
| 297 // static | 309 // static |
| 298 bool X509Certificate::GetDEREncoded(X509Certificate::OSCertHandle cert_handle, | 310 bool X509Certificate::GetDEREncoded(X509Certificate::OSCertHandle cert_handle, |
| 299 std::string* encoded) { | 311 std::string* encoded) { |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 430 bool X509Certificate::IsSelfSigned(OSCertHandle cert_handle) { | 442 bool X509Certificate::IsSelfSigned(OSCertHandle cert_handle) { |
| 431 bssl::UniquePtr<EVP_PKEY> scoped_key(X509_get_pubkey(cert_handle)); | 443 bssl::UniquePtr<EVP_PKEY> scoped_key(X509_get_pubkey(cert_handle)); |
| 432 if (!scoped_key) | 444 if (!scoped_key) |
| 433 return false; | 445 return false; |
| 434 if (!X509_verify(cert_handle, scoped_key.get())) | 446 if (!X509_verify(cert_handle, scoped_key.get())) |
| 435 return false; | 447 return false; |
| 436 return X509_check_issued(cert_handle, cert_handle) == X509_V_OK; | 448 return X509_check_issued(cert_handle, cert_handle) == X509_V_OK; |
| 437 } | 449 } |
| 438 | 450 |
| 439 } // namespace net | 451 } // namespace net |
| OLD | NEW |