Home | History | Annotate | Download | only in cert
      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 
     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 
     36 NSSProfileFilterChromeOS::NSSProfileFilterChromeOS() {}
     37 
     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   system_slot_.reset(
     47       other.system_slot_ ? PK11_ReferenceSlot(other.system_slot_.get()) : NULL);
     48 }
     49 
     50 NSSProfileFilterChromeOS::~NSSProfileFilterChromeOS() {}
     51 
     52 NSSProfileFilterChromeOS& NSSProfileFilterChromeOS::operator=(
     53     const NSSProfileFilterChromeOS& other) {
     54   public_slot_.reset(other.public_slot_ ?
     55       PK11_ReferenceSlot(other.public_slot_.get()) :
     56       NULL);
     57   private_slot_.reset(other.private_slot_ ?
     58       PK11_ReferenceSlot(other.private_slot_.get()) :
     59       NULL);
     60   system_slot_.reset(
     61       other.system_slot_ ? PK11_ReferenceSlot(other.system_slot_.get()) : NULL);
     62   return *this;
     63 }
     64 
     65 void NSSProfileFilterChromeOS::Init(crypto::ScopedPK11Slot public_slot,
     66                                     crypto::ScopedPK11Slot private_slot,
     67                                     crypto::ScopedPK11Slot system_slot) {
     68   // crypto::ScopedPK11Slot actually holds a reference counted object.
     69   // Because scoped_ptr<T> assignment is a no-op if it already points to
     70   // the same pointer, a reference would be leaked because .Pass() does
     71   // not release its reference, and the receiving object won't free
     72   // its copy.
     73   if (public_slot_.get() != public_slot.get())
     74     public_slot_ = public_slot.Pass();
     75   if (private_slot_.get() != private_slot.get())
     76     private_slot_ = private_slot.Pass();
     77   if (system_slot_.get() != system_slot.get())
     78     system_slot_ = system_slot.Pass();
     79 }
     80 
     81 bool NSSProfileFilterChromeOS::IsModuleAllowed(PK11SlotInfo* slot) const {
     82   // If this is one of the public/private slots for this profile or the system
     83   // slot, allow it.
     84   if (slot == public_slot_.get() || slot == private_slot_.get() ||
     85       slot == system_slot_.get()) {
     86     return true;
     87   }
     88   // Allow the root certs module.
     89   if (PK11_HasRootCerts(slot))
     90     return true;
     91   // If it's from the read-only slots, allow it.
     92   if (PK11_IsInternal(slot) && !PK11_IsRemovable(slot))
     93     return true;
     94   // If |public_slot_| or |private_slot_| is null, there isn't a way to get the
     95   // modules to use in the final test.
     96   if (!public_slot_.get() || !private_slot_.get())
     97     return false;
     98   // If this is not the internal (file-system) module or the TPM module, allow
     99   // it. This would allow smartcards/etc, although ChromeOS doesn't currently
    100   // support that. (This assumes that private_slot_ and system_slot_ are on the
    101   // same module.)
    102   DCHECK(!system_slot_.get() ||
    103          PK11_GetModule(private_slot_.get()) ==
    104              PK11_GetModule(system_slot_.get()));
    105   SECMODModule* module_for_slot = PK11_GetModule(slot);
    106   if (module_for_slot != PK11_GetModule(public_slot_.get()) &&
    107       module_for_slot != PK11_GetModule(private_slot_.get())) {
    108     return true;
    109   }
    110   return false;
    111 }
    112 
    113 bool NSSProfileFilterChromeOS::IsCertAllowed(CERTCertificate* cert) const {
    114   crypto::ScopedPK11SlotList slots_for_cert(
    115       PK11_GetAllSlotsForCert(cert, NULL));
    116   if (!slots_for_cert) {
    117     DVLOG(2) << "cert no slots: " << base::StringPiece(cert->nickname);
    118     return false;
    119   }
    120 
    121   for (PK11SlotListElement* slot_element =
    122            PK11_GetFirstSafe(slots_for_cert.get());
    123        slot_element;
    124        slot_element =
    125            PK11_GetNextSafe(slots_for_cert.get(), slot_element, PR_FALSE)) {
    126     if (IsModuleAllowed(slot_element->slot)) {
    127       DVLOG(3) << "cert from " << CertSlotsString(cert)
    128                << " allowed: " << base::StringPiece(cert->nickname);
    129       PK11_FreeSlotListElement(slots_for_cert.get(), slot_element);
    130       return true;
    131     }
    132   }
    133   DVLOG(2) << "cert from " << CertSlotsString(cert)
    134            << " filtered: " << base::StringPiece(cert->nickname);
    135   return false;
    136 }
    137 
    138 NSSProfileFilterChromeOS::CertNotAllowedForProfilePredicate::
    139     CertNotAllowedForProfilePredicate(const NSSProfileFilterChromeOS& filter)
    140     : filter_(filter) {}
    141 
    142 bool NSSProfileFilterChromeOS::CertNotAllowedForProfilePredicate::operator()(
    143     const scoped_refptr<X509Certificate>& cert) const {
    144   return !filter_.IsCertAllowed(cert->os_cert_handle());
    145 }
    146 
    147 NSSProfileFilterChromeOS::ModuleNotAllowedForProfilePredicate::
    148     ModuleNotAllowedForProfilePredicate(const NSSProfileFilterChromeOS& filter)
    149     : filter_(filter) {}
    150 
    151 bool NSSProfileFilterChromeOS::ModuleNotAllowedForProfilePredicate::operator()(
    152     const scoped_refptr<CryptoModule>& module) const {
    153   return !filter_.IsModuleAllowed(module->os_module_handle());
    154 }
    155 
    156 }  // namespace net
    157 
    158