| Index: net/base/cert_database_nss.cc
|
| ===================================================================
|
| --- net/base/cert_database_nss.cc (revision 0)
|
| +++ net/base/cert_database_nss.cc (revision 0)
|
| @@ -0,0 +1,102 @@
|
| +// Copyright (c) 2009 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "net/base/cert_database.h"
|
| +
|
| +// Work around https://bugzilla.mozilla.org/show_bug.cgi?id=455424
|
| +// until NSS 3.12.2 comes out and we update to it.
|
| +#define Lock FOO_NSS_Lock
|
| +#include <pk11pub.h>
|
| +#include <secmod.h>
|
| +#include <ssl.h>
|
| +#include <nssb64.h> // NSSBase64_EncodeItem()
|
| +#include <secder.h> // DER_Encode()
|
| +#include <cryptohi.h> // SEC_DerSignData()
|
| +#include <keyhi.h> // SECKEY_CreateSubjectPublicKeyInfo()
|
| +#undef Lock
|
| +
|
| +#include "base/logging.h"
|
| +#include "base/scoped_ptr.h"
|
| +#include "base/nss_init.h"
|
| +
|
| +namespace net {
|
| +
|
| +CertDatabase::CertDatabase() {
|
| + Init();
|
| +}
|
| +
|
| +bool CertDatabase::AddUserCert(const char* data, int len) {
|
| + CERTCertificate* cert = NULL;
|
| + PK11SlotInfo* slot = NULL;
|
| + std::string nickname;
|
| + char* data_copy = new char[len];
|
| + bool is_success = true;
|
| +
|
| + // Make a copy of "data" since CERT_DecodeCertPackage
|
| + // might modify it.
|
| + memcpy(data_copy, data, len);
|
| +
|
| + // Parse into a certificate structure.
|
| + cert = CERT_DecodeCertFromPackage(data_copy, len);
|
| + if (!cert) {
|
| + LOG(ERROR) << "Couldn't create a temporary certificate";
|
| + return false;
|
| + }
|
| + delete [] data_copy;
|
| +
|
| + // Check if the private key corresponding to the certificate exist
|
| + // We shouldn't accept any random client certificate sent by a CA.
|
| +
|
| + // Note: The NSS source documentation wrongly suggests that this
|
| + // also imports the certificate if the private key exists. This
|
| + // doesn't seem to be the case.
|
| +
|
| + slot = PK11_KeyForCertExists(cert, NULL, NULL);
|
| + if (!slot) {
|
| + LOG(ERROR) << "No corresponding private key in store";
|
| + CERT_DestroyCertificate(cert);
|
| + return false;
|
| + }
|
| + PK11_FreeSlot(slot);
|
| + slot = NULL;
|
| +
|
| + // TODO(gauravsh): We also need to make sure another certificate
|
| + // doesn't already exist for the same private key.
|
| +
|
| + // Create a nickname for this certificate.
|
| + // We use the scheme used by Firefox:
|
| + // --> <subject's common name>'s <issuer's common name> ID.
|
| + //
|
| +
|
| + std::string username, ca_name;
|
| + char* temp_username = CERT_GetCommonName(&cert->subject);
|
| + char* temp_ca_name = CERT_GetCommonName(&cert->issuer);
|
| + if (temp_username) {
|
| + username = temp_username;
|
| + PORT_Free(temp_username);
|
| + }
|
| + if (temp_ca_name) {
|
| + ca_name = temp_ca_name;
|
| + PORT_Free(temp_ca_name);
|
| + }
|
| + nickname = username + "'s " + ca_name + " ID";
|
| +
|
| + slot = PK11_ImportCertForKey(cert,
|
| + const_cast<char*>(nickname.c_str()),
|
| + NULL);
|
| + if (slot) {
|
| + PK11_FreeSlot(slot);
|
| + } else {
|
| + LOG(ERROR) << "Couldn't import user certificate.";
|
| + is_success = false;
|
| + }
|
| + CERT_DestroyCertificate(cert);
|
| + return is_success;
|
| +}
|
| +
|
| +void CertDatabase::Init() {
|
| + base::EnsureNSSInit();
|
| +}
|
| +
|
| +} // namespace net
|
|
|
| Property changes on: net/base/cert_database_nss.cc
|
| ___________________________________________________________________
|
| Name: svn:eol-style
|
| + LF
|
|
|
|
|