Botan 3.5.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 ()
 
 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 358 of file pkix_types.h.

Constructor & Destructor Documentation

◆ NameConstraints() [1/2]

Botan::NameConstraints::NameConstraints ( )
inline

Creates an empty name NameConstraints.

Definition at line 363 of file pkix_types.h.

363: m_permitted_subtrees(), m_excluded_subtrees() {}

◆ 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 289 of file name_constraint.cpp.

290 :
291 m_permitted_subtrees(std::move(permitted_subtrees)), m_excluded_subtrees(std::move(excluded_subtrees)) {
292 for(const auto& c : m_permitted_subtrees) {
293 m_permitted_name_types.insert(c.base().type_code());
294 }
295 for(const auto& c : m_excluded_subtrees) {
296 m_excluded_name_types.insert(c.base().type_code());
297 }
298}

Member Function Documentation

◆ excluded()

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

Definition at line 383 of file pkix_types.h.

383 {
384 return m_excluded_subtrees;
385 }

Referenced by is_excluded(), Botan::X509_Certificate::to_string(), and Botan::Cert_Extension::Name_Constraints::validate().

◆ 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 438 of file name_constraint.cpp.

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

Referenced by Botan::Cert_Extension::Name_Constraints::validate().

◆ 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 321 of file name_constraint.cpp.

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

References Botan::X509_DN::count(), Botan::GeneralName::DN, Botan::GeneralName::DNS, Botan::GeneralName::IPv4, name, 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.

Referenced by Botan::Cert_Extension::Name_Constraints::validate().

◆ permitted()

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

Definition at line 376 of file pkix_types.h.

376 {
377 return m_permitted_subtrees;
378 }

Referenced by is_permitted(), Botan::X509_Certificate::to_string(), and Botan::Cert_Extension::Name_Constraints::validate().


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