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 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
85 x509_util::ParsePrincipalValueByNID(x509_name, NID_commonName, | 85 x509_util::ParsePrincipalValueByNID(x509_name, NID_commonName, |
86 &principal->common_name); | 86 &principal->common_name); |
87 x509_util::ParsePrincipalValueByNID(x509_name, NID_localityName, | 87 x509_util::ParsePrincipalValueByNID(x509_name, NID_localityName, |
88 &principal->locality_name); | 88 &principal->locality_name); |
89 x509_util::ParsePrincipalValueByNID(x509_name, NID_stateOrProvinceName, | 89 x509_util::ParsePrincipalValueByNID(x509_name, NID_stateOrProvinceName, |
90 &principal->state_or_province_name); | 90 &principal->state_or_province_name); |
91 x509_util::ParsePrincipalValueByNID(x509_name, NID_countryName, | 91 x509_util::ParsePrincipalValueByNID(x509_name, NID_countryName, |
92 &principal->country_name); | 92 &principal->country_name); |
93 } | 93 } |
94 | 94 |
95 void ParseSubjectAltName(X509Certificate::OSCertHandle cert, | 95 bool ParseSubjectAltName(X509Certificate::OSCertHandle cert, |
96 std::vector<std::string>* dns_names, | 96 std::vector<std::string>* dns_names, |
97 std::vector<std::string>* ip_addresses) { | 97 std::vector<std::string>* ip_addresses) { |
98 DCHECK(dns_names || ip_addresses); | |
99 int index = X509_get_ext_by_NID(cert, NID_subject_alt_name, -1); | 98 int index = X509_get_ext_by_NID(cert, NID_subject_alt_name, -1); |
100 X509_EXTENSION* alt_name_ext = X509_get_ext(cert, index); | 99 X509_EXTENSION* alt_name_ext = X509_get_ext(cert, index); |
101 if (!alt_name_ext) | 100 if (!alt_name_ext) |
102 return; | 101 return false; |
103 | 102 |
104 bssl::UniquePtr<GENERAL_NAMES> alt_names( | 103 bssl::UniquePtr<GENERAL_NAMES> alt_names( |
105 reinterpret_cast<GENERAL_NAMES*>(X509V3_EXT_d2i(alt_name_ext))); | 104 reinterpret_cast<GENERAL_NAMES*>(X509V3_EXT_d2i(alt_name_ext))); |
106 if (!alt_names.get()) | 105 if (!alt_names.get()) |
107 return; | 106 return false; |
108 | 107 |
| 108 bool has_san = false; |
109 for (size_t i = 0; i < sk_GENERAL_NAME_num(alt_names.get()); ++i) { | 109 for (size_t i = 0; i < sk_GENERAL_NAME_num(alt_names.get()); ++i) { |
110 const GENERAL_NAME* name = sk_GENERAL_NAME_value(alt_names.get(), i); | 110 const GENERAL_NAME* name = sk_GENERAL_NAME_value(alt_names.get(), i); |
111 if (name->type == GEN_DNS && dns_names) { | 111 if (name->type == GEN_DNS) { |
112 const unsigned char* dns_name = ASN1_STRING_data(name->d.dNSName); | 112 has_san = true; |
113 if (!dns_name) | 113 if (dns_names) { |
114 continue; | 114 const unsigned char* dns_name = ASN1_STRING_data(name->d.dNSName); |
115 int dns_name_len = ASN1_STRING_length(name->d.dNSName); | 115 int dns_name_len = ASN1_STRING_length(name->d.dNSName); |
116 dns_names->push_back( | 116 dns_names->push_back( |
117 std::string(reinterpret_cast<const char*>(dns_name), dns_name_len)); | 117 base::StringPiece(reinterpret_cast<const char*>(dns_name), |
118 } else if (name->type == GEN_IPADD && ip_addresses) { | 118 dns_name_len) |
119 const unsigned char* ip_addr = name->d.iPAddress->data; | 119 .as_string()); |
120 if (!ip_addr) | |
121 continue; | |
122 int ip_addr_len = name->d.iPAddress->length; | |
123 if (ip_addr_len != static_cast<int>(IPAddress::kIPv4AddressSize) && | |
124 ip_addr_len != static_cast<int>(IPAddress::kIPv6AddressSize)) { | |
125 // http://www.ietf.org/rfc/rfc3280.txt requires subjectAltName iPAddress | |
126 // to have 4 or 16 bytes, whereas in a name constraint it includes a | |
127 // net mask hence 8 or 32 bytes. Logging to help diagnose any mixup. | |
128 LOG(WARNING) << "Bad sized IP Address in cert: " << ip_addr_len; | |
129 continue; | |
130 } | 120 } |
131 ip_addresses->push_back( | 121 } else if (name->type == GEN_IPADD) { |
132 std::string(reinterpret_cast<const char*>(ip_addr), ip_addr_len)); | 122 has_san = true; |
| 123 if (ip_addresses) { |
| 124 const unsigned char* ip_addr = name->d.iPAddress->data; |
| 125 int ip_addr_len = name->d.iPAddress->length; |
| 126 ip_addresses->push_back( |
| 127 base::StringPiece(reinterpret_cast<const char*>(ip_addr), |
| 128 ip_addr_len) |
| 129 .as_string()); |
| 130 } |
133 } | 131 } |
| 132 // Fast path: Found at least one subjectAltName and the caller doesn't |
| 133 // need the actual values. |
| 134 if (has_san && !ip_addresses && !dns_names) |
| 135 return true; |
134 } | 136 } |
| 137 return has_san; |
135 } | 138 } |
136 | 139 |
137 class X509InitSingleton { | 140 class X509InitSingleton { |
138 public: | 141 public: |
139 static X509InitSingleton* GetInstance() { | 142 static X509InitSingleton* GetInstance() { |
140 // We allow the X509 store to leak, because it is used from a non-joinable | 143 // We allow the X509 store to leak, because it is used from a non-joinable |
141 // worker that is not stopped on shutdown, hence may still be using | 144 // worker that is not stopped on shutdown, hence may still be using |
142 // OpenSSL library after the AtExit runner has completed. | 145 // OpenSSL library after the AtExit runner has completed. |
143 return base::Singleton<X509InitSingleton, base::LeakySingletonTraits< | 146 return base::Singleton<X509InitSingleton, base::LeakySingletonTraits< |
144 X509InitSingleton>>::get(); | 147 X509InitSingleton>>::get(); |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
273 } | 276 } |
274 default: { | 277 default: { |
275 NOTREACHED() << "Certificate format " << format << " unimplemented"; | 278 NOTREACHED() << "Certificate format " << format << " unimplemented"; |
276 break; | 279 break; |
277 } | 280 } |
278 } | 281 } |
279 | 282 |
280 return results; | 283 return results; |
281 } | 284 } |
282 | 285 |
283 void X509Certificate::GetSubjectAltName( | 286 bool X509Certificate::GetSubjectAltName( |
284 std::vector<std::string>* dns_names, | 287 std::vector<std::string>* dns_names, |
285 std::vector<std::string>* ip_addrs) const { | 288 std::vector<std::string>* ip_addrs) const { |
286 if (dns_names) | 289 if (dns_names) |
287 dns_names->clear(); | 290 dns_names->clear(); |
288 if (ip_addrs) | 291 if (ip_addrs) |
289 ip_addrs->clear(); | 292 ip_addrs->clear(); |
290 | 293 |
291 ParseSubjectAltName(cert_handle_, dns_names, ip_addrs); | 294 return ParseSubjectAltName(cert_handle_, dns_names, ip_addrs); |
292 } | 295 } |
293 | 296 |
294 // static | 297 // static |
295 X509_STORE* X509Certificate::cert_store() { | 298 X509_STORE* X509Certificate::cert_store() { |
296 return X509InitSingleton::GetInstance()->store(); | 299 return X509InitSingleton::GetInstance()->store(); |
297 } | 300 } |
298 | 301 |
299 // static | 302 // static |
300 bool X509Certificate::GetDEREncoded(X509Certificate::OSCertHandle cert_handle, | 303 bool X509Certificate::GetDEREncoded(X509Certificate::OSCertHandle cert_handle, |
301 std::string* encoded) { | 304 std::string* encoded) { |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
432 bool X509Certificate::IsSelfSigned(OSCertHandle cert_handle) { | 435 bool X509Certificate::IsSelfSigned(OSCertHandle cert_handle) { |
433 bssl::UniquePtr<EVP_PKEY> scoped_key(X509_get_pubkey(cert_handle)); | 436 bssl::UniquePtr<EVP_PKEY> scoped_key(X509_get_pubkey(cert_handle)); |
434 if (!scoped_key) | 437 if (!scoped_key) |
435 return false; | 438 return false; |
436 if (!X509_verify(cert_handle, scoped_key.get())) | 439 if (!X509_verify(cert_handle, scoped_key.get())) |
437 return false; | 440 return false; |
438 return X509_check_issued(cert_handle, cert_handle) == X509_V_OK; | 441 return X509_check_issued(cert_handle, cert_handle) == X509_V_OK; |
439 } | 442 } |
440 | 443 |
441 } // namespace net | 444 } // namespace net |
OLD | NEW |