@@ -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,77 @@ 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 ! (
167+ result. is_ok( ) ,
168+ "failed to validate self-signed ca certificate"
169+ ) ;
170+
171+ #[ cfg( not( target_vendor = "apple" ) ) ]
172+ assert ! (
173+ result. is_err( ) ,
174+ "self-signed ca certificate is accepted unexpectly"
175+ ) ;
176+
177+ let result = verifier. verify_server_cert (
178+ & selfsigned_as_leaf,
179+ & [ ] ,
180+ & server_name,
181+ & [ ] ,
182+ verification_time ( ) ,
183+ ) ;
184+
185+ #[ cfg( not( target_os = "windows" ) ) ]
186+ assert ! (
187+ result. is_ok( ) ,
188+ "failed to validate self-signed leaf certificate"
189+ ) ;
190+
191+ #[ cfg( target_os = "windows" ) ]
192+ assert ! (
193+ result. is_err( ) ,
194+ "self-signed leaf certificate is accepted unexpectly"
195+ ) ;
196+ }
197+
198+ #[ cfg( not( target_os = "android" ) ) ]
199+ #[ test]
200+ fn test_chain_signed_with_extra_roots ( ) {
201+ let crypto_provider = test_provider ( ) ;
202+
203+ let server_name = pki_types:: ServerName :: try_from ( EXAMPLE_COM ) . unwrap ( ) ;
204+ let end_entity = CertificateDer :: from ( ROOT1_INT1_EXAMPLE_COM_GOOD ) ;
205+ let intermediates = [ CertificateDer :: from ( ROOT1_INT1 ) ] ;
206+ let roots = vec ! [ ROOT1 ] ;
207+
208+ let verifier = Verifier :: new_with_extra_roots ( roots, crypto_provider) . unwrap ( ) ;
209+
210+ verifier
211+ . verify_server_cert (
212+ & end_entity,
213+ & intermediates,
214+ & server_name,
215+ & [ ] ,
216+ verification_time ( ) ,
217+ )
218+ . expect ( "failed to validate extra root-only certificate chain" ) ;
219+ }
220+
142221// Note: Android does not currently support IP address hosts, so these tests are disabled for
143222// Android.
144223// Verifies that our test trust anchor(s) are not trusted when `Verifier::new()`
@@ -349,10 +428,10 @@ fn test_with_mock_root<E: std::error::Error + PartialEq + 'static>(
349428 let mut chain = test_case
350429 . chain
351430 . iter ( )
352- . map ( |bytes| pki_types :: CertificateDer :: from ( * bytes) ) ;
431+ . map ( |bytes| CertificateDer :: from ( * bytes) ) ;
353432
354433 let end_entity = chain. next ( ) . unwrap ( ) ;
355- let intermediates: Vec < pki_types :: CertificateDer < ' _ > > = chain. collect ( ) ;
434+ let intermediates: Vec < CertificateDer < ' _ > > = chain. collect ( ) ;
356435
357436 let server_name = pki_types:: ServerName :: try_from ( test_case. reference_id ) . unwrap ( ) ;
358437
0 commit comments