Index: chrome/browser/chromeos/net/profile_cert_filter.cc |
diff --git a/chrome/browser/chromeos/net/profile_cert_filter.cc b/chrome/browser/chromeos/net/profile_cert_filter.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..80d2880ee3dfb7dd7a40ee2c11183c478d11b9d0 |
--- /dev/null |
+++ b/chrome/browser/chromeos/net/profile_cert_filter.cc |
@@ -0,0 +1,108 @@ |
+#include "chrome/browser/chromeos/net/profile_cert_filter.h" |
+ |
+#include "base/bind.h" |
+#include "base/callback.h" |
+#include "base/strings/string_number_conversions.h" |
+#include "chrome/browser/net/nss_slot_factory.h" |
+ |
+namespace { |
+ |
+std::string CertSlotsString(const scoped_refptr<net::X509Certificate>& cert) { |
+ std::string r; |
+ crypto::ScopedPK11SlotList slots_for_cert( |
+ PK11_GetAllSlotsForCert(cert->os_cert_handle(), NULL)); |
+ for (PK11SlotListElement* slot_element = |
+ PK11_GetFirstSafe(slots_for_cert.get()); |
+ slot_element; |
+ slot_element = |
+ PK11_GetNextSafe(slots_for_cert.get(), slot_element, PR_FALSE)) { |
+ if (!r.empty()) |
+ r += ','; |
+ r += base::IntToString(PK11_GetModuleID(slot_element->slot)) + ":" + |
+ base::IntToString(PK11_GetSlotID(slot_element->slot)); |
+ } |
+ return r; |
+} |
+ |
+} |
+ |
+namespace chromeos { |
+ |
+void ProfileCertFilter::Init(crypto::ScopedPK11Slot public_slot, |
+ crypto::ScopedPK11Slot private_slot) { |
+ public_slot_ = public_slot.Pass(); |
+ private_slot_ = private_slot.Pass(); |
+} |
+ |
+void ProfileCertFilter::Init(content::ResourceContext* context, |
+ const base::Closure& callback) { |
+ public_slot_ = GetPublicNSSKeySlotForResourceContext(context); |
+ OnPrivateNSSKeySlotForResourceContextReady( |
+ context, |
+ base::Bind(&ProfileCertFilter::GotPrivateSlot, |
+ base::Unretained(this), |
+ callback)); |
+} |
+ |
+bool ProfileCertFilter::IsModuleAllowed(PK11SlotInfo* slot) const { |
+ // If this is one of the public/private slots for this profile, allow it. |
+ if (slot == public_slot_.get() || slot == private_slot_.get()) |
+ return true; |
+ // If it's from the read-only slot, allow it. |
+ if (slot == PK11_GetInternalKeySlot()) |
+ return true; |
+ // If this is a completely different module, allow it. |
+ SECMODModule* module_for_slot = PK11_GetModule(slot); |
+ if (module_for_slot != PK11_GetModule(public_slot_.get()) && |
+ module_for_slot != PK11_GetModule(private_slot_.get())) |
+ return true; |
+ return false; |
+} |
+ |
+bool ProfileCertFilter::IsCertAllowed( |
+ const scoped_refptr<net::X509Certificate>& cert) const { |
+ crypto::ScopedPK11SlotList slots_for_cert( |
+ PK11_GetAllSlotsForCert(cert->os_cert_handle(), NULL)); |
+ if (!slots_for_cert) { |
+ VLOG(1) << "cert no slots: " << cert->subject().GetDisplayName(); |
+ return false; |
+ } |
+ |
+ for (PK11SlotListElement* slot_element = |
+ PK11_GetFirstSafe(slots_for_cert.get()); |
+ slot_element; |
+ slot_element = |
+ PK11_GetNextSafe(slots_for_cert.get(), slot_element, PR_FALSE)) { |
+ if (IsModuleAllowed(slot_element->slot)) { |
+ VLOG(3) << "cert allowed:" << cert->subject().GetDisplayName() |
+ << " from:" << CertSlotsString(cert); |
+ return true; |
+ } |
+ } |
+ VLOG(1) << "cert filtered:" << cert->subject().GetDisplayName() |
+ << " from:" << CertSlotsString(cert); |
+ return false; |
+} |
+ |
+ProfileCertFilter::Predicate::Predicate(const ProfileCertFilter& filter) |
+ : filter_(filter) {} |
+ |
+bool ProfileCertFilter::Predicate::operator()( |
+ const scoped_refptr<net::CryptoModule>& module) const { |
+ return !filter_.IsModuleAllowed(module->os_module_handle()); |
+} |
+ |
+bool ProfileCertFilter::Predicate::operator()( |
+ const scoped_refptr<net::X509Certificate>& cert) const { |
+ return !filter_.IsCertAllowed(cert); |
+} |
+ |
+void ProfileCertFilter::GotPrivateSlot(const base::Closure& callback, |
+ crypto::ScopedPK11Slot private_slot) { |
+ LOG(WARNING) << __func__; |
+ private_slot_ = private_slot.Pass(); |
+ callback.Run(); |
+} |
+ |
+} // namespace chromeos |
+ |