| // Copyright (c) 2006-2010 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "net/base/x509_cert_types.h" |
| |
| #include <ostream> |
| |
| #include "net/base/x509_certificate.h" |
| #include "base/logging.h" |
| |
| namespace net { |
| |
| bool match(const std::string &str, const std::string &against) { |
| // TODO(snej): Use the full matching rules specified in RFC 5280 sec. 7.1 |
| // including trimming and case-folding: <http://www.ietf.org/rfc/rfc5280.txt>. |
| return against == str; |
| } |
| |
| bool match(const std::vector<std::string> &rdn1, |
| const std::vector<std::string> &rdn2) { |
| // "Two relative distinguished names RDN1 and RDN2 match if they have the |
| // same number of naming attributes and for each naming attribute in RDN1 |
| // there is a matching naming attribute in RDN2." --RFC 5280 sec. 7.1. |
| if (rdn1.size() != rdn2.size()) |
| return false; |
| for (unsigned i1 = 0; i1 < rdn1.size(); ++i1) { |
| unsigned i2; |
| for (i2 = 0; i2 < rdn2.size(); ++i2) { |
| if (match(rdn1[i1], rdn2[i2])) |
| break; |
| } |
| if (i2 == rdn2.size()) |
| return false; |
| } |
| return true; |
| } |
| |
| CertPrincipal::CertPrincipal() { |
| } |
| |
| CertPrincipal::CertPrincipal(const std::string& name) : common_name(name) {} |
| |
| CertPrincipal::~CertPrincipal() { |
| } |
| |
| bool CertPrincipal::Matches(const CertPrincipal& against) const { |
| return match(common_name, against.common_name) && |
| match(common_name, against.common_name) && |
| match(locality_name, against.locality_name) && |
| match(state_or_province_name, against.state_or_province_name) && |
| match(country_name, against.country_name) && |
| match(street_addresses, against.street_addresses) && |
| match(organization_names, against.organization_names) && |
| match(organization_unit_names, against.organization_unit_names) && |
| match(domain_components, against.domain_components); |
| } |
| |
| std::string CertPrincipal::GetDisplayName() const { |
| if (!common_name.empty()) |
| return common_name; |
| if (!organization_names.empty()) |
| return organization_names[0]; |
| if (!organization_unit_names.empty()) |
| return organization_unit_names[0]; |
| |
| return std::string(); |
| } |
| |
| std::ostream& operator<<(std::ostream& s, const CertPrincipal& p) { |
| s << "CertPrincipal["; |
| if (!p.common_name.empty()) |
| s << "cn=\"" << p.common_name << "\" "; |
| for (unsigned i = 0; i < p.street_addresses.size(); ++i) |
| s << "street=\"" << p.street_addresses[i] << "\" "; |
| if (!p.locality_name.empty()) |
| s << "l=\"" << p.locality_name << "\" "; |
| for (unsigned i = 0; i < p.organization_names.size(); ++i) |
| s << "o=\"" << p.organization_names[i] << "\" "; |
| for (unsigned i = 0; i < p.organization_unit_names.size(); ++i) |
| s << "ou=\"" << p.organization_unit_names[i] << "\" "; |
| if (!p.state_or_province_name.empty()) |
| s << "st=\"" << p.state_or_province_name << "\" "; |
| if (!p.country_name.empty()) |
| s << "c=\"" << p.country_name << "\" "; |
| for (unsigned i = 0; i < p.domain_components.size(); ++i) |
| s << "dc=\"" << p.domain_components[i] << "\" "; |
| return s << "]"; |
| } |
| |
| CertPolicy::CertPolicy() { |
| } |
| |
| CertPolicy::~CertPolicy() { |
| } |
| |
| CertPolicy::Judgment CertPolicy::Check( |
| X509Certificate* cert) const { |
| // It shouldn't matter which set we check first, but we check denied first |
| // in case something strange has happened. |
| |
| if (denied_.find(cert->fingerprint()) != denied_.end()) { |
| // DCHECK that the order didn't matter. |
| DCHECK(allowed_.find(cert->fingerprint()) == allowed_.end()); |
| return DENIED; |
| } |
| |
| if (allowed_.find(cert->fingerprint()) != allowed_.end()) { |
| // DCHECK that the order didn't matter. |
| DCHECK(denied_.find(cert->fingerprint()) == denied_.end()); |
| return ALLOWED; |
| } |
| |
| // We don't have a policy for this cert. |
| return UNKNOWN; |
| } |
| |
| void CertPolicy::Allow(X509Certificate* cert) { |
| // Put the cert in the allowed set and (maybe) remove it from the denied set. |
| denied_.erase(cert->fingerprint()); |
| allowed_.insert(cert->fingerprint()); |
| } |
| |
| void CertPolicy::Deny(X509Certificate* cert) { |
| // Put the cert in the denied set and (maybe) remove it from the allowed set. |
| allowed_.erase(cert->fingerprint()); |
| denied_.insert(cert->fingerprint()); |
| } |
| |
| bool CertPolicy::HasAllowedCert() const { |
| return !allowed_.empty(); |
| } |
| |
| bool CertPolicy::HasDeniedCert() const { |
| return !denied_.empty(); |
| } |
| |
| } // namespace net |