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 |