1// Copyright 2013 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/ssl/client_cert_store_chromeos.h"
6
7#include <cert.h>
8
9#include "base/bind.h"
10#include "crypto/nss_crypto_module_delegate.h"
11#include "crypto/nss_util_internal.h"
12
13namespace net {
14
15namespace {
16
17typedef base::Callback<void(crypto::ScopedPK11Slot system_slot,
18                            crypto::ScopedPK11Slot private_slot)>
19    GetSystemAndPrivateSlotCallback;
20
21// Gets the private slot for the user with the username hash |username_hash| and
22// calls |callback| with both |system_slot| and the obtained private slot.
23void GetPrivateSlotAndCallBack(const std::string& username_hash,
24                               const GetSystemAndPrivateSlotCallback& callback,
25                               crypto::ScopedPK11Slot system_slot) {
26  base::Callback<void(crypto::ScopedPK11Slot)> wrapped_callback =
27      base::Bind(callback, base::Passed(&system_slot));
28
29  crypto::ScopedPK11Slot slot(
30      crypto::GetPrivateSlotForChromeOSUser(username_hash, wrapped_callback));
31  if (slot)
32    wrapped_callback.Run(slot.Pass());
33}
34
35// Gets the system slot, then the private slot for the user with the username
36// hash |username_hash|, and finally calls |callback| with both slots.
37void GetSystemAndPrivateSlot(const std::string& username_hash,
38                             const GetSystemAndPrivateSlotCallback& callback) {
39  crypto::ScopedPK11Slot system_slot(crypto::GetSystemNSSKeySlot(
40      base::Bind(&GetPrivateSlotAndCallBack, username_hash, callback)));
41  if (system_slot)
42    GetPrivateSlotAndCallBack(username_hash, callback, system_slot.Pass());
43}
44
45}  // namespace
46
47ClientCertStoreChromeOS::ClientCertStoreChromeOS(
48    bool use_system_slot,
49    const std::string& username_hash,
50    const PasswordDelegateFactory& password_delegate_factory)
51    : ClientCertStoreNSS(password_delegate_factory),
52      use_system_slot_(use_system_slot),
53      username_hash_(username_hash) {
54}
55
56ClientCertStoreChromeOS::~ClientCertStoreChromeOS() {}
57
58void ClientCertStoreChromeOS::GetClientCerts(
59    const SSLCertRequestInfo& cert_request_info,
60    CertificateList* selected_certs,
61    const base::Closure& callback) {
62  GetSystemAndPrivateSlotCallback bound_callback =
63      base::Bind(&ClientCertStoreChromeOS::DidGetSystemAndPrivateSlot,
64                 // Caller is responsible for keeping the ClientCertStore alive
65                 // until the callback is run.
66                 base::Unretained(this),
67                 &cert_request_info,
68                 selected_certs,
69                 callback);
70
71  if (use_system_slot_) {
72    GetSystemAndPrivateSlot(username_hash_, bound_callback);
73  } else {
74    // Skip getting the system slot.
75    GetPrivateSlotAndCallBack(
76        username_hash_, bound_callback, crypto::ScopedPK11Slot());
77  }
78}
79
80void ClientCertStoreChromeOS::GetClientCertsImpl(
81    CERTCertList* cert_list,
82    const SSLCertRequestInfo& request,
83    bool query_nssdb,
84    CertificateList* selected_certs) {
85  ClientCertStoreNSS::GetClientCertsImpl(
86      cert_list, request, query_nssdb, selected_certs);
87
88  size_t pre_size = selected_certs->size();
89  selected_certs->erase(
90      std::remove_if(
91          selected_certs->begin(),
92          selected_certs->end(),
93          NSSProfileFilterChromeOS::CertNotAllowedForProfilePredicate(
94              profile_filter_)),
95      selected_certs->end());
96  DVLOG(1) << "filtered " << pre_size - selected_certs->size() << " of "
97           << pre_size << " certs";
98}
99
100void ClientCertStoreChromeOS::DidGetSystemAndPrivateSlot(
101    const SSLCertRequestInfo* request,
102    CertificateList* selected_certs,
103    const base::Closure& callback,
104    crypto::ScopedPK11Slot system_slot,
105    crypto::ScopedPK11Slot private_slot) {
106  profile_filter_.Init(crypto::GetPublicSlotForChromeOSUser(username_hash_),
107                       private_slot.Pass(),
108                       system_slot.Pass());
109  ClientCertStoreNSS::GetClientCerts(*request, selected_certs, callback);
110}
111
112}  // namespace net
113