Botan 3.10.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 287 of file name_constraint.cpp.

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

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

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

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