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