• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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