@@ -5,7 +5,12 @@ use async_std::io::Write;
55use async_std:: net:: TcpStream ;
66use async_std:: task;
77use async_tls:: TlsConnector ;
8+ use rustls:: ClientConfig ;
9+ use std:: sync:: Arc ;
10+ use std:: fs:: File ;
11+ use std:: io:: BufReader ;
812use std:: net:: ToSocketAddrs ;
13+ use std:: path:: { Path , PathBuf } ;
914use structopt:: StructOpt ;
1015
1116#[ derive( StructOpt ) ]
@@ -20,6 +25,11 @@ struct Options {
2025 /// The domain to connect to. This may be different from the host!
2126 #[ structopt( short = "d" , long = "domain" ) ]
2227 domain : Option < String > ,
28+
29+ /// A file with a certificate authority chain, allows to connect
30+ /// to certificate authories not included in the default set
31+ #[ structopt( short = "c" , long = "cafile" , parse( from_os_str) ) ]
32+ cafile : Option < PathBuf > ,
2333}
2434
2535fn main ( ) -> io:: Result < ( ) > {
@@ -40,7 +50,11 @@ fn main() -> io::Result<()> {
4050
4151 // Create default connector comes preconfigured with all you need to safely connect
4252 // to remote servers!
43- let connector = TlsConnector :: default ( ) ;
53+ let connector = if let Some ( cafile) = & options. cafile {
54+ connector_for_ca_file ( cafile) ?
55+ } else {
56+ TlsConnector :: default ( )
57+ } ;
4458
4559 task:: block_on ( async {
4660 // Open a normal TCP connection, just as you are used to
@@ -66,3 +80,13 @@ fn main() -> io::Result<()> {
6680 Ok ( ( ) )
6781 } )
6882}
83+
84+ fn connector_for_ca_file ( cafile : & Path ) -> io:: Result < TlsConnector > {
85+ let mut config = ClientConfig :: new ( ) ;
86+ let mut pem = BufReader :: new ( File :: open ( cafile) ?) ;
87+ config
88+ . root_store
89+ . add_pem_file ( & mut pem)
90+ . map_err ( |_| io:: Error :: new ( io:: ErrorKind :: InvalidInput , "invalid cert" ) ) ?;
91+ Ok ( TlsConnector :: from ( Arc :: new ( config) ) )
92+ }
0 commit comments