OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "net/base/cert_database.h" |
| 6 |
| 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. |
| 9 #define Lock FOO_NSS_Lock |
| 10 #include <pk11pub.h> |
| 11 #include <secmod.h> |
| 12 #include <ssl.h> |
| 13 #include <nssb64.h> // NSSBase64_EncodeItem() |
| 14 #include <secder.h> // DER_Encode() |
| 15 #include <cryptohi.h> // SEC_DerSignData() |
| 16 #include <keyhi.h> // SECKEY_CreateSubjectPublicKeyInfo() |
| 17 #undef Lock |
| 18 |
| 19 #include "base/logging.h" |
| 20 #include "base/scoped_ptr.h" |
| 21 #include "base/nss_init.h" |
| 22 |
| 23 namespace net { |
| 24 |
| 25 CertDatabase::CertDatabase() { |
| 26 Init(); |
| 27 } |
| 28 |
| 29 bool CertDatabase::AddUserCert(const char* data, int len) { |
| 30 CERTCertificate* cert = NULL; |
| 31 PK11SlotInfo* slot = NULL; |
| 32 std::string nickname; |
| 33 char* data_copy = new char[len]; |
| 34 bool is_success = true; |
| 35 |
| 36 // Make a copy of "data" since CERT_DecodeCertPackage |
| 37 // might modify it. |
| 38 memcpy(data_copy, data, len); |
| 39 |
| 40 // Parse into a certificate structure. |
| 41 cert = CERT_DecodeCertFromPackage(data_copy, len); |
| 42 if (!cert) { |
| 43 LOG(ERROR) << "Couldn't create a temporary certificate"; |
| 44 return false; |
| 45 } |
| 46 delete [] data_copy; |
| 47 |
| 48 // Check if the private key corresponding to the certificate exist |
| 49 // We shouldn't accept any random client certificate sent by a CA. |
| 50 |
| 51 // Note: The NSS source documentation wrongly suggests that this |
| 52 // also imports the certificate if the private key exists. This |
| 53 // doesn't seem to be the case. |
| 54 |
| 55 slot = PK11_KeyForCertExists(cert, NULL, NULL); |
| 56 if (!slot) { |
| 57 LOG(ERROR) << "No corresponding private key in store"; |
| 58 CERT_DestroyCertificate(cert); |
| 59 return false; |
| 60 } |
| 61 PK11_FreeSlot(slot); |
| 62 slot = NULL; |
| 63 |
| 64 // TODO(gauravsh): We also need to make sure another certificate |
| 65 // doesn't already exist for the same private key. |
| 66 |
| 67 // Create a nickname for this certificate. |
| 68 // We use the scheme used by Firefox: |
| 69 // --> <subject's common name>'s <issuer's common name> ID. |
| 70 // |
| 71 |
| 72 std::string username, ca_name; |
| 73 char* temp_username = CERT_GetCommonName(&cert->subject); |
| 74 char* temp_ca_name = CERT_GetCommonName(&cert->issuer); |
| 75 if (temp_username) { |
| 76 username = temp_username; |
| 77 PORT_Free(temp_username); |
| 78 } |
| 79 if (temp_ca_name) { |
| 80 ca_name = temp_ca_name; |
| 81 PORT_Free(temp_ca_name); |
| 82 } |
| 83 nickname = username + "'s " + ca_name + " ID"; |
| 84 |
| 85 slot = PK11_ImportCertForKey(cert, |
| 86 const_cast<char*>(nickname.c_str()), |
| 87 NULL); |
| 88 if (slot) { |
| 89 PK11_FreeSlot(slot); |
| 90 } else { |
| 91 LOG(ERROR) << "Couldn't import user certificate."; |
| 92 is_success = false; |
| 93 } |
| 94 CERT_DestroyCertificate(cert); |
| 95 return is_success; |
| 96 } |
| 97 |
| 98 void CertDatabase::Init() { |
| 99 base::EnsureNSSInit(); |
| 100 } |
| 101 |
| 102 } // namespace net |
OLD | NEW |