Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2016 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2016 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 <CommonCrypto/CommonDigest.h> | 7 #include <CommonCrypto/CommonDigest.h> |
| 8 #include <Security/Security.h> | 8 #include <Security/Security.h> |
| 9 | 9 |
| 10 #include "base/mac/scoped_cftyperef.h" | 10 #include "base/mac/scoped_cftyperef.h" |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 93 x509_util::ParsePrincipalValueByNID(x509_name, NID_commonName, | 93 x509_util::ParsePrincipalValueByNID(x509_name, NID_commonName, |
| 94 &principal->common_name); | 94 &principal->common_name); |
| 95 x509_util::ParsePrincipalValueByNID(x509_name, NID_localityName, | 95 x509_util::ParsePrincipalValueByNID(x509_name, NID_localityName, |
| 96 &principal->locality_name); | 96 &principal->locality_name); |
| 97 x509_util::ParsePrincipalValueByNID(x509_name, NID_stateOrProvinceName, | 97 x509_util::ParsePrincipalValueByNID(x509_name, NID_stateOrProvinceName, |
| 98 &principal->state_or_province_name); | 98 &principal->state_or_province_name); |
| 99 x509_util::ParsePrincipalValueByNID(x509_name, NID_countryName, | 99 x509_util::ParsePrincipalValueByNID(x509_name, NID_countryName, |
| 100 &principal->country_name); | 100 &principal->country_name); |
| 101 } | 101 } |
| 102 | 102 |
| 103 void ParseSubjectAltName(X509Certificate::OSCertHandle os_cert, | 103 bool ParseSubjectAltName(X509Certificate::OSCertHandle os_cert, |
| 104 std::vector<std::string>* dns_names, | 104 std::vector<std::string>* dns_names, |
| 105 std::vector<std::string>* ip_addresses) { | 105 std::vector<std::string>* ip_addresses) { |
| 106 DCHECK(dns_names || ip_addresses); | |
| 107 bssl::UniquePtr<X509> cert = OSCertHandleToOpenSSL(os_cert); | 106 bssl::UniquePtr<X509> cert = OSCertHandleToOpenSSL(os_cert); |
| 108 if (!cert.get()) | 107 if (!cert.get()) |
| 109 return; | 108 return false; |
| 110 int index = X509_get_ext_by_NID(cert.get(), NID_subject_alt_name, -1); | 109 int index = X509_get_ext_by_NID(cert.get(), NID_subject_alt_name, -1); |
| 111 X509_EXTENSION* alt_name_ext = X509_get_ext(cert.get(), index); | 110 X509_EXTENSION* alt_name_ext = X509_get_ext(cert.get(), index); |
| 112 if (!alt_name_ext) | 111 if (!alt_name_ext) |
| 113 return; | 112 return false; |
| 114 | 113 |
| 115 bssl::UniquePtr<GENERAL_NAMES> alt_names( | 114 bssl::UniquePtr<GENERAL_NAMES> alt_names( |
| 116 reinterpret_cast<GENERAL_NAMES*>(X509V3_EXT_d2i(alt_name_ext))); | 115 reinterpret_cast<GENERAL_NAMES*>(X509V3_EXT_d2i(alt_name_ext))); |
| 117 if (!alt_names.get()) | 116 if (!alt_names.get()) |
| 118 return; | 117 return false; |
| 119 | 118 |
| 119 bool has_san = false; | |
| 120 for (size_t i = 0; i < sk_GENERAL_NAME_num(alt_names.get()); ++i) { | 120 for (size_t i = 0; i < sk_GENERAL_NAME_num(alt_names.get()); ++i) { |
| 121 const GENERAL_NAME* name = sk_GENERAL_NAME_value(alt_names.get(), i); | 121 const GENERAL_NAME* name = sk_GENERAL_NAME_value(alt_names.get(), i); |
| 122 if (name->type == GEN_DNS && dns_names) { | 122 if (name->type == GEN_DNS) { |
| 123 const unsigned char* dns_name = ASN1_STRING_data(name->d.dNSName); | 123 has_san = true; |
| 124 if (!dns_name) | 124 if (dns_names) { |
| 125 continue; | 125 const unsigned char* dns_name = ASN1_STRING_data(name->d.dNSName); |
| 126 int dns_name_len = ASN1_STRING_length(name->d.dNSName); | 126 if (!dns_name) |
| 127 dns_names->push_back( | 127 continue; |
|
eroman
2017/03/21 21:09:54
Is it expected that this code-path sets |has_san =
| |
| 128 std::string(reinterpret_cast<const char*>(dns_name), dns_name_len)); | 128 int dns_name_len = ASN1_STRING_length(name->d.dNSName); |
| 129 } else if (name->type == GEN_IPADD && ip_addresses) { | 129 dns_names->push_back( |
| 130 const unsigned char* ip_addr = name->d.iPAddress->data; | 130 std::string(reinterpret_cast<const char*>(dns_name), dns_name_len)); |
| 131 if (!ip_addr) | |
| 132 continue; | |
| 133 int ip_addr_len = name->d.iPAddress->length; | |
| 134 if (ip_addr_len != static_cast<int>(IPAddress::kIPv4AddressSize) && | |
| 135 ip_addr_len != static_cast<int>(IPAddress::kIPv6AddressSize)) { | |
| 136 // http://www.ietf.org/rfc/rfc3280.txt requires subjectAltName iPAddress | |
| 137 // to have 4 or 16 bytes, whereas in a name constraint it includes a | |
| 138 // net mask hence 8 or 32 bytes. Logging to help diagnose any mixup. | |
| 139 LOG(WARNING) << "Bad sized IP Address in cert: " << ip_addr_len; | |
| 140 continue; | |
| 141 } | 131 } |
| 142 ip_addresses->push_back( | 132 } else if (name->type == GEN_IPADD) { |
| 143 std::string(reinterpret_cast<const char*>(ip_addr), ip_addr_len)); | 133 has_san = true; |
| 134 if (ip_addrs) { | |
| 135 const unsigned char* ip_addr = name->d.iPAddress->data; | |
| 136 if (!ip_addr) | |
| 137 continue; | |
|
eroman
2017/03/21 21:09:54
Same here and other continue.
| |
| 138 int ip_addr_len = name->d.iPAddress->length; | |
| 139 if (ip_addr_len != static_cast<int>(IPAddress::kIPv4AddressSize) && | |
| 140 ip_addr_len != static_cast<int>(IPAddress::kIPv6AddressSize)) { | |
| 141 // http://www.ietf.org/rfc/rfc3280.txt requires subjectAltName | |
| 142 // iPAddress to have 4 or 16 bytes, whereas in a name constraint it | |
| 143 // includes a net mask hence 8 or 32 bytes. Logging to help diagnose | |
| 144 // any mixup. | |
| 145 LOG(WARNING) << "Bad sized IP Address in cert: " << ip_addr_len; | |
| 146 continue; | |
| 147 } | |
| 148 ip_addresses->push_back( | |
| 149 std::string(reinterpret_cast<const char*>(ip_addr), ip_addr_len)); | |
| 150 } | |
| 144 } | 151 } |
| 152 // Fast path: Found at least one subjectAltName and the caller doesn't | |
| 153 // need the actual values. | |
| 154 if (has_san && !ip_addresses && !dns_names) | |
| 155 return true; | |
| 145 } | 156 } |
| 157 | |
| 158 return has_san; | |
| 146 } | 159 } |
| 147 | 160 |
| 148 } // namespace | 161 } // namespace |
| 149 | 162 |
| 150 // static | 163 // static |
| 151 X509Certificate::OSCertHandle X509Certificate::DupOSCertHandle( | 164 X509Certificate::OSCertHandle X509Certificate::DupOSCertHandle( |
| 152 OSCertHandle handle) { | 165 OSCertHandle handle) { |
| 153 if (!handle) | 166 if (!handle) |
| 154 return nullptr; | 167 return nullptr; |
| 155 return reinterpret_cast<OSCertHandle>(const_cast<void*>(CFRetain(handle))); | 168 return reinterpret_cast<OSCertHandle>(const_cast<void*>(CFRetain(handle))); |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 264 } | 277 } |
| 265 default: { | 278 default: { |
| 266 NOTREACHED() << "Certificate format " << format << " unimplemented"; | 279 NOTREACHED() << "Certificate format " << format << " unimplemented"; |
| 267 break; | 280 break; |
| 268 } | 281 } |
| 269 } | 282 } |
| 270 | 283 |
| 271 return results; | 284 return results; |
| 272 } | 285 } |
| 273 | 286 |
| 274 void X509Certificate::GetSubjectAltName( | 287 bool X509Certificate::GetSubjectAltName( |
| 275 std::vector<std::string>* dns_names, | 288 std::vector<std::string>* dns_names, |
| 276 std::vector<std::string>* ip_addrs) const { | 289 std::vector<std::string>* ip_addrs) const { |
| 277 if (dns_names) | 290 if (dns_names) |
| 278 dns_names->clear(); | 291 dns_names->clear(); |
| 279 if (ip_addrs) | 292 if (ip_addrs) |
| 280 ip_addrs->clear(); | 293 ip_addrs->clear(); |
| 281 | 294 |
| 282 ParseSubjectAltName(cert_handle_, dns_names, ip_addrs); | 295 return ParseSubjectAltName(cert_handle_, dns_names, ip_addrs); |
| 283 } | 296 } |
| 284 | 297 |
| 285 // static | 298 // static |
| 286 bool X509Certificate::GetDEREncoded(X509Certificate::OSCertHandle cert_handle, | 299 bool X509Certificate::GetDEREncoded(X509Certificate::OSCertHandle cert_handle, |
| 287 std::string* encoded) { | 300 std::string* encoded) { |
| 288 base::StringPiece der; | 301 base::StringPiece der; |
| 289 if (!cert_handle) | 302 if (!cert_handle) |
| 290 return false; | 303 return false; |
| 291 ScopedCFTypeRef<CFDataRef> der_data(SecCertificateCopyData(cert_handle)); | 304 ScopedCFTypeRef<CFDataRef> der_data(SecCertificateCopyData(cert_handle)); |
| 292 if (!der_data) | 305 if (!der_data) |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 433 return false; | 446 return false; |
| 434 bssl::UniquePtr<EVP_PKEY> scoped_key(X509_get_pubkey(cert.get())); | 447 bssl::UniquePtr<EVP_PKEY> scoped_key(X509_get_pubkey(cert.get())); |
| 435 if (!scoped_key) | 448 if (!scoped_key) |
| 436 return false; | 449 return false; |
| 437 if (!X509_verify(cert.get(), scoped_key.get())) | 450 if (!X509_verify(cert.get(), scoped_key.get())) |
| 438 return false; | 451 return false; |
| 439 return X509_check_issued(cert.get(), cert.get()) == X509_V_OK; | 452 return X509_check_issued(cert.get(), cert.get()) == X509_V_OK; |
| 440 } | 453 } |
| 441 | 454 |
| 442 } // namespace net | 455 } // namespace net |
| OLD | NEW |