@@ -16,8 +16,12 @@ use std::path::PathBuf;
1616use std:: process:: exit;
1717use std:: rc:: Rc ;
1818use std:: time:: { Duration , SystemTime } ;
19+ #[ cfg( feature = "tls" ) ]
20+ use std:: { fs:: File , io:: BufReader , sync:: Arc } ;
1921
2022use futures_util:: future:: FutureExt ;
23+ #[ cfg( feature = "tls" ) ]
24+ use futures_util:: stream;
2125use git2:: Repository ;
2226
2327#[ cfg( feature = "fetch" ) ]
@@ -32,9 +36,18 @@ use hyper_tls::HttpsConnector;
3236#[ cfg( unix) ]
3337use hyper_unix_connector:: UnixConnector ;
3438
39+ #[ cfg( feature = "tls" ) ]
40+ use rustls_pemfile:: { certs, pkcs8_private_keys} ;
41+ #[ cfg( feature = "tls" ) ]
42+ use tokio:: net:: TcpListener ;
3543use tokio:: select;
3644#[ cfg( unix) ]
3745use tokio:: signal:: unix:: SignalKind ;
46+ #[ cfg( feature = "tls" ) ]
47+ use tokio_rustls:: {
48+ rustls:: { Certificate , PrivateKey , ServerConfig } ,
49+ TlsAcceptor ,
50+ } ;
3851
3952use indy_vdr:: common:: error:: prelude:: * ;
4053use indy_vdr:: pool:: { helpers:: perform_refresh, LocalPool , PoolBuilder , PoolTransactions } ;
@@ -352,11 +365,64 @@ async fn init_server(config: app::Config) -> Result<(), String> {
352365 . parse :: < IpAddr > ( )
353366 . map_err ( |_| "Error parsing host IP" ) ?;
354367 let addr = ( ip, config. port . unwrap ( ) ) . into ( ) ;
355- let builder =
356- Server :: try_bind ( & addr) . map_err ( |err| format ! ( "Error binding TCP socket: {}" , err) ) ?;
368+
369+ #[ cfg( feature = "tls" ) ]
370+ if let ( Some ( tls_cert_path) , Some ( tls_key_path) ) = ( & config. tls_cert_path , & config. tls_key_path )
371+ {
372+ let tls_cfg = build_tls_config ( & tls_cert_path, & tls_key_path) ?;
373+ let tls_acceptor = TlsAcceptor :: from ( Arc :: new ( tls_cfg) ) ;
374+ let tcp_listener = TcpListener :: bind ( & addr)
375+ . await
376+ . map_err ( |err| format ! ( "Error binding TCP socket: {}" , err) ) ?;
377+
378+ let incoming_tls_stream = stream:: try_unfold ( tcp_listener, move |tcp_listener| {
379+ let tls_acceptor = tls_acceptor. clone ( ) ;
380+ async move {
381+ match tcp_listener. accept ( ) . await {
382+ Ok ( ( socket, _) ) => Ok ( Some ( (
383+ tls_acceptor. clone ( ) . accept ( socket) . await ?,
384+ tcp_listener,
385+ ) ) ) ,
386+ Err ( err) => Err ( err) ,
387+ }
388+ }
389+ } ) ;
390+ let builder = Server :: builder ( hyper:: server:: accept:: from_stream ( incoming_tls_stream) ) ;
391+ return run_server ( builder, state, format ! ( "https://{}" , addr) , config) . await ;
392+ }
393+
394+ let builder = Server :: try_bind ( & addr)
395+ . map_err ( |err| format ! ( "Error binding TCP socket: {}" , err. to_string( ) ) ) ?;
357396 run_server ( builder, state, format ! ( "http://{}" , addr) , config) . await
358397}
359398
399+ #[ cfg( feature = "tls" ) ]
400+ fn build_tls_config ( cert_path : & str , key_path : & str ) -> Result < ServerConfig , String > {
401+ let certs = certs ( & mut BufReader :: new (
402+ File :: open ( cert_path)
403+ . map_err ( |err| format ! ( "Error opening TLS certificate file: {}" , err) ) ?,
404+ ) )
405+ . map_err ( |err| format ! ( "Error parsing TLS certificate file: {}" , err) ) ?;
406+ let keys = pkcs8_private_keys ( & mut BufReader :: new (
407+ File :: open ( key_path) . map_err ( |err| format ! ( "Error opening TLS key file: {}" , err) ) ?,
408+ ) )
409+ . map_err ( |err| format ! ( "Error parsing TLS key file: {}" , err) ) ?;
410+ ServerConfig :: builder ( )
411+ . with_safe_defaults ( )
412+ . with_no_client_auth ( )
413+ . with_single_cert (
414+ vec ! [ Certificate ( certs. into_iter( ) . next( ) . ok_or_else( || {
415+ "Error parsing TLS certificate file: no certificates found" . to_string( )
416+ } ) ?) ] ,
417+ PrivateKey (
418+ keys. into_iter ( )
419+ . next ( )
420+ . ok_or_else ( || "Error parsing TLS key file: no keys found" . to_string ( ) ) ?,
421+ ) ,
422+ )
423+ . map_err ( |err| format ! ( "Error building TLS config: {}" , err. to_string( ) ) )
424+ }
425+
360426async fn run_server < I > (
361427 builder : hyper:: server:: Builder < I > ,
362428 state : Rc < RefCell < AppState > > ,
0 commit comments