| 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   bool is_success = true; | 
 |   34  | 
 |   35   // Make a copy of "data" since CERT_DecodeCertPackage | 
 |   36   // might modify it. | 
 |   37   char* data_copy = new char[len]; | 
 |   38   memcpy(data_copy, data, len); | 
 |   39  | 
 |   40   // Parse into a certificate structure. | 
 |   41   cert = CERT_DecodeCertFromPackage(data_copy, len); | 
 |   42   delete [] data_copy; | 
 |   43   if (!cert) { | 
 |   44     LOG(ERROR) << "Couldn't create a temporary certificate"; | 
 |   45     return false; | 
 |   46   } | 
 |   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 |