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/cert/nss_profile_filter_chromeos.h"
6
7 #include "base/strings/string_piece.h"
8 #include "base/strings/stringprintf.h"
9 #include "net/cert/x509_certificate.h"
10
11 namespace net {
12
13 namespace {
14
CertSlotsString(CERTCertificate * cert)15 std::string CertSlotsString(CERTCertificate* cert) {
16 std::string result;
17 crypto::ScopedPK11SlotList slots_for_cert(
18 PK11_GetAllSlotsForCert(cert, NULL));
19 for (PK11SlotListElement* slot_element =
20 PK11_GetFirstSafe(slots_for_cert.get());
21 slot_element;
22 slot_element =
23 PK11_GetNextSafe(slots_for_cert.get(), slot_element, PR_FALSE)) {
24 if (!result.empty())
25 result += ',';
26 base::StringAppendF(&result,
27 "%lu:%lu",
28 PK11_GetModuleID(slot_element->slot),
29 PK11_GetSlotID(slot_element->slot));
30 }
31 return result;
32 }
33
34 } // namespace
35
NSSProfileFilterChromeOS()36 NSSProfileFilterChromeOS::NSSProfileFilterChromeOS() {}
37
NSSProfileFilterChromeOS(const NSSProfileFilterChromeOS & other)38 NSSProfileFilterChromeOS::NSSProfileFilterChromeOS(
39 const NSSProfileFilterChromeOS& other) {
40 public_slot_.reset(other.public_slot_ ?
41 PK11_ReferenceSlot(other.public_slot_.get()) :
42 NULL);
43 private_slot_.reset(other.private_slot_ ?
44 PK11_ReferenceSlot(other.private_slot_.get()) :
45 NULL);
46 }
47
~NSSProfileFilterChromeOS()48 NSSProfileFilterChromeOS::~NSSProfileFilterChromeOS() {}
49
operator =(const NSSProfileFilterChromeOS & other)50 NSSProfileFilterChromeOS& NSSProfileFilterChromeOS::operator=(
51 const NSSProfileFilterChromeOS& other) {
52 public_slot_.reset(other.public_slot_ ?
53 PK11_ReferenceSlot(other.public_slot_.get()) :
54 NULL);
55 private_slot_.reset(other.private_slot_ ?
56 PK11_ReferenceSlot(other.private_slot_.get()) :
57 NULL);
58 return *this;
59 }
60
Init(crypto::ScopedPK11Slot public_slot,crypto::ScopedPK11Slot private_slot)61 void NSSProfileFilterChromeOS::Init(crypto::ScopedPK11Slot public_slot,
62 crypto::ScopedPK11Slot private_slot) {
63 // crypto::ScopedPK11Slot actually holds a reference counted object.
64 // Because scoped_ptr<T> assignment is a no-op if it already points to
65 // the same pointer, a reference would be leaked because .Pass() does
66 // not release its reference, and the receiving object won't free
67 // its copy.
68 if (public_slot_.get() != public_slot.get())
69 public_slot_ = public_slot.Pass();
70 if (private_slot_.get() != private_slot.get())
71 private_slot_ = private_slot.Pass();
72 }
73
IsModuleAllowed(PK11SlotInfo * slot) const74 bool NSSProfileFilterChromeOS::IsModuleAllowed(PK11SlotInfo* slot) const {
75 // If this is one of the public/private slots for this profile, allow it.
76 if (slot == public_slot_.get() || slot == private_slot_.get())
77 return true;
78 // Allow the root certs module.
79 if (PK11_HasRootCerts(slot))
80 return true;
81 // If it's from the read-only slots, allow it.
82 if (PK11_IsInternal(slot) && !PK11_IsRemovable(slot))
83 return true;
84 // If |public_slot_| or |private_slot_| is null, there isn't a way to get the
85 // modules to use in the final test.
86 if (!public_slot_.get() || !private_slot_.get())
87 return false;
88 // If this is not the internal (file-system) module or the TPM module, allow
89 // it.
90 SECMODModule* module_for_slot = PK11_GetModule(slot);
91 if (module_for_slot != PK11_GetModule(public_slot_.get()) &&
92 module_for_slot != PK11_GetModule(private_slot_.get()))
93 return true;
94 return false;
95 }
96
IsCertAllowed(CERTCertificate * cert) const97 bool NSSProfileFilterChromeOS::IsCertAllowed(CERTCertificate* cert) const {
98 crypto::ScopedPK11SlotList slots_for_cert(
99 PK11_GetAllSlotsForCert(cert, NULL));
100 if (!slots_for_cert) {
101 DVLOG(2) << "cert no slots: " << base::StringPiece(cert->nickname);
102 return false;
103 }
104
105 for (PK11SlotListElement* slot_element =
106 PK11_GetFirstSafe(slots_for_cert.get());
107 slot_element;
108 slot_element =
109 PK11_GetNextSafe(slots_for_cert.get(), slot_element, PR_FALSE)) {
110 if (IsModuleAllowed(slot_element->slot)) {
111 DVLOG(3) << "cert from " << CertSlotsString(cert)
112 << " allowed: " << base::StringPiece(cert->nickname);
113 PK11_FreeSlotListElement(slots_for_cert.get(), slot_element);
114 return true;
115 }
116 }
117 DVLOG(2) << "cert from " << CertSlotsString(cert)
118 << " filtered: " << base::StringPiece(cert->nickname);
119 return false;
120 }
121
122 NSSProfileFilterChromeOS::CertNotAllowedForProfilePredicate::
CertNotAllowedForProfilePredicate(const NSSProfileFilterChromeOS & filter)123 CertNotAllowedForProfilePredicate(const NSSProfileFilterChromeOS& filter)
124 : filter_(filter) {}
125
operator ()(const scoped_refptr<X509Certificate> & cert) const126 bool NSSProfileFilterChromeOS::CertNotAllowedForProfilePredicate::operator()(
127 const scoped_refptr<X509Certificate>& cert) const {
128 return !filter_.IsCertAllowed(cert->os_cert_handle());
129 }
130
131 NSSProfileFilterChromeOS::ModuleNotAllowedForProfilePredicate::
ModuleNotAllowedForProfilePredicate(const NSSProfileFilterChromeOS & filter)132 ModuleNotAllowedForProfilePredicate(const NSSProfileFilterChromeOS& filter)
133 : filter_(filter) {}
134
operator ()(const scoped_refptr<CryptoModule> & module) const135 bool NSSProfileFilterChromeOS::ModuleNotAllowedForProfilePredicate::operator()(
136 const scoped_refptr<CryptoModule>& module) const {
137 return !filter_.IsModuleAllowed(module->os_module_handle());
138 }
139
140 } // namespace net
141
142