1 // Copyright 2015 The Chromium Authors
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/pki/name_constraints.h"
6
7 #include <limits.h>
8
9 #include <memory>
10
11 #include "base/numerics/clamped_math.h"
12 #include "net/cert/pki/cert_errors.h"
13 #include "net/cert/pki/common_cert_errors.h"
14 #include "net/cert/pki/string_util.h"
15 #include "net/cert/pki/verify_name_match.h"
16 #include "net/der/input.h"
17 #include "net/der/parser.h"
18 #include "net/der/tag.h"
19 #include "third_party/abseil-cpp/absl/types/optional.h"
20
21 namespace net {
22
23 namespace {
24
25 // The name types of GeneralName that are fully supported in name constraints.
26 //
27 // (The other types will have the minimal checking described by RFC 5280
28 // section 4.2.1.10: If a name constraints extension that is marked as critical
29 // imposes constraints on a particular name form, and an instance of
30 // that name form appears in the subject field or subjectAltName
31 // extension of a subsequent certificate, then the application MUST
32 // either process the constraint or reject the certificate.)
33 const int kSupportedNameTypes = GENERAL_NAME_DNS_NAME |
34 GENERAL_NAME_DIRECTORY_NAME |
35 GENERAL_NAME_IP_ADDRESS;
36
37 // Controls wildcard handling of DNSNameMatches.
38 // If WildcardMatchType is WILDCARD_PARTIAL_MATCH "*.bar.com" is considered to
39 // match the constraint "foo.bar.com". If it is WILDCARD_FULL_MATCH, "*.bar.com"
40 // will match "bar.com" but not "foo.bar.com".
41 enum WildcardMatchType { WILDCARD_PARTIAL_MATCH, WILDCARD_FULL_MATCH };
42
43 // Returns true if |name| falls in the subtree defined by |dns_constraint|.
44 // RFC 5280 section 4.2.1.10:
45 // DNS name restrictions are expressed as host.example.com. Any DNS
46 // name that can be constructed by simply adding zero or more labels
47 // to the left-hand side of the name satisfies the name constraint. For
48 // example, www.host.example.com would satisfy the constraint but
49 // host1.example.com would not.
50 //
51 // |wildcard_matching| controls handling of wildcard names (|name| starts with
52 // "*."). Wildcard handling is not specified by RFC 5280, but certificate
53 // verification allows it, name constraints must check it similarly.
DNSNameMatches(std::string_view name,std::string_view dns_constraint,WildcardMatchType wildcard_matching)54 bool DNSNameMatches(std::string_view name,
55 std::string_view dns_constraint,
56 WildcardMatchType wildcard_matching) {
57 // Everything matches the empty DNS name constraint.
58 if (dns_constraint.empty())
59 return true;
60
61 // Normalize absolute DNS names by removing the trailing dot, if any.
62 if (!name.empty() && *name.rbegin() == '.')
63 name.remove_suffix(1);
64 if (!dns_constraint.empty() && *dns_constraint.rbegin() == '.')
65 dns_constraint.remove_suffix(1);
66
67 // Wildcard partial-match handling ("*.bar.com" matching name constraint
68 // "foo.bar.com"). This only handles the case where the the dnsname and the
69 // constraint match after removing the leftmost label, otherwise it is handled
70 // by falling through to the check of whether the dnsname is fully within or
71 // fully outside of the constraint.
72 if (wildcard_matching == WILDCARD_PARTIAL_MATCH && name.size() > 2 &&
73 name[0] == '*' && name[1] == '.') {
74 size_t dns_constraint_dot_pos = dns_constraint.find('.');
75 if (dns_constraint_dot_pos != std::string::npos) {
76 std::string_view dns_constraint_domain =
77 dns_constraint.substr(dns_constraint_dot_pos + 1);
78 std::string_view wildcard_domain = name.substr(2);
79 if (net::string_util::IsEqualNoCase(wildcard_domain,
80 dns_constraint_domain)) {
81 return true;
82 }
83 }
84 }
85
86 if (!net::string_util::EndsWithNoCase(name, dns_constraint)) {
87 return false;
88 }
89
90 // Exact match.
91 if (name.size() == dns_constraint.size())
92 return true;
93 // If dNSName constraint starts with a dot, only subdomains should match.
94 // (e.g., "foo.bar.com" matches constraint ".bar.com", but "bar.com" doesn't.)
95 // RFC 5280 is ambiguous, but this matches the behavior of other platforms.
96 if (!dns_constraint.empty() && dns_constraint[0] == '.')
97 dns_constraint.remove_prefix(1);
98 // Subtree match.
99 if (name.size() > dns_constraint.size() &&
100 name[name.size() - dns_constraint.size() - 1] == '.') {
101 return true;
102 }
103 // Trailing text matches, but not in a subtree (e.g., "foobar.com" is not a
104 // match for "bar.com").
105 return false;
106 }
107
108 // Parses a GeneralSubtrees |value| and store the contents in |subtrees|.
109 // The individual values stored into |subtrees| are not validated by this
110 // function.
111 // NOTE: |subtrees| is not pre-initialized by the function(it is expected to be
112 // a default initialized object), and it will be modified regardless of the
113 // return value.
ParseGeneralSubtrees(const der::Input & value,GeneralNames * subtrees,CertErrors * errors)114 [[nodiscard]] bool ParseGeneralSubtrees(const der::Input& value,
115 GeneralNames* subtrees,
116 CertErrors* errors) {
117 DCHECK(errors);
118
119 // GeneralSubtrees ::= SEQUENCE SIZE (1..MAX) OF GeneralSubtree
120 //
121 // GeneralSubtree ::= SEQUENCE {
122 // base GeneralName,
123 // minimum [0] BaseDistance DEFAULT 0,
124 // maximum [1] BaseDistance OPTIONAL }
125 //
126 // BaseDistance ::= INTEGER (0..MAX)
127 der::Parser sequence_parser(value);
128 // The GeneralSubtrees sequence should have at least 1 element.
129 if (!sequence_parser.HasMore())
130 return false;
131 while (sequence_parser.HasMore()) {
132 der::Parser subtree_sequence;
133 if (!sequence_parser.ReadSequence(&subtree_sequence))
134 return false;
135
136 der::Input raw_general_name;
137 if (!subtree_sequence.ReadRawTLV(&raw_general_name))
138 return false;
139
140 if (!ParseGeneralName(raw_general_name,
141 GeneralNames::IP_ADDRESS_AND_NETMASK, subtrees,
142 errors)) {
143 errors->AddError(kFailedParsingGeneralName);
144 return false;
145 }
146
147 // RFC 5280 section 4.2.1.10:
148 // Within this profile, the minimum and maximum fields are not used with any
149 // name forms, thus, the minimum MUST be zero, and maximum MUST be absent.
150 // However, if an application encounters a critical name constraints
151 // extension that specifies other values for minimum or maximum for a name
152 // form that appears in a subsequent certificate, the application MUST
153 // either process these fields or reject the certificate.
154
155 // Note that technically failing here isn't required: rather only need to
156 // fail if a name of this type actually appears in a subsequent cert and
157 // this extension was marked critical. However the minimum and maximum
158 // fields appear uncommon enough that implementing that isn't useful.
159 if (subtree_sequence.HasMore())
160 return false;
161 }
162 return true;
163 }
164
165 } // namespace
166
167 NameConstraints::~NameConstraints() = default;
168
169 // static
Create(const der::Input & extension_value,bool is_critical,CertErrors * errors)170 std::unique_ptr<NameConstraints> NameConstraints::Create(
171 const der::Input& extension_value,
172 bool is_critical,
173 CertErrors* errors) {
174 DCHECK(errors);
175
176 auto name_constraints = std::make_unique<NameConstraints>();
177 if (!name_constraints->Parse(extension_value, is_critical, errors))
178 return nullptr;
179 return name_constraints;
180 }
181
Parse(const der::Input & extension_value,bool is_critical,CertErrors * errors)182 bool NameConstraints::Parse(const der::Input& extension_value,
183 bool is_critical,
184 CertErrors* errors) {
185 DCHECK(errors);
186
187 der::Parser extension_parser(extension_value);
188 der::Parser sequence_parser;
189
190 // NameConstraints ::= SEQUENCE {
191 // permittedSubtrees [0] GeneralSubtrees OPTIONAL,
192 // excludedSubtrees [1] GeneralSubtrees OPTIONAL }
193 if (!extension_parser.ReadSequence(&sequence_parser))
194 return false;
195 if (extension_parser.HasMore())
196 return false;
197
198 absl::optional<der::Input> permitted_subtrees_value;
199 if (!sequence_parser.ReadOptionalTag(der::ContextSpecificConstructed(0),
200 &permitted_subtrees_value)) {
201 return false;
202 }
203 if (permitted_subtrees_value &&
204 !ParseGeneralSubtrees(permitted_subtrees_value.value(),
205 &permitted_subtrees_, errors)) {
206 return false;
207 }
208 constrained_name_types_ |=
209 permitted_subtrees_.present_name_types &
210 (is_critical ? GENERAL_NAME_ALL_TYPES : kSupportedNameTypes);
211
212 absl::optional<der::Input> excluded_subtrees_value;
213 if (!sequence_parser.ReadOptionalTag(der::ContextSpecificConstructed(1),
214 &excluded_subtrees_value)) {
215 return false;
216 }
217 if (excluded_subtrees_value &&
218 !ParseGeneralSubtrees(excluded_subtrees_value.value(),
219 &excluded_subtrees_, errors)) {
220 return false;
221 }
222 constrained_name_types_ |=
223 excluded_subtrees_.present_name_types &
224 (is_critical ? GENERAL_NAME_ALL_TYPES : kSupportedNameTypes);
225
226 // RFC 5280 section 4.2.1.10:
227 // Conforming CAs MUST NOT issue certificates where name constraints is an
228 // empty sequence. That is, either the permittedSubtrees field or the
229 // excludedSubtrees MUST be present.
230 if (!permitted_subtrees_value && !excluded_subtrees_value)
231 return false;
232
233 if (sequence_parser.HasMore())
234 return false;
235
236 return true;
237 }
238
IsPermittedCert(const der::Input & subject_rdn_sequence,const GeneralNames * subject_alt_names,CertErrors * errors) const239 void NameConstraints::IsPermittedCert(const der::Input& subject_rdn_sequence,
240 const GeneralNames* subject_alt_names,
241 CertErrors* errors) const {
242 // Checking NameConstraints is O(number_of_names * number_of_constraints).
243 // Impose a hard limit to mitigate the use of name constraints as a DoS
244 // mechanism.
245 const size_t kMaxChecks = 1048576; // 1 << 20
246 base::ClampedNumeric<size_t> check_count = 0;
247
248 if (subject_alt_names) {
249 check_count +=
250 base::ClampMul(subject_alt_names->dns_names.size(),
251 base::ClampAdd(excluded_subtrees_.dns_names.size(),
252 permitted_subtrees_.dns_names.size()));
253 check_count += base::ClampMul(
254 subject_alt_names->directory_names.size(),
255 base::ClampAdd(excluded_subtrees_.directory_names.size(),
256 permitted_subtrees_.directory_names.size()));
257 check_count += base::ClampMul(
258 subject_alt_names->ip_addresses.size(),
259 base::ClampAdd(excluded_subtrees_.ip_address_ranges.size(),
260 permitted_subtrees_.ip_address_ranges.size()));
261 }
262
263 if (!(subject_alt_names && subject_rdn_sequence.Length() == 0)) {
264 check_count += base::ClampAdd(excluded_subtrees_.directory_names.size(),
265 permitted_subtrees_.directory_names.size());
266 }
267
268 if (check_count > kMaxChecks) {
269 errors->AddError(cert_errors::kTooManyNameConstraintChecks);
270 return;
271 }
272
273 // Subject Alternative Name handling:
274 //
275 // RFC 5280 section 4.2.1.6:
276 // id-ce-subjectAltName OBJECT IDENTIFIER ::= { id-ce 17 }
277 //
278 // SubjectAltName ::= GeneralNames
279 //
280 // GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
281
282 if (subject_alt_names) {
283 // Check unsupported name types:
284 // constrained_name_types() for the unsupported types will only be true if
285 // that type of name was present in a name constraint that was marked
286 // critical.
287 //
288 // RFC 5280 section 4.2.1.10:
289 // If a name constraints extension that is marked as critical
290 // imposes constraints on a particular name form, and an instance of
291 // that name form appears in the subject field or subjectAltName
292 // extension of a subsequent certificate, then the application MUST
293 // either process the constraint or reject the certificate.
294 if (constrained_name_types() & subject_alt_names->present_name_types &
295 ~kSupportedNameTypes) {
296 errors->AddError(cert_errors::kNotPermittedByNameConstraints);
297 return;
298 }
299
300 // Check supported name types:
301 for (const auto& dns_name : subject_alt_names->dns_names) {
302 if (!IsPermittedDNSName(dns_name)) {
303 errors->AddError(cert_errors::kNotPermittedByNameConstraints);
304 return;
305 }
306 }
307
308 for (const auto& directory_name : subject_alt_names->directory_names) {
309 if (!IsPermittedDirectoryName(directory_name)) {
310 errors->AddError(cert_errors::kNotPermittedByNameConstraints);
311 return;
312 }
313 }
314
315 for (const auto& ip_address : subject_alt_names->ip_addresses) {
316 if (!IsPermittedIP(ip_address)) {
317 errors->AddError(cert_errors::kNotPermittedByNameConstraints);
318 return;
319 }
320 }
321 }
322
323 // Subject handling:
324
325 // RFC 5280 section 4.2.1.10:
326 // Legacy implementations exist where an electronic mail address is embedded
327 // in the subject distinguished name in an attribute of type emailAddress
328 // (Section 4.1.2.6). When constraints are imposed on the rfc822Name name
329 // form, but the certificate does not include a subject alternative name, the
330 // rfc822Name constraint MUST be applied to the attribute of type emailAddress
331 // in the subject distinguished name.
332 if (!subject_alt_names &&
333 (constrained_name_types() & GENERAL_NAME_RFC822_NAME)) {
334 bool contained_email_address = false;
335 if (!NameContainsEmailAddress(subject_rdn_sequence,
336 &contained_email_address)) {
337 errors->AddError(cert_errors::kNotPermittedByNameConstraints);
338 return;
339 }
340 if (contained_email_address) {
341 errors->AddError(cert_errors::kNotPermittedByNameConstraints);
342 return;
343 }
344 }
345
346 // RFC 5280 4.1.2.6:
347 // If subject naming information is present only in the subjectAltName
348 // extension (e.g., a key bound only to an email address or URI), then the
349 // subject name MUST be an empty sequence and the subjectAltName extension
350 // MUST be critical.
351 // This code assumes that criticality condition is checked by the caller, and
352 // therefore only needs to avoid the IsPermittedDirectoryName check against an
353 // empty subject in such a case.
354 if (subject_alt_names && subject_rdn_sequence.Length() == 0)
355 return;
356
357 if (!IsPermittedDirectoryName(subject_rdn_sequence)) {
358 errors->AddError(cert_errors::kNotPermittedByNameConstraints);
359 return;
360 }
361 }
362
IsPermittedDNSName(std::string_view name) const363 bool NameConstraints::IsPermittedDNSName(std::string_view name) const {
364 for (const auto& excluded_name : excluded_subtrees_.dns_names) {
365 // When matching wildcard hosts against excluded subtrees, consider it a
366 // match if the constraint would match any expansion of the wildcard. Eg,
367 // *.bar.com should match a constraint of foo.bar.com.
368 if (DNSNameMatches(name, excluded_name, WILDCARD_PARTIAL_MATCH))
369 return false;
370 }
371
372 // If permitted subtrees are not constrained, any name that is not excluded is
373 // allowed.
374 if (!(permitted_subtrees_.present_name_types & GENERAL_NAME_DNS_NAME))
375 return true;
376
377 for (const auto& permitted_name : permitted_subtrees_.dns_names) {
378 // When matching wildcard hosts against permitted subtrees, consider it a
379 // match only if the constraint would match all expansions of the wildcard.
380 // Eg, *.bar.com should match a constraint of bar.com, but not foo.bar.com.
381 if (DNSNameMatches(name, permitted_name, WILDCARD_FULL_MATCH))
382 return true;
383 }
384
385 return false;
386 }
387
IsPermittedDirectoryName(const der::Input & name_rdn_sequence) const388 bool NameConstraints::IsPermittedDirectoryName(
389 const der::Input& name_rdn_sequence) const {
390 for (const auto& excluded_name : excluded_subtrees_.directory_names) {
391 if (VerifyNameInSubtree(name_rdn_sequence, excluded_name))
392 return false;
393 }
394
395 // If permitted subtrees are not constrained, any name that is not excluded is
396 // allowed.
397 if (!(permitted_subtrees_.present_name_types & GENERAL_NAME_DIRECTORY_NAME))
398 return true;
399
400 for (const auto& permitted_name : permitted_subtrees_.directory_names) {
401 if (VerifyNameInSubtree(name_rdn_sequence, permitted_name))
402 return true;
403 }
404
405 return false;
406 }
407
IsPermittedIP(const IPAddress & ip) const408 bool NameConstraints::IsPermittedIP(const IPAddress& ip) const {
409 for (const auto& excluded_ip : excluded_subtrees_.ip_address_ranges) {
410 if (IPAddressMatchesPrefix(ip, excluded_ip.first, excluded_ip.second))
411 return false;
412 }
413
414 // If permitted subtrees are not constrained, any name that is not excluded is
415 // allowed.
416 if (!(permitted_subtrees_.present_name_types & GENERAL_NAME_IP_ADDRESS))
417 return true;
418
419 for (const auto& permitted_ip : permitted_subtrees_.ip_address_ranges) {
420 if (IPAddressMatchesPrefix(ip, permitted_ip.first, permitted_ip.second))
421 return true;
422 }
423
424 return false;
425 }
426
427 } // namespace net
428