aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/cert/x509/x509path.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/cert/x509/x509path.cpp')
-rw-r--r--src/lib/cert/x509/x509path.cpp60
1 files changed, 58 insertions, 2 deletions
diff --git a/src/lib/cert/x509/x509path.cpp b/src/lib/cert/x509/x509path.cpp
index 71c025280..df286cfd7 100644
--- a/src/lib/cert/x509/x509path.cpp
+++ b/src/lib/cert/x509/x509path.cpp
@@ -16,8 +16,6 @@
#include <vector>
#include <set>
-#include <iostream>
-
namespace Botan {
namespace {
@@ -143,6 +141,62 @@ check_chain(const std::vector<X509_Certificate>& cert_path,
if(!trusted_hashes.count(subject.hash_used_for_signature()))
status.insert(Certificate_Status_Code::UNTRUSTED_HASH);
}
+
+ const NameConstraints& name_constr = issuer.name_constraints();
+
+ if(!name_constr.permitted().empty() || !name_constr.excluded().empty())
+ {
+ if(!issuer.is_CA_cert() || !issuer.is_critical("X509v3.NameConstraints"))
+ cert_status.at(i).insert(Certificate_Status_Code::NAME_CONSTRAINT_ERROR);
+
+ // Check that all subordinate certs pass the name constraint
+ for(int j = i; j >= 0; j--)
+ {
+ if(i == j && at_self_signed_root)
+ continue;
+
+ bool permitted = name_constr.permitted().empty();
+ bool failed = false;
+
+ for(auto c: name_constr.permitted())
+ {
+ switch(c.base().matches(cert_path.at(j)))
+ {
+ case GeneralName::MatchResult::NotFound:
+ case GeneralName::MatchResult::All:
+ permitted = true;
+ break;
+ case GeneralName::MatchResult::UnknownType:
+ failed = issuer.is_critical("X509v3.NameConstraints");
+ permitted = true;
+ break;
+ default:
+ break;
+ }
+ }
+
+ for(auto c: name_constr.excluded())
+ {
+ switch(c.base().matches(cert_path.at(j)))
+ {
+ case GeneralName::MatchResult::All:
+ case GeneralName::MatchResult::Some:
+ failed = true;
+ break;
+ case GeneralName::MatchResult::UnknownType:
+ failed = issuer.is_critical("X509v3.NameConstraints");
+ break;
+ default:
+ break;
+ }
+ }
+
+ if(failed || !permitted)
+ {
+ cert_status.at(j).insert(Certificate_Status_Code::NAME_CONSTRAINT_ERROR);
+ }
+ }
+ }
}
for(size_t i = 0; i != cert_path.size() - 1; ++i)
@@ -416,6 +470,8 @@ const char* Path_Validation_Result::status_string(Certificate_Status_Code code)
return "OCSP bad status";
case Certificate_Status_Code::CERT_NAME_NOMATCH:
return "Certificate does not match provided name";
+ case Certificate_Status_Code::NAME_CONSTRAINT_ERROR:
+ return "Certificate does not pass name constraint";
case Certificate_Status_Code::CERT_IS_REVOKED:
return "Certificate is revoked";