@@ -180,75 +180,51 @@ pub fn load_certificate(file: &str) -> Result<Certificate> {
180180 }
181181}
182182
183- /// Private key for rustls.
184- #[ cfg( feature = "tls-rustls" ) ]
183+ #[ cfg( feature = "_tls" ) ]
185184#[ derive( Clone ) ]
186- pub struct PrivateKey ( Arc < rustls:: pki_types:: PrivateKeyDer < ' static > > ) ;
187- #[ cfg( feature = "tls-rustls" ) ]
188- impl PrivateKey {
189- pub fn from_pem ( pem : & [ u8 ] ) -> Result < Self > {
190- let key = rustls:: pki_types:: PrivateKeyDer :: from_pem_slice ( & mut pem. as_ref ( ) ) . map_err ( |_| UrlError :: Invalid ) ?;
191- Ok ( Self ( Arc :: new ( key) ) )
192- }
193- }
194- #[ cfg( feature = "tls-rustls" ) ]
195- impl From < PrivateKey > for rustls:: pki_types:: PrivateKeyDer < ' static > {
196- fn from ( value : PrivateKey ) -> Self {
197- rustls:: pki_types:: PrivateKeyDer :: clone_key ( value. 0 . as_ref ( ) )
198- }
199- }
200- #[ cfg( feature = "tls-rustls" ) ]
201- impl fmt:: Debug for PrivateKey {
202- fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
203- write ! ( f, "[Private Key]" )
204- }
205- }
206- #[ cfg( feature = "tls-rustls" ) ]
207- impl PartialEq for PrivateKey {
208- fn eq ( & self , _other : & Self ) -> bool {
209- true
210- }
211- }
212- #[ cfg( feature = "tls-rustls" ) ]
213- pub fn load_private_key ( file : & str ) -> Result < PrivateKey > {
214- let data = fs:: read ( file) ?;
215- PrivateKey :: from_pem ( & data)
185+ pub enum ClientTlsIdentity {
186+ #[ cfg( feature = "tls-rustls" ) ]
187+ Pem {
188+ key : Arc < rustls:: pki_types:: PrivateKeyDer < ' static > > ,
189+ certs : Certificate ,
190+ } ,
191+ #[ cfg( feature = "tls-native-tls" ) ]
192+ Pkcs ( native_tls:: Identity ) ,
216193}
217194
218- /// Identity for mTLS for native-tls
219- # [ cfg ( feature = "tls-native-tls" ) ]
220- # [ derive ( Clone ) ]
221- pub struct TlsIdentity ( Arc < native_tls :: Identity > ) ;
222- # [ cfg ( feature = "tls-native-tls" ) ]
223- impl TlsIdentity {
224- pub fn from_pkcs12_der ( der : & [ u8 ] ) -> Result < Self > {
225- // FIXME: support password
226- Ok ( Self ( Arc :: new ( native_tls :: Identity :: from_pkcs12 ( der , "" ) . map_err ( |_| UrlError :: Invalid ) ? ) ) )
195+ # [ cfg ( feature = "_tls" ) ]
196+ impl ClientTlsIdentity {
197+ # [ cfg ( feature = "tls-rustls" ) ]
198+ pub fn load ( cert_path : & str , key_path : & str ) -> Result < Self > {
199+ let key = rustls :: pki_types :: PrivateKeyDer :: from_pem_slice ( fs :: read ( key_path ) ? . as_ref ( ) )
200+ . map_err ( |e| format ! ( "Cannot read private key from {}: {}" , key_path , e ) ) ? ;
201+ let key = Arc :: new ( key ) ;
202+ let certs = load_certificate ( cert_path ) ? ;
203+ return Ok ( Self :: Pem { key , certs } ) ;
227204 }
228- }
229- #[ cfg( feature = "tls-native-tls" ) ]
230- impl From < TlsIdentity > for native_tls:: Identity {
231- fn from ( value : TlsIdentity ) -> Self {
232- value. 0 . as_ref ( ) . clone ( )
205+
206+ #[ cfg( feature = "tls-native-tls" ) ]
207+ pub fn load ( cert_path : & str , key_path : & str ) -> Result < Self > {
208+ let identity = native_tls:: Identity :: from_pkcs8 (
209+ fs:: read ( cert_path) ?. as_ref ( ) ,
210+ fs:: read ( key_path) ?. as_ref ( ) ,
211+ ) . map_err ( |e| format ! ( "Cannot load identity from {} and {}: {}" , cert_path, key_path, e) ) ?;
212+ return Ok ( Self :: Pkcs ( identity) ) ;
233213 }
234214}
235- #[ cfg( feature = "tls-native-tls" ) ]
236- impl fmt:: Debug for TlsIdentity {
215+
216+ #[ cfg( feature = "_tls" ) ]
217+ impl fmt:: Debug for ClientTlsIdentity {
237218 fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
238- write ! ( f, "[Private Key ]" )
219+ write ! ( f, "[Client Certificate ]" )
239220 }
240221}
241- #[ cfg( feature = "tls-native-tls " ) ]
242- impl PartialEq for TlsIdentity {
222+ #[ cfg( feature = "_tls " ) ]
223+ impl PartialEq for ClientTlsIdentity {
243224 fn eq ( & self , _other : & Self ) -> bool {
244225 true
245226 }
246227}
247- #[ cfg( feature = "tls-native-tls" ) ]
248- pub fn load_tls_identity ( file : & str ) -> Result < TlsIdentity > {
249- let data = fs:: read ( file) ?;
250- TlsIdentity :: from_pkcs12_der ( & data)
251- }
252228
253229#[ derive( Clone , PartialEq , Debug ) ]
254230pub enum SettingType {
@@ -375,16 +351,9 @@ pub struct Options {
375351 #[ cfg( feature = "_tls" ) ]
376352 pub ( crate ) ca_certificate : Option < Certificate > ,
377353
378- /// Certificate for authorization .
354+ /// Authorization with certificate (mTLS) .
379355 #[ cfg( feature = "_tls" ) ]
380- pub ( crate ) certificate_file : Option < Certificate > ,
381-
382- /// Private key for certificate.
383- /// TODO: merge private_key_file + certificate_file into client_tls_identity
384- #[ cfg( feature = "tls-rustls" ) ]
385- pub ( crate ) private_key_file : Option < PrivateKey > ,
386- #[ cfg( feature = "tls-native-tls" ) ]
387- pub ( crate ) tls_identity : Option < TlsIdentity > ,
356+ pub ( crate ) client_tls_identity : Option < ClientTlsIdentity > ,
388357
389358 /// Query settings
390359 pub ( crate ) settings : HashMap < String , SettingValue > ,
@@ -442,11 +411,7 @@ impl Default for Options {
442411 #[ cfg( feature = "_tls" ) ]
443412 ca_certificate : None ,
444413 #[ cfg( feature = "_tls" ) ]
445- certificate_file : None ,
446- #[ cfg( feature = "tls-rustls" ) ]
447- private_key_file : None ,
448- #[ cfg( feature = "tls-native-tls" ) ]
449- tls_identity : None ,
414+ client_tls_identity : None ,
450415 settings : HashMap :: new ( ) ,
451416 alt_hosts : Vec :: new ( ) ,
452417 }
@@ -603,20 +568,8 @@ impl Options {
603568
604569 #[ cfg( feature = "_tls" ) ]
605570 property ! {
606- /// Certificate for authorization.
607- => certificate_file: Option <Certificate >
608- }
609-
610- #[ cfg( feature = "tls-rustls" ) ]
611- property ! {
612- /// Private key for certificate.
613- => private_key_file: Option <PrivateKey >
614- }
615-
616- #[ cfg( feature = "tls-native-tls" ) ]
617- property ! {
618- /// Identity for mTLS.
619- => tls_identity: Option <TlsIdentity >
571+ /// Authorization with certificate (mTLS).
572+ => client_tls_identity: Option <ClientTlsIdentity >
620573 }
621574
622575 property ! {
@@ -683,6 +636,9 @@ fn set_params<'a, I>(options: &mut Options, iter: I) -> std::result::Result<(),
683636where
684637 I : Iterator < Item = ( Cow < ' a , str > , Cow < ' a , str > ) > ,
685638{
639+ let mut client_certificate = None ;
640+ let mut client_private_key = None ;
641+
686642 for ( key, value) in iter {
687643 match key. as_ref ( ) {
688644 "pool_min" => options. pool_min = parse_param ( key, value, usize:: from_str) ?,
@@ -713,11 +669,9 @@ where
713669 #[ cfg( feature = "_tls" ) ]
714670 "ca_certificate" => options. ca_certificate = Some ( parse_param ( key, value, load_certificate) ?) ,
715671 #[ cfg( feature = "_tls" ) ]
716- "certificate_file" => options. certificate_file = Some ( parse_param ( key, value, load_certificate) ?) ,
717- #[ cfg( feature = "tls-rustls" ) ]
718- "private_key_file" => options. private_key_file = Some ( parse_param ( key, value, load_private_key) ?) ,
719- #[ cfg( feature = "tls-native-tls" ) ]
720- "tls_identity" => options. tls_identity = Some ( parse_param ( key, value, load_tls_identity) ?) ,
672+ "client_certificate" => client_certificate = Some ( value) ,
673+ #[ cfg( feature = "_tls" ) ]
674+ "client_private_key" => client_private_key = Some ( value) ,
721675 "alt_hosts" => options. alt_hosts = parse_param ( key, value, parse_hosts) ?,
722676 _ => {
723677 let value = SettingType :: String ( value. to_string ( ) ) ;
@@ -732,6 +686,16 @@ where
732686 } ;
733687 }
734688
689+ match ( client_certificate, client_private_key) {
690+ ( Some ( cert) , Some ( key) ) => {
691+ options. client_tls_identity = Some ( ClientTlsIdentity :: load ( & cert, & key) . map_err ( |_| UrlError :: Invalid ) ?) ;
692+ }
693+ ( None , None ) => { }
694+ _ => {
695+ return Err ( UrlError :: Invalid ) ;
696+ } ,
697+ }
698+
735699 Ok ( ( ) )
736700}
737701
0 commit comments