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}