diff --git a/openssl-sys/src/handwritten/mod.rs b/openssl-sys/src/handwritten/mod.rs index d3adfa5a13df601cea526e3be3fe8fb5766a6636..292c0ecaa842e80b0c6a4809f1c0c9ffe75338c2 100644 --- a/openssl-sys/src/handwritten/mod.rs +++ b/openssl-sys/src/handwritten/mod.rs @@ -31,6 +31,7 @@ pub use self::stack::*; pub use self::tls1::*; pub use self::types::*; pub use self::x509::*; +pub use self::x509_sbgp::*; pub use self::x509_vfy::*; pub use self::x509v3::*; @@ -67,5 +68,6 @@ mod stack; mod tls1; mod types; mod x509; +mod x509_sbgp; mod x509_vfy; mod x509v3; diff --git a/openssl-sys/src/handwritten/x509_sbgp.rs b/openssl-sys/src/handwritten/x509_sbgp.rs new file mode 100644 index 0000000000000000000000000000000000000000..ee709b90ebb248bb61e25d9c35b91a2515b986cf --- /dev/null +++ b/openssl-sys/src/handwritten/x509_sbgp.rs @@ -0,0 +1,39 @@ +use super::super::*; +use libc::*; + +#[repr(C)] +pub struct ASRange { + pub min: *mut ASN1_INTEGER, + pub max: *mut ASN1_INTEGER, +} + +#[repr(C)] +pub struct _ASIdOrRange { + pub type_: c_int, + pub u: ASIdOrRange_st_anon_union, +} + +#[repr(C)] +pub union ASIdOrRange_st_anon_union { + pub id: *mut ASN1_INTEGER, + pub range: *mut ASRange, +} + +stack!(stack_st_ASIdOrRange); + +#[repr(C)] +pub struct ASIdentifierChoice { + pub type_: c_int, + pub asIdsOrRanges: *mut stack_st_ASIdOrRange, +} + +#[repr(C)] +pub struct _ASIdentifiers { + pub asnum: *mut ASIdentifierChoice, + pub rdi: *mut ASIdentifierChoice, +} + +extern "C" { + pub fn ASIdentifiers_free(asi: *mut _ASIdentifiers); + pub fn ASIdOrRange_free(asi: *mut _ASIdOrRange); +} diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index 0e23386fd34a0c3efb352eebe8418b158eaf2de7..0eacff2d3043f08488f212d7fd18f560ac9dcef0 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -64,6 +64,7 @@ mod openssl { pub use self::tls1::*; pub use self::types::*; pub use self::x509::*; + pub use self::x509_sbgp::*; pub use self::x509_vfy::*; pub use self::x509v3::*; @@ -94,6 +95,7 @@ mod openssl { mod tls1; mod types; mod x509; + mod x509_sbgp; mod x509_vfy; mod x509v3; diff --git a/openssl-sys/src/x509_sbgp.rs b/openssl-sys/src/x509_sbgp.rs new file mode 100644 index 0000000000000000000000000000000000000000..6f627c634b3e2160b8df82c9f114a3035895eef1 --- /dev/null +++ b/openssl-sys/src/x509_sbgp.rs @@ -0,0 +1,9 @@ +use libc::*; + +use super::*; + +pub const ASIdOrRange_id: c_int = 0; +pub const ASIdOrRange_range: c_int = 1; + +pub const ASIdentifierChoice_inherit: c_int = 0; +pub const ASIdentifierChoice_asIdsOrRanges: c_int = 1; diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs index 97242ff4d8fb008b703ab424273f247846c83aeb..0a2a726bf79014f2255acaf9c6e82a40e193458c 100644 --- a/openssl/src/x509/mod.rs +++ b/openssl/src/x509/mod.rs @@ -44,6 +44,8 @@ use openssl_macros::corresponds; #[cfg(any(ossl102, libressl261))] pub mod verify; +pub mod sbgp; + pub mod extension; pub mod store; diff --git a/openssl/src/x509/sbgp.rs b/openssl/src/x509/sbgp.rs new file mode 100644 index 0000000000000000000000000000000000000000..f105ab427b906917678060a62a40ab543305629c --- /dev/null +++ b/openssl/src/x509/sbgp.rs @@ -0,0 +1,99 @@ +use ffi::{ + ASIdOrRange_id, ASIdOrRange_range, ASIdentifierChoice_asIdsOrRanges, + ASIdentifierChoice_inherit, ASN1_INTEGER, +}; +use foreign_types::{ForeignType, ForeignTypeRef}; + +use crate::{ + asn1::Asn1IntegerRef, + stack::{StackRef, Stackable}, + util::{ForeignTypeExt, ForeignTypeRefExt}, +}; + +use super::X509; + +foreign_type_and_impl_send_sync! { + type CType = ffi::_ASIdOrRange; + fn drop = ffi::ASIdOrRange_free; + + /// The AS number extension of an `X509` certificate. + pub struct ASIdOrRange; + /// Reference to `ASIdOrRange`. + pub struct ASIdOrRangeRef; +} + +impl Stackable for ASIdOrRange { + type StackType = ffi::stack_st_ASIdOrRange; +} + +foreign_type_and_impl_send_sync! { + type CType = ffi::_ASIdentifiers; + fn drop = ffi::ASIdentifiers_free; + + /// The AS number extension of an `X509` certificate. + pub struct ASIdentifiers; + /// Reference to `ASIdentifiers`. + pub struct ASIdentifiersRef; +} + +impl ASIdentifiers { + pub fn inherited(&self) -> bool { + unsafe { + let asptr = self.0; + let asnum = (*asptr).asnum; + (*asnum).type_ == ASIdentifierChoice_inherit + } + } + + pub fn ranges(&self) -> Option> { + let mut r = Vec::new(); + unsafe { + let asptr = self.0; + let asnum = (*asptr).asnum; + if (*asnum).type_ == ASIdentifierChoice_asIdsOrRanges { + if let Some(s) = StackRef::::from_const_ptr_opt((*asnum).asIdsOrRanges) + { + for a_ptr in s { + let a = a_ptr.as_ptr(); + if (*a).type_ == ASIdOrRange_id { + let asn = Self::parse_asn1_integer((*a).u.id)?; + r.push((asn, asn)); + } else if (*a).type_ == ASIdOrRange_range { + let range = (*a).u.range; + let asn1 = Self::parse_asn1_integer((*range).min)?; + let asn2 = Self::parse_asn1_integer((*range).max)?; + r.push((asn1, asn2)); + } + } + } + } + } + Some(r) + } + + fn parse_asn1_integer(v: *mut ASN1_INTEGER) -> Option { + let v_parsed; + unsafe { + v_parsed = Asn1IntegerRef::from_ptr(v); + } + v_parsed.to_bn().ok()?.to_dec_str().ok()?.parse().ok() + } +} + +pub trait ExtractASN { + fn asn(&self) -> Option; +} + +impl ExtractASN for X509 { + fn asn(&self) -> Option { + unsafe { + let asn = ffi::X509_get_ext_d2i( + self.as_ptr(), + ffi::NID_sbgp_autonomousSysNum, + std::ptr::null_mut(), + std::ptr::null_mut(), + ); + ASIdentifiers::from_ptr_opt(asn as *mut _) + } + } +} diff --git a/systest/build.rs b/systest/build.rs index 53407eafad0d7a5b189fe6a228d8f5412c9cc340..ad41ca798e61662f483b6e6babe7992679d8b2e2 100644 --- a/systest/build.rs +++ b/systest/build.rs @@ -118,6 +118,7 @@ fn main() { s == "ProbeResult" || s == "X509_OBJECT_data" || // inline union s == "DIST_POINT_NAME_st_anon_union" || // inline union + s == "_ASIdOrRange_st_anon_union" || // inline union s == "PKCS7_data" || s == "ASN1_TYPE_value" });