Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(325)

Side by Side Diff: chromeos/network/onc/onc_certificate_importer.cc

Issue 11299236: This moves the ONC parsing code into chromeos/network/onc (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Remove translated strings Created 8 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 "chrome/browser/chromeos/network_settings/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
11 #include "base/base64.h" 11 #include "base/base64.h"
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "chrome/browser/chromeos/cros/onc_constants.h" 13 #include "base/values.h"
14 #include "grit/generated_resources.h" 14 #include "chromeos/network/onc/onc_constants.h"
15 #include "net/base/crypto_module.h" 15 #include "net/base/crypto_module.h"
16 #include "net/base/net_errors.h" 16 #include "net/base/net_errors.h"
17 #include "net/base/nss_cert_database.h" 17 #include "net/base/nss_cert_database.h"
18 #include "net/base/pem_tokenizer.h" 18 #include "net/base/pem_tokenizer.h"
19 #include "net/base/x509_certificate.h" 19 #include "net/base/x509_certificate.h"
20 #include "ui/base/l10n/l10n_util.h"
21 20
22 namespace { 21 namespace {
23 22
24 // The PEM block header used for DER certificates 23 // The PEM block header used for DER certificates
25 const char kCertificateHeader[] = "CERTIFICATE"; 24 const char kCertificateHeader[] = "CERTIFICATE";
26 // This is an older PEM marker for DER certificates. 25 // This is an older PEM marker for DER certificates.
27 const char kX509CertificateHeader[] = "X509 CERTIFICATE"; 26 const char kX509CertificateHeader[] = "X509 CERTIFICATE";
28 27
29 } // namespace 28 } // namespace
30 29
31 namespace chromeos { 30 namespace chromeos {
32 namespace onc { 31 namespace onc {
33 32
33 const char kErrorCertDataMalformed[] = "Certificate data malformed";
34 const char kErrorCertDataMissing[] = "Certificate data missing";
35 const char kErrorCertDelete[] = "Certificate delete";
36 const char kErrorCertGuidCollision[] = "Certificate GUID collision";
37 const char kErrorCertGuidMissing[] = "Certificate GUID missing";
38 const char kErrorCertImport[] = "Certificate import error";
39 const char kErrorCertTrustInvalid[] = "Certificate trust invalid";
40 const char kErrorCertTrustUnknown[] = "Certificate trust unknown";
41 const char kErrorCertTypeMissing[] = "Certificate type missing";
42 const char kErrorUnknown[] = "Unknown error";
43
34 CertificateImporter::CertificateImporter( 44 CertificateImporter::CertificateImporter(
35 NetworkUIData::ONCSource onc_source, 45 ONCSource onc_source,
36 bool allow_web_trust_from_policy) 46 bool allow_web_trust_from_policy)
37 : onc_source_(onc_source), 47 : onc_source_(onc_source),
38 allow_web_trust_from_policy_(allow_web_trust_from_policy) { 48 allow_web_trust_from_policy_(allow_web_trust_from_policy) {
39 } 49 }
40 50
41 bool CertificateImporter::ParseAndStoreCertificates( 51 bool CertificateImporter::ParseAndStoreCertificates(
42 const base::ListValue& certificates, std::string* error) { 52 const base::ListValue& certificates,
43 error_.clear(); 53 std::string* result) {
44 for (size_t i = 0; i < certificates.GetSize(); ++i) { 54 for (size_t i = 0; i < certificates.GetSize(); ++i) {
45 const base::DictionaryValue* certificate = NULL; 55 const base::DictionaryValue* certificate = NULL;
46 if (!certificates.GetDictionary(i, &certificate)) { 56 if (!certificates.GetDictionary(i, &certificate)) {
47 if (error) { 57 if (result)
48 *error = l10n_util::GetStringUTF8( 58 *result = kErrorCertDataMalformed;
49 IDS_NETWORK_CONFIG_ERROR_CERT_DATA_MALFORMED);
50 }
51 return false; 59 return false;
52 } 60 }
53 61
54 if (VLOG_IS_ON(2)) 62 if (VLOG_IS_ON(2))
55 VLOG(2) << "Parsing certificate at index " << i << ": " << *certificate; 63 VLOG(2) << "Parsing certificate at index " << i << ": " << *certificate;
56 64
57 if (ParseAndStoreCertificate(*certificate)) { 65 if (ParseAndStoreCertificate(*certificate, result)) {
58 VLOG(2) << "Successfully imported certificate at index " << i; 66 VLOG(2) << "Successfully imported certificate at index " << i;
59 continue; 67 continue;
60 } 68 }
61 69
62 LOG(WARNING) << "Cannot parse certificate at index " << i << ": " << error_; 70 LOG(WARNING) << "Cannot parse certificate at index " << i << ": "
63 if (error) 71 << *result;
64 *error = error_;
65 return false; 72 return false;
66 } 73 }
67 return true; 74 return true;
68 } 75 }
69 76
70 bool CertificateImporter::ParseAndStoreCertificate( 77 bool CertificateImporter::ParseAndStoreCertificate(
71 const base::DictionaryValue& certificate) { 78 const base::DictionaryValue& certificate,
72 79 std::string* result) {
73 // Get out the attributes of the given certificate. 80 // Get out the attributes of the given certificate.
74 std::string guid; 81 std::string guid;
75 if (!certificate.GetString(kGUID, &guid) || guid.empty()) { 82 if (!certificate.GetString(kGUID, &guid) || guid.empty()) {
76 LOG(WARNING) << "Certificate missing GUID identifier"; 83 LOG(WARNING) << "Certificate missing GUID identifier";
77 error_ = l10n_util::GetStringUTF8( 84 if (result)
78 IDS_NETWORK_CONFIG_ERROR_CERT_GUID_MISSING); 85 *result = kErrorCertGuidMissing;
79 return false; 86 return false;
80 } 87 }
81 88
82 bool remove = false; 89 bool remove = false;
83 if (certificate.GetBoolean(kRemove, &remove) && remove) { 90 if (certificate.GetBoolean(kRemove, &remove) && remove) {
84 if (!DeleteCertAndKeyByNickname(guid)) { 91 if (!DeleteCertAndKeyByNickname(guid)) {
85 error_ = l10n_util::GetStringUTF8(IDS_NETWORK_CONFIG_ERROR_CERT_DELETE); 92 if (result)
93 *result = kErrorCertDelete;
86 return false; 94 return false;
87 } else { 95 } else {
88 return true; 96 return true;
89 } 97 }
90 } 98 }
91 99
92 // Not removing, so let's get the data we need to add this certificate. 100 // Not removing, so let's get the data we need to add this certificate.
93 std::string cert_type; 101 std::string cert_type;
94 certificate.GetString(certificate::kType, &cert_type); 102 certificate.GetString(certificate::kType, &cert_type);
95 if (cert_type == certificate::kServer || cert_type == certificate::kAuthority) 103 if (cert_type == certificate::kServer || cert_type == certificate::kAuthority)
96 return ParseServerOrCaCertificate(cert_type, guid, certificate); 104 return ParseServerOrCaCertificate(cert_type, guid, certificate, result);
97 105
98 if (cert_type == certificate::kClient) 106 if (cert_type == certificate::kClient)
99 return ParseClientCertificate(guid, certificate); 107 return ParseClientCertificate(guid, certificate, result);
100 108
101 LOG(WARNING) << "ONC File: certificate of unknown type: " << cert_type; 109 LOG(WARNING) << "ONC File: certificate of unknown type: " << cert_type;
102 error_ = l10n_util::GetStringUTF8(IDS_NETWORK_CONFIG_ERROR_CERT_TYPE_MISSING); 110 if (result)
111 *result = kErrorCertTypeMissing;
103 return false; 112 return false;
104 } 113 }
105 114
106 // static 115 // static
107 void CertificateImporter::ListCertsWithNickname(const std::string& label, 116 void CertificateImporter::ListCertsWithNickname(const std::string& label,
108 net::CertificateList* result) { 117 net::CertificateList* result) {
109 net::CertificateList all_certs; 118 net::CertificateList all_certs;
110 net::NSSCertDatabase::GetInstance()->ListCerts(&all_certs); 119 net::NSSCertDatabase::GetInstance()->ListCerts(&all_certs);
111 result->clear(); 120 result->clear();
112 for (net::CertificateList::iterator iter = all_certs.begin(); 121 for (net::CertificateList::iterator iter = all_certs.begin();
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
155 // label, and the cert not being found is one of the few reasons the 164 // label, and the cert not being found is one of the few reasons the
156 // delete could fail, but still... The other choice is to return 165 // delete could fail, but still... The other choice is to return
157 // failure immediately, but that doesn't seem to do what is intended. 166 // failure immediately, but that doesn't seem to do what is intended.
158 if (!net::NSSCertDatabase::GetInstance()->DeleteCertAndKey(iter->get())) 167 if (!net::NSSCertDatabase::GetInstance()->DeleteCertAndKey(iter->get()))
159 result = false; 168 result = false;
160 } 169 }
161 return result; 170 return result;
162 } 171 }
163 172
164 bool CertificateImporter::ParseServerOrCaCertificate( 173 bool CertificateImporter::ParseServerOrCaCertificate(
165 const std::string& cert_type, 174 const std::string& cert_type,
166 const std::string& guid, 175 const std::string& guid,
167 const base::DictionaryValue& certificate) { 176 const base::DictionaryValue& certificate,
177 std::string* result) {
168 // Device policy can't import certificates. 178 // Device policy can't import certificates.
169 if (onc_source_ == NetworkUIData::ONC_SOURCE_DEVICE_POLICY) { 179 if (onc_source_ == ONC_SOURCE_DEVICE_POLICY) {
170 LOG(WARNING) << "Refusing to import certificate from device policy"; 180 LOG(WARNING) << "Refusing to import certificate from device policy";
171 // This isn't a parsing error, so just return NULL here. 181 // This isn't a parsing error.
172 return true; 182 return true;
173 } 183 }
174 184
175 bool web_trust = false; 185 bool web_trust = false;
176 const base::ListValue* trust_list = NULL; 186 const base::ListValue* trust_list = NULL;
177 if (certificate.GetList(certificate::kTrust, &trust_list)) { 187 if (certificate.GetList(certificate::kTrust, &trust_list)) {
178 for (size_t i = 0; i < trust_list->GetSize(); ++i) { 188 for (size_t i = 0; i < trust_list->GetSize(); ++i) {
179 std::string trust_type; 189 std::string trust_type;
180 if (!trust_list->GetString(i, &trust_type)) { 190 if (!trust_list->GetString(i, &trust_type)) {
181 LOG(WARNING) << "ONC File: certificate trust is invalid"; 191 LOG(WARNING) << "ONC File: certificate trust is invalid";
182 error_ = l10n_util::GetStringUTF8( 192 if (result)
183 IDS_NETWORK_CONFIG_ERROR_CERT_TRUST_INVALID); 193 *result = kErrorCertTrustInvalid;
184 return false; 194 return false;
185 } 195 }
186 if (trust_type == certificate::kWeb) { 196 if (trust_type == certificate::kWeb) {
187 // "Web" implies that the certificate is to be trusted for SSL 197 // "Web" implies that the certificate is to be trusted for SSL
188 // identification. 198 // identification.
189 web_trust = true; 199 web_trust = true;
190 } else { 200 } else {
191 LOG(WARNING) << "ONC File: certificate contains unknown " 201 LOG(WARNING) << "ONC File: certificate contains unknown "
192 << "trust type: " << trust_type; 202 << "trust type: " << trust_type;
193 error_ = l10n_util::GetStringUTF8( 203 if (result)
194 IDS_NETWORK_CONFIG_ERROR_CERT_TRUST_UNKNOWN); 204 *result = kErrorCertTrustUnknown;
195 return false; 205 return false;
196 } 206 }
197 } 207 }
198 } 208 }
199 209
200 // Web trust is only granted to certificates imported for a managed user 210 // Web trust is only granted to certificates imported for a managed user
201 // on a managed device. 211 // on a managed device.
202 if (onc_source_ == NetworkUIData::ONC_SOURCE_USER_POLICY && 212 if (onc_source_ == ONC_SOURCE_USER_POLICY &&
203 web_trust && !allow_web_trust_from_policy_) { 213 web_trust && !allow_web_trust_from_policy_) {
204 LOG(WARNING) << "Web trust not granted for certificate: " << guid; 214 LOG(WARNING) << "Web trust not granted for certificate: " << guid;
205 web_trust = false; 215 web_trust = false;
206 } 216 }
207 217
208 std::string x509_data; 218 std::string x509_data;
209 if (!certificate.GetString(certificate::kX509, &x509_data) || 219 if (!certificate.GetString(certificate::kX509, &x509_data) ||
210 x509_data.empty()) { 220 x509_data.empty()) {
211 LOG(WARNING) << "ONC File: certificate missing appropriate " 221 LOG(WARNING) << "ONC File: certificate missing appropriate "
212 << "certificate data for type: " << cert_type; 222 << "certificate data for type: " << cert_type;
213 error_ = l10n_util::GetStringUTF8( 223 if (result)
214 IDS_NETWORK_CONFIG_ERROR_CERT_DATA_MISSING); 224 *result = kErrorCertDataMissing;
215 return false; 225 return false;
216 } 226 }
217 227
218 // Parse PEM certificate, and get the decoded data for use in creating 228 // Parse PEM certificate, and get the decoded data for use in creating
219 // certificate below. 229 // certificate below.
220 std::vector<std::string> pem_headers; 230 std::vector<std::string> pem_headers;
221 pem_headers.push_back(kCertificateHeader); 231 pem_headers.push_back(kCertificateHeader);
222 pem_headers.push_back(kX509CertificateHeader); 232 pem_headers.push_back(kX509CertificateHeader);
223 233
224 net::PEMTokenizer pem_tokenizer(x509_data, pem_headers); 234 net::PEMTokenizer pem_tokenizer(x509_data, pem_headers);
225 std::string decoded_x509; 235 std::string decoded_x509;
226 if (!pem_tokenizer.GetNext()) { 236 if (!pem_tokenizer.GetNext()) {
227 // If we failed to read the data as a PEM file, then let's just try plain 237 // If we failed to read the data as a PEM file, then let's just try plain
228 // base64 decode: some versions of Spigots didn't apply the PEM marker 238 // base64 decode: some versions of Spigots didn't apply the PEM marker
229 // strings. For this to work, there has to be no white space, and it has to 239 // strings. For this to work, there has to be no white space, and it has to
230 // only contain the base64-encoded data. 240 // only contain the base64-encoded data.
231 if (!base::Base64Decode(x509_data, &decoded_x509)) { 241 if (!base::Base64Decode(x509_data, &decoded_x509)) {
232 LOG(WARNING) << "Unable to base64 decode X509 data: \"" 242 LOG(WARNING) << "Unable to base64 decode X509 data: \""
233 << x509_data << "\"."; 243 << x509_data << "\".";
234 error_ = l10n_util::GetStringUTF8( 244 if (result)
235 IDS_NETWORK_CONFIG_ERROR_CERT_DATA_MALFORMED); 245 *result = kErrorCertDataMalformed;
236 return false; 246 return false;
237 } 247 }
238 } else { 248 } else {
239 decoded_x509 = pem_tokenizer.data(); 249 decoded_x509 = pem_tokenizer.data();
240 } 250 }
241 251
242 scoped_refptr<net::X509Certificate> x509_cert = 252 scoped_refptr<net::X509Certificate> x509_cert =
243 net::X509Certificate::CreateFromBytesWithNickname( 253 net::X509Certificate::CreateFromBytesWithNickname(
244 decoded_x509.data(), 254 decoded_x509.data(),
245 decoded_x509.size(), 255 decoded_x509.size(),
246 guid.c_str()); 256 guid.c_str());
247 if (!x509_cert.get()) { 257 if (!x509_cert.get()) {
248 LOG(WARNING) << "Unable to create X509 certificate from bytes."; 258 LOG(WARNING) << "Unable to create X509 certificate from bytes.";
249 error_ = l10n_util::GetStringUTF8( 259 if (result)
250 IDS_NETWORK_CONFIG_ERROR_CERT_DATA_MALFORMED); 260 *result = kErrorCertDataMalformed;
251 return false; 261 return false;
252 } 262 }
253 263
254 // Due to a mismatch regarding cert identity between NSS (cert identity is 264 // Due to a mismatch regarding cert identity between NSS (cert identity is
255 // determined by the raw bytes) and ONC (cert identity is determined by 265 // determined by the raw bytes) and ONC (cert identity is determined by
256 // GUIDs), we have to special-case a number of situations here: 266 // GUIDs), we have to special-case a number of situations here:
257 // 267 //
258 // a) The cert bits we're trying to insert are already present in the NSS cert 268 // a) The cert bits we're trying to insert are already present in the NSS cert
259 // store. This is indicated by the isperm bit in CERTCertificateStr. Since 269 // store. This is indicated by the isperm bit in CERTCertificateStr. Since
260 // we might have to update the nick name, we just delete the existing cert 270 // we might have to update the nick name, we just delete the existing cert
261 // and reimport the cert bits. 271 // and reimport the cert bits.
262 // b) NSS gives us an actual temporary certificate. In this case, there is no 272 // b) NSS gives us an actual temporary certificate. In this case, there is no
263 // identical certificate known to NSS, so we can safely import the 273 // identical certificate known to NSS, so we can safely import the
264 // certificate. The GUID being imported may still be on a different 274 // certificate. The GUID being imported may still be on a different
265 // certificate, and we could jump through hoops to reimport the existing 275 // certificate, and we could jump through hoops to reimport the existing
266 // certificate with a different nickname. However, that would mean lots of 276 // certificate with a different nickname. However, that would mean lots of
267 // effort for a case that's pretty much illegal (reusing GUIDs contradicts 277 // effort for a case that's pretty much illegal (reusing GUIDs contradicts
268 // the intention of GUIDs), so we just report an error. 278 // the intention of GUIDs), so we just report an error.
269 // 279 //
270 // TODO(mnissler, gspencer): We should probably switch to a mode where we 280 // TODO(mnissler, gspencer): We should probably switch to a mode where we
271 // keep our own database for mapping GUIDs to certs in order to enable several 281 // keep our own database for mapping GUIDs to certs in order to enable several
272 // GUIDs to map to the same cert. See http://crosbug.com/26073. 282 // GUIDs to map to the same cert. See http://crosbug.com/26073.
273 net::NSSCertDatabase* cert_database = net::NSSCertDatabase::GetInstance(); 283 net::NSSCertDatabase* cert_database = net::NSSCertDatabase::GetInstance();
274 if (x509_cert->os_cert_handle()->isperm) { 284 if (x509_cert->os_cert_handle()->isperm) {
275 if (!cert_database->DeleteCertAndKey(x509_cert.get())) { 285 if (!cert_database->DeleteCertAndKey(x509_cert.get())) {
276 error_ = l10n_util::GetStringUTF8(IDS_NETWORK_CONFIG_ERROR_CERT_DELETE); 286 LOG(WARNING) << "Unable to delete X509 certificate.";
287 if (result)
288 *result = kErrorCertDelete;
277 return false; 289 return false;
278 } 290 }
279 291
280 // Reload the cert here to get an actual temporary cert instance. 292 // Reload the cert here to get an actual temporary cert instance.
281 x509_cert = 293 x509_cert =
282 net::X509Certificate::CreateFromBytesWithNickname( 294 net::X509Certificate::CreateFromBytesWithNickname(
283 decoded_x509.data(), 295 decoded_x509.data(),
284 decoded_x509.size(), 296 decoded_x509.size(),
285 guid.c_str()); 297 guid.c_str());
286 if (!x509_cert.get()) { 298 if (!x509_cert.get()) {
287 LOG(WARNING) << "Unable to create X509 certificate from bytes."; 299 LOG(WARNING) << "Unable to create X509 certificate from bytes.";
288 error_ = l10n_util::GetStringUTF8( 300 if (result)
289 IDS_NETWORK_CONFIG_ERROR_CERT_DATA_MALFORMED); 301 *result = kErrorCertDataMalformed;
290 return false; 302 return false;
291 } 303 }
292 DCHECK(!x509_cert->os_cert_handle()->isperm); 304 DCHECK(!x509_cert->os_cert_handle()->isperm);
293 DCHECK(x509_cert->os_cert_handle()->istemp); 305 DCHECK(x509_cert->os_cert_handle()->istemp);
294 } 306 }
295 307
296 // Make sure the GUID is not already taken. Note that for the reimport case we 308 // Make sure the GUID is not already taken. Note that for the reimport case we
297 // have removed the existing cert above. 309 // have removed the existing cert above.
298 net::CertificateList certs; 310 net::CertificateList certs;
299 ListCertsWithNickname(guid, &certs); 311 ListCertsWithNickname(guid, &certs);
300 if (!certs.empty()) { 312 if (!certs.empty()) {
301 LOG(WARNING) << "Cert GUID is already in use: " << guid; 313 LOG(WARNING) << "Cert GUID is already in use: " << guid;
302 error_ = l10n_util::GetStringUTF8( 314 if (result)
303 IDS_NETWORK_CONFIG_ERROR_CERT_GUID_COLLISION); 315 *result = kErrorCertGuidCollision;
304 return false; 316 return false;
305 } 317 }
306 318
307 net::CertificateList cert_list; 319 net::CertificateList cert_list;
308 cert_list.push_back(x509_cert); 320 cert_list.push_back(x509_cert);
309 net::NSSCertDatabase::ImportCertFailureList failures; 321 net::NSSCertDatabase::ImportCertFailureList failures;
310 bool success = false; 322 bool success = false;
311 net::NSSCertDatabase::TrustBits trust = web_trust ? 323 net::NSSCertDatabase::TrustBits trust = web_trust ?
312 net::NSSCertDatabase::TRUSTED_SSL : 324 net::NSSCertDatabase::TRUSTED_SSL :
313 net::NSSCertDatabase::TRUST_DEFAULT; 325 net::NSSCertDatabase::TRUST_DEFAULT;
314 if (cert_type == certificate::kServer) 326 if (cert_type == certificate::kServer)
315 success = cert_database->ImportServerCert(cert_list, trust, &failures); 327 success = cert_database->ImportServerCert(cert_list, trust, &failures);
316 else // Authority cert 328 else // Authority cert
317 success = cert_database->ImportCACerts(cert_list, trust, &failures); 329 success = cert_database->ImportCACerts(cert_list, trust, &failures);
318 330
319 if (!failures.empty()) { 331 if (!failures.empty()) {
320 LOG(WARNING) << "ONC File: Error (" 332 LOG(WARNING) << "ONC File: Error ("
321 << net::ErrorToString(failures[0].net_error) 333 << net::ErrorToString(failures[0].net_error)
322 << ") importing " << cert_type << " certificate"; 334 << ") importing " << cert_type << " certificate";
323 error_ = l10n_util::GetStringUTF8(IDS_NETWORK_CONFIG_ERROR_CERT_IMPORT); 335 if (result)
336 *result = kErrorCertImport;
324 return false; 337 return false;
325 } 338 }
326 if (!success) { 339 if (!success) {
327 LOG(WARNING) << "ONC File: Unknown error importing " << cert_type 340 LOG(WARNING) << "ONC File: Unknown error importing " << cert_type
328 << " certificate"; 341 << " certificate";
329 error_ = l10n_util::GetStringUTF8(IDS_NETWORK_CONFIG_ERROR_UNKNOWN); 342 if (result)
343 *result = kErrorUnknown;
330 return false; 344 return false;
331 } 345 }
332 346
333 return true; 347 return true;
334 } 348 }
335 349
336 bool CertificateImporter::ParseClientCertificate( 350 bool CertificateImporter::ParseClientCertificate(
337 const std::string& guid, 351 const std::string& guid,
338 const base::DictionaryValue& certificate) { 352 const base::DictionaryValue& certificate,
353 std::string* result) {
339 std::string pkcs12_data; 354 std::string pkcs12_data;
340 if (!certificate.GetString(certificate::kPKCS12, &pkcs12_data) || 355 if (!certificate.GetString(certificate::kPKCS12, &pkcs12_data) ||
341 pkcs12_data.empty()) { 356 pkcs12_data.empty()) {
342 LOG(WARNING) << "ONC File: PKCS12 data is missing for Client " 357 LOG(WARNING) << "ONC File: PKCS12 data is missing for Client "
343 << "certificate"; 358 << "certificate";
344 error_ = l10n_util::GetStringUTF8( 359 if (result)
345 IDS_NETWORK_CONFIG_ERROR_CERT_DATA_MISSING); 360 *result = kErrorCertDataMissing;
346 return false; 361 return false;
347 } 362 }
348 363
349 std::string decoded_pkcs12; 364 std::string decoded_pkcs12;
350 if (!base::Base64Decode(pkcs12_data, &decoded_pkcs12)) { 365 if (!base::Base64Decode(pkcs12_data, &decoded_pkcs12)) {
351 LOG(WARNING) << "Unable to base64 decode PKCS#12 data: \"" 366 LOG(WARNING) << "Unable to base64 decode PKCS#12 data: \""
352 << pkcs12_data << "\"."; 367 << pkcs12_data << "\".";
353 error_ = l10n_util::GetStringUTF8( 368 if (result)
354 IDS_NETWORK_CONFIG_ERROR_CERT_DATA_MALFORMED); 369 *result = kErrorCertDataMalformed;
355 return false; 370 return false;
356 } 371 }
357 372
358 // Since this has a private key, always use the private module. 373 // Since this has a private key, always use the private module.
359 net::NSSCertDatabase* cert_database = net::NSSCertDatabase::GetInstance(); 374 net::NSSCertDatabase* cert_database = net::NSSCertDatabase::GetInstance();
360 scoped_refptr<net::CryptoModule> module(cert_database->GetPrivateModule()); 375 scoped_refptr<net::CryptoModule> module(cert_database->GetPrivateModule());
361 net::CertificateList imported_certs; 376 net::CertificateList imported_certs;
362 377
363 int result = cert_database->ImportFromPKCS12( 378 int import_result = cert_database->ImportFromPKCS12(
364 module.get(), decoded_pkcs12, string16(), false, &imported_certs); 379 module.get(), decoded_pkcs12, string16(), false, &imported_certs);
365 if (result != net::OK) { 380 if (import_result != net::OK) {
366 LOG(WARNING) << "ONC File: Unable to import Client certificate" 381 LOG(WARNING) << "ONC File: Unable to import Client certificate"
367 << " (error " << net::ErrorToString(result) << ")."; 382 << " (error " << net::ErrorToString(import_result) << ").";
368 error_ = l10n_util::GetStringUTF8(IDS_NETWORK_CONFIG_ERROR_CERT_IMPORT); 383 if (result)
384 *result = kErrorCertImport;
369 return false; 385 return false;
370 } 386 }
371 387
372 if (imported_certs.size() == 0) { 388 if (imported_certs.size() == 0) {
373 LOG(WARNING) << "ONC File: PKCS12 data contains no importable certificates"; 389 LOG(WARNING) << "ONC File: PKCS12 data contains no importable certificates";
pneubeck (no reviews) 2012/12/04 10:43:56 It would be helpful for feedback and debugging to
Greg Spencer (Chromium) 2012/12/07 18:12:27 We log warnings to the network log now.
374 return true; 390 return true;
375 } 391 }
376 392
377 if (imported_certs.size() != 1) { 393 if (imported_certs.size() != 1) {
378 LOG(WARNING) << "ONC File: PKCS12 data contains more than one certificate." 394 LOG(WARNING) << "ONC File: PKCS12 data contains more than one certificate."
379 << "Only the first one will be imported."; 395 << "Only the first one will be imported.";
380 } 396 }
381 397
382 scoped_refptr<net::X509Certificate> cert_result = imported_certs[0]; 398 scoped_refptr<net::X509Certificate> cert_result = imported_certs[0];
383 399
384 // Find the private key associated with this certificate, and set the 400 // Find the private key associated with this certificate, and set the
385 // nickname on it. 401 // nickname on it.
386 SECKEYPrivateKey* private_key = PK11_FindPrivateKeyFromCert( 402 SECKEYPrivateKey* private_key = PK11_FindPrivateKeyFromCert(
387 cert_result->os_cert_handle()->slot, 403 cert_result->os_cert_handle()->slot,
388 cert_result->os_cert_handle(), 404 cert_result->os_cert_handle(),
389 NULL); // wincx 405 NULL); // wincx
390 if (private_key) { 406 if (private_key) {
391 PK11_SetPrivateKeyNickname(private_key, const_cast<char*>(guid.c_str())); 407 PK11_SetPrivateKeyNickname(private_key, const_cast<char*>(guid.c_str()));
392 SECKEY_DestroyPrivateKey(private_key); 408 SECKEY_DestroyPrivateKey(private_key);
393 } else { 409 } else {
394 LOG(WARNING) << "ONC File: Unable to find private key for cert"; 410 LOG(WARNING) << "ONC File: Unable to find private key for cert";
pneubeck (no reviews) 2012/12/04 10:43:56 same here: set |result| to a warning
Greg Spencer (Chromium) 2012/12/07 18:12:27 result no longer exists.
395 } 411 }
396 return true; 412 return true;
397 } 413 }
398 414
399 } // chromeos 415 } // chromeos
400 } // onc 416 } // onc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698