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 "chromeos/network/onc/onc_certificate_importer.h" | 5 #include "chromeos/network/onc/onc_certificate_importer.h" |
6 | 6 |
7 #include <cert.h> | 7 #include <cert.h> |
8 #include <keyhi.h> | 8 #include <keyhi.h> |
9 #include <pk11pub.h> | 9 #include <pk11pub.h> |
10 | 10 |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
63 return IMPORT_FAILED; | 63 return IMPORT_FAILED; |
64 } else { | 64 } else { |
65 return IMPORT_INCOMPLETE; | 65 return IMPORT_INCOMPLETE; |
66 } | 66 } |
67 } | 67 } |
68 | 68 |
69 bool CertificateImporter::ParseAndStoreCertificate( | 69 bool CertificateImporter::ParseAndStoreCertificate( |
70 const base::DictionaryValue& certificate) { | 70 const base::DictionaryValue& certificate) { |
71 // Get out the attributes of the given certificate. | 71 // Get out the attributes of the given certificate. |
72 std::string guid; | 72 std::string guid; |
73 certificate.GetString(certificate::kGUID, &guid); | 73 certificate.GetStringWithoutPathExpansion(certificate::kGUID, &guid); |
74 DCHECK(!guid.empty()); | 74 DCHECK(!guid.empty()); |
75 | 75 |
76 bool remove = false; | 76 bool remove = false; |
77 if (certificate.GetBoolean(kRemove, &remove) && remove) { | 77 if (certificate.GetBooleanWithoutPathExpansion(kRemove, &remove) && remove) { |
78 if (!DeleteCertAndKeyByNickname(guid)) { | 78 if (!DeleteCertAndKeyByNickname(guid)) { |
79 ONC_LOG_ERROR("Unable to delete certificate"); | 79 ONC_LOG_ERROR("Unable to delete certificate"); |
80 return false; | 80 return false; |
81 } else { | 81 } else { |
82 return true; | 82 return true; |
83 } | 83 } |
84 } | 84 } |
85 | 85 |
86 // Not removing, so let's get the data we need to add this certificate. | 86 // Not removing, so let's get the data we need to add this certificate. |
87 std::string cert_type; | 87 std::string cert_type; |
88 certificate.GetString(certificate::kType, &cert_type); | 88 certificate.GetStringWithoutPathExpansion(certificate::kType, &cert_type); |
89 if (cert_type == certificate::kServer || | 89 if (cert_type == certificate::kServer || |
90 cert_type == certificate::kAuthority) { | 90 cert_type == certificate::kAuthority) { |
91 return ParseServerOrCaCertificate(cert_type, guid, certificate); | 91 return ParseServerOrCaCertificate(cert_type, guid, certificate); |
92 } else if (cert_type == certificate::kClient) { | 92 } else if (cert_type == certificate::kClient) { |
93 return ParseClientCertificate(guid, certificate); | 93 return ParseClientCertificate(guid, certificate); |
94 } | 94 } |
95 | 95 |
96 NOTREACHED(); | 96 NOTREACHED(); |
97 return false; | 97 return false; |
98 } | 98 } |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
154 } | 154 } |
155 return result; | 155 return result; |
156 } | 156 } |
157 | 157 |
158 bool CertificateImporter::ParseServerOrCaCertificate( | 158 bool CertificateImporter::ParseServerOrCaCertificate( |
159 const std::string& cert_type, | 159 const std::string& cert_type, |
160 const std::string& guid, | 160 const std::string& guid, |
161 const base::DictionaryValue& certificate) { | 161 const base::DictionaryValue& certificate) { |
162 bool web_trust = false; | 162 bool web_trust = false; |
163 const base::ListValue* trust_list = NULL; | 163 const base::ListValue* trust_list = NULL; |
164 if (certificate.GetList(certificate::kTrust, &trust_list)) { | 164 if (certificate.GetListWithoutPathExpansion(certificate::kTrustBits, |
165 for (size_t i = 0; i < trust_list->GetSize(); ++i) { | 165 &trust_list)) { |
166 for (base::ListValue::const_iterator it = trust_list->begin(); | |
167 it != trust_list->end(); ++it) { | |
166 std::string trust_type; | 168 std::string trust_type; |
167 if (!trust_list->GetString(i, &trust_type)) | 169 if (!(*it)->GetAsString(&trust_type)) |
168 NOTREACHED(); | 170 NOTREACHED(); |
169 | 171 |
170 if (trust_type == certificate::kWeb) { | 172 if (trust_type == certificate::kWeb) { |
171 // "Web" implies that the certificate is to be trusted for SSL | 173 // "Web" implies that the certificate is to be trusted for SSL |
172 // identification. | 174 // identification. |
173 web_trust = true; | 175 web_trust = true; |
174 } else { | 176 } else { |
175 ONC_LOG_ERROR("Certificate contains unknown trust type " + trust_type); | 177 // Trust bits should only increase trust and never restrict. Thus, |
176 return false; | 178 // ignoring unknown bits should be safe. |
179 ONC_LOG_WARNING("Certificate contains unknown trust type " + | |
180 trust_type); | |
Joao da Silva
2013/04/03 12:49:53
It'd be nice to add a test for this: have an ONC f
pneubeck (no reviews)
2013/04/04 11:24:49
Added the flag to an existing test.
| |
177 } | 181 } |
178 } | 182 } |
179 } | 183 } |
180 | 184 |
181 if (web_trust && !allow_web_trust_) { | 185 if (web_trust && !allow_web_trust_) { |
182 LOG(WARNING) << "Web trust not granted for certificate: " << guid; | 186 ONC_LOG_WARNING("Web trust not granted for certificate: " + guid); |
183 web_trust = false; | 187 web_trust = false; |
184 } | 188 } |
185 | 189 |
186 std::string x509_data; | 190 std::string x509_data; |
187 if (!certificate.GetString(certificate::kX509, &x509_data) || | 191 if (!certificate.GetStringWithoutPathExpansion(certificate::kX509, |
192 &x509_data) || | |
188 x509_data.empty()) { | 193 x509_data.empty()) { |
189 ONC_LOG_ERROR( | 194 ONC_LOG_ERROR( |
190 "Certificate missing appropriate certificate data for type: " + | 195 "Certificate missing appropriate certificate data for type: " + |
191 cert_type); | 196 cert_type); |
192 return false; | 197 return false; |
193 } | 198 } |
194 | 199 |
195 // Parse PEM certificate, and get the decoded data for use in creating | 200 // Parse PEM certificate, and get the decoded data for use in creating |
196 // certificate below. | 201 // certificate below. |
197 std::vector<std::string> pem_headers; | 202 std::vector<std::string> pem_headers; |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
243 // keep our own database for mapping GUIDs to certs in order to enable several | 248 // keep our own database for mapping GUIDs to certs in order to enable several |
244 // GUIDs to map to the same cert. See http://crosbug.com/26073. | 249 // GUIDs to map to the same cert. See http://crosbug.com/26073. |
245 net::NSSCertDatabase* cert_database = net::NSSCertDatabase::GetInstance(); | 250 net::NSSCertDatabase* cert_database = net::NSSCertDatabase::GetInstance(); |
246 if (x509_cert->os_cert_handle()->isperm) { | 251 if (x509_cert->os_cert_handle()->isperm) { |
247 if (!cert_database->DeleteCertAndKey(x509_cert.get())) { | 252 if (!cert_database->DeleteCertAndKey(x509_cert.get())) { |
248 ONC_LOG_ERROR("Unable to delete X509 certificate."); | 253 ONC_LOG_ERROR("Unable to delete X509 certificate."); |
249 return false; | 254 return false; |
250 } | 255 } |
251 | 256 |
252 // Reload the cert here to get an actual temporary cert instance. | 257 // Reload the cert here to get an actual temporary cert instance. |
253 x509_cert = | 258 x509_cert = net::X509Certificate::CreateFromBytesWithNickname( |
254 net::X509Certificate::CreateFromBytesWithNickname( | 259 decoded_x509.data(), |
255 decoded_x509.data(), | 260 decoded_x509.size(), |
256 decoded_x509.size(), | 261 guid.c_str()); |
257 guid.c_str()); | |
258 if (!x509_cert.get()) { | 262 if (!x509_cert.get()) { |
259 ONC_LOG_ERROR("Unable to create X509 certificate from bytes."); | 263 ONC_LOG_ERROR("Unable to create X509 certificate from bytes."); |
260 return false; | 264 return false; |
261 } | 265 } |
262 DCHECK(!x509_cert->os_cert_handle()->isperm); | 266 DCHECK(!x509_cert->os_cert_handle()->isperm); |
263 DCHECK(x509_cert->os_cert_handle()->istemp); | 267 DCHECK(x509_cert->os_cert_handle()->istemp); |
264 } | 268 } |
265 | 269 |
266 // Make sure the GUID is not already taken. Note that for the reimport case we | 270 // Make sure the GUID is not already taken. Note that for the reimport case we |
267 // have removed the existing cert above. | 271 // have removed the existing cert above. |
(...skipping 27 matching lines...) Expand all Loading... | |
295 return false; | 299 return false; |
296 } | 300 } |
297 | 301 |
298 return true; | 302 return true; |
299 } | 303 } |
300 | 304 |
301 bool CertificateImporter::ParseClientCertificate( | 305 bool CertificateImporter::ParseClientCertificate( |
302 const std::string& guid, | 306 const std::string& guid, |
303 const base::DictionaryValue& certificate) { | 307 const base::DictionaryValue& certificate) { |
304 std::string pkcs12_data; | 308 std::string pkcs12_data; |
305 if (!certificate.GetString(certificate::kPKCS12, &pkcs12_data) || | 309 if (!certificate.GetStringWithoutPathExpansion(certificate::kPKCS12, |
310 &pkcs12_data) || | |
306 pkcs12_data.empty()) { | 311 pkcs12_data.empty()) { |
307 ONC_LOG_ERROR("PKCS12 data is missing for client certificate."); | 312 ONC_LOG_ERROR("PKCS12 data is missing for client certificate."); |
308 return false; | 313 return false; |
309 } | 314 } |
310 | 315 |
311 std::string decoded_pkcs12; | 316 std::string decoded_pkcs12; |
312 if (!base::Base64Decode(pkcs12_data, &decoded_pkcs12)) { | 317 if (!base::Base64Decode(pkcs12_data, &decoded_pkcs12)) { |
313 ONC_LOG_ERROR( | 318 ONC_LOG_ERROR( |
314 "Unable to base64 decode PKCS#12 data: \"" + pkcs12_data + "\"."); | 319 "Unable to base64 decode PKCS#12 data: \"" + pkcs12_data + "\"."); |
315 return false; | 320 return false; |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
350 PK11_SetPrivateKeyNickname(private_key, const_cast<char*>(guid.c_str())); | 355 PK11_SetPrivateKeyNickname(private_key, const_cast<char*>(guid.c_str())); |
351 SECKEY_DestroyPrivateKey(private_key); | 356 SECKEY_DestroyPrivateKey(private_key); |
352 } else { | 357 } else { |
353 ONC_LOG_WARNING("Unable to find private key for certificate."); | 358 ONC_LOG_WARNING("Unable to find private key for certificate."); |
354 } | 359 } |
355 return true; | 360 return true; |
356 } | 361 } |
357 | 362 |
358 } // namespace onc | 363 } // namespace onc |
359 } // namespace chromeos | 364 } // namespace chromeos |
OLD | NEW |