drogue_bazaar/actix/http/
bind.rs1use crate::core::tls::TlsAuthConfig;
2use actix_http::{Request, Response};
3use actix_service::{IntoServiceFactory, ServiceFactory};
4use actix_web::{body::MessageBody, dev::AppConfig, Error, HttpServer};
5use std::{fmt, path::Path};
6use tokio::io;
7
8pub fn bind_http<F, I, S, B, K, C>(
10 main: HttpServer<F, I, S, B>,
11 bind_addr: String,
12 tls_auth_config: Option<TlsAuthConfig>,
13 key_file: Option<K>,
14 cert_bundle_file: Option<C>,
15) -> io::Result<HttpServer<F, I, S, B>>
16where
17 F: Fn() -> I + Send + Clone + 'static,
18 I: IntoServiceFactory<S, Request>,
19 S: ServiceFactory<Request, Config = AppConfig> + 'static,
20 S::Error: Into<Error> + 'static,
21 S::InitError: fmt::Debug,
22 S::Response: Into<Response<B>> + 'static,
23 B: MessageBody + 'static,
24 K: AsRef<Path>,
25 C: AsRef<Path>,
26{
27 match (tls_auth_config, key_file, cert_bundle_file) {
28 #[allow(unused_variables)]
29 (Some(tls_auth_config), Some(key), Some(cert)) => {
30 #[cfg(feature = "openssl")]
31 if cfg!(feature = "openssl") {
32 return bind_http_openssl(main, tls_auth_config, bind_addr, key, cert);
33 }
34 panic!("TLS is required, but no TLS implementation enabled")
35 }
36 (None, None, None) => main.bind(bind_addr),
37 (Some(_), _, _) => {
38 panic!("Wrong TLS configuration: TLS enabled, but key or cert is missing")
39 }
40 (None, Some(_), _) | (None, _, Some(_)) => {
41 panic!("Wrong TLS configuration: key or cert specified, but TLS is disabled")
43 }
44 }
45}
46
47#[cfg(feature = "openssl")]
48fn bind_http_openssl<F, I, S, B, K, C>(
49 main: HttpServer<F, I, S, B>,
50 tls_auth_config: TlsAuthConfig,
51 bind_addr: String,
52 key_file: K,
53 cert_bundle_file: C,
54) -> io::Result<HttpServer<F, I, S, B>>
55where
56 F: Fn() -> I + Send + Clone + 'static,
57 I: IntoServiceFactory<S, Request>,
58 S: ServiceFactory<Request, Config = AppConfig> + 'static,
59 S::Error: Into<Error> + 'static,
60 S::InitError: fmt::Debug,
61 S::Response: Into<Response<B>> + 'static,
62 B: MessageBody + 'static,
63 K: AsRef<Path>,
64 C: AsRef<Path>,
65{
66 use crate::core::tls::TlsMode;
67 use openssl::ssl;
68
69 let method = ssl::SslMethod::tls_server();
70 let mut builder = ssl::SslAcceptor::mozilla_intermediate_v5(method)?;
71 builder.set_private_key_file(key_file, ssl::SslFiletype::PEM)?;
72 builder.set_certificate_chain_file(cert_bundle_file)?;
73
74 if let TlsMode::Client = tls_auth_config.mode {
75 builder.set_verify_callback(ssl::SslVerifyMode::PEER, |_, ctx| {
77 log::debug!(
78 "Accepting client certificates: {:?}",
79 ctx.current_cert()
80 .map(|cert| format!("{:?}", cert.subject_name()))
81 .unwrap_or_else(|| "<unknown>".into())
82 );
83 true
84 });
85 }
86
87 if let Some(psk) = tls_auth_config.psk {
88 builder.set_psk_server_callback(move |ssl, identity, secret_mut| {
89 match psk(ssl, identity, secret_mut) {
90 Ok(len) => Ok(len),
91 Err(e) => {
92 log::debug!("Error during TLS-PSK handshake: {:?}", e);
93 Ok(0)
94 }
95 }
96 });
97 }
98
99 Ok(main
100 .bind_openssl(bind_addr, builder)?
101 .tls_handshake_timeout(std::time::Duration::from_secs(10)))
102}