Skip to content

Commit ec64479

Browse files
committed
impl Initial parsing validation logic
1 parent eb57cb0 commit ec64479

File tree

4 files changed

+62
-3
lines changed

4 files changed

+62
-3
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@
22
**/*.rs.bk
33
certs/
44
.idea
5+
tags

rcgen/Cargo.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ ring = { workspace = true, optional = true }
2828
pem = { workspace = true, optional = true }
2929
pki-types = { workspace = true }
3030
time = { version = "0.3.6", default-features = false }
31-
x509-parser = { workspace = true, features = ["verify"], optional = true }
31+
#x509-parser = { workspace = true, features = ["verify"], optional = true }
32+
x509-parser = { features = ["verify"], optional = true, git = "https://github.com/jean-airoldie/x509-parser", branch = "custom-extension" }
3233
zeroize = { version = "1.2", optional = true }
3334

3435
[features]
@@ -51,7 +52,7 @@ allowed_external_types = [
5152
[dev-dependencies]
5253
openssl = "0.10"
5354
pki-types = { package = "rustls-pki-types", version = "1" }
54-
x509-parser = { workspace = true, features = ["verify"] }
55+
x509-parser = { features = ["verify"], git = "https://github.com/jean-airoldie/x509-parser", branch = "custom-extension" }
5556
rustls-webpki = { version = "0.103", features = ["ring", "std"] }
5657
botan = { version = "0.11", features = ["vendored"] }
5758
ring = { workspace = true }

rcgen/src/csr.rs

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ use crate::{
1111
};
1212
#[cfg(feature = "x509-parser")]
1313
use crate::{DistinguishedName, SanType};
14+
#[cfg(feature = "x509-parser")]
15+
use x509_parser::asn1_rs::Oid;
1416

1517
/// A public key, extracted from a CSR
1618
#[derive(Debug, PartialEq, Eq, Hash)]
@@ -84,6 +86,23 @@ impl CertificateSigningRequestParams {
8486
Self::from_der(&csr.contents().into())
8587
}
8688

89+
/// Parse a certificate signing request from the ASCII PEM format
90+
/// using the provided validator function to handle unknown extension
91+
/// types.
92+
///
93+
/// The validator function must return an error if the attribute OID or value
94+
/// is incorrect.
95+
///
96+
/// See [`from_der`](Self::from_der) for more details.
97+
#[cfg(all(feature = "pem", feature = "x509-parser"))]
98+
pub fn from_pem_validated<F>(pem_str: &str, valid_fn: F) -> Result<Self, Error>
99+
where
100+
F: FnMut(&Oid, &[u8]) -> Result<(), Error>,
101+
{
102+
let csr = pem::parse(pem_str).or(Err(Error::CouldNotParseCertificationRequest))?;
103+
Self::from_der_validated(&csr.contents().into(), valid_fn)
104+
}
105+
87106
/// Parse a certificate signing request from DER-encoded bytes
88107
///
89108
/// Currently, this only supports the `Subject Alternative Name` extension.
@@ -96,6 +115,24 @@ impl CertificateSigningRequestParams {
96115
/// [`rustls_pemfile::csr()`]: https://docs.rs/rustls-pemfile/latest/rustls_pemfile/fn.csr.html
97116
#[cfg(feature = "x509-parser")]
98117
pub fn from_der(csr: &CertificateSigningRequestDer<'_>) -> Result<Self, Error> {
118+
Self::from_der_validated(csr, |_, _| Ok(()))
119+
}
120+
121+
/// Parse a certificate signing request from DER-encoded bytes using the provided
122+
/// validator function to handle unknown extension types.
123+
///
124+
/// The validator function must return an error if the attribute OID or value
125+
/// is incorrect.
126+
///
127+
/// See [`from_der`](Self::from_der) for more details.
128+
#[cfg(feature = "x509-parser")]
129+
pub fn from_der_validated<F>(
130+
csr: &CertificateSigningRequestDer<'_>,
131+
mut valid_fn: F,
132+
) -> Result<Self, Error>
133+
where
134+
F: FnMut(&Oid, &[u8]) -> Result<(), Error>,
135+
{
99136
use crate::KeyUsagePurpose;
100137
use x509_parser::prelude::FromDer;
101138

@@ -171,7 +208,13 @@ impl CertificateSigningRequestParams {
171208
return Err(Error::UnsupportedExtension);
172209
}
173210
},
174-
_ => return Err(Error::UnsupportedExtension),
211+
x509_parser::extensions::ParsedExtension::UnsupportedExtension { oid, value } => {
212+
valid_fn(oid, value)?;
213+
},
214+
other => {
215+
dbg!(&other);
216+
return Err(Error::UnsupportedExtension);
217+
}
175218
}
176219
}
177220
}

rcgen/tests/generic.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,20 @@ mod test_x509_custom_ext {
132132
.expect("missing requested custom extension");
133133
assert!(custom_ext.critical);
134134
assert_eq!(custom_ext.value, test_ext);
135+
136+
let csr_params = rcgen::CertificateSigningRequestParams::from_der_validated(
137+
test_cert_csr.der(),
138+
|oid, value| {
139+
if oid != &test_oid || value != &test_ext {
140+
Err(rcgen::Error::UnsupportedExtension)
141+
} else {
142+
Ok(())
143+
}
144+
},
145+
)
146+
.unwrap();
147+
148+
assert_eq!(csr_params.params, params);
135149
}
136150
}
137151

0 commit comments

Comments
 (0)