@@ -28,7 +28,7 @@ use std::net::{Ipv4Addr, Ipv6Addr};
2828use std:: sync:: Arc ;
2929
3030use rustls:: client:: danger:: ServerCertVerifier ;
31- use rustls:: pki_types;
31+ use rustls:: pki_types:: { self , CertificateDer } ;
3232#[ cfg( not( any( target_vendor = "apple" , windows) ) ) ]
3333use rustls:: pki_types:: { DnsName , ServerName } ;
3434use rustls:: { CertificateError , Error as TlsError , OtherError } ;
@@ -80,13 +80,21 @@ macro_rules! no_error {
8080 } ;
8181}
8282
83- const ROOT1 : pki_types:: CertificateDer < ' static > =
84- pki_types:: CertificateDer :: from_slice ( include_bytes ! ( "root1.crt" ) ) ;
83+ const ROOT1 : CertificateDer = CertificateDer :: from_slice ( include_bytes ! ( "root1.crt" ) ) ;
8584const ROOT1_INT1 : & [ u8 ] = include_bytes ! ( "root1-int1.crt" ) ;
8685const ROOT1_INT1_EXAMPLE_COM_GOOD : & [ u8 ] = include_bytes ! ( "root1-int1-ee_example.com-good.crt" ) ;
8786const ROOT1_INT1_LOCALHOST_IPV4_GOOD : & [ u8 ] = include_bytes ! ( "root1-int1-ee_127.0.0.1-good.crt" ) ;
8887const ROOT1_INT1_LOCALHOST_IPV6_GOOD : & [ u8 ] = include_bytes ! ( "root1-int1-ee_1-good.crt" ) ;
8988
89+ // `ffi-testing` is currently only used for Android, which doesn't support extra roots yet.
90+ #[ cfg_attr( feature = "ffi-testing" , allow( unused) ) ]
91+ #[ cfg( not( target_os = "android" ) ) ]
92+ const ROOT2 : CertificateDer = CertificateDer :: from_slice ( include_bytes ! ( "root2.crt" ) ) ;
93+
94+ #[ cfg_attr( feature = "ffi-testing" , allow( unused) ) ]
95+ #[ cfg( not( target_os = "android" ) ) ]
96+ const ROOT3 : CertificateDer = CertificateDer :: from_slice ( include_bytes ! ( "root3.crt" ) ) ;
97+
9098const EXAMPLE_COM : & str = "example.com" ;
9199const LOCALHOST_IPV4 : & str = "127.0.0.1" ;
92100const LOCALHOST_IPV6 : & str = "::1" ;
@@ -111,8 +119,8 @@ pub(super) fn verification_without_mock_root() {
111119 let verifier = Verifier :: new ( crypto_provider) . unwrap ( ) ;
112120
113121 let server_name = pki_types:: ServerName :: try_from ( EXAMPLE_COM ) . unwrap ( ) ;
114- let end_entity = pki_types :: CertificateDer :: from ( ROOT1_INT1_EXAMPLE_COM_GOOD ) ;
115- let intermediates = [ pki_types :: CertificateDer :: from ( ROOT1_INT1 ) ] ;
122+ let end_entity = CertificateDer :: from ( ROOT1_INT1_EXAMPLE_COM_GOOD ) ;
123+ let intermediates = [ CertificateDer :: from ( ROOT1_INT1 ) ] ;
116124
117125 // Fails because the server cert has no trust root in Windows, and can't since it uses a self-signed CA.
118126 // Similarly on UNIX platforms using the Webpki verifier, it can't fetch extra certificates through
@@ -139,6 +147,74 @@ fn test_verification_without_mock_root() {
139147 verification_without_mock_root ( )
140148}
141149
150+ #[ cfg( not( target_os = "android" ) ) ]
151+ #[ test]
152+ fn test_selfsigned_cert_with_extra_roots ( ) {
153+ let crypto_provider = test_provider ( ) ;
154+
155+ let selfsigned = ROOT2 ;
156+ let selfsigned_as_leaf = ROOT3 ;
157+ let roots = vec ! [ selfsigned. clone( ) , selfsigned_as_leaf. clone( ) ] ;
158+ let server_name = pki_types:: ServerName :: try_from ( EXAMPLE_COM ) . unwrap ( ) ;
159+
160+ let verifier = Verifier :: new_with_extra_roots ( roots, crypto_provider) . unwrap ( ) ;
161+
162+ let result =
163+ verifier. verify_server_cert ( & selfsigned, & [ ] , & server_name, & [ ] , verification_time ( ) ) ;
164+
165+ #[ cfg( target_vendor = "apple" ) ]
166+ assert ! ( result. is_ok( ) , "failed to validate self-signed certificate" ) ;
167+
168+ #[ cfg( not( target_vendor = "apple" ) ) ]
169+ assert ! (
170+ result. is_err( ) ,
171+ "self-signed certificate is accepted unexpectly"
172+ ) ;
173+
174+ let result = verifier. verify_server_cert (
175+ & selfsigned_as_leaf,
176+ & [ ] ,
177+ & server_name,
178+ & [ ] ,
179+ verification_time ( ) ,
180+ ) ;
181+
182+ #[ cfg( not( target_os = "windows" ) ) ]
183+ assert ! (
184+ result. is_ok( ) ,
185+ "failed to validate self-signed leaf certificate"
186+ ) ;
187+
188+ #[ cfg( target_os = "windows" ) ]
189+ assert ! (
190+ result. is_err( ) ,
191+ "self-signed leaf certificate is accepted unexpectly"
192+ ) ;
193+ }
194+
195+ #[ cfg( not( target_os = "android" ) ) ]
196+ #[ test]
197+ fn test_chain_signed_with_extra_roots ( ) {
198+ let crypto_provider = test_provider ( ) ;
199+
200+ let server_name = pki_types:: ServerName :: try_from ( EXAMPLE_COM ) . unwrap ( ) ;
201+ let end_entity = CertificateDer :: from ( ROOT1_INT1_EXAMPLE_COM_GOOD ) ;
202+ let intermediates = [ CertificateDer :: from ( ROOT1_INT1 ) ] ;
203+ let roots = vec ! [ ROOT1 ] ;
204+
205+ let verifier = Verifier :: new_with_extra_roots ( roots, crypto_provider) . unwrap ( ) ;
206+
207+ verifier
208+ . verify_server_cert (
209+ & end_entity,
210+ & intermediates,
211+ & server_name,
212+ & [ ] ,
213+ verification_time ( ) ,
214+ )
215+ . expect ( "failed to validate extra root-only certificate chain" ) ;
216+ }
217+
142218// Note: Android does not currently support IP address hosts, so these tests are disabled for
143219// Android.
144220// Verifies that our test trust anchor(s) are not trusted when `Verifier::new()`
@@ -349,10 +425,10 @@ fn test_with_mock_root<E: std::error::Error + PartialEq + 'static>(
349425 let mut chain = test_case
350426 . chain
351427 . iter ( )
352- . map ( |bytes| pki_types :: CertificateDer :: from ( * bytes) ) ;
428+ . map ( |bytes| CertificateDer :: from ( * bytes) ) ;
353429
354430 let end_entity = chain. next ( ) . unwrap ( ) ;
355- let intermediates: Vec < pki_types :: CertificateDer < ' _ > > = chain. collect ( ) ;
431+ let intermediates: Vec < CertificateDer < ' _ > > = chain. collect ( ) ;
356432
357433 let server_name = pki_types:: ServerName :: try_from ( test_case. reference_id ) . unwrap ( ) ;
358434
0 commit comments