@@ -9,7 +9,7 @@ use std::net::SocketAddr;
9
9
use std:: slice:: Chunks ;
10
10
use std:: time:: Duration ;
11
11
12
- #[ cfg( all( feature = "ssl" , not ( target_os = "windows" ) ) ) ]
12
+ #[ cfg( all( feature = "ssl" ) ) ]
13
13
use crate :: conn:: SslOpts ;
14
14
15
15
use super :: consts;
@@ -32,6 +32,14 @@ use flate2::{read::ZlibDecoder, write::ZlibEncoder, Compression};
32
32
use named_pipe as np;
33
33
#[ cfg( all( feature = "ssl" , all( unix, not( target_os = "macos" ) ) ) ) ]
34
34
use openssl:: ssl:: { self , SslContext , SslStream } ;
35
+ #[ cfg( all( feature = "ssl" , target_os = "windows" ) ) ]
36
+ use schannel:: cert_context:: CertContext ;
37
+ #[ cfg( all( feature = "ssl" , target_os = "windows" ) ) ]
38
+ use schannel:: cert_store;
39
+ #[ cfg( all( feature = "ssl" , target_os = "windows" ) ) ]
40
+ use schannel:: schannel_cred;
41
+ #[ cfg( all( feature = "ssl" , target_os = "windows" ) ) ]
42
+ use schannel:: tls_stream;
35
43
#[ cfg( all( feature = "ssl" , target_os = "macos" ) ) ]
36
44
use security_framework:: certificate:: SecCertificate ;
37
45
#[ cfg( all( feature = "ssl" , target_os = "macos" ) ) ]
@@ -763,6 +771,103 @@ impl Stream {
763
771
}
764
772
}
765
773
774
+ #[ cfg( all( feature = "ssl" , target_os = "windows" ) ) ]
775
+ impl Stream {
776
+ pub fn make_secure (
777
+ mut self ,
778
+ verify_peer : bool ,
779
+ ip_or_hostname : Option < & str > ,
780
+ ssl_opts : & SslOpts ,
781
+ ) -> MyResult < Stream > {
782
+ use std:: path:: Path ;
783
+
784
+ fn load_cert_data ( path : & Path ) -> MyResult < String > {
785
+ let mut client_file = :: std:: fs:: File :: open ( path) ?;
786
+ let mut client_data = String :: new ( ) ;
787
+ client_file. read_to_string ( & mut client_data) ?;
788
+ Ok ( client_data)
789
+ }
790
+
791
+ fn load_client_cert ( path : & Path ) -> MyResult < CertContext > {
792
+ let cert_data = load_cert_data ( path) ?;
793
+ let cert = CertContext :: from_pem ( & cert_data) ?;
794
+ Ok ( cert)
795
+ }
796
+
797
+ fn load_client_cert_with_key ( cert_path : & Path , key_path : & Path ) -> MyResult < CertContext > {
798
+ let mut cert_data = load_cert_data ( cert_path) ?;
799
+ let cert = CertContext :: from_pem ( & cert_data) ?;
800
+ let key_data = load_cert_data ( key_path) ?;
801
+ cert_data. push_str ( & key_data) ;
802
+ Ok ( cert)
803
+ }
804
+
805
+ fn load_ca_store ( path : & Path ) -> MyResult < cert_store:: CertStore > {
806
+ let ca_cert = load_client_cert ( path) ?;
807
+ let mut cert_store = cert_store:: Memory :: new ( ) . unwrap ( ) . into_store ( ) ;
808
+ cert_store. add_cert ( & ca_cert, cert_store:: CertAdd :: Always ) ?;
809
+ Ok ( cert_store)
810
+ }
811
+
812
+ if self . is_insecure ( ) {
813
+ let mut stream_builder = tls_stream:: Builder :: new ( ) ;
814
+ let mut cred_builder = schannel_cred:: Builder :: default ( ) ;
815
+ cred_builder. enabled_protocols ( & [
816
+ schannel_cred:: Protocol :: Tls10 ,
817
+ schannel_cred:: Protocol :: Tls11 ,
818
+ ] ) ;
819
+ cred_builder. supported_algorithms ( & [
820
+ schannel_cred:: Algorithm :: DhEphem ,
821
+ schannel_cred:: Algorithm :: RsaSign ,
822
+ schannel_cred:: Algorithm :: Aes256 ,
823
+ schannel_cred:: Algorithm :: Sha1 ,
824
+ ] ) ;
825
+ if verify_peer {
826
+ stream_builder. domain ( ip_or_hostname. as_ref ( ) . unwrap_or ( & ( "localhost" . into ( ) ) ) ) ;
827
+ }
828
+
829
+ match * ssl_opts {
830
+ Some ( ( ref ca_cert, None ) ) => {
831
+ stream_builder. cert_store ( load_ca_store ( & ca_cert) ?) ;
832
+ }
833
+ Some ( ( ref ca_cert, Some ( ( ref client_cert, ref client_key) ) ) ) => {
834
+ cred_builder. cert ( load_client_cert_with_key ( & client_cert, & client_key) ?) ;
835
+ stream_builder. cert_store ( load_ca_store ( & ca_cert) ?) ;
836
+ }
837
+ _ => unreachable ! ( ) ,
838
+ }
839
+
840
+ let cred = cred_builder. acquire ( schannel_cred:: Direction :: Outbound ) ?;
841
+ match self {
842
+ Stream :: TcpStream ( ref mut opt_stream) if opt_stream. is_some ( ) => {
843
+ let stream = opt_stream. take ( ) . unwrap ( ) ;
844
+ match stream {
845
+ TcpStream :: Insecure ( mut stream) => {
846
+ stream. flush ( ) ?;
847
+ let s_stream = match stream_builder
848
+ . connect ( cred, stream. into_inner ( ) . unwrap ( ) )
849
+ {
850
+ Ok ( s_stream) => s_stream,
851
+ Err ( tls_stream:: HandshakeError :: Failure ( err) ) => {
852
+ return Err ( err. into ( ) ) ;
853
+ }
854
+ Err ( tls_stream:: HandshakeError :: Interrupted ( _) ) => unreachable ! ( ) ,
855
+ } ;
856
+ Ok ( Stream :: TcpStream ( Some ( TcpStream :: Secure ( BufStream :: new (
857
+ s_stream,
858
+ ) ) ) ) )
859
+ }
860
+ _ => unreachable ! ( ) ,
861
+ }
862
+ }
863
+ _ => unreachable ! ( ) ,
864
+ }
865
+ } else {
866
+ Ok ( self )
867
+ }
868
+ }
869
+ }
870
+
766
871
#[ cfg( all( feature = "ssl" , not( target_os = "macos" ) , unix) ) ]
767
872
impl Stream {
768
873
pub fn make_secure (
@@ -838,13 +943,15 @@ impl Drop for Stream {
838
943
pub enum TcpStream {
839
944
#[ cfg( all( feature = "ssl" , any( unix, target_os = "macos" ) ) ) ]
840
945
Secure ( BufStream < SslStream < net:: TcpStream > > ) ,
946
+ #[ cfg( all( feature = "ssl" , target_os = "windows" ) ) ]
947
+ Secure ( BufStream < tls_stream:: TlsStream < net:: TcpStream > > ) ,
841
948
Insecure ( BufStream < net:: TcpStream > ) ,
842
949
}
843
950
844
951
impl AsMut < dyn IoPack > for TcpStream {
845
952
fn as_mut ( & mut self ) -> & mut dyn IoPack {
846
953
match * self {
847
- #[ cfg( all( feature = "ssl" , any( unix, target_os = "macos" ) ) ) ]
954
+ #[ cfg( all( feature = "ssl" , any( unix, target_os = "macos" , target_os = "windows" ) ) ) ]
848
955
TcpStream :: Secure ( ref mut stream) => stream,
849
956
TcpStream :: Insecure ( ref mut stream) => stream,
850
957
}
@@ -854,7 +961,7 @@ impl AsMut<dyn IoPack> for TcpStream {
854
961
impl fmt:: Debug for TcpStream {
855
962
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
856
963
match * self {
857
- #[ cfg( all( feature = "ssl" , any( unix, target_os = "macos" ) ) ) ]
964
+ #[ cfg( all( feature = "ssl" , any( unix, target_os = "macos" , target_os = "windows" ) ) ) ]
858
965
TcpStream :: Secure ( _) => write ! ( f, "Secure stream" ) ,
859
966
TcpStream :: Insecure ( ref s) => write ! ( f, "Insecure stream {:?}" , s) ,
860
967
}
0 commit comments