webhdfs/
https.rs

1use hyper::client::HttpConnector;
2use hyper_tls::HttpsConnector;
3use native_tls::{TlsConnector, Identity, Protocol, Certificate};
4use crate::config::HttpsConfig;
5use crate::error::*;
6
7pub type HttpsConnectorType = HttpsConnector<HttpConnector>;
8
9pub struct HttpsSettings {
10    hc: HttpsConnectorType
11}
12
13impl From<HttpsConfig> for HttpsSettings {
14    fn from(config: HttpsConfig) -> HttpsSettings {
15        https_settings_from_config_f(config).unwrap_or_else(|e| panic!("https settings failure: {}", e))
16    }
17}
18
19pub type HttpsSettingsPtr = std::rc::Rc<HttpsSettings>;
20
21#[inline]
22pub fn https_settings_ptr(https_settings: HttpsSettings) -> HttpsSettingsPtr {
23    std::rc::Rc::new(https_settings)
24}
25
26pub fn https_connector(cfg: &HttpsSettingsPtr) -> HttpsConnectorType {
27    cfg.hc.clone()
28}
29
30fn _test_types() {
31    fn is_clone<T: Clone>() { }
32    is_clone::<HttpsConnectorType>();
33}
34
35
36pub fn read_identity_file(file_path: &str, password: &str) -> Result<Identity> {
37    use std::io::Read;
38    let mut file_data = vec![];
39    let _ = std::fs::File::open(file_path)?.read_to_end(&mut file_data)?;
40    let r = Identity::from_pkcs12(&file_data, password)?;
41    Ok(r)
42}
43
44pub fn read_cert_file(file_path: &str) -> Result<Certificate> {
45    use std::io::Read;
46    let mut file_data = vec![];
47    let _ = std::fs::File::open(file_path)?.read_to_end(&mut file_data)?;
48    let r = Certificate::from_der(&file_data)?;
49    Ok(r)
50}
51
52/// fallible version of convert_https_settings
53fn https_settings_from_config_f(config: HttpsConfig) -> Result<HttpsSettings> {
54    let identity_password: &str = if let Some(s) = &config.identity_password { &s } else { "" };
55
56    fn pv(s: String) -> Result<Option<Protocol>> {
57        match s.as_ref() {
58            "Sslv3" => Ok(Some(Protocol::Sslv3)),
59            "Tlsv10" => Ok(Some(Protocol::Tlsv10)),
60            "Tlsv11" => Ok(Some(Protocol::Tlsv11)),
61            "Tlsv12" => Ok(Some(Protocol::Tlsv12)),
62            "no_check" => Ok(None),
63            other => Err(app_error!(generic "Invalid TLS protocol version setting '{}'", other))
64        }
65    }
66
67    let mut cb = TlsConnector::builder();
68    if let Some(w) = config.danger_accept_invalid_certs { cb.danger_accept_invalid_certs(w); }
69    if let Some(w) = config.danger_accept_invalid_hostnames { cb.danger_accept_invalid_hostnames(w); }
70    if let Some(w) = config.use_sni { cb.use_sni(w); }
71    if let Some(w) = config.min_protocol_version { cb.min_protocol_version(pv(w)?); }
72    if let Some(w) = config.max_protocol_version { cb.max_protocol_version(pv(w)?); }
73    if let Some(w) = config.identity_file { 
74        cb.identity(read_identity_file(&w,identity_password).aerr_f(|| format!("read_identity_file({}): error", &w))?);
75    }
76    if let Some(w) = config.root_certificates { for c in w { cb.add_root_certificate(read_cert_file(&c)?); } }
77    let tc = cb.build().unwrap_or_else(|e| panic!("HttpsConnector::new() failure: {}", e));
78    let mut httpc = HttpConnector::new();
79    httpc.enforce_http(false);
80    let hc: HttpsConnectorType = (httpc, tc.into()).into();
81    Ok(HttpsSettings { hc })
82}