@@ -49,6 +49,8 @@ use std::fmt;
49
49
use std:: convert:: TryFrom ;
50
50
use std:: error:: Error ;
51
51
use std:: net:: IpAddr ;
52
+ #[ cfg( feature = "x509-parser" ) ]
53
+ use std:: net:: { Ipv4Addr , Ipv6Addr } ;
52
54
use std:: str:: FromStr ;
53
55
use std:: hash:: { Hash , Hasher } ;
54
56
@@ -159,6 +161,19 @@ pub enum SanType {
159
161
IpAddress ( IpAddr ) ,
160
162
}
161
163
164
+ #[ cfg( feature = "x509-parser" ) ]
165
+ fn ip_addr_from_octets ( octets : & [ u8 ] ) -> Result < IpAddr , RcgenError > {
166
+ if let Ok ( ipv6_octets) = <& [ u8 ; 16 ] >:: try_from ( octets) {
167
+ Ok ( Ipv6Addr :: from ( * ipv6_octets) . into ( ) )
168
+ }
169
+ else if let Ok ( ipv4_octets) = <& [ u8 ; 4 ] >:: try_from ( octets) {
170
+ Ok ( Ipv4Addr :: from ( * ipv4_octets) . into ( ) )
171
+ }
172
+ else {
173
+ Err ( RcgenError :: InvalidIpAddressOctetLength ( octets. len ( ) ) )
174
+ }
175
+ }
176
+
162
177
impl SanType {
163
178
#[ cfg( feature = "x509-parser" ) ]
164
179
fn try_from_general ( name : & x509_parser:: extensions:: GeneralName < ' _ > ) -> Result < Self , RcgenError > {
@@ -172,6 +187,9 @@ impl SanType {
172
187
x509_parser:: extensions:: GeneralName :: URI ( name) => {
173
188
SanType :: URI ( ( * name) . into ( ) )
174
189
}
190
+ x509_parser:: extensions:: GeneralName :: IPAddress ( octets) => {
191
+ SanType :: IpAddress ( ip_addr_from_octets ( octets) ?)
192
+ }
175
193
_ => return Err ( RcgenError :: InvalidNameType ) ,
176
194
} )
177
195
}
@@ -1585,6 +1603,8 @@ pub enum RcgenError {
1585
1603
#[ cfg( feature = "x509-parser" ) ]
1586
1604
/// Invalid subject alternative name type
1587
1605
InvalidNameType ,
1606
+ /// An IP address was provided as a byte array, but the byte array was an invalid length.
1607
+ InvalidIpAddressOctetLength ( usize ) ,
1588
1608
/// There is no support for generating
1589
1609
/// keys for the given algorithm
1590
1610
KeyGenerationUnavailable ,
@@ -1621,6 +1641,7 @@ impl fmt::Display for RcgenError {
1621
1641
CouldNotParseKeyPair => write ! ( f, "Could not parse key pair" ) ?,
1622
1642
#[ cfg( feature = "x509-parser" ) ]
1623
1643
InvalidNameType => write ! ( f, "Invalid subject alternative name type" ) ?,
1644
+ InvalidIpAddressOctetLength ( actual) => write ! ( f, "Invalid IP address octet length of {actual} bytes" ) ?,
1624
1645
KeyGenerationUnavailable => write ! ( f, "There is no support for generating \
1625
1646
keys for the given algorithm") ?,
1626
1647
UnsupportedSignatureAlgorithm => write ! ( f, "The requested signature algorithm \
@@ -2249,4 +2270,74 @@ mod tests {
2249
2270
}
2250
2271
}
2251
2272
}
2273
+
2274
+ #[ cfg( feature = "x509-parser" ) ]
2275
+ mod test_ip_address_from_octets {
2276
+ use std:: net:: IpAddr ;
2277
+ use super :: super :: ip_addr_from_octets;
2278
+ use super :: super :: RcgenError ;
2279
+
2280
+ #[ test]
2281
+ fn ipv4 ( ) {
2282
+ let octets = [ 10 , 20 , 30 , 40 ] ;
2283
+
2284
+ let actual = ip_addr_from_octets ( & octets)
2285
+ . unwrap ( ) ;
2286
+
2287
+ assert_eq ! ( IpAddr :: from( octets) , actual)
2288
+ }
2289
+
2290
+ #[ test]
2291
+ fn ipv6 ( ) {
2292
+ let octets = [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 , 16 ] ;
2293
+
2294
+ let actual = ip_addr_from_octets ( & octets)
2295
+ . unwrap ( ) ;
2296
+
2297
+ assert_eq ! ( IpAddr :: from( octets) , actual)
2298
+ }
2299
+
2300
+ #[ test]
2301
+ fn mismatch ( ) {
2302
+ let incorrect: Vec < u8 > = ( 0 ..10 ) . into_iter ( ) . collect ( ) ;
2303
+ let actual = ip_addr_from_octets ( & incorrect)
2304
+ . unwrap_err ( ) ;
2305
+
2306
+ assert_eq ! ( RcgenError :: InvalidIpAddressOctetLength ( 10 ) , actual) ;
2307
+ }
2308
+
2309
+ #[ test]
2310
+ fn none ( ) {
2311
+ let actual = ip_addr_from_octets ( & [ ] )
2312
+ . unwrap_err ( ) ;
2313
+
2314
+ assert_eq ! ( RcgenError :: InvalidIpAddressOctetLength ( 0 ) , actual) ;
2315
+ }
2316
+
2317
+ #[ test]
2318
+ fn too_many ( ) {
2319
+ let incorrect: Vec < u8 > = ( 0 ..20 ) . into_iter ( ) . collect ( ) ;
2320
+ let actual = ip_addr_from_octets ( & incorrect)
2321
+ . unwrap_err ( ) ;
2322
+
2323
+ assert_eq ! ( RcgenError :: InvalidIpAddressOctetLength ( 20 ) , actual) ;
2324
+ }
2325
+ }
2326
+
2327
+ #[ cfg( feature = "x509-parser" ) ]
2328
+ mod test_san_type_from_general_name {
2329
+ use std:: net:: IpAddr ;
2330
+ use x509_parser:: extensions:: GeneralName ;
2331
+ use crate :: SanType ;
2332
+
2333
+ #[ test]
2334
+ fn with_ipv4 ( ) {
2335
+ let octets = [ 1 , 2 , 3 , 4 ] ;
2336
+ let value = GeneralName :: IPAddress ( & octets) ;
2337
+ let actual = SanType :: try_from_general ( & value)
2338
+ . unwrap ( ) ;
2339
+
2340
+ assert_eq ! ( SanType :: IpAddress ( IpAddr :: from( octets) ) , actual) ;
2341
+ }
2342
+ }
2252
2343
}
0 commit comments