| 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 // Work around https://bugzilla.mozilla.org/show_bug.cgi?id=455424 | 7 // Work around https://bugzilla.mozilla.org/show_bug.cgi?id=455424 |
| 8 // until NSS 3.12.2 comes out and we update to it. | 8 // until NSS 3.12.2 comes out and we update to it. |
| 9 #define Lock FOO_NSS_Lock | 9 #define Lock FOO_NSS_Lock |
| 10 #include <cert.h> | 10 #include <cert.h> |
| 11 #include <prtime.h> | 11 #include <prtime.h> |
| 12 #include <secder.h> | 12 #include <secder.h> |
| 13 #include <sechash.h> | 13 #include <sechash.h> |
| 14 #undef Lock | 14 #undef Lock |
| 15 | 15 |
| 16 #include "base/logging.h" | 16 #include "base/logging.h" |
| 17 #include "base/pickle.h" |
| 17 #include "base/time.h" | 18 #include "base/time.h" |
| 18 #include "base/nss_init.h" | 19 #include "base/nss_init.h" |
| 19 #include "net/base/net_errors.h" | 20 #include "net/base/net_errors.h" |
| 20 | 21 |
| 21 namespace net { | 22 namespace net { |
| 22 | 23 |
| 23 namespace { | 24 namespace { |
| 24 | 25 |
| 25 // TODO(port): Implement this more simply, and put it in the right place | 26 // TODO(port): Implement this more simply, and put it in the right place |
| 26 base::Time PRTimeToBaseTime(PRTime prtime) { | 27 base::Time PRTimeToBaseTime(PRTime prtime) { |
| 27 PRExplodedTime prxtime; | 28 PRExplodedTime prxtime; |
| 28 PR_ExplodeTime(prtime, PR_GMTParameters, &prxtime); | 29 PR_ExplodeTime(prtime, PR_GMTParameters, &prxtime); |
| 29 | 30 |
| 30 base::Time::Exploded exploded; | 31 base::Time::Exploded exploded; |
| 31 exploded.year = prxtime.tm_year; | 32 exploded.year = prxtime.tm_year; |
| 32 exploded.month = prxtime.tm_month + 1; | 33 exploded.month = prxtime.tm_month + 1; |
| 33 exploded.day_of_week = prxtime.tm_wday; | 34 exploded.day_of_week = prxtime.tm_wday; |
| 34 exploded.day_of_month = prxtime.tm_mday; | 35 exploded.day_of_month = prxtime.tm_mday; |
| 35 exploded.hour = prxtime.tm_hour; | 36 exploded.hour = prxtime.tm_hour; |
| 36 exploded.minute = prxtime.tm_min; | 37 exploded.minute = prxtime.tm_min; |
| 37 exploded.second = prxtime.tm_sec; | 38 exploded.second = prxtime.tm_sec; |
| 38 exploded.millisecond = prxtime.tm_usec / 1000; | 39 exploded.millisecond = prxtime.tm_usec / 1000; |
| 39 | 40 |
| 40 return base::Time::FromUTCExploded(exploded); | 41 return base::Time::FromUTCExploded(exploded); |
| 41 } | 42 } |
| 42 | 43 |
| 43 void ParsePrincipal(SECItem* der_name, | 44 void ParsePrincipal(SECItem* der_name, |
| 44 X509Certificate::Principal* principal) { | 45 X509Certificate::Principal* principal) { |
| 45 | 46 |
| 46 CERTName name; | 47 CERTName name; |
| 47 PRArenaPool* arena = NULL; | 48 PRArenaPool* arena = NULL; |
| 48 | 49 |
| 49 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | 50 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
| 50 DCHECK(arena != NULL); | 51 DCHECK(arena != NULL); |
| 51 if (arena == NULL) | 52 if (arena == NULL) |
| 52 return; | 53 return; |
| 53 | 54 |
| 54 // TODO(dkegel): is CERT_NameTemplate what we always want here? | 55 // TODO(dkegel): is CERT_NameTemplate what we always want here? |
| 55 SECStatus rv; | 56 SECStatus rv; |
| 56 rv = SEC_QuickDERDecodeItem(arena, &name, CERT_NameTemplate, der_name); | 57 rv = SEC_QuickDERDecodeItem(arena, &name, CERT_NameTemplate, der_name); |
| 57 DCHECK(rv == SECSuccess); | 58 DCHECK(rv == SECSuccess); |
| 58 if ( rv != SECSuccess ) { | 59 if ( rv != SECSuccess ) { |
| 59 PORT_FreeArena(arena, PR_FALSE); | 60 PORT_FreeArena(arena, PR_FALSE); |
| 60 return; | 61 return; |
| 61 } | 62 } |
| 62 | 63 |
| 63 std::vector<std::string> common_names, locality_names, state_names, | 64 std::vector<std::string> common_names, locality_names, state_names, |
| 64 country_names; | 65 country_names; |
| 65 | 66 |
| 66 // TODO(jcampan): add business_category and serial_number. | 67 // TODO(jcampan): add business_category and serial_number. |
| 67 static const SECOidTag kOIDs[] = { | 68 static const SECOidTag kOIDs[] = { |
| 68 SEC_OID_AVA_COMMON_NAME, | 69 SEC_OID_AVA_COMMON_NAME, |
| 69 SEC_OID_AVA_LOCALITY, | 70 SEC_OID_AVA_LOCALITY, |
| 70 SEC_OID_AVA_STATE_OR_PROVINCE, | 71 SEC_OID_AVA_STATE_OR_PROVINCE, |
| 71 SEC_OID_AVA_COUNTRY_NAME, | 72 SEC_OID_AVA_COUNTRY_NAME, |
| 72 SEC_OID_AVA_STREET_ADDRESS, | 73 SEC_OID_AVA_STREET_ADDRESS, |
| 73 SEC_OID_AVA_ORGANIZATION_NAME, | 74 SEC_OID_AVA_ORGANIZATION_NAME, |
| 74 SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME, | 75 SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME, |
| 75 SEC_OID_AVA_DC }; | 76 SEC_OID_AVA_DC }; |
| 76 | 77 |
| 77 std::vector<std::string>* values[] = { | 78 std::vector<std::string>* values[] = { |
| 78 &common_names, &locality_names, | 79 &common_names, &locality_names, |
| 79 &state_names, &country_names, | 80 &state_names, &country_names, |
| 80 &principal->street_addresses, | 81 &principal->street_addresses, |
| 81 &principal->organization_names, | 82 &principal->organization_names, |
| 82 &principal->organization_unit_names, | 83 &principal->organization_unit_names, |
| 83 &principal->domain_components }; | 84 &principal->domain_components }; |
| 84 DCHECK(arraysize(kOIDs) == arraysize(values)); | 85 DCHECK(arraysize(kOIDs) == arraysize(values)); |
| 85 | 86 |
| 86 CERTRDN** rdns = name.rdns; | 87 CERTRDN** rdns = name.rdns; |
| 87 for (size_t rdn = 0; rdns[rdn]; ++rdn) { | 88 for (size_t rdn = 0; rdns[rdn]; ++rdn) { |
| 88 CERTAVA** avas = rdns[rdn]->avas; | 89 CERTAVA** avas = rdns[rdn]->avas; |
| 89 for (size_t pair = 0; avas[pair] != 0; ++pair) { | 90 for (size_t pair = 0; avas[pair] != 0; ++pair) { |
| 90 SECOidTag tag = CERT_GetAVATag(avas[pair]); | 91 SECOidTag tag = CERT_GetAVATag(avas[pair]); |
| 91 for (size_t oid = 0; oid < arraysize(kOIDs); ++oid) { | 92 for (size_t oid = 0; oid < arraysize(kOIDs); ++oid) { |
| 92 if (kOIDs[oid] == tag) { | 93 if (kOIDs[oid] == tag) { |
| 93 SECItem* decode_item = CERT_DecodeAVAValue(&avas[pair]->value); | 94 SECItem* decode_item = CERT_DecodeAVAValue(&avas[pair]->value); |
| 94 if (!decode_item) | 95 if (!decode_item) |
| 95 break; | 96 break; |
| 96 std::string value(reinterpret_cast<char*>(decode_item->data), | 97 std::string value(reinterpret_cast<char*>(decode_item->data), |
| 97 decode_item->len); | 98 decode_item->len); |
| 98 values[oid]->push_back(value); | 99 values[oid]->push_back(value); |
| 99 SECITEM_FreeItem(decode_item, PR_TRUE); | 100 SECITEM_FreeItem(decode_item, PR_TRUE); |
| 100 break; | 101 break; |
| 101 } | 102 } |
| 102 } | 103 } |
| 103 } | 104 } |
| 104 } | 105 } |
| 105 | 106 |
| 106 // We don't expect to have more than one CN, L, S, and C. | 107 // We don't expect to have more than one CN, L, S, and C. |
| (...skipping 14 matching lines...) Expand all Loading... |
| 121 PRTime prtime; | 122 PRTime prtime; |
| 122 SECStatus rv = DER_DecodeTimeChoice(&prtime, der_date); | 123 SECStatus rv = DER_DecodeTimeChoice(&prtime, der_date); |
| 123 DCHECK(rv == SECSuccess); | 124 DCHECK(rv == SECSuccess); |
| 124 *result = PRTimeToBaseTime(prtime); | 125 *result = PRTimeToBaseTime(prtime); |
| 125 } | 126 } |
| 126 | 127 |
| 127 void GetCertSubjectAltNamesOfType(X509Certificate::OSCertHandle cert_handle, | 128 void GetCertSubjectAltNamesOfType(X509Certificate::OSCertHandle cert_handle, |
| 128 CERTGeneralNameType name_type, | 129 CERTGeneralNameType name_type, |
| 129 std::vector<std::string>* result) { | 130 std::vector<std::string>* result) { |
| 130 | 131 |
| 131 SECItem alt_name; | 132 SECItem alt_name; |
| 132 SECStatus rv = CERT_FindCertExtension(cert_handle, | 133 SECStatus rv = CERT_FindCertExtension(cert_handle, |
| 133 SEC_OID_X509_SUBJECT_ALT_NAME, &alt_name); | 134 SEC_OID_X509_SUBJECT_ALT_NAME, &alt_name); |
| 134 if (rv != SECSuccess) | 135 if (rv != SECSuccess) |
| 135 return; | 136 return; |
| 136 | 137 |
| 137 PRArenaPool* arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); | 138 PRArenaPool* arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
| 138 DCHECK(arena != NULL); | 139 DCHECK(arena != NULL); |
| 139 | 140 |
| 140 CERTGeneralName* alt_name_list; | 141 CERTGeneralName* alt_name_list; |
| 141 alt_name_list = CERT_DecodeAltNameExtension(arena, &alt_name); | 142 alt_name_list = CERT_DecodeAltNameExtension(arena, &alt_name); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 161 } | 162 } |
| 162 | 163 |
| 163 } // namespace | 164 } // namespace |
| 164 | 165 |
| 165 void X509Certificate::Initialize() { | 166 void X509Certificate::Initialize() { |
| 166 ParsePrincipal(&cert_handle_->derSubject, &subject_); | 167 ParsePrincipal(&cert_handle_->derSubject, &subject_); |
| 167 ParsePrincipal(&cert_handle_->derIssuer, &issuer_); | 168 ParsePrincipal(&cert_handle_->derIssuer, &issuer_); |
| 168 | 169 |
| 169 ParseDate(&cert_handle_->validity.notBefore, &valid_start_); | 170 ParseDate(&cert_handle_->validity.notBefore, &valid_start_); |
| 170 ParseDate(&cert_handle_->validity.notAfter, &valid_expiry_); | 171 ParseDate(&cert_handle_->validity.notAfter, &valid_expiry_); |
| 171 | 172 |
| 172 fingerprint_ = CalculateFingerprint(cert_handle_); | 173 fingerprint_ = CalculateFingerprint(cert_handle_); |
| 173 | 174 |
| 174 // Store the certificate in the cache in case we need it later. | 175 // Store the certificate in the cache in case we need it later. |
| 175 X509Certificate::Cache::GetInstance()->Insert(this); | 176 X509Certificate::Cache::GetInstance()->Insert(this); |
| 176 } | 177 } |
| 177 | 178 |
| 178 // static | 179 // static |
| 179 X509Certificate* X509Certificate::CreateFromPickle(const Pickle& pickle, | 180 X509Certificate* X509Certificate::CreateFromPickle(const Pickle& pickle, |
| 180 void** pickle_iter) { | 181 void** pickle_iter) { |
| 181 NOTIMPLEMENTED(); | 182 const char* data; |
| 182 return NULL; | 183 int length; |
| 184 if (!pickle.ReadData(pickle_iter, &data, &length)) |
| 185 return NULL; |
| 186 |
| 187 return CreateFromBytes(data, length); |
| 183 } | 188 } |
| 184 | 189 |
| 185 void X509Certificate::Persist(Pickle* pickle) { | 190 void X509Certificate::Persist(Pickle* pickle) { |
| 186 // TODO(port): implement. | 191 pickle->WriteData(reinterpret_cast<const char*>(cert_handle_->derCert.data), |
| 187 | 192 cert_handle_->derCert.len); |
| 188 // Calling NOTIMPLEMENTED here breaks webkit tests. | |
| 189 //NOTIMPLEMENTED(); | |
| 190 } | 193 } |
| 191 | 194 |
| 192 void X509Certificate::GetDNSNames(std::vector<std::string>* dns_names) const { | 195 void X509Certificate::GetDNSNames(std::vector<std::string>* dns_names) const { |
| 193 dns_names->clear(); | 196 dns_names->clear(); |
| 194 | 197 |
| 195 // Compare with CERT_VerifyCertName(). | 198 // Compare with CERT_VerifyCertName(). |
| 196 GetCertSubjectAltNamesOfType(cert_handle_, certDNSName, dns_names); | 199 GetCertSubjectAltNamesOfType(cert_handle_, certDNSName, dns_names); |
| 197 | 200 |
| 198 // TODO(port): suppress nss's support of the obsolete extension | 201 // TODO(port): suppress nss's support of the obsolete extension |
| 199 // SEC_OID_NS_CERT_EXT_SSL_SERVER_NAME | 202 // SEC_OID_NS_CERT_EXT_SSL_SERVER_NAME |
| 200 // by providing our own authCertificate callback. | 203 // by providing our own authCertificate callback. |
| 201 | 204 |
| 202 if (dns_names->empty()) | 205 if (dns_names->empty()) |
| 203 dns_names->push_back(subject_.common_name); | 206 dns_names->push_back(subject_.common_name); |
| 204 } | 207 } |
| 205 | 208 |
| 206 bool X509Certificate::HasExpired() const { | 209 bool X509Certificate::HasExpired() const { |
| 207 NOTIMPLEMENTED(); | 210 NOTIMPLEMENTED(); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 240 | 243 |
| 241 DCHECK(NULL != cert->derCert.data); | 244 DCHECK(NULL != cert->derCert.data); |
| 242 DCHECK(0 != cert->derCert.len); | 245 DCHECK(0 != cert->derCert.len); |
| 243 | 246 |
| 244 SECStatus rv = HASH_HashBuf(HASH_AlgSHA1, sha1.data, | 247 SECStatus rv = HASH_HashBuf(HASH_AlgSHA1, sha1.data, |
| 245 cert->derCert.data, cert->derCert.len); | 248 cert->derCert.data, cert->derCert.len); |
| 246 DCHECK(rv == SECSuccess); | 249 DCHECK(rv == SECSuccess); |
| 247 | 250 |
| 248 return sha1; | 251 return sha1; |
| 249 } | 252 } |
| 250 | 253 |
| 251 } // namespace net | 254 } // namespace net |
| 252 | 255 |
| OLD | NEW |