Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,15 +93,18 @@ pub enum Error {
/// invalid labels.
MalformedNameConstraint,

/// The maximum number of signature checks has been reached. Path complexity is too great.
MaximumSignatureChecksExceeded,
/// The maximum number of name constraint comparisons has been reached.
MaximumNameConstraintComparisonsExceeded,

/// The maximum number of internal path building calls has been reached. Path complexity is too great.
MaximumPathBuildCallsExceeded,

/// The path search was terminated because it became too deep.
MaximumPathDepthExceeded,

/// The maximum number of signature checks has been reached. Path complexity is too great.
MaximumSignatureChecksExceeded,

/// The certificate violates one or more name constraints.
NameConstraintViolation,

Expand Down Expand Up @@ -248,6 +251,7 @@ impl Error {
// Special case errors - not subject to ranking.
Error::MaximumSignatureChecksExceeded => 0,
Error::MaximumPathBuildCallsExceeded => 0,
Error::MaximumNameConstraintComparisonsExceeded => 0,

// Default catch all error - should be renamed in the future.
Error::UnknownIssuer => 0,
Expand Down
22 changes: 17 additions & 5 deletions src/subject_name/verify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use super::name::SubjectNameRef;
use crate::cert::{Cert, EndEntityOrCa};
use crate::der::{self, FromDer};
use crate::error::{DerTypeId, Error};
use crate::verify_cert::Budget;

pub(crate) fn verify_cert_dns_name(
cert: &crate::EndEntityCert,
Expand Down Expand Up @@ -97,11 +98,12 @@ pub(crate) fn verify_cert_subject_name(

// https://tools.ietf.org/html/rfc5280#section-4.2.1.10
pub(crate) fn check_name_constraints(
input: Option<&mut untrusted::Reader>,
constraints: Option<&mut untrusted::Reader>,
subordinate_certs: &Cert,
subject_common_name_contents: SubjectCommonNameContents,
budget: &mut Budget,
) -> Result<(), Error> {
let input = match input {
let constraints = match constraints {
Some(input) => input,
None => return Ok(()),
};
Expand All @@ -116,8 +118,8 @@ pub(crate) fn check_name_constraints(
der::expect_tag(inner, subtrees_tag).map(Some)
}

let permitted_subtrees = parse_subtrees(input, der::Tag::ContextSpecificConstructed0)?;
let excluded_subtrees = parse_subtrees(input, der::Tag::ContextSpecificConstructed1)?;
let permitted_subtrees = parse_subtrees(constraints, der::Tag::ContextSpecificConstructed0)?;
let excluded_subtrees = parse_subtrees(constraints, der::Tag::ContextSpecificConstructed1)?;

let mut child = subordinate_certs;
loop {
Expand All @@ -132,7 +134,12 @@ pub(crate) fn check_name_constraints(
Err(err) => return Some(Err(err)),
};

check_presented_id_conforms_to_constraints(name, permitted_subtrees, excluded_subtrees)
check_presented_id_conforms_to_constraints(
name,
permitted_subtrees,
excluded_subtrees,
budget,
)
});

if let Some(Err(err)) = result {
Expand All @@ -154,6 +161,7 @@ fn check_presented_id_conforms_to_constraints(
name: GeneralName,
permitted_subtrees: Option<untrusted::Input>,
excluded_subtrees: Option<untrusted::Input>,
budget: &mut Budget,
) -> Option<Result<(), Error>> {
let subtrees = [
(Subtrees::PermittedSubtrees, permitted_subtrees),
Expand All @@ -173,6 +181,10 @@ fn check_presented_id_conforms_to_constraints(
let mut has_permitted_subtrees_match = false;
let mut has_permitted_subtrees_mismatch = false;
while !constraints.at_end() {
if let Err(e) = budget.consume_name_constraint_comparison() {
return Some(Err(e));
}

// http://tools.ietf.org/html/rfc5280#section-4.2.1.10: "Within this
// profile, the minimum and maximum fields are not used with any name
// forms, thus, the minimum MUST be zero, and maximum MUST be absent."
Expand Down
Loading