• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2023 Huawei Device Co., Ltd.
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 //     http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 
14 use std::net::IpAddr;
15 use std::path::Path;
16 
17 use crate::error::HttpClientError;
18 use crate::util::c_openssl::error::ErrorStack;
19 use crate::util::c_openssl::ssl::{
20     Ssl, SslContext, SslContextBuilder, SslFiletype, SslMethod, SslVersion,
21 };
22 use crate::util::c_openssl::x509::{X509Ref, X509Store, X509};
23 use crate::util::AlpnProtocolList;
24 use crate::ErrorKind;
25 
26 /// `TlsContextBuilder` implementation based on `SSL_CTX`.
27 ///
28 /// # Examples
29 ///
30 /// ```
31 /// use ylong_http_client::util::{TlsConfigBuilder, TlsVersion};
32 ///
33 /// let context = TlsConfigBuilder::new()
34 ///     .ca_file("ca.crt")
35 ///     .max_proto_version(TlsVersion::TLS_1_2)
36 ///     .min_proto_version(TlsVersion::TLS_1_2)
37 ///     .cipher_list("DEFAULT:!aNULL:!eNULL:!MD5:!3DES:!DES:!RC4:!IDEA:!SEED:!aDSS:!SRP:!PSK")
38 ///     .build();
39 /// ```
40 pub struct TlsConfigBuilder {
41     inner: Result<SslContextBuilder, ErrorStack>,
42     use_sni: bool,
43     verify_hostname: bool,
44 }
45 
46 impl TlsConfigBuilder {
47     /// Creates a new, default `SslContextBuilder`.
48     ///
49     /// # Examples
50     ///
51     /// ```
52     /// use ylong_http_client::util::TlsConfigBuilder;
53     ///
54     /// let builder = TlsConfigBuilder::new();
55     /// ```
new() -> Self56     pub fn new() -> Self {
57         Self {
58             inner: SslContext::builder(SslMethod::tls_client()),
59             use_sni: true,
60             verify_hostname: true,
61         }
62     }
63 
64     /// Loads trusted root certificates from a file. The file should contain a
65     /// sequence of PEM-formatted CA certificates.
66     ///
67     /// # Examples
68     ///
69     /// ```
70     /// use ylong_http_client::util::TlsConfigBuilder;
71     ///
72     /// let builder = TlsConfigBuilder::new().ca_file("ca.crt");
73     /// ```
ca_file<T: AsRef<Path>>(mut self, path: T) -> Self74     pub fn ca_file<T: AsRef<Path>>(mut self, path: T) -> Self {
75         self.inner = self
76             .inner
77             .and_then(|mut builder| builder.set_ca_file(path).map(|_| builder));
78         self
79     }
80 
81     /// Sets the maximum supported protocol version. A value of `None` will
82     /// enable protocol versions down the the highest version supported by
83     /// `OpenSSL`.
84     ///
85     /// Requires `OpenSSL 1.1.0` or or `LibreSSL 2.6.1` or newer.
86     ///
87     /// # Examples
88     ///
89     /// ```
90     /// use ylong_http_client::util::{TlsConfigBuilder, TlsVersion};
91     ///
92     /// let builder = TlsConfigBuilder::new().max_proto_version(TlsVersion::TLS_1_2);
93     /// ```
max_proto_version(mut self, version: TlsVersion) -> Self94     pub fn max_proto_version(mut self, version: TlsVersion) -> Self {
95         self.inner = self.inner.and_then(|mut builder| {
96             builder
97                 .set_max_proto_version(version.into_inner())
98                 .map(|_| builder)
99         });
100         self
101     }
102 
103     /// Sets the minimum supported protocol version. A value of `None` will
104     /// enable protocol versions down the the lowest version supported by
105     /// `OpenSSL`.
106     ///
107     /// Requires `OpenSSL 1.1.0` or `LibreSSL 2.6.1` or newer.
108     ///
109     /// # Examples
110     ///
111     /// ```
112     /// use ylong_http_client::util::{TlsConfigBuilder, TlsVersion};
113     ///
114     /// let builder = TlsConfigBuilder::new().min_proto_version(TlsVersion::TLS_1_2);
115     /// ```
min_proto_version(mut self, version: TlsVersion) -> Self116     pub fn min_proto_version(mut self, version: TlsVersion) -> Self {
117         self.inner = self.inner.and_then(|mut builder| {
118             builder
119                 .set_min_proto_version(version.into_inner())
120                 .map(|_| builder)
121         });
122         self
123     }
124 
125     /// Sets the list of supported ciphers for protocols before `TLSv1.3`.
126     ///
127     /// The `set_ciphersuites` method controls the cipher suites for `TLSv1.3`.
128     ///
129     /// See [`ciphers`] for details on the format.
130     ///
131     /// [`ciphers`]: https://www.openssl.org/docs/man1.1.0/apps/ciphers.html
132     ///
133     /// # Examples
134     ///
135     /// ```
136     /// use ylong_http_client::util::TlsConfigBuilder;
137     ///
138     /// let builder = TlsConfigBuilder::new()
139     ///     .cipher_list("DEFAULT:!aNULL:!eNULL:!MD5:!3DES:!DES:!RC4:!IDEA:!SEED:!aDSS:!SRP:!PSK");
140     /// ```
cipher_list(mut self, list: &str) -> Self141     pub fn cipher_list(mut self, list: &str) -> Self {
142         self.inner = self
143             .inner
144             .and_then(|mut builder| builder.set_cipher_list(list).map(|_| builder));
145         self
146     }
147 
148     /// Sets the list of supported ciphers for the `TLSv1.3` protocol.
149     ///
150     /// The `set_cipher_list` method controls the cipher suites for protocols
151     /// before `TLSv1.3`.
152     ///
153     /// The format consists of TLSv1.3 cipher suite names separated by `:`
154     /// characters in order of preference.
155     ///
156     /// Requires `OpenSSL 1.1.1` or `LibreSSL 3.4.0` or newer.
157     ///
158     /// # Examples
159     ///
160     /// ```
161     /// use ylong_http_client::util::TlsConfigBuilder;
162     ///
163     /// let builder = TlsConfigBuilder::new()
164     ///     .cipher_suites("DEFAULT:!aNULL:!eNULL:!MD5:!3DES:!DES:!RC4:!IDEA:!SEED:!aDSS:!SRP:!PSK");
165     /// ```
cipher_suites(mut self, list: &str) -> Self166     pub fn cipher_suites(mut self, list: &str) -> Self {
167         self.inner = self
168             .inner
169             .and_then(|mut builder| builder.set_cipher_suites(list).map(|_| builder));
170         self
171     }
172 
173     /// Loads a leaf certificate from a file.
174     ///
175     /// Only a single certificate will be loaded - use `add_extra_chain_cert` to
176     /// add the remainder of the certificate chain, or
177     /// `set_certificate_chain_file` to load the entire chain from a single
178     /// file.
179     ///
180     /// # Examples
181     ///
182     /// ```
183     /// use ylong_http_client::util::{TlsConfigBuilder, TlsFileType};
184     ///
185     /// let builder = TlsConfigBuilder::new().certificate_file("cert.pem", TlsFileType::PEM);
186     /// ```
certificate_file<T: AsRef<Path>>(mut self, path: T, file_type: TlsFileType) -> Self187     pub fn certificate_file<T: AsRef<Path>>(mut self, path: T, file_type: TlsFileType) -> Self {
188         self.inner = self.inner.and_then(|mut builder| {
189             builder
190                 .set_certificate_file(path, file_type.into_inner())
191                 .map(|_| builder)
192         });
193         self
194     }
195 
196     /// Loads a certificate chain from a file.
197     ///
198     /// The file should contain a sequence of PEM-formatted certificates,
199     /// the first being the leaf certificate, and the remainder forming the
200     /// chain of certificates up to and including the trusted root certificate.
201     ///
202     /// # Examples
203     ///
204     /// ```
205     /// use ylong_http_client::util::TlsConfigBuilder;
206     ///
207     /// let builder = TlsConfigBuilder::new().certificate_chain_file("cert.pem");
208     /// ```
certificate_chain_file<T: AsRef<Path>>(mut self, path: T) -> Self209     pub fn certificate_chain_file<T: AsRef<Path>>(mut self, path: T) -> Self {
210         self.inner = self
211             .inner
212             .and_then(|mut builder| builder.set_certificate_chain_file(path).map(|_| builder));
213         self
214     }
215 
216     /// Adds custom root certificate.
add_root_certificates(mut self, certs: Certificate) -> Self217     pub fn add_root_certificates(mut self, certs: Certificate) -> Self {
218         for cert in certs.inner {
219             self.inner = self.inner.and_then(|mut builder| {
220                 { Ok(builder.cert_store_mut()).map(|store| store.add_cert(cert.0)) }
221                     .map(|_| builder)
222             });
223         }
224         self
225     }
226 
227     /// Sets the protocols to sent to the server for Application Layer Protocol
228     /// Negotiation (ALPN).
229     ///
230     /// Requires OpenSSL 1.0.2 or LibreSSL 2.6.1 or newer.
231     ///
232     /// # Examples
233     /// ```
234     /// use ylong_http_client::util::TlsConfigBuilder;
235     ///
236     /// let protocols = b"\x06spdy/1\x08http/1.1";
237     /// let builder = TlsConfigBuilder::new().alpn_protos(protocols);
238     /// ```
alpn_protos(mut self, protocols: &[u8]) -> Self239     pub fn alpn_protos(mut self, protocols: &[u8]) -> Self {
240         self.inner = self
241             .inner
242             .and_then(|mut builder| builder.set_alpn_protos(protocols).map(|_| builder));
243         self
244     }
245 
246     /// Sets the protocols to sent to the server for Application Layer Protocol
247     /// Negotiation (ALPN).
248     ///
249     /// This method is based on `openssl::SslContextBuilder::set_alpn_protos`.
250     ///
251     /// Requires OpenSSL 1.0.2 or LibreSSL 2.6.1 or newer.
252     ///
253     /// # Examples
254     /// ```
255     /// use ylong_http_client::util::{AlpnProtocol, AlpnProtocolList, TlsConfigBuilder};
256     ///
257     /// let protocols = AlpnProtocolList::new()
258     ///     .extend(AlpnProtocol::SPDY1)
259     ///     .extend(AlpnProtocol::HTTP11);
260     /// let builder = TlsConfigBuilder::new().alpn_protos(protocols.as_slice());
261     /// ```
alpn_proto_list(mut self, list: AlpnProtocolList) -> Self262     pub fn alpn_proto_list(mut self, list: AlpnProtocolList) -> Self {
263         self.inner = self
264             .inner
265             .and_then(|mut builder| builder.set_alpn_protos(list.as_slice()).map(|_| builder));
266         self
267     }
268 
269     /// Controls the use of built-in system certificates during certificate
270     /// validation. Default to `true` -- uses built-in system certs.
build_in_root_certs(mut self, is_use: bool) -> Self271     pub fn build_in_root_certs(mut self, is_use: bool) -> Self {
272         if !is_use {
273             self.inner = X509Store::new().and_then(|store| {
274                 self.inner.and_then(|mut builder| {
275                     {
276                         builder.set_cert_store(store);
277                         Ok(())
278                     }
279                     .map(|_| builder)
280                 })
281             });
282         }
283         self
284     }
285 
286     /// Controls the use of certificates verification.
287     ///
288     /// Defaults to `false` -- verify certificates.
289     ///
290     /// # Warning
291     ///
292     /// When sets `true`, any certificate for any site will be trusted for use.
293     ///
294     /// # Examples
295     ///
296     /// ```
297     /// use ylong_http_client::util::TlsConfigBuilder;
298     ///
299     /// let builder = TlsConfigBuilder::new().danger_accept_invalid_certs(true);
300     /// ```
danger_accept_invalid_certs(mut self, is_invalid: bool) -> Self301     pub fn danger_accept_invalid_certs(mut self, is_invalid: bool) -> Self {
302         if is_invalid {
303             self.inner = self.inner.and_then(|mut builder| {
304                 {
305                     builder.set_verify(crate::util::c_openssl::ssl::SSL_VERIFY_NONE);
306                     Ok(())
307                 }
308                 .map(|_| builder)
309             });
310         }
311         self
312     }
313 
314     /// Controls the use of hostname verification.
315     ///
316     /// Defaults to `false` -- verify hostname.
317     ///
318     /// # Warning
319     ///
320     /// When sets `true`, any valid certificate for any site will be trusted for
321     /// use from any other.
322     ///
323     /// # Examples
324     ///
325     /// ```
326     /// use ylong_http_client::util::TlsConfigBuilder;
327     ///
328     /// let builder = TlsConfigBuilder::new().danger_accept_invalid_hostnames(true);
329     /// ```
danger_accept_invalid_hostnames(mut self, invalid_hostname: bool) -> Self330     pub fn danger_accept_invalid_hostnames(mut self, invalid_hostname: bool) -> Self {
331         self.verify_hostname = !invalid_hostname;
332         self
333     }
334 
335     /// Controls the use of TLS server name indication.
336     ///
337     /// Defaults to `true` -- sets sni.
338     ///
339     /// # Examples
340     ///
341     /// ```
342     /// use ylong_http_client::util::TlsConfigBuilder;
343     ///
344     /// let builder = TlsConfigBuilder::new().sni(true);
345     /// ```
sni(mut self, use_sni: bool) -> Self346     pub fn sni(mut self, use_sni: bool) -> Self {
347         self.use_sni = use_sni;
348         self
349     }
350 
351     /// Builds a `TlsContext`. Returns `Err` if an error occurred during
352     /// configuration.
353     ///
354     /// # Examples
355     ///
356     /// ```
357     /// use ylong_http_client::util::{TlsConfigBuilder, TlsVersion};
358     ///
359     /// let context = TlsConfigBuilder::new()
360     ///     .ca_file("ca.crt")
361     ///     .max_proto_version(TlsVersion::TLS_1_2)
362     ///     .min_proto_version(TlsVersion::TLS_1_2)
363     ///     .cipher_list("DEFAULT:!aNULL:!eNULL:!MD5:!3DES:!DES:!RC4:!IDEA:!SEED:!aDSS:!SRP:!PSK")
364     ///     .build();
365     /// ```
build(self) -> Result<TlsConfig, HttpClientError>366     pub fn build(self) -> Result<TlsConfig, HttpClientError> {
367         let ctx = self
368             .inner
369             .map(|builder| builder.build())
370             .map_err(|e| HttpClientError::new_with_cause(ErrorKind::Build, Some(e)))?;
371 
372         Ok(TlsConfig {
373             ctx,
374             use_sni: self.use_sni,
375             verify_hostname: self.verify_hostname,
376         })
377     }
378 }
379 
380 impl Default for TlsConfigBuilder {
default() -> Self381     fn default() -> Self {
382         Self::new()
383     }
384 }
385 
386 /// `TlsContext` is based on `SSL_CTX`, which provides context
387 /// object of `TLS` streams.
388 ///
389 /// # Examples
390 ///
391 /// ```
392 /// use ylong_http_client::util::TlsConfig;
393 ///
394 /// let builder = TlsConfig::builder();
395 /// ```
396 #[derive(Clone)]
397 pub struct TlsConfig {
398     ctx: SslContext,
399     use_sni: bool,
400     verify_hostname: bool,
401 }
402 
403 impl TlsConfig {
404     /// Creates a new, default `TlsContextBuilder`.
405     ///
406     /// # Examples
407     ///
408     /// ```
409     /// use ylong_http_client::util::TlsConfig;
410     ///
411     /// let builder = TlsConfig::builder();
412     /// ```
builder() -> TlsConfigBuilder413     pub fn builder() -> TlsConfigBuilder {
414         TlsConfigBuilder::new()
415     }
416 
417     /// Creates a new, default `TlsSsl`.
ssl_new(&self, domain: &str) -> Result<TlsSsl, ErrorStack>418     pub(crate) fn ssl_new(&self, domain: &str) -> Result<TlsSsl, ErrorStack> {
419         let ctx = &self.ctx;
420         let mut ssl = Ssl::new(ctx)?;
421 
422         // SNI extension in `ClientHello` stage.
423         if self.use_sni && domain.parse::<IpAddr>().is_err() {
424             ssl.set_host_name_in_sni(domain)?;
425         }
426 
427         // Hostname verification in certificate verification.
428         if self.verify_hostname {
429             ssl.set_verify_hostname(domain)?;
430         }
431         Ok(TlsSsl(ssl))
432     }
433 }
434 
435 impl Default for TlsConfig {
default() -> Self436     fn default() -> Self {
437         // It must can be successful.
438         TlsConfig::builder()
439             .build()
440             .expect("TlsConfig build error!")
441     }
442 }
443 
444 /// /// `TlsSsl` is based on `Ssl`
445 pub(crate) struct TlsSsl(Ssl);
446 
447 impl TlsSsl {
into_inner(self) -> Ssl448     pub(crate) fn into_inner(self) -> Ssl {
449         self.0
450     }
451 }
452 
453 /// `TlsVersion` is based on `openssl::SslVersion`, which provides `SSL/TLS`
454 /// protocol version.
455 ///
456 /// # Examples
457 ///
458 /// ```
459 /// use ylong_http_client::util::TlsVersion;
460 ///
461 /// let version = TlsVersion::TLS_1_2;
462 /// ```
463 pub struct TlsVersion(SslVersion);
464 
465 impl TlsVersion {
466     /// Constant for TLS version 1.
467     pub const TLS_1_0: Self = Self(SslVersion::TLS_1_0);
468     /// Constant for TLS version 1.1.
469     pub const TLS_1_1: Self = Self(SslVersion::TLS_1_1);
470     /// Constant for TLS version 1.2.
471     pub const TLS_1_2: Self = Self(SslVersion::TLS_1_2);
472     /// Constant for TLS version 1.3.
473     pub const TLS_1_3: Self = Self(SslVersion::TLS_1_3);
474 
475     /// Consumes `TlsVersion` and then takes `SslVersion`.
into_inner(self) -> SslVersion476     pub(crate) fn into_inner(self) -> SslVersion {
477         self.0
478     }
479 }
480 
481 /// `TlsFileType` is based on `openssl::SslFileType`, which provides an
482 /// identifier of the format of a certificate or key file.
483 ///
484 /// ```
485 /// use ylong_http_client::util::TlsFileType;
486 ///
487 /// let file_type = TlsFileType::PEM;
488 /// ```
489 pub struct TlsFileType(SslFiletype);
490 
491 impl TlsFileType {
492     /// Constant for PEM file type.
493     pub const PEM: Self = Self(SslFiletype::PEM);
494     /// Constant for ASN1 file type.
495     pub const ASN1: Self = Self(SslFiletype::ASN1);
496 
497     /// Consumes `TlsFileType` and then takes `SslFiletype`.
into_inner(self) -> SslFiletype498     pub(crate) fn into_inner(self) -> SslFiletype {
499         self.0
500     }
501 }
502 
503 /// `Cert` is based on `X509`, which indicates `X509` public
504 /// key certificate.
505 ///
506 /// ```
507 /// # use ylong_http_client::Cert;
508 ///
509 /// # fn read_from_pem(pem: &[u8]) {
510 /// let cert = Cert::from_pem(pem);
511 /// # }
512 ///
513 /// # fn read_from_der(der: &[u8]) {
514 /// let cert = Cert::from_der(der);
515 /// # }
516 /// ```
517 pub struct Cert(X509);
518 
519 impl Cert {
520     /// Deserializes a PEM-encoded `Cert` structure.
521     ///
522     /// The input should have a header like below:
523     ///
524     /// ```text
525     /// -----BEGIN CERTIFICATE-----
526     /// ```
527     ///
528     /// # Examples
529     ///
530     /// ```
531     /// # use ylong_http_client::Cert;
532     ///
533     /// # fn read_from_pem(pem: &[u8]) {
534     /// let cert = Cert::from_pem(pem);
535     /// # }
536     /// ```
from_pem(pem: &[u8]) -> Result<Self, HttpClientError>537     pub fn from_pem(pem: &[u8]) -> Result<Self, HttpClientError> {
538         Ok(Self(X509::from_pem(pem).map_err(|e| {
539             HttpClientError::new_with_cause(ErrorKind::Build, Some(e))
540         })?))
541     }
542 
543     /// Deserializes a DER-encoded `Cert` structure.
544     ///
545     /// # Examples
546     ///
547     /// ```
548     /// use ylong_http_client::Cert;
549     ///
550     /// # fn read_from_der(der: &[u8]) {
551     /// let cert = Cert::from_der(der);
552     /// # }
553     /// ```
from_der(der: &[u8]) -> Result<Self, HttpClientError>554     pub fn from_der(der: &[u8]) -> Result<Self, HttpClientError> {
555         Ok(Self(X509::from_der(der).map_err(|e| {
556             HttpClientError::new_with_cause(ErrorKind::Build, Some(e))
557         })?))
558     }
559 
560     /// Deserializes a list of PEM-formatted certificates.
stack_from_pem(pem: &[u8]) -> Result<Vec<Self>, HttpClientError>561     pub fn stack_from_pem(pem: &[u8]) -> Result<Vec<Self>, HttpClientError> {
562         Ok(X509::stack_from_pem(pem)
563             .map_err(|e| HttpClientError::new_with_cause(ErrorKind::Build, Some(e)))?
564             .into_iter()
565             .map(Self)
566             .collect())
567     }
568 
569     /// Gets a reference to `X509Ref`.
as_ref(&self) -> &X509Ref570     pub(crate) fn as_ref(&self) -> &X509Ref {
571         self.0.as_ref()
572     }
573 
574     /// Consumes `X509` and then takes `X509`.
into_inner(self) -> X509575     pub(crate) fn into_inner(self) -> X509 {
576         self.0
577     }
578 }
579 
580 /// Represents a server X509 certificates.
581 ///
582 /// You can use `from_pem` to parse a `&[u8]` into a list of certificates.
583 ///
584 /// # Examples
585 ///
586 /// ```
587 /// use ylong_http_client::Certificate;
588 ///
589 /// fn from_pem(pem: &[u8]) {
590 ///     let certs = Certificate::from_pem(pem);
591 /// }
592 /// ```
593 pub struct Certificate {
594     inner: Vec<Cert>,
595 }
596 
597 impl Certificate {
598     /// Deserializes a list of PEM-formatted certificates.
from_pem(pem: &[u8]) -> Result<Self, HttpClientError>599     pub fn from_pem(pem: &[u8]) -> Result<Self, HttpClientError> {
600         let inner = X509::stack_from_pem(pem)
601             .map_err(|e| HttpClientError::new_with_cause(ErrorKind::Build, Some(e)))?
602             .into_iter()
603             .map(Cert)
604             .collect();
605         Ok(Certificate { inner })
606     }
607 
into_inner(self) -> Vec<Cert>608     pub(crate) fn into_inner(self) -> Vec<Cert> {
609         self.inner
610     }
611 }
612 
613 #[cfg(test)]
614 mod ut_openssl_adapter {
615     use crate::util::{Cert, TlsConfigBuilder, TlsFileType, TlsVersion};
616     use crate::{AlpnProtocol, AlpnProtocolList, Certificate};
617 
618     /// UT test cases for `TlsConfigBuilder::new`.
619     ///
620     /// # Brief
621     /// 1. Creates a `TlsConfigBuilder` by calling `TlsConfigBuilder::new`
622     /// 2. Checks if the result is as expected.
623     #[test]
ut_tls_config_builder_new()624     fn ut_tls_config_builder_new() {
625         let _ = TlsConfigBuilder::default();
626         let builder = TlsConfigBuilder::new();
627         assert!(builder.ca_file("folder/ca.crt").build().is_err());
628     }
629 
630     /// UT test cases for `TlsConfigBuilder::new`.
631     ///
632     /// # Brief
633     /// 1. Creates a `TlsConfigBuilder` by calling `TlsConfigBuilder::new`.
634     /// 2. Calls `set_cipher_suites`.
635     /// 3. Provides an invalid path as argument.
636     /// 4. Checks if the result is as expected.
637     #[test]
ut_set_cipher_suites()638     fn ut_set_cipher_suites() {
639         let builder = TlsConfigBuilder::new().cipher_suites("INVALID STRING");
640         assert!(builder.build().is_err());
641     }
642 
643     /// UT test cases for `TlsConfigBuilder::set_max_proto_version`.
644     ///
645     /// # Brief
646     /// 1. Creates a `TlsConfigBuilder` by calling `TlsConfigBuilder::new`.
647     /// 2. Calls `set_max_proto_version`.
648     /// 3. Checks if the result is as expected.
649     #[test]
ut_set_max_proto_version()650     fn ut_set_max_proto_version() {
651         let builder = TlsConfigBuilder::new()
652             .max_proto_version(TlsVersion::TLS_1_2)
653             .build();
654         assert!(builder.is_ok());
655     }
656 
657     /// UT test cases for `TlsConfigBuilder::set_min_proto_version`.
658     ///
659     /// # Brief
660     /// 1. Creates a `TlsConfigBuilder` by calling `TlsConfigBuilder::new`.
661     /// 2. Calls `set_min_proto_version`.
662     /// 3. Checks if the result is as expected.
663     #[test]
ut_set_min_proto_version()664     fn ut_set_min_proto_version() {
665         let builder = TlsConfigBuilder::new()
666             .min_proto_version(TlsVersion::TLS_1_2)
667             .build();
668         assert!(builder.is_ok());
669     }
670 
671     /// UT test cases for `TlsConfigBuilder::set_cipher_list`.
672     ///
673     /// # Brief
674     /// 1. Creates a `TlsConfigBuilder` by calling `TlsConfigBuilder::new`.
675     /// 2. Calls `set_cipher_list`.
676     /// 3. Checks if the result is as expected.
677     #[test]
ut_set_cipher_list()678     fn ut_set_cipher_list() {
679         let builder = TlsConfigBuilder::new()
680             .cipher_list("DEFAULT:!aNULL:!eNULL:!MD5:!3DES:!DES:!RC4:!IDEA:!SEED:!aDSS:!SRP:!PSK")
681             .build();
682         assert!(builder.is_ok());
683     }
684 
685     /// UT test cases for `TlsConfigBuilder::set_certificate_file`.
686     ///
687     /// # Brief
688     /// 1. Creates a `TlsConfigBuilder` by calling `TlsConfigBuilder::new`.
689     /// 2. Calls `set_certificate_file`.
690     /// 3. Provides an invalid path as argument.
691     /// 4. Checks if the result is as expected.
692     #[test]
ut_set_certificate_file()693     fn ut_set_certificate_file() {
694         let builder = TlsConfigBuilder::new()
695             .certificate_file("cert.pem", TlsFileType::PEM)
696             .build();
697         assert!(builder.is_err());
698     }
699 
700     /// UT test cases for `TlsConfigBuilder::set_certificate_chain_file`.
701     ///
702     /// # Brief
703     /// 1. Creates a `TlsConfigBuilder` by calling `TlsConfigBuilder::new`.
704     /// 2. Calls `set_certificate_chain_file`.
705     /// 3. Provides an invalid path as argument.
706     /// 4. Checks if the result is as expected.
707     #[test]
ut_set_certificate_chain_file()708     fn ut_set_certificate_chain_file() {
709         let builder = TlsConfigBuilder::new()
710             .certificate_chain_file("cert.pem")
711             .build();
712         assert!(builder.is_err());
713     }
714 
715     /// UT test cases for `TlsConfigBuilder::add_root_certificates`.
716     ///
717     /// # Brief
718     /// 1. Creates a `TlsConfigBuilder` by calling `TlsConfigBuilder::new`.
719     /// 2. Calls `add_root_certificates`.
720     /// 3. Provides PEM-formatted certificates.
721     /// 4. Checks if the result is as expected.
722     #[test]
ut_add_root_certificates()723     fn ut_add_root_certificates() {
724         let builder = TlsConfigBuilder::new()
725             .add_root_certificates(
726                 Certificate::from_pem(include_bytes!("../../../tests/file/root-ca.pem"))
727                     .expect("Sets certs error."),
728             )
729             .build();
730         assert!(builder.is_ok());
731     }
732 
733     /// UT test cases for `TlsConfigBuilder::build_in_root_certs`.
734     ///
735     /// # Brief
736     /// 1. Creates a `TlsConfigBuilder` by calling `TlsConfigBuilder::new`.
737     /// 2. Calls `build_in_root_certs`.
738     /// 3. Checks if the result is as expected.
739     #[test]
ut_build_in_root_certs()740     fn ut_build_in_root_certs() {
741         let builder = TlsConfigBuilder::new().build_in_root_certs(true).build();
742         assert!(builder.is_ok());
743     }
744 
745     /// UT test cases for `TlsConfigBuilder::set_alpn_proto_list`.
746     ///
747     /// # Brief
748     /// 1. Creates a `TlsConfigBuilder` by calling `TlsConfigBuilder::new`.
749     /// 2. Calls `set_alpn_proto_list`.
750     /// 3. Provides `AlpnProtocol`s.
751     /// 4. Checks if the result is as expected.
752     #[test]
ut_set_alpn_proto_list()753     fn ut_set_alpn_proto_list() {
754         let builder = TlsConfigBuilder::new()
755             .alpn_proto_list(
756                 AlpnProtocolList::new()
757                     .extend(AlpnProtocol::HTTP11)
758                     .extend(AlpnProtocol::H2),
759             )
760             .build();
761         assert!(builder.is_ok());
762     }
763 
764     /// UT test cases for `TlsConfig::ssl`.
765     ///
766     /// # Brief
767     /// 1. Creates a `TlsConfig` by calling `TlsConfigBuilder::new` and
768     ///    `TlsConfigBuilder::build`.
769     /// 2. Creates a `TlsSsl` by calling `TlsConfig::ssl_new`.
770     /// 3. Calls `TlsSsl::into_inner`.
771     /// 4. Checks if the result is as expected.
772     #[test]
ut_tls_ssl()773     fn ut_tls_ssl() {
774         let config = TlsConfigBuilder::new()
775             .build()
776             .expect("TlsConfig build error.");
777         let _ssl = config
778             .ssl_new("host name")
779             .expect("Ssl build error.")
780             .into_inner();
781     }
782 
783     /// UT test cases for `Cert::from_pem`.
784     ///
785     /// # Brief
786     /// 1. Creates a `Cert` by calling `Cert::from_pem`.
787     /// 2. Provides an invalid pem as argument.
788     /// 3. Checks if the result is as expected.
789     #[test]
ut_x509_from_pem()790     fn ut_x509_from_pem() {
791         let pem = "(pem-content)";
792         let x509 = Cert::from_pem(pem.as_bytes());
793         assert!(x509.is_err());
794 
795         let cert = include_bytes!("../../../tests/file/root-ca.pem");
796         println!("{:?}", std::str::from_utf8(cert).unwrap());
797         let x509 = Cert::from_pem(cert);
798         assert!(x509.is_ok());
799     }
800 
801     /// UT test cases for `Cert::from_der`.
802     ///
803     /// # Brief
804     /// 1. Creates a `Cert` by calling `Cert::from_der`.
805     /// 2. Provides an invalid der as argument.
806     /// 3. Checks if the result is as expected.
807     #[test]
ut_x509_from_der()808     fn ut_x509_from_der() {
809         let der = "(dar-content)";
810         let x509 = Cert::from_der(der.as_bytes());
811         assert!(x509.is_err());
812     }
813 
814     /// UT test cases for `Cert::stack_from_pem`.
815     ///
816     /// # Brief
817     /// 1. Creates a `Cert` by calling `Cert::stack_from_pem`.
818     /// 2. Provides pem bytes as argument.
819     /// 3. Checks if the result is as expected.
820     #[test]
ut_cert_stack_from_der()821     fn ut_cert_stack_from_der() {
822         let v = include_bytes!("../../../tests/file/root-ca.pem");
823         let x509 = Cert::stack_from_pem(v);
824         assert!(x509.is_ok());
825     }
826 
827     /// UT test cases for `Certificate::from_pem`.
828     ///
829     /// # Brief
830     /// 1. Creates a `Certificate` by calling `Certificate::from_pem`.
831     /// 2. Provides pem bytes as argument.
832     /// 3. Checks if the result is as expected.
833     #[test]
ut_certificate_from_pem()834     fn ut_certificate_from_pem() {
835         let v = include_bytes!("../../../tests/file/root-ca.pem");
836         let certs = Certificate::from_pem(v);
837         assert!(certs.is_ok());
838     }
839 }
840