1+ use std:: mem:: MaybeUninit ;
2+
13use ffi:: {
24 ASIdOrRange_id , ASIdOrRange_range , ASIdentifierChoice_asIdsOrRanges ,
3- ASIdentifierChoice_inherit , ASN1_INTEGER ,
5+ ASIdentifierChoice_inherit , IPAddressChoice_addressesOrRanges , X509v3_addr_get_afi ,
6+ X509v3_addr_get_range , ASN1_INTEGER , IANA_AFI_IPV4 , IANA_AFI_IPV6 ,
47} ;
58use foreign_types:: { ForeignType , ForeignTypeRef } ;
69
710use crate :: {
811 asn1:: Asn1IntegerRef ,
9- stack:: { StackRef , Stackable } ,
12+ stack:: { Stack , StackRef , Stackable } ,
1013 util:: { ForeignTypeExt , ForeignTypeRefExt } ,
1114} ;
1215
@@ -47,25 +50,27 @@ impl ASIdentifiers {
4750
4851 pub fn ranges ( & self ) -> Option < Vec < ( u32 , u32 ) > > {
4952 let mut r = Vec :: new ( ) ;
53+ let asptr = self . 0 ;
5054 unsafe {
51- let asptr = self . 0 ;
5255 let asnum = ( * asptr) . asnum ;
53- if ( * asnum) . type_ = = ASIdentifierChoice_asIdsOrRanges {
54- if let Some ( s ) = StackRef :: < ASIdOrRange > :: from_const_ptr_opt ( ( * asnum ) . asIdsOrRanges )
55- {
56- for a_ptr in s {
57- let a = a_ptr . as_ptr ( ) ;
58- if ( * a ) . type_ == ASIdOrRange_id {
59- let asn = Self :: parse_asn1_integer ( ( * a) . u . id ) ? ;
60- r . push ( ( asn , asn ) ) ;
61- } else if ( * a ) . type_ == ASIdOrRange_range {
62- let range = ( * a) . u . range ;
63- let asn1 = Self :: parse_asn1_integer ( ( * range ) . min ) ? ;
64- let asn2 = Self :: parse_asn1_integer ( ( * range) . max ) ?;
65- r . push ( ( asn1 , asn2 ) ) ;
66- }
56+ if ( * asnum) . type_ ! = ASIdentifierChoice_asIdsOrRanges {
57+ return None ;
58+ }
59+ if let Some ( s ) = StackRef :: < ASIdOrRange > :: from_const_ptr_opt ( ( * asnum ) . asIdsOrRanges ) {
60+ for a_ptr in s {
61+ let a = a_ptr . as_ptr ( ) ;
62+ if ( * a) . type_ == ASIdOrRange_id {
63+ let asn = Self :: parse_asn1_integer ( ( * a ) . u . id ) ? ;
64+ r . push ( ( asn , asn ) ) ;
65+ } else if ( * a) . type_ == ASIdOrRange_range {
66+ let range = ( * a ) . u . range ;
67+ let asn1 = Self :: parse_asn1_integer ( ( * range) . min ) ?;
68+ let asn2 = Self :: parse_asn1_integer ( ( * range ) . max ) ? ;
69+ r . push ( ( asn1 , asn2 ) ) ;
6770 }
6871 }
72+ } else {
73+ return None ;
6974 }
7075 }
7176 Some ( r)
@@ -80,11 +85,105 @@ impl ASIdentifiers {
8085 }
8186}
8287
83- pub trait ExtractASN {
88+ foreign_type_and_impl_send_sync ! {
89+ type CType = ffi:: _IPAddressOrRange;
90+ fn drop = ffi:: IPAddressOrRange_free ;
91+
92+ /// The AS number extension of an `X509` certificate.
93+ pub struct IPAddressOrRange ;
94+ /// Reference to `IPAddressOrRange`.
95+ pub struct IPAddressOrRangeRef ;
96+ }
97+
98+ impl Stackable for IPAddressOrRange {
99+ type StackType = ffi:: stack_st_IPAddressOrRange ;
100+ }
101+
102+ foreign_type_and_impl_send_sync ! {
103+ type CType = ffi:: _IPAddressFamily;
104+ fn drop = ffi:: IPAddressFamily_free ;
105+
106+ /// The AS number extension of an `X509` certificate.
107+ pub struct IPAddressFamily ;
108+ /// Reference to `IPAddressFamily`.
109+ pub struct IPAddressFamilyRef ;
110+ }
111+
112+ impl Stackable for IPAddressFamily {
113+ type StackType = ffi:: stack_st_IPAddressFamily ;
114+ }
115+
116+ #[ derive( PartialEq , Eq , Debug ) ]
117+ pub enum IPVersion {
118+ V4 ,
119+ V6 ,
120+ }
121+
122+ impl IPAddressFamily {
123+ pub fn fam ( & self ) -> Option < IPVersion > {
124+ let ptr = self . 0 ;
125+ match X509v3_addr_get_afi ( ptr) {
126+ IANA_AFI_IPV4 => Some ( IPVersion :: V4 ) ,
127+ IANA_AFI_IPV6 => Some ( IPVersion :: V6 ) ,
128+ _ => None ,
129+ }
130+ }
131+
132+ pub fn range ( & self ) -> Option < Vec < ( std:: net:: IpAddr , std:: net:: IpAddr ) > > {
133+ let ptr = self . 0 ;
134+ let mut r = Vec :: new ( ) ;
135+ unsafe {
136+ let choice = ( * ptr) . ipAddressChoice ;
137+ if ( * choice) . type_ != IPAddressChoice_addressesOrRanges {
138+ return None ;
139+ }
140+ let stack =
141+ StackRef :: < IPAddressOrRange > :: from_const_ptr_opt ( ( * choice) . addressesOrRanges ) ?;
142+ for e in stack {
143+ let mut min = MaybeUninit :: < [ u8 ; 16 ] > :: uninit ( ) ;
144+ let mut max = MaybeUninit :: < [ u8 ; 16 ] > :: uninit ( ) ;
145+ let size = X509v3_addr_get_range (
146+ e. as_ptr ( ) ,
147+ X509v3_addr_get_afi ( ptr) ,
148+ min. as_mut_ptr ( ) as * mut u8 ,
149+ max. as_mut_ptr ( ) as * mut u8 ,
150+ 16 ,
151+ ) ;
152+ r. push ( (
153+ Self :: data_to_ip_addr ( min. assume_init ( ) , size) ?,
154+ Self :: data_to_ip_addr ( max. assume_init ( ) , size) ?,
155+ ) )
156+ }
157+ }
158+ Some ( r)
159+ }
160+
161+ fn data_to_ip_addr ( data : [ u8 ; 16 ] , len : isize ) -> Option < std:: net:: IpAddr > {
162+ match len {
163+ 4 => Some ( std:: net:: IpAddr :: V4 ( std:: net:: Ipv4Addr :: new (
164+ data[ 0 ] , data[ 1 ] , data[ 2 ] , data[ 3 ] ,
165+ ) ) ) ,
166+ 16 => Some ( std:: net:: IpAddr :: V6 ( std:: net:: Ipv6Addr :: new (
167+ ( data[ 0 ] as u16 ) << 8 | data[ 1 ] as u16 ,
168+ ( data[ 2 ] as u16 ) << 8 | data[ 3 ] as u16 ,
169+ ( data[ 4 ] as u16 ) << 8 | data[ 5 ] as u16 ,
170+ ( data[ 6 ] as u16 ) << 8 | data[ 7 ] as u16 ,
171+ ( data[ 8 ] as u16 ) << 8 | data[ 9 ] as u16 ,
172+ ( data[ 10 ] as u16 ) << 8 | data[ 11 ] as u16 ,
173+ ( data[ 12 ] as u16 ) << 8 | data[ 13 ] as u16 ,
174+ ( data[ 14 ] as u16 ) << 8 | data[ 15 ] as u16 ,
175+ ) ) ) ,
176+ _ => None ,
177+ }
178+ }
179+ }
180+
181+ pub trait ExtractSBGPInfo {
84182 fn asn ( & self ) -> Option < ASIdentifiers > ;
183+ fn ip_addresses ( & self ) -> Option < Stack < IPAddressFamily > > ;
85184}
86185
87- impl ExtractASN for X509 {
186+ impl ExtractSBGPInfo for X509 {
88187 fn asn ( & self ) -> Option < ASIdentifiers > {
89188 unsafe {
90189 let asn = ffi:: X509_get_ext_d2i (
@@ -96,4 +195,16 @@ impl ExtractASN for X509 {
96195 ASIdentifiers :: from_ptr_opt ( asn as * mut _ )
97196 }
98197 }
198+
199+ fn ip_addresses ( & self ) -> Option < Stack < IPAddressFamily > > {
200+ unsafe {
201+ let asn = ffi:: X509_get_ext_d2i (
202+ self . as_ptr ( ) ,
203+ ffi:: NID_sbgp_ipAddrBlock ,
204+ std:: ptr:: null_mut ( ) ,
205+ std:: ptr:: null_mut ( ) ,
206+ ) ;
207+ Stack :: from_ptr_opt ( asn as * mut _ )
208+ }
209+ }
99210}
0 commit comments