ice_rs/
ssltools.rs

1use std::io::prelude::*;
2use openssl::ssl::SslVersion;
3use openssl::x509::*;
4use openssl::pkcs12::*;
5use openssl::pkey::*;
6use std::fs::File;
7use std::path::Path;
8
9use crate::errors::*;
10
11pub (crate) fn read_pem(pem_file: &str, dir: &Path) ->Result<(Option<X509>, Option<PKey<Private>>), Box<dyn std::error::Error + Sync + Send>> {
12    let mut buffer = vec![];
13    let mut file = File::open(&dir.join(pem_file))?;
14    file.read_to_end(&mut buffer)?;
15
16    match (X509::from_pem(&buffer), PKey::private_key_from_pem(&buffer)) {
17        (Ok(cert), Ok(pkey)) => {
18            Ok((Some(cert), Some(pkey)))
19        }
20        (Ok(cert), _) => {
21            Ok((Some(cert), None))
22        }
23        (_, Ok(pkey)) => {
24            Ok((None, Some(pkey)))
25        }
26        _ => Err(Box::new(ProtocolError::new(&format!("SSL: Error reading PEM file: {}", pem_file))))
27    }
28}
29
30pub (crate) fn read_pkcs12(pkcs12_path: &Path, password: &str, dir: &Path) -> Result<ParsedPkcs12, Box<dyn std::error::Error + Sync + Send>> {
31    let mut buffer = vec![];
32    let mut file = File::open(&dir.join(pkcs12_path))?;
33    file.read_to_end(&mut buffer)?;
34
35    match Pkcs12::from_der(&buffer) {
36        Ok(pkcs12) => {
37            match pkcs12.parse(password) {
38                Ok(parsed) => Ok(parsed),
39                _ => Err(Box::new(ProtocolError::new("SSL: Could not parse pkcs12")))
40            }
41        },
42        _ => Err(Box::new(ProtocolError::new("SSL: Could not read pkcs12")))
43    }
44}
45
46pub (crate) fn parse_protocol(protocol: &str) -> Option<SslVersion> {
47    match protocol.to_lowercase().as_ref() {
48        "ssl3" | "sslv3" => {
49            Some(SslVersion::SSL3)
50        },
51        "tls1_3" | "tlsv1_3" => {
52            Some(SslVersion::TLS1_3)
53        }
54        "tls1_2" | "tlsv1_2" => {
55            Some(SslVersion::TLS1_2)
56        }
57        "tls1_1" | "tlsv1_1" => {
58            Some(SslVersion::TLS1_1)
59        }
60        "tls1" | "tlsv1" | "tls1_0" | "tlsv1_0" => {
61            Some(SslVersion::TLS1)
62        }
63        _ => {
64            None
65        }
66    }
67}
68
69fn protocol_to_num(version: SslVersion) -> i32 {
70    match version {
71        SslVersion::TLS1 => 1,
72        SslVersion::TLS1_1 => 2,
73        SslVersion::TLS1_2 => 3,
74        SslVersion::TLS1_3 => 4,
75        _ => 0
76    }
77}
78
79fn num_to_protocol(num: i32) -> SslVersion {
80    match num {
81        4 => SslVersion::TLS1_3,
82        3 => SslVersion::TLS1_2,
83        2 => SslVersion::TLS1_1,
84        1 => SslVersion::TLS1,
85        _ => SslVersion::SSL3,
86    }
87}
88
89pub (crate) fn max_protocol(new_value: SslVersion, current_max: Option<SslVersion>) -> SslVersion {
90    let new_numeric = protocol_to_num(new_value);
91    if let Some(current_max) = current_max {
92        num_to_protocol(std::cmp::max(new_numeric, protocol_to_num(current_max)))
93    } else {
94        new_value
95    }
96}
97
98pub (crate) fn min_protocol(new_value: SslVersion, current_min: Option<SslVersion>) -> SslVersion {
99    let new_numeric = protocol_to_num(new_value);
100    if let Some(current_min) = current_min {
101        num_to_protocol(std::cmp::min(new_numeric, protocol_to_num(current_min)))
102    } else {
103        new_value
104    }
105}