Skip to content

Commit

Permalink
csr: support reading name constraints from CSR
Browse files Browse the repository at this point in the history
  • Loading branch information
cpu committed Oct 6, 2023
1 parent ea1e260 commit d8d040a
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 5 deletions.
30 changes: 25 additions & 5 deletions src/csr.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#[cfg(feature = "x509-parser")]
use crate::{
BasicConstraints, CustomExtension, DistinguishedName, ExtendedKeyUsagePurpose, IsCa, SanType,
BasicConstraints, CustomExtension, DistinguishedName, ExtendedKeyUsagePurpose, GeneralSubtree,
IsCa, NameConstraints, SanType,
};
#[cfg(feature = "pem")]
use pem::Pem;
Expand Down Expand Up @@ -142,6 +143,29 @@ impl CertificateSigningRequest {
params.extended_key_usages = usages;
true
},
x509_parser::extensions::ParsedExtension::NameConstraints(ncs) => {
let mut permitted_subtrees = Vec::default();
if let Some(ncs_permitted) = &ncs.permitted_subtrees {
permitted_subtrees = ncs_permitted
.iter()
.map(GeneralSubtree::from_x509_general_subtree)
.collect::<Result<Vec<_>, _>>()?;
}
let mut excluded_subtrees = Vec::default();
if let Some(ncs_excluded) = &ncs.excluded_subtrees {
excluded_subtrees = ncs_excluded
.iter()
.map(GeneralSubtree::from_x509_general_subtree)
.collect::<Result<Vec<_>, _>>()?;
}
if !permitted_subtrees.is_empty() || !excluded_subtrees.is_empty() {
params.name_constraints = Some(NameConstraints {
permitted_subtrees,
excluded_subtrees,
});
}
true
},
_ => false,
};
if !supported {
Expand All @@ -154,10 +178,6 @@ impl CertificateSigningRequest {
}
}

// Not yet handled:
// * name_constraints
// and any other extensions.

Ok(Self {
params,
public_key: PublicKey { alg, raw },
Expand Down
5 changes: 5 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ pub enum Error {
/// Unsupported extension requested in CSR
#[cfg(feature = "x509-parser")]
UnsupportedExtension,
/// Unsupported general name type in CSR
#[cfg(feature = "x509-parser")]
UnsupportedGeneralName,
/// Unsupported field when generating a CSR
UnsupportedInCsr,
/// The requested signature algorithm is not supported
Expand Down Expand Up @@ -104,6 +107,8 @@ impl fmt::Display for Error {
f,
"Unsupported basic constraints extension path length constraint in CSR"
)?,
#[cfg(feature = "x509-parser")]
UnsupportedGeneralName => write!(f, "Unsupported general name in CSR",)?,
};
Ok(())
}
Expand Down
18 changes: 18 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,24 @@ impl GeneralSubtree {
GeneralSubtree::IpAddress(_addr) => TAG_IP_ADDRESS,
}
}

#[cfg(feature = "x509-parser")]
pub(crate) fn from_x509_general_subtree(
general_subtree: &x509_parser::extensions::GeneralSubtree,
) -> Result<Self, Error> {
use x509_parser::extensions::GeneralName as X509GeneralName;
match &general_subtree.base {
X509GeneralName::RFC822Name(name) => Ok(GeneralSubtree::Rfc822Name(name.to_string())),
X509GeneralName::DNSName(name) => Ok(GeneralSubtree::DnsName(name.to_string())),
X509GeneralName::DirectoryName(name) => Ok(GeneralSubtree::DirectoryName(
DistinguishedName::from_name(name)?,
)),
// TODO(XXX): Consider how to handle the &[u8] that x509_parser provides.
// It would need to be mapped into the rcgen CidrSubnet type.
// GeneralName::IPAddress(addr) => GeneralSubtree::IpAddress(...)
_ => Err(Error::UnsupportedGeneralName),
}
}
}

#[derive(Debug, PartialEq, Eq, Hash, Clone)]
Expand Down

0 comments on commit d8d040a

Please sign in to comment.