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