Index: net/cert/internal/verify_name_match.cc |
diff --git a/net/cert/internal/verify_name_match.cc b/net/cert/internal/verify_name_match.cc |
index 5b6cf4cbf2a4b13b75643da116902315f824a0af..d7913993090f98293397600d375eb7163382ce52 100644 |
--- a/net/cert/internal/verify_name_match.cc |
+++ b/net/cert/internal/verify_name_match.cc |
@@ -22,6 +22,17 @@ namespace net { |
namespace { |
+// RFC 5280 section A.1: |
+// |
+// pkcs-9 OBJECT IDENTIFIER ::= |
+// { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 9 } |
+// |
+// id-emailAddress AttributeType ::= { pkcs-9 1 } |
+// |
+// In dotted form: 1.2.840.113549.1.9.1 |
+const uint8_t kOidEmailAddress[] = {0x2A, 0x86, 0x48, 0x86, 0xF7, |
+ 0x0D, 0x01, 0x09, 0x01}; |
+ |
// Types of character set checking that NormalizeDirectoryString can perform. |
enum CharsetEnforcement { |
NO_ENFORCEMENT, |
@@ -389,8 +400,16 @@ bool VerifyRdnMatch(der::Parser* a_parser, der::Parser* b_parser) { |
return true; |
} |
-} // namespace |
+enum NameMatchType { |
+ EXACT_MATCH, |
+ SUBTREE_MATCH, |
+}; |
+// Verify that |a| matches |b|. If |match_type| is EXACT_MATCH, returns true if |
+// they are an exact match as defined by RFC 5280 7.1. If |match_type| is |
+// SUBTREE_MATCH, returns true if |a| is within the subtree defined by |b| as |
+// defined by RFC 5280 7.1. |
+// |
// |a| and |b| are ASN.1 RDNSequence values (not including the Sequence tag), |
// defined in RFC 5280 section 4.1.2.4: |
// |
@@ -401,7 +420,9 @@ bool VerifyRdnMatch(der::Parser* a_parser, der::Parser* b_parser) { |
// |
// RelativeDistinguishedName ::= |
// SET SIZE (1..MAX) OF AttributeTypeAndValue |
-bool VerifyNameMatch(const der::Input& a, const der::Input& b) { |
+bool VerifyNameMatchInternal(const der::Input& a, |
+ const der::Input& b, |
+ NameMatchType match_type) { |
// Empty Names are allowed. RFC 5280 section 4.1.2.4 requires "The issuer |
// field MUST contain a non-empty distinguished name (DN)", while section |
// 4.1.2.6 allows for the Subject to be empty in certain cases. The caller is |
@@ -421,7 +442,12 @@ bool VerifyNameMatch(const der::Input& a, const der::Input& b) { |
return false; |
} |
} |
- if (a_rdn_sequence_counter.HasMore() || b_rdn_sequence_counter.HasMore()) |
+ // If doing exact match and either of the sequences has more elements than the |
+ // other, not a match. If doing a subtree match, the first Name may have more |
+ // RDNs than the second. |
+ if (b_rdn_sequence_counter.HasMore()) |
+ return false; |
+ if (match_type == EXACT_MATCH && a_rdn_sequence_counter.HasMore()) |
return false; |
// Same number of RDNs, now check if they match. |
@@ -440,4 +466,42 @@ bool VerifyNameMatch(const der::Input& a, const der::Input& b) { |
return true; |
} |
+} // namespace |
+ |
+bool VerifyNameMatch(const der::Input& a_rdn_sequence, |
+ const der::Input& b_rdn_sequence) { |
+ return VerifyNameMatchInternal(a_rdn_sequence, b_rdn_sequence, EXACT_MATCH); |
+} |
+ |
+bool VerifyNameInSubtree(const der::Input& name_rdn_sequence, |
+ const der::Input& parent_rdn_sequence) { |
+ return VerifyNameMatchInternal(name_rdn_sequence, parent_rdn_sequence, |
+ SUBTREE_MATCH); |
+} |
+ |
+bool NameContainsEmailAddress(const der::Input& name_rdn_sequence, |
+ bool* contained_email_address) { |
+ der::Parser rdn_sequence_parser(name_rdn_sequence); |
+ |
+ while (rdn_sequence_parser.HasMore()) { |
+ der::Parser rdn_parser; |
+ if (!rdn_sequence_parser.ReadConstructed(der::kSet, &rdn_parser)) |
+ return false; |
+ |
+ std::vector<AttributeTypeAndValue> type_and_values; |
+ if (!ReadRdn(&rdn_parser, &type_and_values)) |
+ return false; |
+ |
+ for (const auto& type_and_value : type_and_values) { |
+ if (type_and_value.type.Equals(der::Input(kOidEmailAddress))) { |
+ *contained_email_address = true; |
+ return true; |
+ } |
+ } |
+ } |
+ |
+ *contained_email_address = false; |
+ return true; |
+} |
+ |
} // namespace net |