| 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 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 123 result = false; | 123 result = false; |
| 124 } | 124 } |
| 125 return result; | 125 return result; |
| 126 } | 126 } |
| 127 | 127 |
| 128 bool CertificateImporter::ParseAndStoreCertificate( | 128 bool CertificateImporter::ParseAndStoreCertificate( |
| 129 const base::DictionaryValue& certificate, | 129 const base::DictionaryValue& certificate, |
| 130 net::CertificateList* onc_trusted_certificates) { | 130 net::CertificateList* onc_trusted_certificates) { |
| 131 // Get out the attributes of the given certificate. | 131 // Get out the attributes of the given certificate. |
| 132 std::string guid; | 132 std::string guid; |
| 133 certificate.GetString(certificate::kGUID, &guid); | 133 certificate.GetStringWithoutPathExpansion(certificate::kGUID, &guid); |
| 134 DCHECK(!guid.empty()); | 134 DCHECK(!guid.empty()); |
| 135 | 135 |
| 136 bool remove = false; | 136 bool remove = false; |
| 137 if (certificate.GetBoolean(kRemove, &remove) && remove) { | 137 if (certificate.GetBooleanWithoutPathExpansion(kRemove, &remove) && remove) { |
| 138 if (!DeleteCertAndKeyByNickname(guid)) { | 138 if (!DeleteCertAndKeyByNickname(guid)) { |
| 139 ONC_LOG_ERROR("Unable to delete certificate"); | 139 ONC_LOG_ERROR("Unable to delete certificate"); |
| 140 return false; | 140 return false; |
| 141 } else { | 141 } else { |
| 142 return true; | 142 return true; |
| 143 } | 143 } |
| 144 } | 144 } |
| 145 | 145 |
| 146 // Not removing, so let's get the data we need to add this certificate. | 146 // Not removing, so let's get the data we need to add this certificate. |
| 147 std::string cert_type; | 147 std::string cert_type; |
| 148 certificate.GetString(certificate::kType, &cert_type); | 148 certificate.GetStringWithoutPathExpansion(certificate::kType, &cert_type); |
| 149 if (cert_type == certificate::kServer || | 149 if (cert_type == certificate::kServer || |
| 150 cert_type == certificate::kAuthority) { | 150 cert_type == certificate::kAuthority) { |
| 151 return ParseServerOrCaCertificate( | 151 return ParseServerOrCaCertificate( |
| 152 cert_type, guid, certificate, onc_trusted_certificates); | 152 cert_type, guid, certificate, onc_trusted_certificates); |
| 153 } else if (cert_type == certificate::kClient) { | 153 } else if (cert_type == certificate::kClient) { |
| 154 return ParseClientCertificate(guid, certificate); | 154 return ParseClientCertificate(guid, certificate); |
| 155 } | 155 } |
| 156 | 156 |
| 157 NOTREACHED(); | 157 NOTREACHED(); |
| 158 return false; | 158 return false; |
| 159 } | 159 } |
| 160 | 160 |
| 161 bool CertificateImporter::ParseServerOrCaCertificate( | 161 bool CertificateImporter::ParseServerOrCaCertificate( |
| 162 const std::string& cert_type, | 162 const std::string& cert_type, |
| 163 const std::string& guid, | 163 const std::string& guid, |
| 164 const base::DictionaryValue& certificate, | 164 const base::DictionaryValue& certificate, |
| 165 net::CertificateList* onc_trusted_certificates) { | 165 net::CertificateList* onc_trusted_certificates) { |
| 166 bool web_trust_flag = false; | 166 bool web_trust_flag = false; |
| 167 const base::ListValue* trust_list = NULL; | 167 const base::ListValue* trust_list = NULL; |
| 168 if (certificate.GetList(certificate::kTrust, &trust_list)) { | 168 if (certificate.GetListWithoutPathExpansion(certificate::kTrustBits, |
| 169 for (size_t i = 0; i < trust_list->GetSize(); ++i) { | 169 &trust_list)) { |
| 170 for (base::ListValue::const_iterator it = trust_list->begin(); |
| 171 it != trust_list->end(); ++it) { |
| 170 std::string trust_type; | 172 std::string trust_type; |
| 171 if (!trust_list->GetString(i, &trust_type)) | 173 if (!(*it)->GetAsString(&trust_type)) |
| 172 NOTREACHED(); | 174 NOTREACHED(); |
| 173 | 175 |
| 174 if (trust_type == certificate::kWeb) { | 176 if (trust_type == certificate::kWeb) { |
| 175 // "Web" implies that the certificate is to be trusted for SSL | 177 // "Web" implies that the certificate is to be trusted for SSL |
| 176 // identification. | 178 // identification. |
| 177 web_trust_flag = true; | 179 web_trust_flag = true; |
| 178 } else { | 180 } else { |
| 179 ONC_LOG_ERROR("Certificate contains unknown trust type " + trust_type); | 181 // Trust bits should only increase trust and never restrict. Thus, |
| 180 return false; | 182 // ignoring unknown bits should be safe. |
| 183 ONC_LOG_WARNING("Certificate contains unknown trust type " + |
| 184 trust_type); |
| 181 } | 185 } |
| 182 } | 186 } |
| 183 } | 187 } |
| 184 | 188 |
| 185 bool import_with_ssl_trust = false; | 189 bool import_with_ssl_trust = false; |
| 186 if (web_trust_flag) { | 190 if (web_trust_flag) { |
| 187 if (!allow_trust_imports_) | 191 if (!allow_trust_imports_) |
| 188 LOG(WARNING) << "Web trust not granted for certificate: " << guid; | 192 ONC_LOG_WARNING("Web trust not granted for certificate: " + guid); |
| 189 else | 193 else |
| 190 import_with_ssl_trust = true; | 194 import_with_ssl_trust = true; |
| 191 } | 195 } |
| 192 | 196 |
| 193 std::string x509_data; | 197 std::string x509_data; |
| 194 if (!certificate.GetString(certificate::kX509, &x509_data) || | 198 if (!certificate.GetStringWithoutPathExpansion(certificate::kX509, |
| 199 &x509_data) || |
| 195 x509_data.empty()) { | 200 x509_data.empty()) { |
| 196 ONC_LOG_ERROR( | 201 ONC_LOG_ERROR( |
| 197 "Certificate missing appropriate certificate data for type: " + | 202 "Certificate missing appropriate certificate data for type: " + |
| 198 cert_type); | 203 cert_type); |
| 199 return false; | 204 return false; |
| 200 } | 205 } |
| 201 | 206 |
| 202 // Parse PEM certificate, and get the decoded data for use in creating | 207 // Parse PEM certificate, and get the decoded data for use in creating |
| 203 // certificate below. | 208 // certificate below. |
| 204 std::vector<std::string> pem_headers; | 209 std::vector<std::string> pem_headers; |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 250 // keep our own database for mapping GUIDs to certs in order to enable several | 255 // keep our own database for mapping GUIDs to certs in order to enable several |
| 251 // GUIDs to map to the same cert. See http://crosbug.com/26073. | 256 // GUIDs to map to the same cert. See http://crosbug.com/26073. |
| 252 net::NSSCertDatabase* cert_database = net::NSSCertDatabase::GetInstance(); | 257 net::NSSCertDatabase* cert_database = net::NSSCertDatabase::GetInstance(); |
| 253 if (x509_cert->os_cert_handle()->isperm) { | 258 if (x509_cert->os_cert_handle()->isperm) { |
| 254 if (!cert_database->DeleteCertAndKey(x509_cert.get())) { | 259 if (!cert_database->DeleteCertAndKey(x509_cert.get())) { |
| 255 ONC_LOG_ERROR("Unable to delete X509 certificate."); | 260 ONC_LOG_ERROR("Unable to delete X509 certificate."); |
| 256 return false; | 261 return false; |
| 257 } | 262 } |
| 258 | 263 |
| 259 // Reload the cert here to get an actual temporary cert instance. | 264 // Reload the cert here to get an actual temporary cert instance. |
| 260 x509_cert = | 265 x509_cert = net::X509Certificate::CreateFromBytesWithNickname( |
| 261 net::X509Certificate::CreateFromBytesWithNickname( | 266 decoded_x509.data(), |
| 262 decoded_x509.data(), | 267 decoded_x509.size(), |
| 263 decoded_x509.size(), | 268 guid.c_str()); |
| 264 guid.c_str()); | |
| 265 if (!x509_cert.get()) { | 269 if (!x509_cert.get()) { |
| 266 ONC_LOG_ERROR("Unable to create X509 certificate from bytes."); | 270 ONC_LOG_ERROR("Unable to create X509 certificate from bytes."); |
| 267 return false; | 271 return false; |
| 268 } | 272 } |
| 269 DCHECK(!x509_cert->os_cert_handle()->isperm); | 273 DCHECK(!x509_cert->os_cert_handle()->isperm); |
| 270 DCHECK(x509_cert->os_cert_handle()->istemp); | 274 DCHECK(x509_cert->os_cert_handle()->istemp); |
| 271 } | 275 } |
| 272 | 276 |
| 273 // Make sure the GUID is not already taken. Note that for the reimport case we | 277 // Make sure the GUID is not already taken. Note that for the reimport case we |
| 274 // have removed the existing cert above. | 278 // have removed the existing cert above. |
| (...skipping 30 matching lines...) Expand all Loading... |
| 305 if (web_trust_flag && onc_trusted_certificates) | 309 if (web_trust_flag && onc_trusted_certificates) |
| 306 onc_trusted_certificates->push_back(x509_cert); | 310 onc_trusted_certificates->push_back(x509_cert); |
| 307 | 311 |
| 308 return true; | 312 return true; |
| 309 } | 313 } |
| 310 | 314 |
| 311 bool CertificateImporter::ParseClientCertificate( | 315 bool CertificateImporter::ParseClientCertificate( |
| 312 const std::string& guid, | 316 const std::string& guid, |
| 313 const base::DictionaryValue& certificate) { | 317 const base::DictionaryValue& certificate) { |
| 314 std::string pkcs12_data; | 318 std::string pkcs12_data; |
| 315 if (!certificate.GetString(certificate::kPKCS12, &pkcs12_data) || | 319 if (!certificate.GetStringWithoutPathExpansion(certificate::kPKCS12, |
| 320 &pkcs12_data) || |
| 316 pkcs12_data.empty()) { | 321 pkcs12_data.empty()) { |
| 317 ONC_LOG_ERROR("PKCS12 data is missing for client certificate."); | 322 ONC_LOG_ERROR("PKCS12 data is missing for client certificate."); |
| 318 return false; | 323 return false; |
| 319 } | 324 } |
| 320 | 325 |
| 321 std::string decoded_pkcs12; | 326 std::string decoded_pkcs12; |
| 322 if (!base::Base64Decode(pkcs12_data, &decoded_pkcs12)) { | 327 if (!base::Base64Decode(pkcs12_data, &decoded_pkcs12)) { |
| 323 ONC_LOG_ERROR( | 328 ONC_LOG_ERROR( |
| 324 "Unable to base64 decode PKCS#12 data: \"" + pkcs12_data + "\"."); | 329 "Unable to base64 decode PKCS#12 data: \"" + pkcs12_data + "\"."); |
| 325 return false; | 330 return false; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 360 PK11_SetPrivateKeyNickname(private_key, const_cast<char*>(guid.c_str())); | 365 PK11_SetPrivateKeyNickname(private_key, const_cast<char*>(guid.c_str())); |
| 361 SECKEY_DestroyPrivateKey(private_key); | 366 SECKEY_DestroyPrivateKey(private_key); |
| 362 } else { | 367 } else { |
| 363 ONC_LOG_WARNING("Unable to find private key for certificate."); | 368 ONC_LOG_WARNING("Unable to find private key for certificate."); |
| 364 } | 369 } |
| 365 return true; | 370 return true; |
| 366 } | 371 } |
| 367 | 372 |
| 368 } // namespace onc | 373 } // namespace onc |
| 369 } // namespace chromeos | 374 } // namespace chromeos |
| OLD | NEW |