diff options
| author | Alex Gaynor <alex.gaynor@gmail.com> | 2021-11-13 16:42:10 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-11-14 05:42:10 +0800 |
| commit | 4da2a68118840a6aeb7cdaa9bd880fb5c908a809 (patch) | |
| tree | 153df76da3c8b6201114722e577b73bdcacf7481 /src | |
| parent | 105400786a9d812241334effe7a7fd41b89aa76c (diff) | |
| download | cryptography-4da2a68118840a6aeb7cdaa9bd880fb5c908a809.tar.gz | |
Allow parsing CSR extensions with the critical bit having an explicitly encoded default (#6600)
* Allow parsing CSR extensions with the critical bit having an explicitly encoded default
* Poke for zuul
Diffstat (limited to 'src')
| -rw-r--r-- | src/rust/src/x509/csr.rs | 36 |
1 files changed, 33 insertions, 3 deletions
diff --git a/src/rust/src/x509/csr.rs b/src/rust/src/x509/csr.rs index 57f62ae3c..6bf517ee7 100644 --- a/src/rust/src/x509/csr.rs +++ b/src/rust/src/x509/csr.rs @@ -49,15 +49,26 @@ fn check_attribute_length<'a>(values: asn1::SetOf<'a, asn1::Tlv<'a>>) -> Result< } } +// CsrExtension has same layout as Extension, but doesn't use `#[default]` for +// `critical` so we can avoid erroring on explicitly-encoded defaults. +#[derive(asn1::Asn1Read, asn1::Asn1Write, PartialEq, Hash)] +pub(crate) struct CsrExtension<'a> { + pub(crate) extn_id: asn1::ObjectIdentifier<'a>, + pub(crate) critical: Option<bool>, + pub(crate) extn_value: &'a [u8], +} + impl CertificationRequestInfo<'_> { - fn get_extension_attribute<'a>(&'a self) -> Result<Option<x509::Extensions<'a>>, PyAsn1Error> { + fn get_extension_attribute( + &self, + ) -> Result<Option<asn1::SequenceOf<'_, CsrExtension<'_>>>, PyAsn1Error> { for attribute in self.attributes.unwrap_read().clone() { if attribute.type_id == *oid::EXTENSION_REQUEST || attribute.type_id == *oid::MS_EXTENSION_REQUEST { check_attribute_length(attribute.values.unwrap_read().clone())?; let val = attribute.values.unwrap_read().clone().next().unwrap(); - let exts = asn1::parse_single::<x509::Extensions<'a>>(val.full_data())?; + let exts = asn1::parse_single(val.full_data())?; return Ok(Some(exts)); } } @@ -242,7 +253,26 @@ impl CertificateSigningRequest { #[getter] fn extensions(&mut self, py: pyo3::Python<'_>) -> pyo3::PyResult<pyo3::PyObject> { - let exts = self.raw.borrow_value().csr_info.get_extension_attribute()?; + let csr_exts = self.raw.borrow_value().csr_info.get_extension_attribute()?; + let data; + // This is all very inefficient, to temporarily allow accepting + // extensions with `critical` having an explicit default encoding. + let exts = if let Some(v) = csr_exts { + let x509_exts: Vec<x509::common::Extension<'_>> = v + .map(|e| x509::common::Extension { + extn_id: e.extn_id, + critical: e.critical.unwrap_or_default(), + extn_value: e.extn_value, + }) + .collect(); + data = asn1::write_single(&asn1::SequenceOfWriter::new(x509_exts)); + Some(x509::Asn1ReadableOrWritable::new_read( + asn1::parse_single(&data).unwrap(), + )) + } else { + None + }; + x509::parse_and_cache_extensions(py, &mut self.cached_extensions, &exts, |oid, ext_data| { certificate::parse_cert_ext(py, oid.clone(), ext_data) }) |
