Botan 3.9.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 367 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 297 of file name_constraint.cpp.

298 :
299 m_permitted_subtrees(std::move(permitted_subtrees)), m_excluded_subtrees(std::move(excluded_subtrees)) {
300 for(const auto& c : m_permitted_subtrees) {
301 m_permitted_name_types.insert(c.base().type_code());
302 }
303 for(const auto& c : m_excluded_subtrees) {
304 m_excluded_name_types.insert(c.base().type_code());
305 }
306}

Member Function Documentation

◆ excluded()

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

Definition at line 392 of file pkix_types.h.

392 {
393 return m_excluded_subtrees;
394 }

References excluded().

Referenced by 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 446 of file name_constraint.cpp.

446 {
447 if(excluded().empty()) {
448 return false;
449 }
450
451 const auto& alt_name = cert.subject_alt_name();
452
453 if(exceeds_limit(cert.subject_dn().count(), alt_name.count(), excluded().size())) {
454 return true;
455 }
456
457 if(reject_unknown) {
458 // This is one is overly broad: we should just reject if there is a name constraint
459 // with the same OID as one of the other names
460 if(m_excluded_name_types.contains(GeneralName::NameType::Other) && !alt_name.other_names().empty()) {
461 return true;
462 }
463 if(m_excluded_name_types.contains(GeneralName::NameType::URI) && !alt_name.uris().empty()) {
464 return true;
465 }
466 if(m_excluded_name_types.contains(GeneralName::NameType::RFC822) && !alt_name.email().empty()) {
467 return true;
468 }
469 }
470
471 auto is_excluded_dn = [&](const X509_DN& dn) {
472 // If no restrictions, then immediate accept
473 if(!m_excluded_name_types.contains(GeneralName::NameType::DN)) {
474 return false;
475 }
476
477 for(const auto& c : m_excluded_subtrees) {
478 if(c.base().matches_dn(dn)) {
479 return true;
480 }
481 }
482
483 // There is at least one excluded name and we didn't match
484 return false;
485 };
486
487 auto is_excluded_dns_name = [&](const std::string& name) {
488 if(name.empty() || name.starts_with(".")) {
489 return true;
490 }
491
492 // If no restrictions, then immediate accept
493 if(!m_excluded_name_types.contains(GeneralName::NameType::DNS)) {
494 return false;
495 }
496
497 for(const auto& c : m_excluded_subtrees) {
498 if(c.base().matches_dns(name)) {
499 return true;
500 }
501 }
502
503 // There is at least one excluded name and we didn't match
504 return false;
505 };
506
507 auto is_excluded_ipv4 = [&](uint32_t ipv4) {
508 // If no restrictions, then immediate accept
509 if(!m_excluded_name_types.contains(GeneralName::NameType::IPv4)) {
510 return false;
511 }
512
513 for(const auto& c : m_excluded_subtrees) {
514 if(c.base().matches_ipv4(ipv4)) {
515 return true;
516 }
517 }
518
519 // There is at least one excluded name and we didn't match
520 return false;
521 };
522
523 if(is_excluded_dn(cert.subject_dn())) {
524 return true;
525 }
526
527 for(const auto& alt_dn : alt_name.directory_names()) {
528 if(is_excluded_dn(alt_dn)) {
529 return true;
530 }
531 }
532
533 for(const auto& alt_dns : alt_name.dns()) {
534 if(is_excluded_dns_name(alt_dns)) {
535 return true;
536 }
537 }
538
539 for(const auto& alt_ipv4 : alt_name.ipv4_address()) {
540 if(is_excluded_ipv4(alt_ipv4)) {
541 return true;
542 }
543 }
544
545 if(alt_name.count() == 0) {
546 for(const auto& cn : cert.subject_info("Name")) {
547 if(cn.find(".") != std::string::npos) {
548 if(auto ipv4 = string_to_ipv4(cn)) {
549 if(is_excluded_ipv4(ipv4.value())) {
550 return true;
551 }
552 } else {
553 if(is_excluded_dns_name(canonicalize_dns_name(cn))) {
554 return true;
555 }
556 }
557 }
558 }
559 }
560
561 // We didn't encounter a name that matched any prohibited name
562 return false;
563}
const std::vector< GeneralSubtree > & excluded() const
Definition pkix_types.h:392
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 329 of file name_constraint.cpp.

329 {
330 if(permitted().empty()) {
331 return true;
332 }
333
334 const auto& alt_name = cert.subject_alt_name();
335
336 if(exceeds_limit(cert.subject_dn().count(), alt_name.count(), permitted().size())) {
337 return false;
338 }
339
340 if(reject_unknown) {
341 if(m_permitted_name_types.contains(GeneralName::NameType::Other) && !alt_name.other_names().empty()) {
342 return false;
343 }
344 if(m_permitted_name_types.contains(GeneralName::NameType::URI) && !alt_name.uris().empty()) {
345 return false;
346 }
347 if(m_permitted_name_types.contains(GeneralName::NameType::RFC822) && !alt_name.email().empty()) {
348 return false;
349 }
350 }
351
352 auto is_permitted_dn = [&](const X509_DN& dn) {
353 // If no restrictions, then immediate accept
354 if(!m_permitted_name_types.contains(GeneralName::NameType::DN)) {
355 return true;
356 }
357
358 for(const auto& c : m_permitted_subtrees) {
359 if(c.base().matches_dn(dn)) {
360 return true;
361 }
362 }
363
364 // There is at least one permitted name and we didn't match
365 return false;
366 };
367
368 auto is_permitted_dns_name = [&](const std::string& name) {
369 if(name.empty() || name.starts_with(".")) {
370 return false;
371 }
372
373 // If no restrictions, then immediate accept
374 if(!m_permitted_name_types.contains(GeneralName::NameType::DNS)) {
375 return true;
376 }
377
378 for(const auto& c : m_permitted_subtrees) {
379 if(c.base().matches_dns(name)) {
380 return true;
381 }
382 }
383
384 // There is at least one permitted name and we didn't match
385 return false;
386 };
387
388 auto is_permitted_ipv4 = [&](uint32_t ipv4) {
389 // If no restrictions, then immediate accept
390 if(!m_permitted_name_types.contains(GeneralName::NameType::IPv4)) {
391 return true;
392 }
393
394 for(const auto& c : m_permitted_subtrees) {
395 if(c.base().matches_ipv4(ipv4)) {
396 return true;
397 }
398 }
399
400 // There is at least one permitted name and we didn't match
401 return false;
402 };
403
404 if(!is_permitted_dn(cert.subject_dn())) {
405 return false;
406 }
407
408 for(const auto& alt_dn : alt_name.directory_names()) {
409 if(!is_permitted_dn(alt_dn)) {
410 return false;
411 }
412 }
413
414 for(const auto& alt_dns : alt_name.dns()) {
415 if(!is_permitted_dns_name(alt_dns)) {
416 return false;
417 }
418 }
419
420 for(const auto& alt_ipv4 : alt_name.ipv4_address()) {
421 if(!is_permitted_ipv4(alt_ipv4)) {
422 return false;
423 }
424 }
425
426 if(alt_name.count() == 0) {
427 for(const auto& cn : cert.subject_info("Name")) {
428 if(cn.find(".") != std::string::npos) {
429 if(auto ipv4 = string_to_ipv4(cn)) {
430 if(!is_permitted_ipv4(ipv4.value())) {
431 return false;
432 }
433 } else {
434 if(!is_permitted_dns_name(canonicalize_dns_name(cn))) {
435 return false;
436 }
437 }
438 }
439 }
440 }
441
442 // We didn't encounter a name that doesn't have a matching constraint
443 return true;
444}
const std::vector< GeneralSubtree > & permitted() const
Definition pkix_types.h:385

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 385 of file pkix_types.h.

385 {
386 return m_permitted_subtrees;
387 }

References permitted().

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


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