// Copyright 2015 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. #ifndef NET_CERT_INTERNAL_NAME_CONSTRAINTS_H_ #define NET_CERT_INTERNAL_NAME_CONSTRAINTS_H_ #include #include #include #include "base/compiler_specific.h" #include "net/base/ip_address.h" #include "net/base/net_export.h" namespace net { namespace der { class Input; } // namespace der // Bitfield values for the GeneralName types defined in RFC 5280. The ordering // and exact values are not important, but match the order from the RFC for // convenience. enum GeneralNameTypes { GENERAL_NAME_NONE = 0, GENERAL_NAME_OTHER_NAME = 1 << 0, GENERAL_NAME_RFC822_NAME = 1 << 1, GENERAL_NAME_DNS_NAME = 1 << 2, GENERAL_NAME_X400_ADDRESS = 1 << 3, GENERAL_NAME_DIRECTORY_NAME = 1 << 4, GENERAL_NAME_EDI_PARTY_NAME = 1 << 5, GENERAL_NAME_UNIFORM_RESOURCE_IDENTIFIER = 1 << 6, GENERAL_NAME_IP_ADDRESS = 1 << 7, GENERAL_NAME_REGISTERED_ID = 1 << 8, }; // Represents a GeneralNames structure. When processing GeneralNames, it is // often necessary to know which types of names were present, and to check // all the names of a certain type. Therefore, a bitfield of all the name // types is kept, and the names are split into members for each type. Only // name types that are handled by this code are stored (though all types are // recorded in the bitfield.) // TODO(mattm): move this to some other file? struct NET_EXPORT GeneralNames { GeneralNames(); ~GeneralNames(); // Create a GeneralNames object representing the DER-encoded // |general_names_tlv|. static std::unique_ptr Create( const der::Input& general_names_tlv); // ASCII hostnames. std::vector dns_names; // DER-encoded Name values (not including the Sequence tag). std::vector> directory_names; // iPAddresses as sequences of octets in network byte order. This will be // populated if the GeneralNames represents a Subject Alternative Name. std::vector ip_addresses; // iPAddress ranges, as pairs. This will be populated // if the GeneralNames represents a Name Constraints. std::vector> ip_address_ranges; // Which name types were present, as a bitfield of GeneralNameTypes. // Includes both the supported and unsupported types (although unsupported // ones may not be recorded depending on the context, like non-critical name // constraints.) int present_name_types = GENERAL_NAME_NONE; }; // Parses a NameConstraints extension value and allows testing whether names are // allowed under those constraints as defined by RFC 5280 section 4.2.1.10. class NET_EXPORT NameConstraints { public: ~NameConstraints(); // Parses a DER-encoded NameConstraints extension and initializes this object. // |extension_value| should be the extnValue from the extension (not including // the OCTET STRING tag). |is_critical| should be true if the extension was // marked critical. Returns nullptr if parsing the the extension failed. // The object lifetime is not bound to the lifetime of |extension_value| data. static std::unique_ptr Create( const der::Input& extension_value, bool is_critical); // Tests if a certificate is allowed by the name constraints. // |subject_rdn_sequence| should be the DER-encoded value of the subject's // RDNSequence (not including Sequence tag), and may be an empty ASN.1 // sequence. |subject_alt_names| should be the parsed representation of the // subjectAltName extension or nullptr if the extension was not present. // Note that this method does not check hostname or IP address in commonName, // which is deprecated (crbug.com/308330). bool IsPermittedCert(const der::Input& subject_rdn_sequence, const GeneralNames* subject_alt_names) const; // Returns true if the ASCII hostname |name| is permitted. // |name| may be a wildcard hostname (starts with "*."). Eg, "*.bar.com" // would not be permitted if "bar.com" is permitted and "foo.bar.com" is // excluded, while "*.baz.com" would only be permitted if "baz.com" is // permitted. bool IsPermittedDNSName(const std::string& name) const; // Returns true if the directoryName |name_rdn_sequence| is permitted. // |name_rdn_sequence| should be the DER-encoded RDNSequence value (not // including the Sequence tag.) bool IsPermittedDirectoryName(const der::Input& name_rdn_sequence) const; // Returns true if the iPAddress |ip| is permitted. bool IsPermittedIP(const IPAddress& ip) const; // Returns a bitfield of GeneralNameTypes of all the types constrained by this // NameConstraints. Name types that aren't supported will only be present if // the name constraint they appeared in was marked critical. // // RFC 5280 section 4.2.1.10 says: // Applications conforming to this profile MUST be able to process name // constraints that are imposed on the directoryName name form and SHOULD be // able to process name constraints that are imposed on the rfc822Name, // uniformResourceIdentifier, dNSName, and iPAddress name forms. // If a name constraints extension that is marked as critical // imposes constraints on a particular name form, and an instance of // that name form appears in the subject field or subjectAltName // extension of a subsequent certificate, then the application MUST // either process the constraint or reject the certificate. int ConstrainedNameTypes() const; private: bool Parse(const der::Input& extension_value, bool is_critical) WARN_UNUSED_RESULT; GeneralNames permitted_subtrees_; GeneralNames excluded_subtrees_; }; } // namespace net #endif // NET_CERT_INTERNAL_NAME_CONSTRAINTS_H_