1 //! An abstraction over platform-specific TLS implementations.
2 //!
3 //! Many applications require TLS/SSL communication in one form or another as
4 //! part of their implementation, but finding a library for this isn't always
5 //! trivial! The purpose of this crate is to provide a seamless integration
6 //! experience on all platforms with a cross-platform API that deals with all
7 //! the underlying details for you.
8 //!
9 //! # How is this implemented?
10 //!
11 //! This crate uses SChannel on Windows (via the `schannel` crate), Secure
12 //! Transport on OSX (via the `security-framework` crate), and OpenSSL (via the
13 //! `openssl` crate) on all other platforms. Future futures may also enable
14 //! other TLS frameworks as well, but these initial libraries are likely to
15 //! remain as the defaults.
16 //!
17 //! Note that this crate also strives to be secure-by-default. For example when
18 //! using OpenSSL it will configure validation callbacks to ensure that
19 //! hostnames match certificates, use strong ciphers, etc. This implies that
20 //! this crate is *not* just a thin abstraction around the underlying libraries,
21 //! but also an implementation that strives to strike reasonable defaults.
22 //!
23 //! # Supported features
24 //!
25 //! This crate supports the following features out of the box:
26 //!
27 //! * TLS/SSL client communication
28 //! * TLS/SSL server communication
29 //! * PKCS#12 encoded identities
30 //! * Secure-by-default for client and server
31 //!     * Includes hostname verification for clients
32 //! * Supports asynchronous I/O for both the server and the client
33 //!
34 //! # Cargo Features
35 //!
36 //! * `vendored` - If enabled, the crate will compile and statically link to a
37 //!     vendored copy of OpenSSL. This feature has no effect on Windows and
38 //!     macOS, where OpenSSL is not used.
39 //!
40 //! # Examples
41 //!
42 //! To connect as a client to a remote server:
43 //!
44 //! ```rust
45 //! use native_tls::TlsConnector;
46 //! use std::io::{Read, Write};
47 //! use std::net::TcpStream;
48 //!
49 //! let connector = TlsConnector::new().unwrap();
50 //!
51 //! let stream = TcpStream::connect("google.com:443").unwrap();
52 //! let mut stream = connector.connect("google.com", stream).unwrap();
53 //!
54 //! stream.write_all(b"GET / HTTP/1.0\r\n\r\n").unwrap();
55 //! let mut res = vec![];
56 //! stream.read_to_end(&mut res).unwrap();
57 //! println!("{}", String::from_utf8_lossy(&res));
58 //! ```
59 //!
60 //! To accept connections as a server from remote clients:
61 //!
62 //! ```rust,no_run
63 //! use native_tls::{Identity, TlsAcceptor, TlsStream};
64 //! use std::fs::File;
65 //! use std::io::{Read};
66 //! use std::net::{TcpListener, TcpStream};
67 //! use std::sync::Arc;
68 //! use std::thread;
69 //!
70 //! let mut file = File::open("identity.pfx").unwrap();
71 //! let mut identity = vec![];
72 //! file.read_to_end(&mut identity).unwrap();
73 //! let identity = Identity::from_pkcs12(&identity, "hunter2").unwrap();
74 //!
75 //! let listener = TcpListener::bind("0.0.0.0:8443").unwrap();
76 //! let acceptor = TlsAcceptor::new(identity).unwrap();
77 //! let acceptor = Arc::new(acceptor);
78 //!
79 //! fn handle_client(stream: TlsStream<TcpStream>) {
80 //!     // ...
81 //! }
82 //!
83 //! for stream in listener.incoming() {
84 //!     match stream {
85 //!         Ok(stream) => {
86 //!             let acceptor = acceptor.clone();
87 //!             thread::spawn(move || {
88 //!                 let stream = acceptor.accept(stream).unwrap();
89 //!                 handle_client(stream);
90 //!             });
91 //!         }
92 //!         Err(e) => { /* connection failed */ }
93 //!     }
94 //! }
95 //! ```
96 #![doc(html_root_url = "https://docs.rs/native-tls/0.2")]
97 #![warn(missing_docs)]
98 #![cfg_attr(docsrs, feature(doc_cfg))]
99 
100 #[macro_use]
101 #[cfg(any(target_os = "macos", target_os = "ios"))]
102 extern crate lazy_static;
103 
104 use std::any::Any;
105 use std::error;
106 use std::fmt;
107 use std::io;
108 use std::result;
109 
110 #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))]
111 #[macro_use]
112 extern crate log;
113 #[cfg(any(target_os = "macos", target_os = "ios"))]
114 #[path = "imp/security_framework.rs"]
115 mod imp;
116 #[cfg(target_os = "windows")]
117 #[path = "imp/schannel.rs"]
118 mod imp;
119 #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))]
120 #[path = "imp/openssl.rs"]
121 mod imp;
122 
123 #[cfg(test)]
124 mod test;
125 
126 /// A typedef of the result-type returned by many methods.
127 pub type Result<T> = result::Result<T, Error>;
128 
129 /// An error returned from the TLS implementation.
130 pub struct Error(imp::Error);
131 
132 impl error::Error for Error {
source(&self) -> Option<&(dyn error::Error + 'static)>133     fn source(&self) -> Option<&(dyn error::Error + 'static)> {
134         error::Error::source(&self.0)
135     }
136 }
137 
138 impl fmt::Display for Error {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result139     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
140         fmt::Display::fmt(&self.0, fmt)
141     }
142 }
143 
144 impl fmt::Debug for Error {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result145     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
146         fmt::Debug::fmt(&self.0, fmt)
147     }
148 }
149 
150 impl From<imp::Error> for Error {
from(err: imp::Error) -> Error151     fn from(err: imp::Error) -> Error {
152         Error(err)
153     }
154 }
155 
156 /// A cryptographic identity.
157 ///
158 /// An identity is an X509 certificate along with its corresponding private key and chain of certificates to a trusted
159 /// root.
160 #[derive(Clone)]
161 pub struct Identity(imp::Identity);
162 
163 impl Identity {
164     /// Parses a DER-formatted PKCS #12 archive, using the specified password to decrypt the key.
165     ///
166     /// The archive should contain a leaf certificate and its private key, as well any intermediate
167     /// certificates that should be sent to clients to allow them to build a chain to a trusted
168     /// root. The chain certificates should be in order from the leaf certificate towards the root.
169     ///
170     /// PKCS #12 archives typically have the file extension `.p12` or `.pfx`, and can be created
171     /// with the OpenSSL `pkcs12` tool:
172     ///
173     /// ```bash
174     /// openssl pkcs12 -export -out identity.pfx -inkey key.pem -in cert.pem -certfile chain_certs.pem
175     /// ```
from_pkcs12(der: &[u8], password: &str) -> Result<Identity>176     pub fn from_pkcs12(der: &[u8], password: &str) -> Result<Identity> {
177         let identity = imp::Identity::from_pkcs12(der, password)?;
178         Ok(Identity(identity))
179     }
180 }
181 
182 /// An X509 certificate.
183 #[derive(Clone)]
184 pub struct Certificate(imp::Certificate);
185 
186 impl Certificate {
187     /// Parses a DER-formatted X509 certificate.
from_der(der: &[u8]) -> Result<Certificate>188     pub fn from_der(der: &[u8]) -> Result<Certificate> {
189         let cert = imp::Certificate::from_der(der)?;
190         Ok(Certificate(cert))
191     }
192 
193     /// Parses a PEM-formatted X509 certificate.
from_pem(pem: &[u8]) -> Result<Certificate>194     pub fn from_pem(pem: &[u8]) -> Result<Certificate> {
195         let cert = imp::Certificate::from_pem(pem)?;
196         Ok(Certificate(cert))
197     }
198 
199     /// Returns the DER-encoded representation of this certificate.
to_der(&self) -> Result<Vec<u8>>200     pub fn to_der(&self) -> Result<Vec<u8>> {
201         let der = self.0.to_der()?;
202         Ok(der)
203     }
204 }
205 
206 /// A TLS stream which has been interrupted midway through the handshake process.
207 pub struct MidHandshakeTlsStream<S>(imp::MidHandshakeTlsStream<S>);
208 
209 impl<S> fmt::Debug for MidHandshakeTlsStream<S>
210 where
211     S: fmt::Debug,
212 {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result213     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
214         fmt::Debug::fmt(&self.0, fmt)
215     }
216 }
217 
218 impl<S> MidHandshakeTlsStream<S> {
219     /// Returns a shared reference to the inner stream.
get_ref(&self) -> &S220     pub fn get_ref(&self) -> &S {
221         self.0.get_ref()
222     }
223 
224     /// Returns a mutable reference to the inner stream.
get_mut(&mut self) -> &mut S225     pub fn get_mut(&mut self) -> &mut S {
226         self.0.get_mut()
227     }
228 }
229 
230 impl<S> MidHandshakeTlsStream<S>
231 where
232     S: io::Read + io::Write,
233 {
234     /// Restarts the handshake process.
235     ///
236     /// If the handshake completes successfully then the negotiated stream is
237     /// returned. If there is a problem, however, then an error is returned.
238     /// Note that the error may not be fatal. For example if the underlying
239     /// stream is an asynchronous one then `HandshakeError::WouldBlock` may
240     /// just mean to wait for more I/O to happen later.
handshake(self) -> result::Result<TlsStream<S>, HandshakeError<S>>241     pub fn handshake(self) -> result::Result<TlsStream<S>, HandshakeError<S>> {
242         match self.0.handshake() {
243             Ok(s) => Ok(TlsStream(s)),
244             Err(e) => Err(e.into()),
245         }
246     }
247 }
248 
249 /// An error returned from `ClientBuilder::handshake`.
250 #[derive(Debug)]
251 pub enum HandshakeError<S> {
252     /// A fatal error.
253     Failure(Error),
254 
255     /// A stream interrupted midway through the handshake process due to a
256     /// `WouldBlock` error.
257     ///
258     /// Note that this is not a fatal error and it should be safe to call
259     /// `handshake` at a later time once the stream is ready to perform I/O
260     /// again.
261     WouldBlock(MidHandshakeTlsStream<S>),
262 }
263 
264 impl<S> error::Error for HandshakeError<S>
265 where
266     S: Any + fmt::Debug,
267 {
source(&self) -> Option<&(dyn error::Error + 'static)>268     fn source(&self) -> Option<&(dyn error::Error + 'static)> {
269         match *self {
270             HandshakeError::Failure(ref e) => Some(e),
271             HandshakeError::WouldBlock(_) => None,
272         }
273     }
274 }
275 
276 impl<S> fmt::Display for HandshakeError<S>
277 where
278     S: Any + fmt::Debug,
279 {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result280     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
281         match *self {
282             HandshakeError::Failure(ref e) => fmt::Display::fmt(e, fmt),
283             HandshakeError::WouldBlock(_) => fmt.write_str("the handshake process was interrupted"),
284         }
285     }
286 }
287 
288 impl<S> From<imp::HandshakeError<S>> for HandshakeError<S> {
from(e: imp::HandshakeError<S>) -> HandshakeError<S>289     fn from(e: imp::HandshakeError<S>) -> HandshakeError<S> {
290         match e {
291             imp::HandshakeError::Failure(e) => HandshakeError::Failure(Error(e)),
292             imp::HandshakeError::WouldBlock(s) => {
293                 HandshakeError::WouldBlock(MidHandshakeTlsStream(s))
294             }
295         }
296     }
297 }
298 
299 /// SSL/TLS protocol versions.
300 #[derive(Debug, Copy, Clone)]
301 pub enum Protocol {
302     /// The SSL 3.0 protocol.
303     ///
304     /// # Warning
305     ///
306     /// SSL 3.0 has severe security flaws, and should not be used unless absolutely necessary. If
307     /// you are not sure if you need to enable this protocol, you should not.
308     Sslv3,
309     /// The TLS 1.0 protocol.
310     Tlsv10,
311     /// The TLS 1.1 protocol.
312     Tlsv11,
313     /// The TLS 1.2 protocol.
314     Tlsv12,
315     #[doc(hidden)]
316     __NonExhaustive,
317 }
318 
319 /// A builder for `TlsConnector`s.
320 pub struct TlsConnectorBuilder {
321     identity: Option<Identity>,
322     min_protocol: Option<Protocol>,
323     max_protocol: Option<Protocol>,
324     root_certificates: Vec<Certificate>,
325     accept_invalid_certs: bool,
326     accept_invalid_hostnames: bool,
327     use_sni: bool,
328     disable_built_in_roots: bool,
329     #[cfg(feature = "alpn")]
330     alpn: Vec<String>,
331 }
332 
333 impl TlsConnectorBuilder {
334     /// Sets the identity to be used for client certificate authentication.
identity(&mut self, identity: Identity) -> &mut TlsConnectorBuilder335     pub fn identity(&mut self, identity: Identity) -> &mut TlsConnectorBuilder {
336         self.identity = Some(identity);
337         self
338     }
339 
340     /// Sets the minimum supported protocol version.
341     ///
342     /// A value of `None` enables support for the oldest protocols supported by the implementation.
343     ///
344     /// Defaults to `Some(Protocol::Tlsv10)`.
min_protocol_version(&mut self, protocol: Option<Protocol>) -> &mut TlsConnectorBuilder345     pub fn min_protocol_version(&mut self, protocol: Option<Protocol>) -> &mut TlsConnectorBuilder {
346         self.min_protocol = protocol;
347         self
348     }
349 
350     /// Sets the maximum supported protocol version.
351     ///
352     /// A value of `None` enables support for the newest protocols supported by the implementation.
353     ///
354     /// Defaults to `None`.
max_protocol_version(&mut self, protocol: Option<Protocol>) -> &mut TlsConnectorBuilder355     pub fn max_protocol_version(&mut self, protocol: Option<Protocol>) -> &mut TlsConnectorBuilder {
356         self.max_protocol = protocol;
357         self
358     }
359 
360     /// Adds a certificate to the set of roots that the connector will trust.
361     ///
362     /// The connector will use the system's trust root by default. This method can be used to add
363     /// to that set when communicating with servers not trusted by the system.
364     ///
365     /// Defaults to an empty set.
add_root_certificate(&mut self, cert: Certificate) -> &mut TlsConnectorBuilder366     pub fn add_root_certificate(&mut self, cert: Certificate) -> &mut TlsConnectorBuilder {
367         self.root_certificates.push(cert);
368         self
369     }
370 
371     /// Controls the use of built-in system certificates during certificate validation.
372     ///
373     /// Defaults to `false` -- built-in system certs will be used.
disable_built_in_roots(&mut self, disable: bool) -> &mut TlsConnectorBuilder374     pub fn disable_built_in_roots(&mut self, disable: bool) -> &mut TlsConnectorBuilder {
375         self.disable_built_in_roots = disable;
376         self
377     }
378 
379     /// Request specific protocols through ALPN (Application-Layer Protocol Negotiation).
380     ///
381     /// Defaults to no protocols.
382     #[cfg(feature = "alpn")]
383     #[cfg_attr(docsrs, doc(cfg(feature = "alpn")))]
request_alpns(&mut self, protocols: &[&str]) -> &mut TlsConnectorBuilder384     pub fn request_alpns(&mut self, protocols: &[&str]) -> &mut TlsConnectorBuilder {
385         self.alpn = protocols.iter().map(|s| (*s).to_owned()).collect();
386         self
387     }
388 
389     /// Controls the use of certificate validation.
390     ///
391     /// Defaults to `false`.
392     ///
393     /// # Warning
394     ///
395     /// You should think very carefully before using this method. If invalid certificates are trusted, *any*
396     /// certificate for *any* site will be trusted for use. This includes expired certificates. This introduces
397     /// significant vulnerabilities, and should only be used as a last resort.
danger_accept_invalid_certs( &mut self, accept_invalid_certs: bool, ) -> &mut TlsConnectorBuilder398     pub fn danger_accept_invalid_certs(
399         &mut self,
400         accept_invalid_certs: bool,
401     ) -> &mut TlsConnectorBuilder {
402         self.accept_invalid_certs = accept_invalid_certs;
403         self
404     }
405 
406     /// Controls the use of Server Name Indication (SNI).
407     ///
408     /// Defaults to `true`.
use_sni(&mut self, use_sni: bool) -> &mut TlsConnectorBuilder409     pub fn use_sni(&mut self, use_sni: bool) -> &mut TlsConnectorBuilder {
410         self.use_sni = use_sni;
411         self
412     }
413 
414     /// Controls the use of hostname verification.
415     ///
416     /// Defaults to `false`.
417     ///
418     /// # Warning
419     ///
420     /// You should think very carefully before using this method. If invalid hostnames are trusted, *any* valid
421     /// certificate for *any* site will be trusted for use. This introduces significant vulnerabilities, and should
422     /// only be used as a last resort.
danger_accept_invalid_hostnames( &mut self, accept_invalid_hostnames: bool, ) -> &mut TlsConnectorBuilder423     pub fn danger_accept_invalid_hostnames(
424         &mut self,
425         accept_invalid_hostnames: bool,
426     ) -> &mut TlsConnectorBuilder {
427         self.accept_invalid_hostnames = accept_invalid_hostnames;
428         self
429     }
430 
431     /// Creates a new `TlsConnector`.
build(&self) -> Result<TlsConnector>432     pub fn build(&self) -> Result<TlsConnector> {
433         let connector = imp::TlsConnector::new(self)?;
434         Ok(TlsConnector(connector))
435     }
436 }
437 
438 /// A builder for client-side TLS connections.
439 ///
440 /// # Examples
441 ///
442 /// ```rust
443 /// use native_tls::TlsConnector;
444 /// use std::io::{Read, Write};
445 /// use std::net::TcpStream;
446 ///
447 /// let connector = TlsConnector::new().unwrap();
448 ///
449 /// let stream = TcpStream::connect("google.com:443").unwrap();
450 /// let mut stream = connector.connect("google.com", stream).unwrap();
451 ///
452 /// stream.write_all(b"GET / HTTP/1.0\r\n\r\n").unwrap();
453 /// let mut res = vec![];
454 /// stream.read_to_end(&mut res).unwrap();
455 /// println!("{}", String::from_utf8_lossy(&res));
456 /// ```
457 #[derive(Clone, Debug)]
458 pub struct TlsConnector(imp::TlsConnector);
459 
460 impl TlsConnector {
461     /// Returns a new connector with default settings.
new() -> Result<TlsConnector>462     pub fn new() -> Result<TlsConnector> {
463         TlsConnector::builder().build()
464     }
465 
466     /// Returns a new builder for a `TlsConnector`.
builder() -> TlsConnectorBuilder467     pub fn builder() -> TlsConnectorBuilder {
468         TlsConnectorBuilder {
469             identity: None,
470             min_protocol: Some(Protocol::Tlsv10),
471             max_protocol: None,
472             root_certificates: vec![],
473             use_sni: true,
474             accept_invalid_certs: false,
475             accept_invalid_hostnames: false,
476             disable_built_in_roots: false,
477             #[cfg(feature = "alpn")]
478             alpn: vec![],
479         }
480     }
481 
482     /// Initiates a TLS handshake.
483     ///
484     /// The provided domain will be used for both SNI and certificate hostname
485     /// validation.
486     ///
487     /// If the socket is nonblocking and a `WouldBlock` error is returned during
488     /// the handshake, a `HandshakeError::WouldBlock` error will be returned
489     /// which can be used to restart the handshake when the socket is ready
490     /// again.
491     ///
492     /// The domain is ignored if both SNI and hostname verification are
493     /// disabled.
connect<S>( &self, domain: &str, stream: S, ) -> result::Result<TlsStream<S>, HandshakeError<S>> where S: io::Read + io::Write,494     pub fn connect<S>(
495         &self,
496         domain: &str,
497         stream: S,
498     ) -> result::Result<TlsStream<S>, HandshakeError<S>>
499     where
500         S: io::Read + io::Write,
501     {
502         let s = self.0.connect(domain, stream)?;
503         Ok(TlsStream(s))
504     }
505 }
506 
507 /// A builder for `TlsAcceptor`s.
508 pub struct TlsAcceptorBuilder {
509     identity: Identity,
510     min_protocol: Option<Protocol>,
511     max_protocol: Option<Protocol>,
512 }
513 
514 impl TlsAcceptorBuilder {
515     /// Sets the minimum supported protocol version.
516     ///
517     /// A value of `None` enables support for the oldest protocols supported by the implementation.
518     ///
519     /// Defaults to `Some(Protocol::Tlsv10)`.
min_protocol_version(&mut self, protocol: Option<Protocol>) -> &mut TlsAcceptorBuilder520     pub fn min_protocol_version(&mut self, protocol: Option<Protocol>) -> &mut TlsAcceptorBuilder {
521         self.min_protocol = protocol;
522         self
523     }
524 
525     /// Sets the maximum supported protocol version.
526     ///
527     /// A value of `None` enables support for the newest protocols supported by the implementation.
528     ///
529     /// Defaults to `None`.
max_protocol_version(&mut self, protocol: Option<Protocol>) -> &mut TlsAcceptorBuilder530     pub fn max_protocol_version(&mut self, protocol: Option<Protocol>) -> &mut TlsAcceptorBuilder {
531         self.max_protocol = protocol;
532         self
533     }
534 
535     /// Creates a new `TlsAcceptor`.
build(&self) -> Result<TlsAcceptor>536     pub fn build(&self) -> Result<TlsAcceptor> {
537         let acceptor = imp::TlsAcceptor::new(self)?;
538         Ok(TlsAcceptor(acceptor))
539     }
540 }
541 
542 /// A builder for server-side TLS connections.
543 ///
544 /// # Examples
545 ///
546 /// ```rust,no_run
547 /// use native_tls::{Identity, TlsAcceptor, TlsStream};
548 /// use std::fs::File;
549 /// use std::io::{Read};
550 /// use std::net::{TcpListener, TcpStream};
551 /// use std::sync::Arc;
552 /// use std::thread;
553 ///
554 /// let mut file = File::open("identity.pfx").unwrap();
555 /// let mut identity = vec![];
556 /// file.read_to_end(&mut identity).unwrap();
557 /// let identity = Identity::from_pkcs12(&identity, "hunter2").unwrap();
558 ///
559 /// let listener = TcpListener::bind("0.0.0.0:8443").unwrap();
560 /// let acceptor = TlsAcceptor::new(identity).unwrap();
561 /// let acceptor = Arc::new(acceptor);
562 ///
563 /// fn handle_client(stream: TlsStream<TcpStream>) {
564 ///     // ...
565 /// }
566 ///
567 /// for stream in listener.incoming() {
568 ///     match stream {
569 ///         Ok(stream) => {
570 ///             let acceptor = acceptor.clone();
571 ///             thread::spawn(move || {
572 ///                 let stream = acceptor.accept(stream).unwrap();
573 ///                 handle_client(stream);
574 ///             });
575 ///         }
576 ///         Err(e) => { /* connection failed */ }
577 ///     }
578 /// }
579 /// ```
580 #[derive(Clone)]
581 pub struct TlsAcceptor(imp::TlsAcceptor);
582 
583 impl TlsAcceptor {
584     /// Creates a acceptor with default settings.
585     ///
586     /// The identity acts as the server's private key/certificate chain.
new(identity: Identity) -> Result<TlsAcceptor>587     pub fn new(identity: Identity) -> Result<TlsAcceptor> {
588         TlsAcceptor::builder(identity).build()
589     }
590 
591     /// Returns a new builder for a `TlsAcceptor`.
592     ///
593     /// The identity acts as the server's private key/certificate chain.
builder(identity: Identity) -> TlsAcceptorBuilder594     pub fn builder(identity: Identity) -> TlsAcceptorBuilder {
595         TlsAcceptorBuilder {
596             identity,
597             min_protocol: Some(Protocol::Tlsv10),
598             max_protocol: None,
599         }
600     }
601 
602     /// Initiates a TLS handshake.
603     ///
604     /// If the socket is nonblocking and a `WouldBlock` error is returned during
605     /// the handshake, a `HandshakeError::WouldBlock` error will be returned
606     /// which can be used to restart the handshake when the socket is ready
607     /// again.
accept<S>(&self, stream: S) -> result::Result<TlsStream<S>, HandshakeError<S>> where S: io::Read + io::Write,608     pub fn accept<S>(&self, stream: S) -> result::Result<TlsStream<S>, HandshakeError<S>>
609     where
610         S: io::Read + io::Write,
611     {
612         match self.0.accept(stream) {
613             Ok(s) => Ok(TlsStream(s)),
614             Err(e) => Err(e.into()),
615         }
616     }
617 }
618 
619 /// A stream managing a TLS session.
620 pub struct TlsStream<S>(imp::TlsStream<S>);
621 
622 impl<S: fmt::Debug> fmt::Debug for TlsStream<S> {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result623     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
624         fmt::Debug::fmt(&self.0, fmt)
625     }
626 }
627 
628 impl<S> TlsStream<S> {
629     /// Returns a shared reference to the inner stream.
get_ref(&self) -> &S630     pub fn get_ref(&self) -> &S {
631         self.0.get_ref()
632     }
633 
634     /// Returns a mutable reference to the inner stream.
get_mut(&mut self) -> &mut S635     pub fn get_mut(&mut self) -> &mut S {
636         self.0.get_mut()
637     }
638 }
639 
640 impl<S: io::Read + io::Write> TlsStream<S> {
641     /// Returns the number of bytes that can be read without resulting in any
642     /// network calls.
buffered_read_size(&self) -> Result<usize>643     pub fn buffered_read_size(&self) -> Result<usize> {
644         Ok(self.0.buffered_read_size()?)
645     }
646 
647     /// Returns the peer's leaf certificate, if available.
peer_certificate(&self) -> Result<Option<Certificate>>648     pub fn peer_certificate(&self) -> Result<Option<Certificate>> {
649         Ok(self.0.peer_certificate()?.map(Certificate))
650     }
651 
652     /// Returns the tls-server-end-point channel binding data as defined in [RFC 5929].
653     ///
654     /// [RFC 5929]: https://tools.ietf.org/html/rfc5929
tls_server_end_point(&self) -> Result<Option<Vec<u8>>>655     pub fn tls_server_end_point(&self) -> Result<Option<Vec<u8>>> {
656         Ok(self.0.tls_server_end_point()?)
657     }
658 
659     /// Returns the negotiated ALPN protocol.
660     #[cfg(feature = "alpn")]
661     #[cfg_attr(docsrs, doc(cfg(feature = "alpn")))]
negotiated_alpn(&self) -> Result<Option<Vec<u8>>>662     pub fn negotiated_alpn(&self) -> Result<Option<Vec<u8>>> {
663         Ok(self.0.negotiated_alpn()?)
664     }
665 
666     /// Shuts down the TLS session.
shutdown(&mut self) -> io::Result<()>667     pub fn shutdown(&mut self) -> io::Result<()> {
668         self.0.shutdown()?;
669         Ok(())
670     }
671 }
672 
673 impl<S: io::Read + io::Write> io::Read for TlsStream<S> {
read(&mut self, buf: &mut [u8]) -> io::Result<usize>674     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
675         self.0.read(buf)
676     }
677 }
678 
679 impl<S: io::Read + io::Write> io::Write for TlsStream<S> {
write(&mut self, buf: &[u8]) -> io::Result<usize>680     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
681         self.0.write(buf)
682     }
683 
flush(&mut self) -> io::Result<()>684     fn flush(&mut self) -> io::Result<()> {
685         self.0.flush()
686     }
687 }
688 
_check_kinds()689 fn _check_kinds() {
690     use std::net::TcpStream;
691 
692     fn is_sync<T: Sync>() {}
693     fn is_send<T: Send>() {}
694     is_sync::<Error>();
695     is_send::<Error>();
696     is_sync::<TlsConnectorBuilder>();
697     is_send::<TlsConnectorBuilder>();
698     is_sync::<TlsConnector>();
699     is_send::<TlsConnector>();
700     is_sync::<TlsAcceptorBuilder>();
701     is_send::<TlsAcceptorBuilder>();
702     is_sync::<TlsAcceptor>();
703     is_send::<TlsAcceptor>();
704     is_sync::<TlsStream<TcpStream>>();
705     is_send::<TlsStream<TcpStream>>();
706     is_sync::<MidHandshakeTlsStream<TcpStream>>();
707     is_send::<MidHandshakeTlsStream<TcpStream>>();
708 }
709