Web MIDI: send back error information to blink on starting sessions
[chromium-blink-merge.git] / net / cert / cert_database_nss.cc
blob9819dded6cb4b4b6c1858446caee09b42374818a
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
3 // found in the LICENSE file.
5 #include "net/cert/cert_database.h"
7 #include <cert.h>
8 #include <pk11pub.h>
9 #include <secmod.h>
11 #include "base/logging.h"
12 #include "base/observer_list_threadsafe.h"
13 #include "crypto/nss_util.h"
14 #include "crypto/scoped_nss_types.h"
15 #include "net/base/net_errors.h"
16 #include "net/cert/nss_cert_database.h"
17 #include "net/cert/x509_certificate.h"
18 #include "net/cert/x509_util_nss.h"
20 namespace net {
22 // Helper that observes events from the NSSCertDatabase and forwards them to
23 // the given CertDatabase.
24 class CertDatabase::Notifier : public NSSCertDatabase::Observer {
25 public:
26 explicit Notifier(CertDatabase* cert_db) : cert_db_(cert_db) {}
28 virtual ~Notifier() {}
30 // NSSCertDatabase::Observer implementation:
31 virtual void OnCertAdded(const X509Certificate* cert) OVERRIDE {
32 cert_db_->NotifyObserversOfCertAdded(cert);
35 virtual void OnCertRemoved(const X509Certificate* cert) OVERRIDE {
36 cert_db_->NotifyObserversOfCertRemoved(cert);
39 virtual void OnCACertChanged(const X509Certificate* cert) OVERRIDE {
40 cert_db_->NotifyObserversOfCACertChanged(cert);
43 private:
44 CertDatabase* cert_db_;
46 DISALLOW_COPY_AND_ASSIGN(Notifier);
49 CertDatabase::CertDatabase()
50 : observer_list_(new ObserverListThreadSafe<Observer>),
51 notifier_(new Notifier(this)) {
52 crypto::EnsureNSSInit();
55 CertDatabase::~CertDatabase() {}
57 int CertDatabase::CheckUserCert(X509Certificate* cert_obj) {
58 if (!cert_obj)
59 return ERR_CERT_INVALID;
60 if (cert_obj->HasExpired())
61 return ERR_CERT_DATE_INVALID;
63 // Check if the private key corresponding to the certificate exist
64 // We shouldn't accept any random client certificate sent by a CA.
66 // Note: The NSS source documentation wrongly suggests that this
67 // also imports the certificate if the private key exists. This
68 // doesn't seem to be the case.
70 CERTCertificate* cert = cert_obj->os_cert_handle();
71 PK11SlotInfo* slot = PK11_KeyForCertExists(cert, NULL, NULL);
72 if (!slot)
73 return ERR_NO_PRIVATE_KEY_FOR_CERT;
75 PK11_FreeSlot(slot);
77 return OK;
80 int CertDatabase::AddUserCert(X509Certificate* cert_obj) {
81 CERTCertificate* cert = cert_obj->os_cert_handle();
82 CK_OBJECT_HANDLE key;
83 crypto::ScopedPK11Slot slot(PK11_KeyForCertExists(cert, &key, NULL));
84 if (!slot.get())
85 return ERR_NO_PRIVATE_KEY_FOR_CERT;
87 std::string nickname = x509_util::GetUniqueNicknameForSlot(
88 cert_obj->GetDefaultNickname(USER_CERT),
89 &cert->derSubject,
90 slot.get());
92 SECStatus rv;
94 crypto::AutoNSSWriteLock lock;
95 rv = PK11_ImportCert(slot.get(), cert, key, nickname.c_str(), PR_FALSE);
98 if (rv != SECSuccess) {
99 LOG(ERROR) << "Couldn't import user certificate. " << PORT_GetError();
100 return ERR_ADD_USER_CERT_FAILED;
103 NotifyObserversOfCertAdded(cert_obj);
104 return OK;
107 void CertDatabase::ObserveNSSCertDatabase(NSSCertDatabase* source) {
108 source->AddObserver(this->notifier_.get());
111 } // namespace net