8#include <botan/pkix_types.h>
9#include <botan/ber_dec.h>
10#include <botan/loadstor.h>
11#include <botan/x509cert.h>
12#include <botan/parsing.h>
21 size_t p = str.find(
':');
23 if(p != std::string::npos)
25 m_type = str.substr(0, p);
26 m_name = str.substr(p + 1, std::string::npos);
78 else if(obj.
length() == 32)
95 std::vector<std::string> nam;
96 std::function<bool(
const GeneralName*,
const std::string&)> match_fn;
112 else if(
type() ==
"DN")
118 const auto alt_dn = alt_name.
dn();
119 if(alt_dn.empty() ==
false)
121 nam.push_back(alt_dn.to_string());
124 else if(
type() ==
"IP")
142 for(
const std::string& n: nam)
144 bool m = match_fn(
this, n);
169 if(nam.size() == constraint.size())
171 return issued == constraint;
173 else if(constraint.size() > nam.size())
180 if(constraint.empty()) {
184 std::string substr = issued.substr(nam.size() - constraint.size(), constraint.size());
186 if(constraint.front() ==
'.') {
187 return substr == constraint;
188 }
else if(substr[0] ==
'.') {
189 return substr.substr(1) == constraint;
191 return substr == constraint && issued[issued.size() - constraint.size() - 1] ==
'.';
198 std::stringstream ss(nam);
206 std::stringstream tt(
name());
214 for(
const auto& c: my_dn.
dn_info())
216 auto i = attr.equal_range(c.first);
218 if(i.first != i.second)
221 ret = ret && (i.first->second == c.second.value());
225 return trys > 0 && ret;
239 return (ip & mask) == net;
244 os << gn.
type() <<
":" << gn.
name();
251 const auto min = std::stoull(str, &p0, 10);
252 const auto max = std::stoull(str.substr(p0 + 1), &p1, 10);
257 m_minimum =
static_cast<size_t>(min);
258 m_maximum =
static_cast<size_t>(max);
282 m_maximum = std::numeric_limits<std::size_t>::max();
292 std::vector<GeneralSubtree>&& excluded_subtrees) :
293 m_permitted_subtrees(permitted_subtrees), m_excluded_subtrees(excluded_subtrees)
295 for(
const auto& c : m_permitted_subtrees)
297 m_permitted_name_types.insert(c.base().type());
299 for(
const auto& c : m_excluded_subtrees)
301 m_excluded_name_types.insert(c.base().type());
307bool looks_like_ipv4(
const std::string& s)
331 if(m_permitted_name_types.find(
"URI") != m_permitted_name_types.end() && !alt_name.get_attribute(
"URI").empty()) {
334 if(m_permitted_name_types.find(
"RFC822") != m_permitted_name_types.end() && !alt_name.get_attribute(
"RFC822").empty()) {
339 auto is_permitted_dn = [&](
const X509_DN& dn) {
341 if(m_permitted_name_types.find(
"DN") == m_permitted_name_types.end()) {
349 for(
const auto& c : m_permitted_subtrees) {
350 if(c.base().type() ==
"DN" && c.base().matches_dn_obj(dn)) {
359 auto is_permitted_dns_name = [&](
const std::string&
name) {
360 if(
name.empty() ||
name[0] ==
'.') {
365 if(m_permitted_name_types.find(
"DNS") == m_permitted_name_types.end()) {
369 for(
const auto& c : m_permitted_subtrees) {
370 if(c.base().type() ==
"DNS" && c.base().matches_dns(
name)) {
379 auto is_permitted_ipv4 = [&](
const std::string& ipv4) {
381 if(m_permitted_name_types.find(
"IP") == m_permitted_name_types.end()) {
385 for(
const auto& c : m_permitted_subtrees) {
386 if(c.base().type() ==
"IP" && c.base().matches_ip(ipv4)) {
399 if(!is_permitted_dn(alt_name.dn()))
404 for(
const auto& alt_dns : alt_name.get_attribute(
"DNS")) {
405 if(!is_permitted_dns_name(alt_dns)) {
410 for(
const auto& alt_ipv4 : alt_name.get_attribute(
"IP")) {
411 if(!is_permitted_ipv4(alt_ipv4)) {
416 if(!alt_name.has_items())
420 if(cn.find(
".") != std::string::npos)
422 if(looks_like_ipv4(cn))
424 if(!is_permitted_ipv4(cn))
431 if(!is_permitted_dns_name(cn))
452 if(m_excluded_name_types.find(
"URI") != m_excluded_name_types.end() && !alt_name.get_attribute(
"URI").empty()) {
455 if(m_excluded_name_types.find(
"RFC822") != m_excluded_name_types.end() && !alt_name.get_attribute(
"RFC822").empty()) {
460 auto is_excluded_dn = [&](
const X509_DN& dn) {
462 if(m_excluded_name_types.find(
"DN") == m_excluded_name_types.end()) {
470 for(
const auto& c : m_excluded_subtrees) {
471 if(c.base().type() ==
"DN" && c.base().matches_dn_obj(dn)) {
480 auto is_excluded_dns_name = [&](
const std::string&
name) {
481 if(
name.empty() ||
name[0] ==
'.') {
486 if(m_excluded_name_types.find(
"DNS") == m_excluded_name_types.end()) {
490 for(
const auto& c : m_excluded_subtrees) {
491 if(c.base().type() ==
"DNS" && c.base().matches_dns(
name)) {
500 auto is_excluded_ipv4 = [&](
const std::string& ipv4) {
502 if(m_excluded_name_types.find(
"IP") == m_excluded_name_types.end()) {
506 for(
const auto& c : m_excluded_subtrees) {
507 if(c.base().type() ==
"IP" && c.base().matches_ip(ipv4)) {
520 if(is_excluded_dn(alt_name.dn())) {
524 for(
const auto& alt_dns : alt_name.get_attribute(
"DNS")) {
525 if(is_excluded_dns_name(alt_dns)) {
530 for(
const auto& alt_ipv4 : alt_name.get_attribute(
"IP")) {
531 if(is_excluded_ipv4(alt_ipv4)) {
536 if(!alt_name.has_items())
540 if(cn.find(
".") != std::string::npos)
542 if(looks_like_ipv4(cn))
544 if(is_excluded_ipv4(cn))
551 if(is_excluded_dns_name(cn))
std::vector< std::string > get_attribute(const std::string &attr) const
BER_Decoder start_cons(ASN1_Tag type_tag, ASN1_Tag class_tag=UNIVERSAL)
BER_Object get_next_object()
BER_Decoder & decode(bool &out)
BER_Decoder & decode_optional(T &out, ASN1_Tag type_tag, ASN1_Tag class_tag, const T &default_value=T())
const uint8_t * bits() const
bool is_a(ASN1_Tag type_tag, ASN1_Tag class_tag) const
const std::string & type() const
void encode_into(DER_Encoder &) const override
MatchResult matches(const X509_Certificate &cert) const
bool matches_dn(const std::string &) const
bool matches_dns(const std::string &) const
void decode_from(BER_Decoder &) override
const std::string & name() const
bool matches_ip(const std::string &) const
bool matches_dn_obj(const X509_DN &dn) const
A single Name Constraint.
void decode_from(BER_Decoder &) override
const GeneralName & base() const
void encode_into(DER_Encoder &) const override
bool is_permitted(const X509_Certificate &cert, bool reject_unknown) const
bool is_excluded(const X509_Certificate &cert, bool reject_unknown) const
const std::vector< GeneralSubtree > & permitted() const
const std::vector< GeneralSubtree > & excluded() const
const X509_DN & subject_dn() const
std::vector< std::string > subject_info(const std::string &name) const
const AlternativeName & subject_alt_name() const
void decode_from(BER_Decoder &) override
std::vector< std::string > get_attribute(const std::string &attr) const
std::multimap< OID, std::string > get_attributes() const
const std::vector< std::pair< OID, ASN1_String > > & dn_info() const
std::string to_string() const
std::string to_string(const BER_Object &obj)
std::vector< std::string > split_on(const std::string &str, char delim)
uint32_t string_to_ipv4(const std::string &str)
uint32_t load_be< uint32_t >(const uint8_t in[], size_t off)
std::string tolower_string(const std::string &in)
int operator<<(int fd, Pipe &pipe)
std::string ipv4_to_string(uint32_t ip)