@@ -17,7 +17,7 @@ use openssl::{
17
17
ssl:: { SslAcceptor , SslAcceptorBuilder , SslMethod , SslVerifyMode } ,
18
18
symm:: Cipher ,
19
19
x509:: store:: X509StoreBuilder ,
20
- x509:: { X509Name , X509 } ,
20
+ x509:: { extension , X509Name , X509 } ,
21
21
} ;
22
22
use picky_asn1_x509:: SubjectPublicKeyInfo ;
23
23
use std:: {
@@ -33,6 +33,9 @@ pub const AES_128_KEY_LEN: usize = 16;
33
33
pub const AES_256_KEY_LEN : usize = 32 ;
34
34
pub const AES_BLOCK_SIZE : usize = 16 ;
35
35
36
+ static LOCAL_IPS : & [ & str ] = & [ "127.0.0.1" , "::1" ] ;
37
+ static LOCAL_DNS_NAMES : & [ & str ] = & [ "localhost" , "localhost.domain" ] ;
38
+
36
39
#[ derive( Error , Debug ) ]
37
40
pub enum CryptoError {
38
41
/// Error getting ASN.1 Time from days from now
@@ -673,6 +676,7 @@ pub fn pkey_pub_to_pem(pubkey: &PKey<Public>) -> Result<String, CryptoError> {
673
676
pub fn generate_x509 (
674
677
key : & PKey < Private > ,
675
678
uuid : & str ,
679
+ additional_ips : Option < Vec < String > > ,
676
680
) -> Result < X509 , CryptoError > {
677
681
let mut name =
678
682
X509Name :: builder ( ) . map_err ( |source| CryptoError :: X509NameError {
@@ -725,7 +729,7 @@ pub fn generate_x509(
725
729
} ) ?;
726
730
builder. set_not_after ( & valid_to) . map_err ( |source| {
727
731
CryptoError :: X509BuilderError {
728
- message : "failed to set X509 certificate Nof After date" . into ( ) ,
732
+ message : "failed to set X509 certificate Not After date" . into ( ) ,
729
733
source,
730
734
}
731
735
} ) ?;
@@ -735,6 +739,37 @@ pub fn generate_x509(
735
739
source,
736
740
}
737
741
} ) ?;
742
+ let mut san = & mut extension:: SubjectAlternativeName :: new ( ) ;
743
+ for local_domain_name in LOCAL_DNS_NAMES . iter ( ) {
744
+ san = san. dns ( local_domain_name) ;
745
+ }
746
+ for local_ip in LOCAL_IPS . iter ( ) {
747
+ san = san. ip ( local_ip) ;
748
+ }
749
+ match additional_ips {
750
+ None => { }
751
+ Some ( ips) => {
752
+ for ip in ips. iter ( ) {
753
+ if !LOCAL_IPS . iter ( ) . any ( |e| ip. contains ( e) ) {
754
+ san = san. ip ( ip) ;
755
+ }
756
+ }
757
+ }
758
+ }
759
+ let x509 =
760
+ san. build ( & builder. x509v3_context ( None , None ) )
761
+ . map_err ( |source| CryptoError :: X509BuilderError {
762
+ message : "failed to build Subject Alternative Name" . into ( ) ,
763
+ source,
764
+ } ) ?;
765
+ builder. append_extension ( x509) . map_err ( |source| {
766
+ CryptoError :: X509BuilderError {
767
+ message :
768
+ "failed to append X509 certificate Subject Alternative Name extension"
769
+ . into ( ) ,
770
+ source,
771
+ }
772
+ } ) ?;
738
773
builder
739
774
. sign ( key, MessageDigest :: sha256 ( ) )
740
775
. map_err ( |source| CryptoError :: X509BuilderError {
@@ -1439,15 +1474,19 @@ mod tests {
1439
1474
fn test_x509 ( privkey : PKey < Private > , pubkey : PKey < Public > ) {
1440
1475
let tempdir = tempfile:: tempdir ( ) . unwrap ( ) ; //#[allow_ci]
1441
1476
1442
- let r = generate_x509 ( & privkey, "uuidA" ) ;
1477
+ let r = generate_x509 ( & privkey, "uuidA" , None ) ;
1443
1478
assert ! ( r. is_ok( ) ) ;
1444
1479
let cert_a = r. unwrap ( ) ; //#[allow_ci]
1445
1480
let cert_a_path = tempdir. path ( ) . join ( "cert_a.pem" ) ;
1446
1481
let r = write_x509 ( & cert_a, & cert_a_path) ;
1447
1482
assert ! ( r. is_ok( ) ) ;
1448
1483
assert ! ( cert_a_path. exists( ) ) ;
1449
1484
1450
- let r = generate_x509 ( & privkey, "uuidB" ) ;
1485
+ let r = generate_x509 (
1486
+ & privkey,
1487
+ "uuidB" ,
1488
+ Some ( vec ! [ "1.2.3.4" . to_string( ) , "1.2.3.5" . to_string( ) ] ) ,
1489
+ ) ;
1451
1490
assert ! ( r. is_ok( ) ) ;
1452
1491
let cert_b = r. unwrap ( ) ; //#[allow_ci]
1453
1492
let cert_b_path = tempdir. path ( ) . join ( "cert_b.pem" ) ;
0 commit comments