1 use crate::flowgger::config::Config;
2 use openssl::bn::BigNum;
3 use openssl::dh::Dh;
4 use openssl::ssl::*;
5 use std::path::{Path, PathBuf};
6 
7 pub mod tls_input;
8 #[cfg(feature = "coroutines")]
9 pub mod tlsco_input;
10 
11 pub use super::Input;
12 
13 const DEFAULT_CERT: &str = "flowgger.pem";
14 const DEFAULT_CIPHERS: &str =
15     "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:\
16      ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:\
17      ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-GCM-SHA384:\
18      ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:\
19      ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:\
20      AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:\
21      ECDHE-RSA-DES-CBC3-SHA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:\
22      !EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA";
23 const DEFAULT_COMPRESSION: bool = false;
24 const DEFAULT_FRAMING: &str = "line";
25 const DEFAULT_KEY: &str = "flowgger.pem";
26 const DEFAULT_LISTEN: &str = "0.0.0.0:6514";
27 #[cfg(feature = "coroutines")]
28 const DEFAULT_THREADS: usize = 1;
29 const DEFAULT_TIMEOUT: u64 = 3600;
30 const DEFAULT_TLS_COMPATIBILITY_LEVEL: &str = "default";
31 const DEFAULT_VERIFY_PEER: bool = false;
32 const TLS_VERIFY_DEPTH: u32 = 6;
33 
34 #[derive(Clone)]
35 pub struct TlsConfig {
36     framing: String,
37     threads: usize,
38     acceptor: SslAcceptor,
39 }
40 
set_fs(ctx: &mut SslContextBuilder)41 fn set_fs(ctx: &mut SslContextBuilder) {
42     let p = BigNum::from_hex_str("87A8E61DB4B6663CFFBBD19C651959998CEEF608660DD0F25D2CEED4435E3B00E00DF8F1D61957D4FAF7DF4561B2AA3016C3D91134096FAA3BF4296D830E9A7C209E0C6497517ABD5A8A9D306BCF67ED91F9E6725B4758C022E0B1EF4275BF7B6C5BFC11D45F9088B941F54EB1E59BB8BC39A0BF12307F5C4FDB70C581B23F76B63ACAE1CAA6B7902D52526735488A0EF13C6D9A51BFA4AB3AD8347796524D8EF6A167B5A41825D967E144E5140564251CCACB83E6B486F6B3CA3F7971506026C0B857F689962856DED4010ABD0BE621C3A3960A54E710C375F26375D7014103A4B54330C198AF126116D2276E11715F693877FAD7EF09CADB094AE91E1A1597").unwrap();
43     let g = BigNum::from_hex_str("3FB32C9B73134D0B2E77506660EDBD484CA7B18F21EF205407F4793A1A0BA12510DBC15077BE463FFF4FED4AAC0BB555BE3A6C1B0C6B47B1BC3773BF7E8C6F62901228F8C28CBB18A55AE31341000A650196F931C77A57F2DDF463E5E9EC144B777DE62AAAB8A8628AC376D282D6ED3864E67982428EBC831D14348F6F2F9193B5045AF2767164E1DFC967C1FB3F2E55A4BD1BFFE83B9C80D052B985D182EA0ADB2A3B7313D3FE14C8484B1E052588B9B7D2BBD2DF016199ECD06E1557CD0915B3353BBB64E0EC377FD028370DF92B52C7891428CDC67EB6184B523D1DB246C32F63078490F00EF8D647D148D47954515E2327CFEF98C582664B4C0F6CC41659").unwrap();
44     let q =
45         BigNum::from_hex_str("8CF83642A709A097B447997640129DA299B1A47D1EB3750BA308B0FE64F5FBD3")
46             .unwrap();
47     let dh = Dh::from_params(p, g, q).unwrap();
48     ctx.set_tmp_dh(&dh).unwrap();
49 }
50 
51 #[cfg(feature = "coroutines")]
get_default_threads(config: &Config) -> usize52 fn get_default_threads(config: &Config) -> usize {
53     config
54         .lookup("input.tls_threads")
55         .map_or(DEFAULT_THREADS, |x| {
56             x.as_integer()
57                 .expect("input.tls_threads must be an unsigned integer") as usize
58         })
59 }
60 
61 #[cfg(not(feature = "coroutines"))]
get_default_threads(_config: &Config) -> usize62 fn get_default_threads(_config: &Config) -> usize {
63     1
64 }
65 
config_parse(config: &Config) -> (TlsConfig, String, u64)66 pub fn config_parse(config: &Config) -> (TlsConfig, String, u64) {
67     let listen = config
68         .lookup("input.listen")
69         .map_or(DEFAULT_LISTEN, |x| {
70             x.as_str().expect("input.listen must be an ip:port string")
71         })
72         .to_owned();
73     let threads = get_default_threads(config);
74     let cert = config
75         .lookup("input.tls_cert")
76         .map_or(DEFAULT_CERT, |x| {
77             x.as_str()
78                 .expect("input.tls_cert must be a path to a .pem file")
79         })
80         .to_owned();
81     let key = config
82         .lookup("input.tls_key")
83         .map_or(DEFAULT_KEY, |x| {
84             x.as_str()
85                 .expect("input.tls_key must be a path to a .pem file")
86         })
87         .to_owned();
88     let ciphers = config
89         .lookup("input.tls_ciphers")
90         .map_or(DEFAULT_CIPHERS, |x| {
91             x.as_str()
92                 .expect("input.tls_ciphers must be a string with a cipher suite")
93         })
94         .to_owned();
95 
96     let tls_modern = match config
97         .lookup("input.tls_compatibility_level")
98         .map_or(DEFAULT_TLS_COMPATIBILITY_LEVEL, |x| {
99             x.as_str().expect(
100                 "input.tls_compatibility_level must be a string with the comptibility level",
101             )
102         })
103         .to_lowercase()
104         .as_ref()
105     {
106         "default" | "any" | "intermediate" => false,
107         "modern" => true,
108         _ => panic!(r#"TLS compatibility level must be "intermediate" or "modern""#),
109     };
110     let verify_peer = config
111         .lookup("input.tls_verify_peer")
112         .map_or(DEFAULT_VERIFY_PEER, |x| {
113             x.as_bool()
114                 .expect("input.tls_verify_peer must be a boolean")
115         });
116     let ca_file: Option<PathBuf> = config.lookup("input.tls_ca_file").and_then(|x| {
117         Some(PathBuf::from(
118             x.as_str()
119                 .expect("input.tls_ca_file must be a path to a file"),
120         ))
121     });
122     let compression = config
123         .lookup("input.tls_compression")
124         .map_or(DEFAULT_COMPRESSION, |x| {
125             x.as_bool()
126                 .expect("input.tls_compression must be a boolean")
127         });
128     let timeout = config.lookup("input.timeout").map_or(DEFAULT_TIMEOUT, |x| {
129         x.as_integer().expect("input.timeout must be an integer") as u64
130     });
131     let framing = if config.lookup("input.framed").map_or(false, |x| {
132         x.as_bool().expect("input.framed must be a boolean")
133     }) {
134         "syslen"
135     } else {
136         DEFAULT_FRAMING
137     };
138     let framing = config
139         .lookup("input.framing")
140         .map_or(framing, |x| {
141             x.as_str()
142                 .expect(r#"input.framing must be a string set to "line", "nul" or "syslen""#)
143         })
144         .to_owned();
145     let mut acceptor_builder = (if tls_modern {
146         SslAcceptor::mozilla_modern(SslMethod::tls())
147     } else {
148         SslAcceptor::mozilla_intermediate(SslMethod::tls())
149     })
150     .unwrap();
151     {
152         let mut ctx = &mut acceptor_builder;
153         if let Some(ca_file) = ca_file {
154             ctx.set_ca_file(&ca_file)
155                 .expect("Unable to read the trusted CA file");
156         }
157         if !verify_peer {
158             ctx.set_verify(SslVerifyMode::NONE);
159         } else {
160             ctx.set_verify_depth(TLS_VERIFY_DEPTH);
161             ctx.set_verify(SslVerifyMode::PEER | SslVerifyMode::FAIL_IF_NO_PEER_CERT);
162         }
163         let mut opts = SslOptions::CIPHER_SERVER_PREFERENCE
164             | SslOptions::NO_SESSION_RESUMPTION_ON_RENEGOTIATION;
165         if !compression {
166             opts |= SslOptions::NO_COMPRESSION;
167         }
168         ctx.set_options(opts);
169         set_fs(&mut ctx);
170         ctx.set_certificate_chain_file(&Path::new(&cert))
171             .expect("Unable to read the TLS certificate chain");
172         ctx.set_private_key_file(&Path::new(&key), SslFiletype::PEM)
173             .expect("Unable to read the TLS key");
174         ctx.set_cipher_list(&ciphers)
175             .expect("Unsupported cipher suite");
176     }
177     let acceptor = acceptor_builder.build();
178     let tls_config = TlsConfig {
179         framing,
180         threads,
181         acceptor,
182     };
183     (tls_config, listen, timeout)
184 }
185