Botan 3.11.0
Crypto and TLS for C&
Botan::NameConstraints Class Referencefinal

Name Constraints. More...

#include <pkix_types.h>

Public Member Functions

const std::vector< GeneralSubtree > & excluded () const
bool is_excluded (const X509_Certificate &cert, bool reject_unknown) const
bool is_permitted (const X509_Certificate &cert, bool reject_unknown) const
 NameConstraints ()=default
 NameConstraints (std::vector< GeneralSubtree > &&permitted_subtrees, std::vector< GeneralSubtree > &&excluded_subtrees)
const std::vector< GeneralSubtree > & permitted () const

Detailed Description

Name Constraints.

Wraps the Name Constraints associated with a certificate.

Definition at line 408 of file pkix_types.h.

Constructor & Destructor Documentation

◆ NameConstraints() [1/2]

Botan::NameConstraints::NameConstraints ( )
default

Creates an empty name NameConstraints.

References NameConstraints().

Referenced by NameConstraints().

◆ NameConstraints() [2/2]

Botan::NameConstraints::NameConstraints ( std::vector< GeneralSubtree > && permitted_subtrees,
std::vector< GeneralSubtree > && excluded_subtrees )

Creates NameConstraints from a list of permitted and excluded subtrees.

Parameters
permitted_subtreesnames for which the certificate is permitted
excluded_subtreesnames for which the certificate is not permitted

Definition at line 354 of file name_constraint.cpp.

355 :
356 m_permitted_subtrees(std::move(permitted_subtrees)), m_excluded_subtrees(std::move(excluded_subtrees)) {
357 for(const auto& c : m_permitted_subtrees) {
358 m_permitted_name_types.insert(c.base().type_code());
359 }
360 for(const auto& c : m_excluded_subtrees) {
361 m_excluded_name_types.insert(c.base().type_code());
362 }
363}

Member Function Documentation

◆ excluded()

const std::vector< GeneralSubtree > & Botan::NameConstraints::excluded ( ) const
inline
Returns
excluded names

Definition at line 433 of file pkix_types.h.

433 {
434 return m_excluded_subtrees;
435 }

References excluded().

Referenced by botan_x509_cert_excluded_name_constraints(), excluded(), and is_excluded().

◆ is_excluded()

bool Botan::NameConstraints::is_excluded ( const X509_Certificate & cert,
bool reject_unknown ) const

Return true if any of the names in the certificate are excluded

Definition at line 503 of file name_constraint.cpp.

503 {
504 if(excluded().empty()) {
505 return false;
506 }
507
508 const auto& alt_name = cert.subject_alt_name();
509
510 if(exceeds_limit(cert.subject_dn().count(), alt_name.count(), excluded().size())) {
511 return true;
512 }
513
514 if(reject_unknown) {
515 // This is one is overly broad: we should just reject if there is a name constraint
516 // with the same OID as one of the other names
517 if(m_excluded_name_types.contains(GeneralName::NameType::Other) && !alt_name.other_names().empty()) {
518 return true;
519 }
520 if(m_excluded_name_types.contains(GeneralName::NameType::URI) && !alt_name.uris().empty()) {
521 return true;
522 }
523 if(m_excluded_name_types.contains(GeneralName::NameType::RFC822) && !alt_name.email().empty()) {
524 return true;
525 }
526 }
527
528 auto is_excluded_dn = [&](const X509_DN& dn) {
529 // If no restrictions, then immediate accept
530 if(!m_excluded_name_types.contains(GeneralName::NameType::DN)) {
531 return false;
532 }
533
534 for(const auto& c : m_excluded_subtrees) {
535 if(c.base().matches_dn(dn)) {
536 return true;
537 }
538 }
539
540 // There is at least one excluded name and we didn't match
541 return false;
542 };
543
544 auto is_excluded_dns_name = [&](const std::string& name) {
545 if(name.empty() || name.starts_with(".")) {
546 return true;
547 }
548
549 // If no restrictions, then immediate accept
550 if(!m_excluded_name_types.contains(GeneralName::NameType::DNS)) {
551 return false;
552 }
553
554 for(const auto& c : m_excluded_subtrees) {
555 if(c.base().matches_dns(name)) {
556 return true;
557 }
558 }
559
560 // There is at least one excluded name and we didn't match
561 return false;
562 };
563
564 auto is_excluded_ipv4 = [&](uint32_t ipv4) {
565 // If no restrictions, then immediate accept
566 if(!m_excluded_name_types.contains(GeneralName::NameType::IPv4)) {
567 return false;
568 }
569
570 for(const auto& c : m_excluded_subtrees) {
571 if(c.base().matches_ipv4(ipv4)) {
572 return true;
573 }
574 }
575
576 // There is at least one excluded name and we didn't match
577 return false;
578 };
579
580 if(is_excluded_dn(cert.subject_dn())) {
581 return true;
582 }
583
584 for(const auto& alt_dn : alt_name.directory_names()) {
585 if(is_excluded_dn(alt_dn)) {
586 return true;
587 }
588 }
589
590 for(const auto& alt_dns : alt_name.dns()) {
591 if(is_excluded_dns_name(alt_dns)) {
592 return true;
593 }
594 }
595
596 for(const auto& alt_ipv4 : alt_name.ipv4_address()) {
597 if(is_excluded_ipv4(alt_ipv4)) {
598 return true;
599 }
600 }
601
602 if(alt_name.count() == 0) {
603 for(const auto& cn : cert.subject_info("Name")) {
604 if(cn.find(".") != std::string::npos) {
605 if(auto ipv4 = string_to_ipv4(cn)) {
606 if(is_excluded_ipv4(ipv4.value())) {
607 return true;
608 }
609 } else {
610 if(is_excluded_dns_name(canonicalize_dns_name(cn))) {
611 return true;
612 }
613 }
614 }
615 }
616 }
617
618 // We didn't encounter a name that matched any prohibited name
619 return false;
620}
const std::vector< GeneralSubtree > & excluded() const
Definition pkix_types.h:433
std::optional< uint32_t > string_to_ipv4(std::string_view str)
Definition parsing.cpp:156

References Botan::X509_DN::count(), Botan::GeneralName::DN, Botan::GeneralName::DNS, excluded(), Botan::GeneralName::IPv4, Botan::GeneralName::Other, Botan::GeneralName::RFC822, Botan::string_to_ipv4(), Botan::X509_Certificate::subject_alt_name(), Botan::X509_Certificate::subject_dn(), Botan::X509_Certificate::subject_info(), and Botan::GeneralName::URI.

◆ is_permitted()

bool Botan::NameConstraints::is_permitted ( const X509_Certificate & cert,
bool reject_unknown ) const

Return true if all of the names in the certificate are permitted

Definition at line 386 of file name_constraint.cpp.

386 {
387 if(permitted().empty()) {
388 return true;
389 }
390
391 const auto& alt_name = cert.subject_alt_name();
392
393 if(exceeds_limit(cert.subject_dn().count(), alt_name.count(), permitted().size())) {
394 return false;
395 }
396
397 if(reject_unknown) {
398 if(m_permitted_name_types.contains(GeneralName::NameType::Other) && !alt_name.other_names().empty()) {
399 return false;
400 }
401 if(m_permitted_name_types.contains(GeneralName::NameType::URI) && !alt_name.uris().empty()) {
402 return false;
403 }
404 if(m_permitted_name_types.contains(GeneralName::NameType::RFC822) && !alt_name.email().empty()) {
405 return false;
406 }
407 }
408
409 auto is_permitted_dn = [&](const X509_DN& dn) {
410 // If no restrictions, then immediate accept
411 if(!m_permitted_name_types.contains(GeneralName::NameType::DN)) {
412 return true;
413 }
414
415 for(const auto& c : m_permitted_subtrees) {
416 if(c.base().matches_dn(dn)) {
417 return true;
418 }
419 }
420
421 // There is at least one permitted name and we didn't match
422 return false;
423 };
424
425 auto is_permitted_dns_name = [&](const std::string& name) {
426 if(name.empty() || name.starts_with(".")) {
427 return false;
428 }
429
430 // If no restrictions, then immediate accept
431 if(!m_permitted_name_types.contains(GeneralName::NameType::DNS)) {
432 return true;
433 }
434
435 for(const auto& c : m_permitted_subtrees) {
436 if(c.base().matches_dns(name)) {
437 return true;
438 }
439 }
440
441 // There is at least one permitted name and we didn't match
442 return false;
443 };
444
445 auto is_permitted_ipv4 = [&](uint32_t ipv4) {
446 // If no restrictions, then immediate accept
447 if(!m_permitted_name_types.contains(GeneralName::NameType::IPv4)) {
448 return true;
449 }
450
451 for(const auto& c : m_permitted_subtrees) {
452 if(c.base().matches_ipv4(ipv4)) {
453 return true;
454 }
455 }
456
457 // There is at least one permitted name and we didn't match
458 return false;
459 };
460
461 if(!is_permitted_dn(cert.subject_dn())) {
462 return false;
463 }
464
465 for(const auto& alt_dn : alt_name.directory_names()) {
466 if(!is_permitted_dn(alt_dn)) {
467 return false;
468 }
469 }
470
471 for(const auto& alt_dns : alt_name.dns()) {
472 if(!is_permitted_dns_name(alt_dns)) {
473 return false;
474 }
475 }
476
477 for(const auto& alt_ipv4 : alt_name.ipv4_address()) {
478 if(!is_permitted_ipv4(alt_ipv4)) {
479 return false;
480 }
481 }
482
483 if(alt_name.count() == 0) {
484 for(const auto& cn : cert.subject_info("Name")) {
485 if(cn.find(".") != std::string::npos) {
486 if(auto ipv4 = string_to_ipv4(cn)) {
487 if(!is_permitted_ipv4(ipv4.value())) {
488 return false;
489 }
490 } else {
491 if(!is_permitted_dns_name(canonicalize_dns_name(cn))) {
492 return false;
493 }
494 }
495 }
496 }
497 }
498
499 // We didn't encounter a name that doesn't have a matching constraint
500 return true;
501}
const std::vector< GeneralSubtree > & permitted() const
Definition pkix_types.h:426

References Botan::X509_DN::count(), Botan::GeneralName::DN, Botan::GeneralName::DNS, Botan::GeneralName::IPv4, Botan::GeneralName::Other, permitted(), Botan::GeneralName::RFC822, Botan::string_to_ipv4(), Botan::X509_Certificate::subject_alt_name(), Botan::X509_Certificate::subject_dn(), Botan::X509_Certificate::subject_info(), and Botan::GeneralName::URI.

◆ permitted()

const std::vector< GeneralSubtree > & Botan::NameConstraints::permitted ( ) const
inline
Returns
permitted names

Definition at line 426 of file pkix_types.h.

426 {
427 return m_permitted_subtrees;
428 }

References permitted().

Referenced by botan_x509_cert_permitted_name_constraints(), is_permitted(), permitted(), and Botan::X509_Certificate::to_string().


The documentation for this class was generated from the following files: