1// Copyright (c) 2010 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/cert/cert_database.h"
6
7#include <windows.h>
8#include <wincrypt.h>
9#pragma comment(lib, "crypt32.lib")
10
11#include "base/observer_list_threadsafe.h"
12#include "net/base/net_errors.h"
13#include "net/cert/x509_certificate.h"
14
15namespace net {
16
17CertDatabase::CertDatabase()
18    : observer_list_(new ObserverListThreadSafe<Observer>) {
19}
20
21CertDatabase::~CertDatabase() {}
22
23int CertDatabase::CheckUserCert(X509Certificate* cert) {
24  if (!cert)
25    return ERR_CERT_INVALID;
26  if (cert->HasExpired())
27    return ERR_CERT_DATE_INVALID;
28
29  // TODO(rsleevi): Should CRYPT_FIND_SILENT_KEYSET_FLAG be specified? A UI
30  // may be shown here / this call may block.
31  if (!CryptFindCertificateKeyProvInfo(cert->os_cert_handle(), 0, NULL))
32    return ERR_NO_PRIVATE_KEY_FOR_CERT;
33
34  return OK;
35}
36
37int CertDatabase::AddUserCert(X509Certificate* cert) {
38  // TODO(rsleevi): Would it be more appropriate to have the CertDatabase take
39  // construction parameters (Keychain filepath on Mac OS X, PKCS #11 slot on
40  // NSS, and Store Type / Path) here? For now, certs will be stashed into the
41  // user's personal store, which will not automatically mark them as trusted,
42  // but will allow them to be used for client auth.
43  HCERTSTORE cert_db = CertOpenSystemStore(NULL, L"MY");
44  if (!cert_db)
45    return ERR_ADD_USER_CERT_FAILED;
46
47  BOOL added = CertAddCertificateContextToStore(cert_db,
48                                                cert->os_cert_handle(),
49                                                CERT_STORE_ADD_USE_EXISTING,
50                                                NULL);
51
52  CertCloseStore(cert_db, 0);
53
54  if (!added)
55    return ERR_ADD_USER_CERT_FAILED;
56
57  NotifyObserversOfCertAdded(cert);
58  return OK;
59}
60
61}  // namespace net
62