1 // Copyright 2013 The Chromium Authors
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 <memory>
8 #include <utility>
9
10 #include "base/logging.h"
11 #include "net/cert/x509_certificate.h"
12
13 namespace net {
14
15 NSSProfileFilterChromeOS::NSSProfileFilterChromeOS() = default;
16
NSSProfileFilterChromeOS(const NSSProfileFilterChromeOS & other)17 NSSProfileFilterChromeOS::NSSProfileFilterChromeOS(
18 const NSSProfileFilterChromeOS& other) {
19 public_slot_.reset(other.public_slot_
20 ? PK11_ReferenceSlot(other.public_slot_.get())
21 : nullptr);
22 private_slot_.reset(other.private_slot_
23 ? PK11_ReferenceSlot(other.private_slot_.get())
24 : nullptr);
25 system_slot_.reset(other.system_slot_
26 ? PK11_ReferenceSlot(other.system_slot_.get())
27 : nullptr);
28 }
29
30 NSSProfileFilterChromeOS::~NSSProfileFilterChromeOS() = default;
31
operator =(const NSSProfileFilterChromeOS & other)32 NSSProfileFilterChromeOS& NSSProfileFilterChromeOS::operator=(
33 const NSSProfileFilterChromeOS& other) {
34 public_slot_.reset(other.public_slot_
35 ? PK11_ReferenceSlot(other.public_slot_.get())
36 : nullptr);
37 private_slot_.reset(other.private_slot_
38 ? PK11_ReferenceSlot(other.private_slot_.get())
39 : nullptr);
40 system_slot_.reset(other.system_slot_
41 ? PK11_ReferenceSlot(other.system_slot_.get())
42 : nullptr);
43 return *this;
44 }
45
Init(crypto::ScopedPK11Slot public_slot,crypto::ScopedPK11Slot private_slot,crypto::ScopedPK11Slot system_slot)46 void NSSProfileFilterChromeOS::Init(crypto::ScopedPK11Slot public_slot,
47 crypto::ScopedPK11Slot private_slot,
48 crypto::ScopedPK11Slot system_slot) {
49 // crypto::ScopedPK11Slot actually holds a reference counted object.
50 // Because std::unique_ptr<T> assignment is a no-op if it already points to
51 // the same pointer, a reference would be leaked because std::move() does
52 // not release its reference, and the receiving object won't free
53 // its copy.
54 // TODO(dcheng): This comment doesn't seem quite right.
55 if (public_slot_.get() != public_slot.get())
56 public_slot_ = std::move(public_slot);
57 if (private_slot_.get() != private_slot.get())
58 private_slot_ = std::move(private_slot);
59 if (system_slot_.get() != system_slot.get())
60 system_slot_ = std::move(system_slot);
61 }
62
IsModuleAllowed(PK11SlotInfo * slot) const63 bool NSSProfileFilterChromeOS::IsModuleAllowed(PK11SlotInfo* slot) const {
64 // If this is one of the public/private slots for this profile or the system
65 // slot, allow it.
66 if (slot == public_slot_.get() || slot == private_slot_.get() ||
67 slot == system_slot_.get()) {
68 return true;
69 }
70 // Allow the root certs module.
71 if (PK11_HasRootCerts(slot))
72 return true;
73 // If it's from the read-only slots, allow it.
74 if (PK11_IsInternal(slot) && !PK11_IsRemovable(slot))
75 return true;
76 // If |public_slot_| or |private_slot_| is null, there isn't a way to get the
77 // modules to use in the final test.
78 if (!public_slot_.get() || !private_slot_.get())
79 return false;
80 // If this is not the internal (file-system) module or the TPM module, allow
81 // it. This would allow smartcards/etc, although ChromeOS doesn't currently
82 // support that. (This assumes that private_slot_ and system_slot_ are on the
83 // same module.)
84 DCHECK(!system_slot_.get() ||
85 PK11_GetModule(private_slot_.get()) ==
86 PK11_GetModule(system_slot_.get()));
87 SECMODModule* module_for_slot = PK11_GetModule(slot);
88 if (module_for_slot != PK11_GetModule(public_slot_.get()) &&
89 module_for_slot != PK11_GetModule(private_slot_.get())) {
90 return true;
91 }
92 return false;
93 }
94
IsCertAllowed(CERTCertificate * cert) const95 bool NSSProfileFilterChromeOS::IsCertAllowed(CERTCertificate* cert) const {
96 crypto::ScopedPK11SlotList slots_for_cert(
97 PK11_GetAllSlotsForCert(cert, nullptr));
98 if (!slots_for_cert)
99 return false;
100
101 for (PK11SlotListElement* slot_element =
102 PK11_GetFirstSafe(slots_for_cert.get());
103 slot_element;
104 slot_element =
105 PK11_GetNextSafe(slots_for_cert.get(), slot_element, PR_FALSE)) {
106 if (IsModuleAllowed(slot_element->slot)) {
107 PK11_FreeSlotListElement(slots_for_cert.get(), slot_element);
108 return true;
109 }
110 }
111
112 return false;
113 }
114
115 } // namespace net
116