Skip to main content

libtls/
config.rs

1// Copyright (c) 2019 Reyk Floeter <contact@reykfloeter.com>
2//
3// Permission to use, copy, modify, and distribute this software for any
4// purpose with or without fee is hereby granted, provided that the above
5// copyright notice and this permission notice appear in all copies.
6//
7// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
10// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
13// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14//
15// The documentation is based on libtls man pages of the LibreSSL project,
16// provided under the same ISC-style license (see https://www.libressl.org/):
17//
18// Copyright (c) 2015, 2016 Bob Beck <beck@openbsd.org>
19// Copyright (c) 2016 Brent Cook <bcook@openbsd.org>
20// Copyright (c) 2017 Claudio Jeker <claudio@openbsd.org>
21// Copyright (c) 2015 Doug Hogan <doug@openbsd.org>
22// Copyright (c) 2017 Ingo Schwarze <schwarze@openbsd.org>
23// Copyright (c) 2014, 2015, 2016, 2017, 2018 Joel Sing <jsing@openbsd.org>
24// Copyright (c) 2015 Reyk Floeter <reyk@openbsd.org>
25// Copyright (c) 2014, 2015 Ted Unangst <tedu@openbsd.org>
26//
27// Permission to use, copy, modify, and distribute this software for any
28// purpose with or without fee is hereby granted, provided that the above
29// copyright notice and this permission notice appear in all copies.
30//
31// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
32// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
33// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
34// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
35// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
36// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
37// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
38
39//! [`Tls`] clients and servers are configured with the [`Config`]
40//! configuration context and its helper funtions.
41//!
42//! # Example
43//!
44//! ```
45//! use libtls::{config::{self, Config}, error};
46//!
47//! fn tls_server_config() -> error::Result<Config> {
48//!     let mut tls_config = Config::new()?;
49//!
50//!     let valid_cert = include_bytes!("../tests/eccert.crt");
51//!     let valid_key = include_bytes!("../tests/eccert.key");
52//!
53//!     // Sets the key pair and wipes the private key file from memory afterwards
54//!     let res = tls_config.set_keypair_mem(valid_cert, valid_key);
55//!     config::unload_file(valid_key.to_vec());
56//!     res?;
57//!
58//!     // The following examples are all set by default and it is not
59//!     // not required to set them.
60//!     tls_config.set_ciphers("secure")?;
61//!     tls_config.set_protocols(libtls::TLS_PROTOCOLS_DEFAULT)?;
62//!     tls_config.prefer_ciphers_server();
63//!     tls_config.verify();
64//!
65//!     Ok(tls_config)
66//! }
67//! # let tls_config = tls_server_config().unwrap();
68//! ```
69//!
70//! [`Tls`]: ../tls/struct.Tls.html
71//! [`Config`]: struct.Config.html
72
73use crate::{error, tls::Tls, util::*};
74use std::{
75    collections::HashMap,
76    convert::TryInto,
77    ffi::{CStr, CString},
78    io,
79    marker::{Send, Sync},
80    os::unix::io::RawFd,
81    path::{Path, PathBuf},
82};
83
84/// The TLS configuration context for [`Tls`] connections.
85///
86/// Before a [`Tls`] connection is created, a configuration must be created.
87/// Several methods exist to change the options of the configuration; see
88/// [`set_protocols`], [`ocsp_require_stapling`], [`verify`].
89///
90/// [`Tls`]: ../tls/struct.Tls.html
91/// [`ocsp_require_stapling`]: #method.ocsp_require_stapling
92/// [`set_protocols`]: #method.set_protocols
93/// [`tls_config_load_file`]: ../fn.tls_config_load_file.html
94/// [`verify`]: #method.verify
95#[derive(Debug)]
96pub struct Config(pub(crate) *mut libtls_sys::tls_config);
97
98/// The TLS configuration context for [`Tls`] connections.
99#[deprecated(since = "1.1.1", note = "Please use `Config` instead of `TlsConfig`")]
100pub type TlsConfig = Config;
101
102impl Config {
103    /// Create a new configuration.
104    ///
105    /// The `new` function allocates, initializes, and returns a new default
106    /// configuration object that can be used for future [`Tls`] connections.
107    ///
108    /// # Errors
109    ///
110    /// Returns an [`io::Error`] on error or an out of memory condition.
111    ///
112    /// # Example
113    ///
114    /// ```
115    /// # use libtls::{config::Config, error::Result};
116    /// # fn tls_config() -> Result<()> {
117    /// let config = Config::new()?;
118    /// #     Ok(())
119    /// # }
120    /// # tls_config().unwrap();
121    /// ```
122    ///
123    /// # See also
124    ///
125    /// [`tls_config_new(3)`](https://man.openbsd.org/tls_config_new.3)
126    ///
127    /// [`Tls`]: ../tls/struct.Tls.html
128    /// [`io::Error`]: https://doc.rust-lang.org/std/io/struct.Error.html
129    pub fn new() -> io::Result<Self> {
130        let config = unsafe { libtls_sys::tls_config_new() };
131        if config.is_null() {
132            Err(io::Error::last_os_error())
133        } else {
134            Ok(Config(config))
135        }
136    }
137
138    /// Wrap a raw C `tls_config` object.
139    ///
140    /// # Safety
141    ///
142    /// This function assumes that the raw pointer is valid, and takes
143    /// ownership of the libtls object.
144    /// Do not call `tls_free` yourself, since the `drop` destructor will
145    /// take care of it.
146    ///
147    /// # Panics
148    ///
149    /// Panics if `config` is a null pointer.
150    pub unsafe fn from_sys(config: *mut libtls_sys::tls_config) -> Self {
151        if config.is_null() {
152            panic!(io::Error::last_os_error())
153        }
154        Config(config)
155    }
156
157    /// Add additional files of a public and private key pair.
158    ///
159    /// The `add_keypair_file` method adds an additional public certificate, and
160    /// private key from the specified files, used as an alternative certificate
161    /// for Server Name Indication (server only).
162    ///
163    /// # Example
164    ///
165    /// ```
166    /// # use libtls::{config::Config, error::Result};
167    /// # fn tls_config() -> Result<()> {
168    /// let mut config = Config::new()?;
169    /// assert!(config.add_keypair_file("does_not_exist.crt", "does_not_exist.key").is_err());
170    /// #     Ok(())
171    /// # }
172    /// # tls_config().unwrap();
173    /// ```
174    ///
175    /// # See also
176    ///
177    /// [`tls_config_add_keypair_file(3)`](https://man.openbsd.org/tls_config_add_keypair_file.3)
178    pub fn add_keypair_file<P: AsRef<Path>>(
179        &mut self,
180        cert_file: P,
181        key_file: P,
182    ) -> error::Result<()> {
183        call_file2(
184            self,
185            (cert_file, "cert file"),
186            (key_file, "key file"),
187            libtls_sys::tls_config_add_keypair_file,
188        )
189    }
190
191    /// Add an additional public and private key pair from memory.
192    ///
193    /// The `add_keypair_mem` method adds an additional public certificate, and
194    /// private key from memory, used as an alternative certificate for Server
195    /// Name Indication (server only).
196    ///
197    /// # Example
198    ///
199    /// ```
200    /// # use libtls::{config::Config, error::Result};
201    /// # fn tls_config() -> Result<()> {
202    /// let mut config = Config::new()?;
203    /// let valid_cert = include_bytes!("../tests/eccert.crt");
204    /// let valid_key = include_bytes!("../tests/eccert.key");
205    /// config.add_keypair_mem(valid_cert, valid_key)?;
206    /// #     Ok(())
207    /// # }
208    /// # tls_config().unwrap();
209    /// ```
210    ///
211    /// # See also
212    ///
213    /// [`tls_config_add_keypair_mem(3)`](https://man.openbsd.org/tls_config_add_keypair_mem.3)
214    pub fn add_keypair_mem(&mut self, cert: &[u8], key: &[u8]) -> error::Result<()> {
215        cvt(self, unsafe {
216            libtls_sys::tls_config_add_keypair_mem(
217                self.0,
218                cert.as_ptr(),
219                cert.len().try_into()?,
220                key.as_ptr(),
221                key.len().try_into()?,
222            )
223        })
224    }
225
226    /// Add additional files of a public and private key pair and an OCSP staple.
227    ///
228    /// The `add_keypair_ocsp_file` method adds an additional public certificate,
229    /// private key, and DER-encoded OCSP staple from the specified files, used
230    /// as an alternative certificate for Server Name Indication (server only).
231    ///
232    /// # See also
233    ///
234    /// [`add_keypair_file`](#method.add_keypair_file),
235    /// [`tls_config_add_keypair_ocsp_file(3)`](https://man.openbsd.org/tls_config_add_keypair_ocsp_file.3)
236    pub fn add_keypair_ocsp_file<P: AsRef<Path>>(
237        &mut self,
238        cert_file: P,
239        key_file: P,
240        ocsp_staple_file: P,
241    ) -> error::Result<()> {
242        call_file3(
243            self,
244            (cert_file, "cert file"),
245            (key_file, "key file"),
246            (ocsp_staple_file, "ocsp staple file"),
247            libtls_sys::tls_config_add_keypair_ocsp_file,
248        )
249    }
250
251    /// Add an additional public and private key pair and OCSP staple from memory.
252    ///
253    /// The `add_keypair_ocsp_mem` method adds an additional public certificate,
254    /// private key, and DER-encoded OCSP staple from memory, used as an
255    /// alternative certificate for Server Name Indication (server only).
256    ///
257    /// # See also
258    ///
259    /// [`add_keypair_mem`](#method.add_keypair_mem),
260    /// [`tls_config_add_keypair_ocsp_mem(3)`](https://man.openbsd.org/tls_config_add_keypair_ocsp_mem.3)
261    pub fn add_keypair_ocsp_mem(
262        &mut self,
263        cert: &[u8],
264        key: &[u8],
265        ocsp_staple: &[u8],
266    ) -> error::Result<()> {
267        cvt(self, unsafe {
268            libtls_sys::tls_config_add_keypair_ocsp_mem(
269                self.0,
270                cert.as_ptr(),
271                cert.len().try_into()?,
272                key.as_ptr(),
273                key.len().try_into()?,
274                ocsp_staple.as_ptr(),
275                ocsp_staple.len().try_into()?,
276            )
277        })
278    }
279
280    /// Set the ALPN protocols that are supported.
281    ///
282    /// The `set_alpn` method sets the ALPN protocols that are supported.  The
283    /// alpn string is a comma separated list of protocols, in order of
284    /// preference.
285    ///
286    /// # Example
287    ///
288    /// ```
289    /// # use libtls::{config::Config, error::Result};
290    /// # fn tls_config() -> Result<()> {
291    /// let mut config = Config::new()?;
292    ///
293    /// // The `h2` ALPN is used by HTTP/2:
294    /// config.set_alpn("h2")?;
295    /// #     Ok(())
296    /// # }
297    /// # tls_config().unwrap();
298    /// ```
299    ///
300    /// # See also
301    ///
302    /// [`tls_config_set_alpn(3)`](https://man.openbsd.org/tls_config_set_alpn.3)
303    pub fn set_alpn(&mut self, alpn: &str) -> error::Result<()> {
304        call_string1(self, alpn, libtls_sys::tls_config_set_alpn)
305    }
306
307    /// Set the CA file.
308    ///
309    /// The `set_ca_file` method sets the filename used to load a file containing
310    /// the root certificates.  The default filename can be returned with the
311    /// [`default_ca_cert_file`] function.
312    ///
313    /// # See also
314    ///
315    /// [`add_keypair_file`](#method.add_keypair_file.html),
316    /// [`tls_config_set_ca_file(3)`](https://man.openbsd.org/tls_config_set_ca_file.3)
317    ///
318    /// [`default_ca_cert_file`]: fn.default_ca_cert_file.html
319    pub fn set_ca_file<P: AsRef<Path>>(&mut self, ca_file: P) -> error::Result<()> {
320        call_file1(
321            self,
322            (ca_file, "ca file"),
323            libtls_sys::tls_config_set_ca_file,
324        )
325    }
326
327    /// Set the path that should be searched for the CA files.
328    ///
329    /// The `set_ca_path` method sets sets the path (directory) which should be
330    /// searched for root certificates.
331    ///
332    /// # See also
333    ///
334    /// [`set_ca_file`](#method.set_ca_file.html),
335    /// [`tls_config_set_ca_path(3)`](https://man.openbsd.org/tls_config_set_ca_path.3)
336    pub fn set_ca_path<P: AsRef<Path>>(&mut self, ca_path: P) -> error::Result<()> {
337        call_file1(
338            self,
339            (ca_path, "ca path"),
340            libtls_sys::tls_config_set_ca_path,
341        )
342    }
343
344    /// Set the CA from memory.
345    ///
346    /// The `set_ca_mem` method directly sets the root certificates directly from memory.
347    ///
348    ///
349    /// # See also
350    ///
351    /// [`add_keypair_mem`](#method.add_keypair_mem),
352    /// [`tls_config_set_ca_mem(3)`](https://man.openbsd.org/tls_config_set_ca_mem.3)
353    pub fn set_ca_mem(&mut self, ca: &[u8]) -> error::Result<()> {
354        cvt(self, unsafe {
355            libtls_sys::tls_config_set_ca_mem(self.0, ca.as_ptr(), ca.len().try_into()?)
356        })
357    }
358
359    /// Set the CA file from memory.
360    ///
361    /// The `set_ca_mem` method sets the root certificates directly from memory.
362    ///
363    /// # See also
364    ///
365    /// [`add_keypair_mem`](#method.add_keypair_mem.html),
366    /// [`tls_config_set_ca_mem(3)`](https://man.openbsd.org/tls_config_set_ca_mem.3)
367    pub fn tls_config_set_ca_mem(&mut self, ca: &[u8]) -> error::Result<()> {
368        cvt(self, unsafe {
369            libtls_sys::tls_config_set_ca_mem(self.0, ca.as_ptr(), ca.len().try_into()?)
370        })
371    }
372
373    /// Set the public certificate file.
374    ///
375    /// The `set_cert_file` method sets file from which the public certificate
376    /// will be read.
377    ///
378    /// # See also
379    ///
380    /// [`add_keypair_file`](#method.add_keypair_file),
381    /// [`tls_config_set_cert_file(3)`](https://man.openbsd.org/tls_config_set_cert_file.3)
382    pub fn set_cert_file<P: AsRef<Path>>(&mut self, cert_file: P) -> error::Result<()> {
383        call_file1(
384            self,
385            (cert_file, "cert file"),
386            libtls_sys::tls_config_set_cert_file,
387        )
388    }
389
390    /// Set the public certificate from memory.
391    ///
392    /// The `set_cert_mem` method sets the public certificate directly from
393    /// memory.
394    ///
395    /// # See also
396    ///
397    /// [`add_keypair_mem`](#method.add_keypair_mem),
398    /// [`tls_config_set_cert_mem(3)`](https://man.openbsd.org/tls_config_set_cert_mem.3)
399    pub fn set_cert_mem(&mut self, cert: &[u8]) -> error::Result<()> {
400        cvt(self, unsafe {
401            libtls_sys::tls_config_set_cert_mem(self.0, cert.as_ptr(), cert.len().try_into()?)
402        })
403    }
404
405    /// Set the list of cipher that may be used.
406    ///
407    /// The `set_ciphers` method sets the list of ciphers that may be used.
408    /// Lists of ciphers are specified by name, and the permitted names are:
409    ///
410    /// * `secure` (or alias `default`)
411    /// * `compat`
412    /// * `legacy`
413    /// * `insecure` (or alias `all`)
414    ///
415    /// Alternatively, libssl cipher strings can be specified.  See the CIPHERS
416    /// section of [`openssl(1)`] for further information.
417    ///
418    /// # Example
419    ///
420    /// ```
421    /// # use libtls::{config::Config, error::Result};
422    /// # fn tls_config() -> Result<()> {
423    /// let mut config = Config::new()?;
424    ///
425    /// // Only use `compat` if you run into problems with the `secure` default!
426    /// config.set_ciphers("compat")?;
427    /// #     Ok(())
428    /// # }
429    /// # tls_config().unwrap();
430    /// ```
431    ///
432    /// # See also
433    ///
434    /// [`openssl(1)`],
435    /// [`tls_config_set_ciphers(3)`](https://man.openbsd.org/tls_config_set_ciphers.3)
436    ///
437    /// [`openssl(1)`]: http://man.openbsd.org/openssl.1#CIPHERS
438    pub fn set_ciphers(&mut self, ciphers: &str) -> error::Result<()> {
439        call_string1(self, ciphers, libtls_sys::tls_config_set_ciphers)
440    }
441
442    /// Set the CRL file.
443    ///
444    /// The `set_crl_file` method sets the filename used to load a file
445    /// containing the Certificate Revocation List (CRL).
446    ///
447    /// # See also
448    ///
449    /// [`add_keypair_file`](#method.add_keypair_file.html),
450    /// [`tls_config_set_crl_file(3)`](https://man.openbsd.org/tls_config_set_crl_file.3)
451    pub fn set_crl_file<P: AsRef<Path>>(&mut self, crl_file: P) -> error::Result<()> {
452        call_file1(
453            self,
454            (crl_file, "crl file"),
455            libtls_sys::tls_config_set_crl_file,
456        )
457    }
458
459    /// Set the CRL from memory.
460    ///
461    /// The `set_crl_mem` method sets the Certificate Revocation List (CRL)
462    /// directly from memory.
463    ///
464    /// # See also
465    ///
466    /// [`add_keypair_mem`](#method.add_keypair_mem.html),
467    /// [`tls_config_set_crl_mem(3)`](https://man.openbsd.org/tls_config_set_crl_mem.3)
468    pub fn set_crl_mem(&mut self, crl: &[u8]) -> error::Result<()> {
469        cvt(self, unsafe {
470            libtls_sys::tls_config_set_crl_mem(self.0, crl.as_ptr(), crl.len().try_into()?)
471        })
472    }
473
474    /// Set the parameters of an Diffie-Hellman Ephemeral (DHE) key exchange.
475    ///
476    /// The `set_dheparams` method specifies the parameters that will be used
477    /// during Diffie-Hellman Ephemeral (DHE) key exchange.  Possible values are
478    /// `none`, `auto` and `legacy`.  In `auto` mode, the key size for the
479    /// ephemeral key is automatically selected based on the size of the private
480    /// key being used for signing.  In `legacy` mode, 1024 bit ephemeral keys
481    /// are used.  The default value is `none`, which disables DHE key exchange.
482    ///
483    /// # Example
484    ///
485    /// ```
486    /// # use libtls::{config::Config, error::Result};
487    /// # fn tls_config() -> Result<()> {
488    /// let mut config = Config::new()?;
489    /// config.set_dheparams("auto")?;
490    /// #     Ok(())
491    /// # }
492    /// # tls_config().unwrap();
493    /// ```
494    ///
495    /// # See also
496    ///
497    /// [`tls_config_set_dheparams(3)`](https://man.openbsd.org/tls_config_set_dheparams.3)
498    pub fn set_dheparams(&mut self, dheparams: &str) -> error::Result<()> {
499        call_string1(self, dheparams, libtls_sys::tls_config_set_dheparams)
500    }
501
502    /// The `set_ecdhecurve` method was replaced by [set_ecdhecurves](#method.set_ecdhecurves).
503    #[deprecated(
504        since = "2.6.1-LibreSSL",
505        note = "Replaced by [set_ecdhecurves](#method.set_ecdhecurves)."
506    )]
507    pub fn set_ecdhecurve(&mut self, ecdhecurve: &str) -> error::Result<()> {
508        call_string1(self, ecdhecurve, libtls_sys::tls_config_set_ecdhecurve)
509    }
510
511    /// Set the curves of an Elliptic Curve Diffie-Hellman Ephemeral (ECDHE) key exchange.
512    ///
513    /// The `set_ecdhecurves` method specifies the names of the elliptic curves
514    /// that may be used during Elliptic Curve Diffie-Hellman Ephemeral (ECDHE)
515    /// key exchange.  This is a comma separated list, given in order of
516    /// preference.  The special value of "default" will use the default curves
517    /// (currently X25519, P-256 and P-384).  This function replaces
518    /// [`set_ecdhecurve`], which is deprecated.
519    ///
520    /// # Example
521    ///
522    /// ```
523    /// # use libtls::{config::Config, error::Result};
524    /// # fn tls_config() -> Result<()> {
525    /// let mut config = Config::new()?;
526    /// config.set_ecdhecurves("X25519,P-384")?;
527    /// #     Ok(())
528    /// # }
529    /// # tls_config().unwrap();
530    /// ```
531    ///
532    /// # See also
533    ///
534    /// [`tls_config_set_ecdhecurves(3)`](https://man.openbsd.org/tls_config_set_ecdhecurves.3)
535    ///
536    /// [`set_ecdhecurve`]: #method.set_ecdhecurve
537    pub fn set_ecdhecurves(&mut self, ecdhecurves: &str) -> error::Result<()> {
538        call_string1(self, ecdhecurves, libtls_sys::tls_config_set_ecdhecurves)
539    }
540
541    /// Set the private key file.
542    ///
543    /// The `set_key_file` method sets the file from which the private key will
544    /// be read.
545    ///
546    /// # See also
547    ///
548    /// [`add_keypair_file`](#method.add_keypair_file),
549    /// [`tls_config_set_key_file(3)`](https://man.openbsd.org/tls_config_set_key_file.3)
550    pub fn set_key_file<P: AsRef<Path>>(&mut self, key_file: P) -> error::Result<()> {
551        call_file1(
552            self,
553            (key_file, "key file"),
554            libtls_sys::tls_config_set_key_file,
555        )
556    }
557
558    /// Set the private key from memory.
559    ///
560    /// The `set_key_mem` method directly sets the private key from memory.
561    ///
562    /// # See also
563    ///
564    /// [`add_keypair_mem`](#method.add_keypair_mem),
565    /// [`tls_config_set_key_mem(3)`](https://man.openbsd.org/tls_config_set_key_mem.3)
566    pub fn set_key_mem(&mut self, key: &[u8]) -> error::Result<()> {
567        cvt(self, unsafe {
568            libtls_sys::tls_config_set_key_mem(self.0, key.as_ptr(), key.len().try_into()?)
569        })
570    }
571
572    /// Set the files of the public and private key pair.
573    ///
574    /// The `set_keypair_file` method sets the files from which the public
575    /// certificate, and private key will be read.
576    ///
577    /// # See also
578    ///
579    /// [`add_keypair_file`](#method.add_keypair_file),
580    /// [`tls_config_set_keypair_file(3)`](https://man.openbsd.org/tls_config_set_keypair_file.3)
581    pub fn set_keypair_file<P: AsRef<Path>>(
582        &mut self,
583        cert_file: P,
584        key_file: P,
585    ) -> error::Result<()> {
586        call_file2(
587            self,
588            (cert_file, "cert file"),
589            (key_file, "key file"),
590            libtls_sys::tls_config_set_keypair_file,
591        )
592    }
593
594    /// Set the public and private key pair from memory.
595    ///
596    /// The `set_keypair_mem` method directly sets the public certificate, and
597    /// private key from memory.
598    ///
599    /// # See also
600    ///
601    /// [`add_keypair_mem`](#method.add_keypair_mem),
602    /// [`tls_config_set_keypair_mem(3)`](https://man.openbsd.org/tls_config_set_keypair_mem.3)
603    pub fn set_keypair_mem(&mut self, cert: &[u8], key: &[u8]) -> error::Result<()> {
604        cvt(self, unsafe {
605            libtls_sys::tls_config_set_keypair_mem(
606                self.0,
607                cert.as_ptr(),
608                cert.len().try_into()?,
609                key.as_ptr(),
610                key.len().try_into()?,
611            )
612        })
613    }
614
615    /// Set the files of a public and private key pair and an OCSP staple.
616    ///
617    /// The `set_keypair_ocsp_file` method sets the public certificate,
618    /// private key, and DER-encoded OCSP staple from the specified files.
619    ///
620    /// # See also
621    ///
622    /// [`add_keypair_ocsp_file`](#method.add_keypair_ocsp_file),
623    /// [`tls_config_set_keypair_ocsp_file(3)`](https://man.openbsd.org/tls_config_set_keypair_ocsp_file.3)
624    pub fn set_keypair_ocsp_file<P: AsRef<Path>>(
625        &mut self,
626        cert_file: P,
627        key_file: P,
628        ocsp_staple_file: P,
629    ) -> error::Result<()> {
630        call_file3(
631            self,
632            (cert_file, "cert file"),
633            (key_file, "key file"),
634            (ocsp_staple_file, "ocsp staple file"),
635            libtls_sys::tls_config_set_keypair_ocsp_file,
636        )
637    }
638
639    /// Set the public and private key pair and an OCSP staple from memory.
640    ///
641    /// The `set_keypair_ocsp_mem` method sets the public certificate,
642    /// private key, and DER-encoded OCSP staple directly from memory.
643    ///
644    /// # See also
645    ///
646    /// [`add_keypair_ocsp_mem`](#method.add_keypair_ocsp_mem),
647    /// [`tls_config_set_keypair_ocsp_mem(3)`](https://man.openbsd.org/tls_config_set_keypair_ocsp_mem.3)
648    pub fn set_keypair_ocsp_mem(
649        &mut self,
650        cert: &[u8],
651        key: &[u8],
652        ocsp_staple: &[u8],
653    ) -> error::Result<()> {
654        cvt(self, unsafe {
655            libtls_sys::tls_config_set_keypair_ocsp_mem(
656                self.0,
657                cert.as_ptr(),
658                cert.len().try_into()?,
659                key.as_ptr(),
660                key.len().try_into()?,
661                ocsp_staple.as_ptr(),
662                ocsp_staple.len().try_into()?,
663            )
664        })
665    }
666
667    /// Set the OCSP staple from memory.
668    ///
669    /// The `set_keypair_ocsp_mem` method sets a DER-encoded OCSP response to be
670    /// stapled during the TLS handshake from memory.
671    ///
672    /// # See also
673    ///
674    /// [`add_keypair_mem`](#method.add_keypair_mem),
675    /// [`tls_config_set_ocsp_staple_mem(3)`](https://man.openbsd.org/tls_config_set_ocsp_staple_mem.3)
676    pub fn set_ocsp_staple_mem(&mut self, ocsp_staple: &[u8]) -> error::Result<()> {
677        cvt(self, unsafe {
678            libtls_sys::tls_config_set_ocsp_staple_mem(
679                self.0,
680                ocsp_staple.as_ptr(),
681                ocsp_staple.len().try_into()?,
682            )
683        })
684    }
685
686    /// Set the OCSP staple file.
687    ///
688    /// The `set_keypair_ocsp_mem` method sets a DER-encoded OCSP response to be
689    /// stapled during the TLS handshake from the specified file.
690    ///
691    ///
692    /// # See also
693    ///
694    /// [`add_keypair_file`](#method.add_keypair_file),
695    /// [`tls_config_set_ocsp_staple_file(3)`](https://man.openbsd.org/tls_config_set_ocsp_staple_file.3)
696    pub fn set_ocsp_staple_file<P: AsRef<Path>>(
697        &mut self,
698        ocsp_staple_file: P,
699    ) -> error::Result<()> {
700        call_file1(
701            self,
702            (ocsp_staple_file, "ocsp staple file"),
703            libtls_sys::tls_config_set_ocsp_staple_file,
704        )
705    }
706
707    /// Set which versions of the TLS protocol may be used.
708    ///
709    /// The `set_protocols` method specifies which versions of the TLS protocol
710    /// may be used.  Possible values are the bitwise OR of:
711    ///
712    /// * [`TLS_PROTOCOL_TLSv1_0`]
713    /// * [`TLS_PROTOCOL_TLSv1_1`]
714    /// * [`TLS_PROTOCOL_TLSv1_2`]
715    ///
716    /// Only supported with LibreSSL 3.1.0 or later:
717    ///
718    /// * [`TLS_PROTOCOL_TLSv1_3`]
719    ///
720    /// Additionally, the values [`TLS_PROTOCOL_TLSv1`] (TLSv1.0,
721    /// TLSv1.1, TLSv1.2, and TLSv1.3), [`TLS_PROTOCOLS_ALL`] (all
722    /// supported protocols) and [`TLS_PROTOCOLS_DEFAULT`] (TLSv1.2
723    /// and TLSv1.3) may be used.  TLSv1.3 is only supported with
724    /// LibreSSL 3.1.0 or later.
725    ///
726    /// # Example
727    ///
728    /// ```
729    /// # use libtls::{config::{self, Config}, error::Result};
730    /// # fn tls_config() -> Result<()> {
731    /// let mut config = Config::new()?;
732    /// let protocols = config::parse_protocols("tlsv1.1,tlsv1.2")?;
733    /// config.set_protocols(protocols)?;
734    /// #    Ok(())
735    /// # }
736    /// # tls_config().unwrap();
737    /// ```
738    ///
739    /// # See also
740    ///
741    /// [`parse_protocols`](fn.parse_protocols.html),
742    /// [`tls_config_set_protocols(3)`](https://man.openbsd.org/tls_config_set_protocols.3)
743    ///
744    /// [`TLS_PROTOCOLS_ALL`]: ../constant.TLS_PROTOCOLS_ALL.html
745    /// [`TLS_PROTOCOLS_DEFAULT`]: ../constant.TLS_PROTOCOLS_DEFAULT.html
746    /// [`TLS_PROTOCOL_TLSv1`]: ../constant.TLS_PROTOCOL_TLSv1.html
747    /// [`TLS_PROTOCOL_TLSv1_0`]: ../constant.TLS_PROTOCOL_TLSv1_0.html
748    /// [`TLS_PROTOCOL_TLSv1_1`]: ../constant.TLS_PROTOCOL_TLSv1_1.html
749    /// [`TLS_PROTOCOL_TLSv1_2`]: ../constant.TLS_PROTOCOL_TLSv1_2.html
750    /// [`TLS_PROTOCOL_TLSv1_3`]: ../constant.TLS_PROTOCOL_TLSv1_3.html
751    pub fn set_protocols(&mut self, protocols: u32) -> error::Result<()> {
752        call_arg1(self, protocols, libtls_sys::tls_config_set_protocols)
753    }
754
755    /// Set a file descriptor to manage data for TLS sessions.
756    ///
757    /// The `set_session_fd` method sets a file descriptor to be used to manage
758    /// data for TLS sessions (client only).  The given file descriptor must be a
759    /// regular file and be owned by the current user, with permissions being
760    /// restricted to only allow the owner to read and write the file (0600).  If
761    /// the file has a non-zero length, the client will attempt to read session
762    /// data from this file and resume the previous TLS session with the server.
763    /// Upon a successful handshake the file will be updated with current session
764    /// data, if available.  The caller is responsible for closing this file
765    /// descriptor, after all [`TLS`] contexts that have been configured to use it
766    /// have been [dropped].
767    ///
768    /// # See also
769    ///
770    /// [`tls_config_set_session_fd(3)`](https://man.openbsd.org/tls_config_set_session_fd.3)
771    ///
772    /// [`Tls`]: ../tls/struct.Tls.html
773    /// [dropped]: ../tls/struct.Tls.html#impl-Drop
774    pub fn set_session_fd(&mut self, session_fd: RawFd) -> error::Result<()> {
775        call_arg1(self, session_fd, libtls_sys::tls_config_set_session_fd)
776    }
777
778    /// Set the certificate verification depth.
779    ///
780    /// The `set_verify_depth` method limits the number of intermediate
781    /// certificates that will be followed during certificate validation.
782    ///
783    /// # See also
784    ///
785    /// [`tls_config_set_verify_depth(3)`](https://man.openbsd.org/tls_config_set_verify_depth.3)
786    pub fn set_verify_depth(&mut self, verify_depth: usize) -> error::Result<()> {
787        call_arg1(
788            self,
789            verify_depth as i32,
790            libtls_sys::tls_config_set_verify_depth,
791        )
792    }
793
794    /// Prefer ciphers in the client's cipher list.
795    ///
796    /// The `prefer_ciphers_client` method prefers ciphers in the client's cipher
797    /// list when selecting a cipher suite (server only).  This is considered to
798    /// be less secure than preferring the server's list.
799    ///
800    /// # See also
801    ///
802    /// [`tls_config_prefer_ciphers_client(3)`](https://man.openbsd.org/tls_config_prefer_ciphers_client.3)
803    pub fn prefer_ciphers_client(&mut self) {
804        unsafe { libtls_sys::tls_config_prefer_ciphers_client(self.0) }
805    }
806
807    /// Prefer ciphers in the servers's cipher list.
808    ///
809    /// The `prefer_ciphers_server` method prefers ciphers in the server's cipher
810    /// list when selecting a cipher suite (server only).  This is considered to
811    /// be more secure than preferring the client's list and is the default.
812    ///
813    /// # See also
814    ///
815    /// [`tls_config_prefer_ciphers_server(3)`](https://man.openbsd.org/tls_config_prefer_ciphers_server.3)
816    pub fn prefer_ciphers_server(&mut self) {
817        unsafe { libtls_sys::tls_config_prefer_ciphers_server(self.0) }
818    }
819
820    /// Disable certificate verification.
821    ///
822    /// The `insecure_noverifycert` method disables certificate verification and
823    /// OCSP validation.
824    ///
825    /// # See also
826    ///
827    /// [`tls_config_insecure_noverifycert(3)`](https://man.openbsd.org/tls_config_insecure_noverifycert.3)
828    pub fn insecure_noverifycert(&mut self) {
829        unsafe { libtls_sys::tls_config_insecure_noverifycert(self.0) }
830    }
831
832    /// Disable server name verification.
833    ///
834    /// The `insecure_noverifyname` method disables server name verification
835    /// (client only).
836    ///
837    /// # See also
838    ///
839    /// [`tls_config_insecure_noverifyname(3)`](https://man.openbsd.org/tls_config_insecure_noverifyname.3)
840    pub fn insecure_noverifyname(&mut self) {
841        unsafe { libtls_sys::tls_config_insecure_noverifyname(self.0) }
842    }
843
844    /// Disable certificate validity checking.
845    ///
846    /// The `insecure_noverifytime` method disables validity checking of
847    /// certificates and OCSP validation.
848    ///
849    /// # See also
850    ///
851    /// [`tls_config_insecure_noverifytime(3)`](https://man.openbsd.org/tls_config_insecure_noverifytime.3)
852    pub fn insecure_noverifytime(&mut self) {
853        unsafe { libtls_sys::tls_config_insecure_noverifytime(self.0) }
854    }
855
856    /// Enable all certificate verification.
857    ///
858    /// The `verify` method reenables server name and certificate verification.
859    ///
860    /// # See also
861    ///
862    /// [`tls_config_verify(3)`](https://man.openbsd.org/tls_config_verify.3)
863    pub fn verify(&mut self) {
864        // reenables OCSP validation as well?
865        unsafe { libtls_sys::tls_config_verify(self.0) }
866    }
867
868    /// Require OCSP stapling.
869    ///
870    /// The `ocsp_require_stapling` method requires that a valid stapled OCSP
871    /// response be provided during the TLS handshake.
872    ///
873    /// # See also
874    ///
875    /// [`tls_config_ocsp_require_stapling(3)`](https://man.openbsd.org/tls_config_ocsp_require_stapling.3)
876    pub fn ocsp_require_stapling(&mut self) {
877        unsafe { libtls_sys::tls_config_ocsp_require_stapling(self.0) }
878    }
879
880    /// Enable client certificate verification.
881    ///
882    /// The `verify_client` method enables client certificate verification,
883    /// requiring the client to send a certificate (server only).
884    ///
885    /// # See also
886    ///
887    /// [`tls_config_verify_client(3)`](https://man.openbsd.org/tls_config_verify_client.3)
888    pub fn verify_client(&mut self) {
889        unsafe { libtls_sys::tls_config_verify_client(self.0) }
890    }
891
892    /// Enable optional client certificate verification.
893    ///
894    /// The `verify_client_optional` method enables client certificate
895    /// verification, without requiring the client to send a certificate (server
896    /// only).
897    ///
898    /// # See also
899    ///
900    /// [`tls_config_verify_client_optional(3)`](https://man.openbsd.org/tls_config_verify_client_optional.3)
901    pub fn verify_client_optional(&mut self) {
902        unsafe { libtls_sys::tls_config_verify_client_optional(self.0) }
903    }
904
905    /// Securely clear secret keys.
906    ///
907    /// The `clear_keys` method clears any secret keys from memory.
908    ///
909    /// # See also
910    ///
911    /// [`tls_config_clear_keys(3)`](https://man.openbsd.org/tls_config_clear_keys.3)
912    pub fn clear_keys(&mut self) {
913        unsafe { libtls_sys::tls_config_clear_keys(self.0) }
914    }
915
916    /// Set the session identifier for TLS sessions.
917    ///
918    /// The `set_session_id` method sets the session identifier that will be used
919    /// by the TLS server when sessions are enabled (server only).  By default a
920    /// random value is used.
921    ///
922    /// # Example
923    ///
924    /// ```
925    /// # use libtls::{config::Config, error::Result, *};
926    /// # use rand::{thread_rng, Rng};
927    /// # fn tls_config() -> Result<()> {
928    /// let mut session_id = [0; TLS_MAX_SESSION_ID_LENGTH as usize];
929    /// thread_rng().fill(&mut session_id[..]);
930    ///
931    /// let mut config = Config::new()?;
932    /// config.set_session_id(&session_id[..])?;
933    /// #     Ok(())
934    /// # }
935    /// # tls_config().unwrap();
936    /// ```
937    ///
938    /// # See also
939    ///
940    /// [`tls_config_set_session_id(3)`](https://man.openbsd.org/tls_config_set_session_id.3)
941    pub fn set_session_id(&mut self, session_id: &[u8]) -> error::Result<()> {
942        cvt(self, unsafe {
943            libtls_sys::tls_config_set_session_id(
944                self.0,
945                session_id.as_ptr(),
946                session_id.len().try_into()?,
947            )
948        })
949    }
950
951    /// Set the lifetime for TLS sessions.
952    ///
953    /// The `set_session_lifetime` method sets the lifetime to be used for TLS
954    /// sessions (server only).  Session support is disabled if a lifetime of
955    /// zero is specified, which is the default.
956    ///
957    /// # See also
958    ///
959    /// [`tls_config_set_session_lifetime(3)`](https://man.openbsd.org/tls_config_set_session_lifetime.3)
960    pub fn set_session_lifetime(&mut self, lifetime: usize) -> error::Result<()> {
961        call_arg1(
962            self,
963            lifetime as i32,
964            libtls_sys::tls_config_set_session_lifetime,
965        )
966    }
967
968    /// Add a key for the encryption and authentication of TLS tickets.
969    ///
970    /// The `add_ticket_key` method adds a key used for the encryption and
971    /// authentication of TLS tickets (server only).  By default keys are
972    /// generated and rotated automatically based on their lifetime.  This
973    /// function should only be used to synchronise ticket encryption key across
974    /// multiple processes.  Re-adding a known key will result in an error,
975    /// unless it is the most recently added key.
976    ///
977    /// # Example
978    ///
979    /// ```
980    /// # use libtls::{config::Config, error::Result, *};
981    /// # use rand::{thread_rng, Rng};
982    /// # fn tls_config() -> Result<()> {
983    /// let mut key = [0; TLS_TICKET_KEY_SIZE as usize];
984    /// thread_rng().fill(&mut key[..]);
985    ///
986    /// let mut config = Config::new()?;
987    /// config.add_ticket_key(1, &mut key[..])?;
988    /// #     Ok(())
989    /// # }
990    /// # tls_config().unwrap();
991    /// ```
992    ///
993    /// # See also
994    ///
995    /// [`tls_config_add_ticket_key(3)`](https://man.openbsd.org/tls_config_add_ticket_key.3)
996    pub fn add_ticket_key(&mut self, keyrev: u32, key: &mut [u8]) -> error::Result<()> {
997        // XXX key should be const, consider changing this in the upstream API
998        cvt(self, unsafe {
999            libtls_sys::tls_config_add_ticket_key(
1000                self.0,
1001                keyrev,
1002                key.as_mut_ptr(),
1003                key.len().try_into()?,
1004            )
1005        })
1006    }
1007}
1008
1009impl error::LastError for Config {
1010    /// Returns the configuration last error.
1011    ///
1012    /// The `last_error` method returns an error if no error occurred with config
1013    /// at all, or if memory allocation failed while trying to assemble the
1014    /// string describing the most recent error related to config.
1015    ///
1016    /// # See also
1017    ///
1018    /// [`tls_config_error(3)`](https://man.openbsd.org/tls_config_error.3)
1019    fn last_error(&self) -> error::Result<String> {
1020        unsafe { cvt_no_error(libtls_sys::tls_config_error(self.0)) }
1021    }
1022
1023    fn to_error<T>(errstr: String) -> error::Result<T> {
1024        Err(error::Error::ConfigError(errstr))
1025    }
1026}
1027
1028impl Drop for Config {
1029    /// Free the configuration object.  This should only happen when no
1030    /// more [`Tls`] contexts are to be configured.
1031    ///
1032    /// # See also
1033    ///
1034    /// [`tls_config_free(3)`](https://man.openbsd.org/tls_config_free.3)
1035    ///
1036    /// [`Tls`]: ../tls/struct.Tls.html
1037    fn drop(&mut self) {
1038        unsafe { libtls_sys::tls_config_free(self.0) };
1039    }
1040}
1041
1042unsafe impl Send for Config {}
1043unsafe impl Sync for Config {}
1044
1045/// Return path of the default CA file.
1046///
1047/// The `default_ca_cert_file` utility function returns the path of the file that
1048/// contains the default root certificates.
1049///
1050/// # Example
1051///
1052/// ```
1053/// # use libtls::config;
1054/// let certs = config::default_ca_cert_file();
1055/// assert!(certs.is_absolute());
1056/// ```
1057///
1058/// # See also
1059///
1060/// [`tls_default_ca_cert_file(3)`](https://man.openbsd.org/tls_default_ca_cert_file.3)
1061pub fn default_ca_cert_file() -> PathBuf {
1062    unsafe { CStr::from_ptr(libtls_sys::tls_default_ca_cert_file()) }
1063        .to_string_lossy()
1064        .into_owned()
1065        .into()
1066}
1067
1068/// Parse protocol string.
1069///
1070/// The `tls_config_parse_protocols` utility function parses a
1071/// protocol string and returns the corresponding value via the
1072/// protocols argument.  This value can then be passed to the
1073/// [`set_protocols`] method.  The protocol string is a comma or colon
1074/// separated list of keywords.  Valid keywords are `tlsv1.0`,
1075/// `tlsv1.1`, `tlsv1.2`, `tlsv1.3`, `all` (all supported protocols),
1076/// `default` (an alias for secure), `legacy` (an alias for all) and
1077/// `secure` (currently TLSv1.2 and TLSv1.3).  If a value has a
1078/// negative prefix (in the form of a leading exclamation mark) then
1079/// it is removed from the list of available protocols, rather than
1080/// being added to it.
1081///
1082/// # Example
1083///
1084/// ```
1085/// # use libtls::{config::Config, error::Result, *};
1086/// # fn tls_config() -> Result<()> {
1087/// // Parse a list of allowed protocols:
1088/// let protocols = config::parse_protocols("tlsv1.1,tlsv1.2").unwrap();
1089/// assert_eq!(protocols, TLS_PROTOCOL_TLSv1_1|TLS_PROTOCOL_TLSv1_2);
1090///
1091/// // The default is to use the `secure` protocols:
1092/// let protocols = config::parse_protocols("default").unwrap();
1093/// assert_eq!(protocols, TLS_PROTOCOLS_DEFAULT);
1094/// assert_ne!(protocols, TLS_PROTOCOLS_ALL);
1095/// #     Ok(())
1096/// # }
1097/// # tls_config().unwrap();
1098/// ```
1099///
1100/// # See also
1101///
1102/// [`tls_config_parse_protocols(3)`](https://man.openbsd.org/tls_config_parse_protocols.3)
1103///
1104/// [`set_protocols`]: #method.set_protocols
1105pub fn parse_protocols(protostr: &str) -> error::Result<u32> {
1106    let c_protostr = CString::new(protostr)?;
1107    let mut protocols: u32 = 0;
1108
1109    let retval =
1110        unsafe { libtls_sys::tls_config_parse_protocols(&mut protocols, c_protostr.as_ptr()) };
1111    if retval == -1 {
1112        Err(io::Error::new(io::ErrorKind::Other, "Invalid protocols string").into())
1113    } else {
1114        Ok(protocols)
1115    }
1116}
1117
1118/// Load a certificate or key file.
1119///
1120/// The `load_file` function loads a certificate or key from disk into memory
1121/// to be used with [`set_ca_mem`], [`set_cert_mem`], [`set_crl_mem`] or
1122/// [`set_key_mem`].  A private key will be decrypted if the optional password
1123/// argument is specified.
1124///
1125/// # Example
1126///
1127/// ```
1128/// # use libtls::{config, error::Result};
1129/// # fn tls_config() -> Result<()> {
1130/// # let filename = file!();
1131/// let data = config::load_file(filename, None)?;
1132/// config::unload_file(data);
1133/// #     Ok(())
1134/// # }
1135/// # tls_config().unwrap();
1136/// ```
1137///
1138/// # See also
1139///
1140/// [`unload_file`],
1141/// [`tls_load_file(3)`](https://man.openbsd.org/tls_load_file.3)
1142///
1143/// [`set_ca_mem`]: struct.Config.html#method.set_ca_mem
1144/// [`set_cert_mem`]: struct.Config.html#method.set_cert_mem
1145/// [`set_crl_mem`]: struct.Config.html#method.set_crl_mem
1146/// [`set_key_mem`]: struct.Config.html#method.set_key_mem
1147/// [`unload_file`]: fn.unload_file.html
1148pub fn load_file<P: AsRef<Path>>(file: P, password: Option<&str>) -> error::Result<Vec<u8>> {
1149    let mut size = 0;
1150    let s_file = cvt_option(
1151        file.as_ref().to_str(),
1152        io::Error::new(io::ErrorKind::InvalidInput, "file"),
1153    )?;
1154    unsafe {
1155        let c_file = CString::new(s_file)?;
1156        let data = match password {
1157            Some(password) => {
1158                let c_password = CString::new(password)?;
1159
1160                let raw = c_password.into_raw();
1161                let data = libtls_sys::tls_load_file(c_file.as_ptr(), &mut size, raw);
1162
1163                // Make sure that the raw pointer is not leaked
1164                let _ = CString::from_raw(raw);
1165
1166                data
1167            }
1168            None => libtls_sys::tls_load_file(c_file.as_ptr(), &mut size, std::ptr::null_mut()),
1169        };
1170        if data.is_null() {
1171            Err(io::Error::last_os_error().into())
1172        } else {
1173            let len = size.try_into()?;
1174            Ok(Vec::from_raw_parts(data, len, len))
1175        }
1176    }
1177}
1178
1179/// Securely unload file that was loaded into memory.
1180///
1181/// The `unload_file` function unloads the memory that was returned from an
1182/// earlier [`load_file`] call, ensuring that the memory contents is discarded.
1183///
1184/// # See also
1185///
1186/// [`tls_unload_file(3)`](https://man.openbsd.org/tls_unload_file.3)
1187///
1188/// [`load_file`]: fn.load_file.html
1189pub fn unload_file(mut data: Vec<u8>) {
1190    let ptr = data.as_mut_ptr();
1191    let len = data.len() as u64;
1192    std::mem::forget(data);
1193    unsafe { libtls_sys::tls_unload_file(ptr, len) }
1194}
1195
1196#[derive(Debug, Clone)]
1197enum KeyData {
1198    File(PathBuf),
1199    Path(PathBuf),
1200    KeyPairFiles(PathBuf, PathBuf, Option<PathBuf>),
1201    KeyPairMem(Vec<u8>, Vec<u8>, Option<Vec<u8>>),
1202    Mem(Vec<u8>),
1203}
1204
1205/// `Builder` for [`Config`].
1206///
1207/// # Example
1208///
1209/// ```
1210/// # use libtls::{config::Builder, error::Result};
1211/// # use libtls_sys::*;
1212/// # fn tls_config() -> Result<()> {
1213/// #     let key = include_bytes!("../tests/eccert.key");
1214/// #     let cert = include_bytes!("../tests/eccert.crt");
1215/// #     let ticket_key1 = [0; TLS_TICKET_KEY_SIZE as usize];
1216/// #     let ticket_key2 = [0; TLS_TICKET_KEY_SIZE as usize];
1217/// let mut config = Builder::new()
1218///     .keypair_mem(cert, key, None)
1219///     .ticket_key(1, &ticket_key1)
1220///     .ticket_key(2, &ticket_key2)
1221///     .protocols(TLS_PROTOCOLS_ALL)
1222///     .ecdhecurves("X25519")
1223///     .alpn("h2")
1224///     .build()?;
1225/// #     Ok(())
1226/// # }
1227/// # tls_config().unwrap();
1228/// ```
1229///
1230/// [`Config`]: struct.Config.html
1231#[derive(Default, Debug, Clone)]
1232pub struct Builder {
1233    alpn: Option<String>,
1234    ca: Option<KeyData>,
1235    ciphers: Option<String>,
1236    crl: Option<KeyData>,
1237    dheparams: Option<String>,
1238    ecdhecurves: Option<String>,
1239    keypairs: Vec<KeyData>,
1240    noverifycert: bool,
1241    noverifyname: bool,
1242    noverifytime: bool,
1243    protocols: Option<u32>,
1244    session_fd: Option<RawFd>,
1245    session_id: Option<Vec<u8>>,
1246    session_lifetime: Option<usize>,
1247    ticket_key: HashMap<u32, Vec<u8>>,
1248    verify: bool,
1249    verify_client: bool,
1250    verify_client_optional: bool,
1251    verify_depth: Option<usize>,
1252}
1253
1254/// `TlsConfigBuilder` for [`TlsConfig`].
1255#[deprecated(
1256    since = "1.1.1",
1257    note = "Please use `Builder` instead of `TlsConfigBuilder`"
1258)]
1259pub type TlsConfigBuilder = Builder;
1260
1261impl Builder {
1262    /// Return new `Builder`.
1263    ///
1264    /// # See also
1265    ///
1266    /// [`Config`](struct.Config.html)
1267    pub fn new() -> Self {
1268        Default::default()
1269    }
1270
1271    /// Build new [`Config`] object.
1272    ///
1273    /// # See also
1274    ///
1275    /// [`Config`]
1276    ///
1277    /// [`Config`]: struct.Config.html
1278    pub fn build(&self) -> error::Result<Config> {
1279        let mut config = Config::new()?;
1280
1281        // First add the keypairs and optional OCSP staples.
1282        self.build_keypairs(&mut config)?;
1283
1284        // Now all the other settings
1285        if let Some(ref alpn) = self.alpn {
1286            config.set_alpn(alpn)?;
1287        }
1288        if let Some(ref ca) = self.ca {
1289            match ca {
1290                KeyData::Mem(mem) => config.set_ca_mem(mem)?,
1291                KeyData::File(file) => config.set_ca_file(file)?,
1292                KeyData::Path(path) => config.set_ca_path(path)?,
1293                _ => return Err(error::Error::NoError),
1294            };
1295        } else if !default_ca_cert_file().exists() {
1296            // Try to use the default CA path as a fallback.
1297            config.set_ca_path("/etc/ssl/certs")?;
1298        };
1299        if let Some(ref ciphers) = self.ciphers {
1300            config.set_ciphers(ciphers)?;
1301        }
1302        if let Some(ref crl) = self.crl {
1303            match crl {
1304                KeyData::Mem(mem) => config.set_ca_mem(mem)?,
1305                KeyData::File(file) => config.set_ca_file(file)?,
1306                _ => return Err(error::Error::NoError),
1307            };
1308        }
1309        if let Some(ref dheparams) = self.dheparams {
1310            config.set_dheparams(dheparams)?;
1311        }
1312        if let Some(ref ecdhecurves) = self.ecdhecurves {
1313            config.set_ecdhecurves(ecdhecurves)?;
1314        }
1315        if let Some(protocols) = self.protocols {
1316            config.set_protocols(protocols)?;
1317        }
1318        if let Some(session_fd) = self.session_fd {
1319            config.set_session_fd(session_fd)?;
1320        }
1321        if let Some(ref session_id) = self.session_id {
1322            config.set_session_id(session_id)?;
1323        }
1324        if let Some(session_lifetime) = self.session_lifetime {
1325            config.set_session_lifetime(session_lifetime)?;
1326        }
1327
1328        // Add ticket keys
1329        for (keyrev, key) in self.ticket_key.iter() {
1330            // The tls_ticket_key() API is "broken" as it requires the key
1331            // as mut and not const.
1332            config.add_ticket_key(*keyrev, key.clone().as_mut_slice())?;
1333        }
1334
1335        // Order verify_* calls in a safe priority.
1336        if self.noverifycert {
1337            config.insecure_noverifycert();
1338        }
1339        if self.noverifyname {
1340            config.insecure_noverifyname();
1341        }
1342        if self.noverifytime {
1343            config.insecure_noverifytime();
1344        }
1345        if let Some(verify_depth) = self.verify_depth {
1346            config.set_verify_depth(verify_depth)?;
1347        }
1348        if self.verify_client_optional {
1349            config.verify_client_optional();
1350        }
1351        if self.verify_client {
1352            config.verify_client();
1353        }
1354        if self.verify {
1355            config.verify();
1356        }
1357
1358        Ok(config)
1359    }
1360
1361    fn build_keypairs(&self, config: &mut Config) -> error::Result<()> {
1362        for (i, kp) in self.keypairs.iter().enumerate() {
1363            match kp {
1364                KeyData::KeyPairMem(cert, key, ocsp) => {
1365                    if let Some(ocsp) = ocsp {
1366                        // Set the first keypair as the default.
1367                        if i == 0 {
1368                            config.set_keypair_ocsp_mem(cert, key, ocsp)?;
1369                        }
1370                        config.add_keypair_ocsp_mem(cert, key, ocsp)?;
1371                    } else {
1372                        if i == 0 {
1373                            config.set_keypair_mem(cert, key)?;
1374                        }
1375                        config.add_keypair_mem(cert, key)?;
1376                    }
1377                }
1378                KeyData::KeyPairFiles(cert, key, ocsp) => {
1379                    if let Some(ocsp) = ocsp {
1380                        if i == 0 {
1381                            config.set_keypair_ocsp_file(cert, key, ocsp)?;
1382                        }
1383                        config.add_keypair_ocsp_file(cert, key, ocsp)?;
1384                    } else {
1385                        if i == 0 {
1386                            config.set_keypair_file(cert, key)?;
1387                        }
1388                        config.add_keypair_file(cert, key)?;
1389                    }
1390                }
1391                _ => return Err(error::Error::NoError),
1392            };
1393        }
1394
1395        Ok(())
1396    }
1397
1398    /// Build new [`Config`] object and return a configured [`Tls`] client.
1399    ///
1400    /// # See also
1401    ///
1402    /// [`Tls`],
1403    /// [`Config`]
1404    ///
1405    /// [`Tls`]: ../tls/struct.Tls.html
1406    /// [`Config`]: struct.Config.html
1407    pub fn client(&self) -> error::Result<Tls> {
1408        let mut client = Tls::client()?;
1409        client.configure(&self.build()?)?;
1410        Ok(client)
1411    }
1412
1413    /// Build new [`Config`] object and return a configured [`Tls`] server.
1414    ///
1415    /// # See also
1416    ///
1417    /// [`Tls`],
1418    /// [`Config`]
1419    ///
1420    /// [`Tls`]: ../tls/struct.Tls.html
1421    /// [`Config`]: struct.Config.html
1422    pub fn server(&self) -> error::Result<Tls> {
1423        let mut server = Tls::server()?;
1424        server.configure(&self.build()?)?;
1425        Ok(server)
1426    }
1427
1428    /// Set the ALPN protocols that are supported.
1429    ///
1430    /// # See also
1431    ///
1432    /// [`Config::set_alpn`](struct.Config.html#method.set_alpn)
1433    pub fn alpn(&'_ mut self, alpn: &str) -> &'_ mut Self {
1434        self.alpn = Some(alpn.to_owned());
1435        self
1436    }
1437
1438    /// Set the CA file.
1439    ///
1440    /// # See also
1441    ///
1442    /// [`Config::set_ca_file`](struct.Config.html#method.set_ca_file)
1443    pub fn ca_file<P: AsRef<Path>>(&'_ mut self, path: P) -> &'_ mut Self {
1444        self.ca = Some(KeyData::File(path.as_ref().to_owned()));
1445        self
1446    }
1447
1448    /// Set the CA path.
1449    ///
1450    /// # See also
1451    ///
1452    /// [`Config::set_ca_path`](struct.Config.html#method.set_ca_path)
1453    pub fn ca_path<P: AsRef<Path>>(&'_ mut self, path: P) -> &'_ mut Self {
1454        self.ca = Some(KeyData::Path(path.as_ref().to_owned()));
1455        self
1456    }
1457
1458    /// Set the CA from memory.
1459    ///
1460    /// # See also
1461    ///
1462    /// [`Config::set_ca_mem`](struct.Config.html#method.set_ca_mem)
1463    pub fn ca_mem(&'_ mut self, mem: &[u8]) -> &'_ mut Self {
1464        self.ca = Some(KeyData::Mem(mem.to_vec()));
1465        self
1466    }
1467
1468    /// Set the list of cipher that may be used.
1469    ///
1470    /// # See also
1471    ///
1472    /// [`Config::set_ciphers`](struct.Config.html#method.set_ciphers)
1473    pub fn ciphers(&'_ mut self, ciphers: &str) -> &'_ mut Self {
1474        self.ciphers = Some(ciphers.to_owned());
1475        self
1476    }
1477
1478    /// Set the CRL file.
1479    ///
1480    /// # See also
1481    ///
1482    /// [`Config::set_crl_file`](struct.Config.html#method.set_crl_file)
1483    pub fn crl_file<P: AsRef<Path>>(&'_ mut self, path: P) -> &'_ mut Self {
1484        self.crl = Some(KeyData::File(path.as_ref().to_owned()));
1485        self
1486    }
1487
1488    /// Set the CRL from memory.
1489    ///
1490    /// # See also
1491    ///
1492    /// [`Config::set_crl_mem`](struct.Config.html#method.set_crl_mem)
1493    pub fn crl_mem(&'_ mut self, mem: &[u8]) -> &'_ mut Self {
1494        self.crl = Some(KeyData::Mem(mem.to_vec()));
1495        self
1496    }
1497
1498    /// Set the parameters of an Diffie-Hellman Ephemeral (DHE) key exchange.
1499    ///
1500    /// # See also
1501    ///
1502    /// [`Config::set_dheparams`](struct.Config.html#method.set_dheparams)
1503    pub fn dheparams(&'_ mut self, dheparams: &str) -> &'_ mut Self {
1504        self.dheparams = Some(dheparams.to_owned());
1505        self
1506    }
1507
1508    /// Set the curves of an Elliptic Curve Diffie-Hellman Ephemeral (ECDHE) key exchange.
1509    ///
1510    /// # See also
1511    ///
1512    /// [`Config::set_ecdhecurves`](struct.Config.html#method.set_ecdhecurves)
1513    pub fn ecdhecurves(&'_ mut self, ecdhecurves: &str) -> &'_ mut Self {
1514        self.ecdhecurves = Some(ecdhecurves.to_owned());
1515        self
1516    }
1517
1518    /// Add additional files of a public and private key pair and OCSP staple.
1519    ///
1520    /// # See also
1521    ///
1522    /// [`Config::add_keypair_file`](struct.Config.html#method.add_keypair_ocsp_file),
1523    /// [`Config::set_keypair_file`](struct.Config.html#method.set_keypair_ocsp_file)
1524    pub fn keypair_file<P: AsRef<Path>>(
1525        &'_ mut self,
1526        cert: P,
1527        key: P,
1528        ocsp_staple: Option<P>,
1529    ) -> &'_ mut Self {
1530        let certdata = cert.as_ref().to_owned();
1531        let keydata = key.as_ref().to_owned();
1532        let ocspdata = match ocsp_staple {
1533            Some(path) => Some(path.as_ref().to_owned()),
1534            None => None,
1535        };
1536        self.keypairs
1537            .push(KeyData::KeyPairFiles(certdata, keydata, ocspdata));
1538        self
1539    }
1540
1541    /// Add an additional public and private key pair and OCSP staple from memory.
1542    ///
1543    /// # See also
1544    ///
1545    /// [`Config::set_keypair_mem`](struct.Config.html#method.add_keypair_ocsp_mem),
1546    /// [`Config::set_keypair_mem`](struct.Config.html#method.set_keypair_ocsp_mem)
1547    pub fn keypair_mem(
1548        &'_ mut self,
1549        cert: &[u8],
1550        key: &[u8],
1551        ocsp_staple: Option<&[u8]>,
1552    ) -> &'_ mut Self {
1553        let certdata = cert.to_vec();
1554        let keydata = key.to_vec();
1555        let ocspdata = match ocsp_staple {
1556            Some(mem) => Some(mem.to_vec()),
1557            None => None,
1558        };
1559        self.keypairs
1560            .push(KeyData::KeyPairMem(certdata, keydata, ocspdata));
1561        self
1562    }
1563
1564    /// Disable certificate verification.
1565    ///
1566    /// # See also
1567    ///
1568    /// [`Config::insecure_noverifycert`](struct.Config.html#method.insecure_noverifycert)
1569    pub fn noverifycert(&'_ mut self) -> &'_ mut Self {
1570        self.noverifycert = true;
1571        self
1572    }
1573
1574    /// Disable server name verification.
1575    ///
1576    /// # See also
1577    ///
1578    /// [`Config::insecure_noverifyname`](struct.Config.html#method.insecure_noverifyname)
1579    pub fn noverifyname(&'_ mut self) -> &'_ mut Self {
1580        self.noverifyname = true;
1581        self
1582    }
1583
1584    /// Disable certificate validity checking.
1585    ///
1586    /// # See also
1587    ///
1588    /// [`Config::insecure_noverifytime`](struct.Config.html#method.insecure_noverifytime)
1589    pub fn noverifytime(&'_ mut self) -> &'_ mut Self {
1590        self.noverifytime = true;
1591        self
1592    }
1593
1594    /// Set which versions of the TLS protocol may be used.
1595    ///
1596    /// # See also
1597    ///
1598    /// [`Config::set_protocols`](struct.Config.html#method.set_protocols)
1599    pub fn protocols(&'_ mut self, protocols: u32) -> &'_ mut Self {
1600        self.protocols = Some(protocols);
1601        self
1602    }
1603
1604    /// Set a file descriptor to manage data for TLS sessions.
1605    ///
1606    /// # See also
1607    ///
1608    /// [`Config::set_session_fd`](struct.Config.html#method.set_session_fd)
1609    pub fn session_fd(&'_ mut self, fd: RawFd) -> &'_ mut Self {
1610        self.session_fd = Some(fd);
1611        self
1612    }
1613
1614    /// Set the session identifier for TLS sessions.
1615    ///
1616    /// # See also
1617    ///
1618    /// [`Config::set_session_id`](struct.Config.html#method.set_session_id)
1619    pub fn session_id(&'_ mut self, id: &[u8]) -> &'_ mut Self {
1620        self.session_id = Some(id.to_vec());
1621        self
1622    }
1623
1624    /// Set the lifetime for TLS sessions.
1625    ///
1626    /// # See also
1627    ///
1628    /// [`Config::set_session_lifetime`](struct.Config.html#method.set_session_lifetime)
1629    pub fn session_lifetime(&'_ mut self, lifetime: usize) -> &'_ mut Self {
1630        self.session_lifetime = Some(lifetime);
1631        self
1632    }
1633
1634    /// # See also
1635    ///
1636    /// [`Config::add_ticket_key`](struct.Config.html#method.add_ticket_key)
1637    pub fn ticket_key(&'_ mut self, keyrev: u32, key: &[u8]) -> &'_ mut Self {
1638        self.ticket_key.insert(keyrev, key.to_vec());
1639        self
1640    }
1641
1642    /// Enable all certificate verification.
1643    ///
1644    /// # See also
1645    ///
1646    /// [`Config::verify`](struct.Config.html#method.verify)
1647    pub fn verify(&'_ mut self) -> &'_ mut Self {
1648        self.verify = true;
1649        self
1650    }
1651
1652    /// Enable client certificate verification.
1653    ///
1654    /// # See also
1655    ///
1656    /// [`Config::verify_client`](struct.Config.html#method.verify_client)
1657    pub fn verify_client(&'_ mut self) -> &'_ mut Self {
1658        self.verify_client = true;
1659        self
1660    }
1661
1662    /// Enable optional client certificate verification.
1663    ///
1664    /// # See also
1665    ///
1666    /// [`Config::verify_client_optional`](struct.Config.html#method.verify_client_optional)
1667    pub fn verify_client_optional(&'_ mut self) -> &'_ mut Self {
1668        self.verify_client_optional = true;
1669        self
1670    }
1671
1672    /// Set the certificate verification depth.
1673    ///
1674    /// # See also
1675    ///
1676    /// [`Config::verify_depth`](struct.Config.html#method.verify_depth)
1677    pub fn verify_depth(&'_ mut self, depth: usize) -> &'_ mut Self {
1678        self.verify_depth = Some(depth);
1679        self
1680    }
1681}