Skip to main content

native_tls/
lib.rs

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