ferron/
main.rs

1mod acme;
2mod config;
3mod handler;
4mod listener_handler_communication;
5mod listener_quic;
6mod listener_tcp;
7mod logging;
8mod request_handler;
9mod runtime;
10mod tls_util;
11mod util;
12
13use std::collections::{HashMap, HashSet};
14use std::error::Error;
15use std::net::{IpAddr, Ipv6Addr, SocketAddr};
16use std::path::{Path, PathBuf};
17use std::str::FromStr;
18use std::sync::{Arc, LazyLock, Mutex};
19use std::thread;
20use std::time::Duration;
21
22use async_channel::{Receiver, Sender};
23use base64::Engine;
24use chrono::{DateTime, Local};
25use clap::{Arg, ArgAction, ArgMatches, Command};
26use config::adapters::ConfigurationAdapter;
27use config::processing::{load_modules, merge_duplicates, premerge_configuration, remove_and_add_global_configuration};
28use config::ServerConfigurations;
29use ferron_common::{get_entry, get_value, get_values};
30use ferron_load_modules::{get_dns_provider, obtain_module_loaders};
31use handler::create_http_handler;
32use human_panic::{setup_panic, Metadata};
33use instant_acme::{ChallengeType, ExternalAccountKey, LetsEncrypt};
34use listener_handler_communication::ConnectionData;
35use listener_quic::create_quic_listener;
36use listener_tcp::create_tcp_listener;
37use logging::LogMessage;
38use mimalloc::MiMalloc;
39use rustls::client::WebPkiServerVerifier;
40use rustls::crypto::aws_lc_rs::cipher_suite::*;
41use rustls::crypto::aws_lc_rs::default_provider;
42use rustls::crypto::aws_lc_rs::kx_group::*;
43use rustls::server::{ResolvesServerCert, WebPkiClientVerifier};
44use rustls::sign::CertifiedKey;
45use rustls::version::{TLS12, TLS13};
46use rustls::{ClientConfig, RootCertStore, ServerConfig};
47use rustls_native_certs::load_native_certs;
48use rustls_platform_verifier::BuilderVerifierExt;
49use shadow_rs::shadow;
50use tls_util::{load_certs, load_private_key, CustomSniResolver, OneCertifiedKeyResolver};
51use tokio::io::{AsyncWriteExt, BufWriter};
52use tokio_util::sync::CancellationToken;
53use xxhash_rust::xxh3::xxh3_128;
54
55use crate::acme::{
56  add_domain_to_cache, check_certificate_validity_or_install_cached, convert_on_demand_config, get_cached_domains,
57  provision_certificate, AcmeCache, AcmeConfig, AcmeOnDemandConfig, AcmeResolver, TlsAlpn01Resolver,
58  ACME_TLS_ALPN_NAME,
59};
60use crate::logging::{LoggerFilter, LoggersBuilder};
61use crate::util::{is_localhost, match_hostname, NoServerVerifier};
62
63// Set the global allocator to use mimalloc for performance optimization
64#[global_allocator]
65static GLOBAL: MiMalloc = MiMalloc;
66
67shadow!(build);
68
69static LISTENER_HANDLER_CHANNEL: LazyLock<Arc<(Sender<ConnectionData>, Receiver<ConnectionData>)>> =
70  LazyLock::new(|| Arc::new(async_channel::unbounded()));
71#[allow(clippy::type_complexity)]
72static TCP_LISTENERS: LazyLock<Arc<Mutex<HashMap<SocketAddr, CancellationToken>>>> =
73  LazyLock::new(|| Arc::new(Mutex::new(HashMap::new())));
74#[allow(clippy::type_complexity)]
75static QUIC_LISTENERS: LazyLock<Arc<Mutex<HashMap<SocketAddr, (CancellationToken, Sender<Arc<ServerConfig>>)>>>> =
76  LazyLock::new(|| Arc::new(Mutex::new(HashMap::new())));
77static LOGGER_BUILDER: LazyLock<Arc<Mutex<LoggersBuilder>>> =
78  LazyLock::new(|| Arc::new(Mutex::new(LoggersBuilder::new())));
79static URING_ENABLED: LazyLock<Arc<Mutex<bool>>> = LazyLock::new(|| Arc::new(Mutex::new(true)));
80
81/// Handles shutdown signals (SIGHUP and CTRL+C) and returns whether to continue running
82fn handle_shutdown_signals(runtime: &tokio::runtime::Runtime) -> bool {
83  runtime.block_on(async move {
84    let (continue_tx, continue_rx) = async_channel::unbounded::<bool>();
85    let cancel_token = tokio_util::sync::CancellationToken::new();
86
87    #[cfg(unix)]
88    {
89      let cancel_token_clone = cancel_token.clone();
90      let continue_tx_clone = continue_tx.clone();
91      tokio::spawn(async move {
92        if let Ok(mut signal) = tokio::signal::unix::signal(tokio::signal::unix::SignalKind::hangup()) {
93          tokio::select! {
94            _ = signal.recv() => {
95              continue_tx_clone.send(true).await.unwrap_or_default();
96            }
97            _ = cancel_token_clone.cancelled() => {}
98          }
99        }
100      });
101    }
102
103    let cancel_token_clone = cancel_token.clone();
104    tokio::spawn(async move {
105      tokio::select! {
106        result = tokio::signal::ctrl_c() => {
107          if result.is_ok() {
108            continue_tx.send(false).await.unwrap_or_default();
109          }
110        }
111        _ = cancel_token_clone.cancelled() => {}
112      }
113    });
114
115    let continue_running = continue_rx.recv().await.unwrap_or(false);
116    cancel_token.cancel();
117    continue_running
118  })
119}
120
121/// Configure logging with the specified server configurations and runtime
122fn configure_logging(
123  log_filename: Option<String>,
124  error_log_filename: Option<String>,
125  secondary_runtime: &tokio::runtime::Runtime,
126  logging_rx: &Receiver<LogMessage>,
127) {
128  // Spawn logging task in the secondary asynchronous runtime
129  let logging_rx = logging_rx.clone();
130  secondary_runtime.spawn(async move {
131    let log_file = match log_filename {
132      Some(log_filename) => Some(
133        tokio::fs::OpenOptions::new()
134          .append(true)
135          .create(true)
136          .open(log_filename)
137          .await,
138      ),
139      None => None,
140    };
141
142    let error_log_file = match error_log_filename {
143      Some(error_log_filename) => Some(
144        tokio::fs::OpenOptions::new()
145          .append(true)
146          .create(true)
147          .open(error_log_filename)
148          .await,
149      ),
150      None => None,
151    };
152
153    let log_file_wrapped = match log_file {
154      Some(Ok(file)) => Some(Arc::new(tokio::sync::Mutex::new(BufWriter::with_capacity(
155        131072, file,
156      )))),
157      Some(Err(e)) => {
158        eprintln!("Failed to open log file: {e}");
159        None
160      }
161      None => None,
162    };
163
164    let error_log_file_wrapped = match error_log_file {
165      Some(Ok(file)) => Some(Arc::new(tokio::sync::Mutex::new(BufWriter::with_capacity(
166        131072, file,
167      )))),
168      Some(Err(e)) => {
169        eprintln!("Failed to open error log file: {e}");
170        None
171      }
172      None => None,
173    };
174
175    // The logs are written when the log message is received by the log event loop, and flushed every 100 ms, improving the server performance.
176    let log_file_wrapped_cloned_for_sleep = log_file_wrapped.clone();
177    let error_log_file_wrapped_cloned_for_sleep = error_log_file_wrapped.clone();
178    tokio::task::spawn(async move {
179      let mut interval = tokio::time::interval(Duration::from_millis(100));
180      loop {
181        interval.tick().await;
182        if let Some(log_file_wrapped_cloned) = log_file_wrapped_cloned_for_sleep.clone() {
183          let mut locked_file = log_file_wrapped_cloned.lock().await;
184          locked_file.flush().await.unwrap_or_default();
185        }
186        if let Some(error_log_file_wrapped_cloned) = error_log_file_wrapped_cloned_for_sleep.clone() {
187          let mut locked_file = error_log_file_wrapped_cloned.lock().await;
188          locked_file.flush().await.unwrap_or_default();
189        }
190      }
191    });
192
193    // Logging loop
194    while let Ok(message) = logging_rx.recv().await {
195      let (mut message, is_error) = message.get_message();
196      let log_file_wrapped_cloned = if !is_error {
197        log_file_wrapped.clone()
198      } else {
199        error_log_file_wrapped.clone()
200      };
201
202      if let Some(log_file_wrapped_cloned) = log_file_wrapped_cloned {
203        tokio::task::spawn(async move {
204          let mut locked_file = log_file_wrapped_cloned.lock().await;
205          if is_error {
206            let now: DateTime<Local> = Local::now();
207            let formatted_time = now.format("%Y-%m-%d %H:%M:%S").to_string();
208            message = format!("[{formatted_time}]: {message}");
209          }
210          message.push('\n');
211          if let Err(e) = locked_file.write(message.as_bytes()).await {
212            eprintln!("Failed to write to log file: {e}");
213          }
214        });
215      }
216    }
217  });
218}
219
220/// Function called before starting a server
221fn before_starting_server(
222  args: &ArgMatches,
223  configuration_adapters: &HashMap<String, Box<dyn ConfigurationAdapter + Send + Sync>>,
224  first_startup: bool,
225) -> Result<bool, Box<dyn Error + Send + Sync>> {
226  // Obtain the module loaders
227  let mut module_loaders = obtain_module_loaders();
228
229  // Obtain the argument values
230  let configuration_path: &Path = args
231    .get_one::<PathBuf>("config")
232    .ok_or(anyhow::anyhow!("Cannot obtain the configuration path"))?
233    .as_path();
234  let configuration_adapter: &str = args
235    .get_one::<String>("config-adapter")
236    .map_or(determine_default_configuration_adapter(configuration_path), |s| {
237      s as &str
238    });
239
240  // Obtain the configuration adapter
241  let configuration_adapter = configuration_adapters
242    .get(configuration_adapter)
243    .ok_or(anyhow::anyhow!(
244      "The \"{}\" configuration adapter isn't supported",
245      configuration_adapter
246    ))?;
247
248  // Determine the available parallelism
249  let available_parallelism = thread::available_parallelism()?.get();
250
251  // Create a secondary Tokio runtime
252  let secondary_runtime = tokio::runtime::Builder::new_multi_thread()
253    .worker_threads(match available_parallelism / 2 {
254      0 => 1,
255      non_zero => non_zero,
256    })
257    .thread_name("Secondary runtime")
258    .enable_all()
259    .build()?;
260
261  // Load the configuration
262  let configs_to_process = configuration_adapter.load_configuration(configuration_path)?;
263
264  // Process the configurations
265  let configs_to_process = merge_duplicates(configs_to_process);
266  let configs_to_process = remove_and_add_global_configuration(configs_to_process);
267  let configs_to_process = premerge_configuration(configs_to_process);
268  let (configs_to_process, first_module_error, unused_properties) =
269    load_modules(configs_to_process, &mut module_loaders, &secondary_runtime);
270
271  // Finalize the configurations
272  let server_configurations = Arc::new(ServerConfigurations::new(configs_to_process));
273
274  let global_configuration = server_configurations.find_global_configuration();
275
276  // Obtain the loggers builder
277  let mut loggers_builder = (*LOGGER_BUILDER)
278    .lock()
279    .map_err(|_| anyhow::anyhow!("Can't access the loggers"))?;
280
281  let mut log_file_names = HashMap::new();
282
283  // Iterate server configurations (logging configuration)
284  for server_configuration in &server_configurations.inner {
285    // Determine log filenames
286    let error_log_filename = get_value!("error_log", server_configuration)
287      .and_then(|v| v.as_str())
288      .map(String::from);
289    let log_filename = get_value!("log", server_configuration)
290      .and_then(|v| v.as_str())
291      .map(String::from);
292    if log_filename.is_some() || error_log_filename.is_some() {
293      // If there are two global configurations, the latest one takes precedence, because the entry is overridden in the `HashMap`
294      log_file_names.insert(
295        LoggerFilter {
296          hostname: server_configuration.filters.hostname.clone(),
297          ip: server_configuration.filters.ip,
298          port: server_configuration.filters.port,
299        },
300        (log_filename, error_log_filename),
301      );
302    }
303  }
304
305  // Remove unused loggers from the logger builder
306  loggers_builder
307    .inner
308    .retain(|filter, _| log_file_names.contains_key(filter));
309
310  // Configure new loggers
311  for (filter, (log_filename, error_log_filename)) in log_file_names {
312    let (_, logging_rx) = loggers_builder.add(filter, async_channel::unbounded());
313    configure_logging(log_filename, error_log_filename, &secondary_runtime, &logging_rx);
314  }
315
316  // Obtain loggers from the logger builder
317  let loggers = loggers_builder.build_borrowed();
318
319  // Obtain the global logger
320  let global_logger = loggers.find_global_logger();
321  let global_logger_clone = global_logger.clone();
322
323  // Reference to the secondary Tokio runtime
324  let secondary_runtime_ref = &secondary_runtime;
325
326  // Execute the rest
327  let execute_rest = move || {
328    if let Some(first_module_error) = first_module_error {
329      // Error out if there was a module error
330      Err(first_module_error)?;
331    }
332
333    // Log unused properties
334    for unused_property in unused_properties {
335      if let Some(logging_tx) = &global_logger {
336        logging_tx
337          .send_blocking(LogMessage::new(
338            format!("Unused configuration property detected: \"{unused_property}\""),
339            true,
340          ))
341          .unwrap_or_default();
342      }
343    }
344
345    // Configure cryptography provider for Rustls
346    let mut crypto_provider = default_provider();
347
348    // Configure cipher suites
349    let cipher_suite: Vec<&config::ServerConfigurationValue> = global_configuration
350      .as_deref()
351      .map_or(vec![], |c| get_values!("tls_cipher_suite", c));
352    if !cipher_suite.is_empty() {
353      let mut cipher_suites = Vec::new();
354      let cipher_suite_iter = cipher_suite.iter();
355      for cipher_suite_config in cipher_suite_iter {
356        if let Some(cipher_suite) = cipher_suite_config.as_str() {
357          let cipher_suite_to_add = match cipher_suite {
358            "TLS_AES_128_GCM_SHA256" => TLS13_AES_128_GCM_SHA256,
359            "TLS_AES_256_GCM_SHA384" => TLS13_AES_256_GCM_SHA384,
360            "TLS_CHACHA20_POLY1305_SHA256" => TLS13_CHACHA20_POLY1305_SHA256,
361            "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" => TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
362            "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384" => TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
363            "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256" => TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
364            "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" => TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
365            "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384" => TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
366            "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256" => TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
367            _ => Err(anyhow::anyhow!(format!(
368              "The \"{}\" cipher suite is not supported",
369              cipher_suite
370            )))?,
371          };
372          cipher_suites.push(cipher_suite_to_add);
373        }
374      }
375      crypto_provider.cipher_suites = cipher_suites;
376    }
377
378    // Configure ECDH curves
379    let ecdh_curves = global_configuration
380      .as_deref()
381      .map_or(vec![], |c| get_values!("tls_ecdh_curve", c));
382    if !ecdh_curves.is_empty() {
383      let mut kx_groups = Vec::new();
384      let ecdh_curves_iter = ecdh_curves.iter();
385      for ecdh_curve_config in ecdh_curves_iter {
386        if let Some(ecdh_curve) = ecdh_curve_config.as_str() {
387          let kx_group_to_add = match ecdh_curve {
388            "secp256r1" => SECP256R1,
389            "secp384r1" => SECP384R1,
390            "x25519" => X25519,
391            "x25519mklem768" => X25519MLKEM768,
392            "mklem768" => MLKEM768,
393            _ => Err(anyhow::anyhow!(format!(
394              "The \"{}\" ECDH curve is not supported",
395              ecdh_curve
396            )))?,
397          };
398          kx_groups.push(kx_group_to_add);
399        }
400      }
401      crypto_provider.kx_groups = kx_groups;
402    }
403
404    // Install a process-wide cryptography provider. If it fails, then error it out.
405    if crypto_provider.clone().install_default().is_err() && first_startup {
406      Err(anyhow::anyhow!("Cannot install a process-wide cryptography provider"))?;
407    }
408
409    let crypto_provider = Arc::new(crypto_provider);
410
411    // Build TLS configuration
412    let tls_config_builder_wants_versions = ServerConfig::builder_with_provider(crypto_provider.clone());
413
414    let min_tls_version_option = global_configuration
415      .as_deref()
416      .and_then(|c| get_value!("tls_min_version", c))
417      .and_then(|v| v.as_str());
418    let max_tls_version_option = global_configuration
419      .as_deref()
420      .and_then(|c| get_value!("tls_max_version", c))
421      .and_then(|v| v.as_str());
422
423    let tls_config_builder_wants_verifier = if min_tls_version_option.is_none() && max_tls_version_option.is_none() {
424      tls_config_builder_wants_versions.with_safe_default_protocol_versions()?
425    } else {
426      let tls_versions = [("TLSv1.2", &TLS12), ("TLSv1.3", &TLS13)];
427      let min_tls_version_index =
428        min_tls_version_option.map_or(Some(0), |v| tls_versions.iter().position(|p| p.0 == v));
429      let max_tls_version_index = max_tls_version_option.map_or(Some(tls_versions.len() - 1), |v| {
430        tls_versions.iter().position(|p| p.0 == v)
431      });
432      if let Some(min_tls_version_index) = min_tls_version_index {
433        if let Some(max_tls_version_index) = max_tls_version_index {
434          tls_config_builder_wants_versions.with_protocol_versions(
435            &tls_versions[min_tls_version_index..max_tls_version_index]
436              .iter()
437              .map(|p| p.1)
438              .collect::<Vec<_>>(),
439          )?
440        } else {
441          Err(anyhow::anyhow!("Invalid maximum TLS version"))?
442        }
443      } else {
444        Err(anyhow::anyhow!("Invalid minimum TLS version"))?
445      }
446    };
447
448    let tls_config_builder_wants_server_cert = if global_configuration
449      .as_deref()
450      .and_then(|c| get_value!("tls_client_certificate", c))
451      .and_then(|v| v.as_bool())
452      .unwrap_or(false)
453    {
454      let roots = (|| {
455        let certs_result = load_native_certs();
456        if !certs_result.errors.is_empty() {
457          return None;
458        }
459        let certs = certs_result.certs;
460
461        let mut roots = RootCertStore::empty();
462        for cert in certs {
463          if roots.add(cert).is_err() {
464            return None;
465          }
466        }
467
468        Some(roots)
469      })()
470      .unwrap_or(RootCertStore {
471        roots: webpki_roots::TLS_SERVER_ROOTS.to_vec(),
472      });
473
474      tls_config_builder_wants_verifier
475        .with_client_cert_verifier(WebPkiClientVerifier::builder(Arc::new(roots)).build()?)
476    } else {
477      tls_config_builder_wants_verifier.with_no_client_auth()
478    };
479
480    let enable_proxy_protocol = global_configuration
481      .as_ref()
482      .and_then(|c| get_value!("protocol_proxy", c))
483      .and_then(|v| v.as_bool())
484      .unwrap_or(false);
485    let protocols = global_configuration
486      .as_ref()
487      .and_then(|c| get_entry!("protocols", c))
488      .map(|e| e.values.iter().filter_map(|v| v.as_str()).collect::<Vec<_>>())
489      .unwrap_or(vec!["h1", "h2"]);
490
491    if enable_proxy_protocol && protocols.contains(&"h3") {
492      Err(anyhow::anyhow!("PROXY protocol isn't supported with HTTP/3"))?
493    }
494
495    let default_http_port = global_configuration
496      .as_deref()
497      .and_then(|c| get_entry!("default_http_port", c))
498      .and_then(|e| e.values.first())
499      .map_or(Some(80), |v| {
500        if v.is_null() {
501          None
502        } else {
503          Some(v.as_i128().unwrap_or(80) as u16)
504        }
505      });
506    let default_https_port = global_configuration
507      .as_deref()
508      .and_then(|c| get_entry!("default_https_port", c))
509      .and_then(|e| e.values.first())
510      .map_or(Some(443), |v| {
511        if v.is_null() {
512          None
513        } else {
514          Some(v.as_i128().unwrap_or(443) as u16)
515        }
516      });
517
518    let mut tls_ports: HashMap<u16, CustomSniResolver> = HashMap::new();
519    #[allow(clippy::type_complexity)]
520    let mut tls_port_locks: HashMap<u16, Arc<tokio::sync::RwLock<Vec<(String, Arc<dyn ResolvesServerCert>)>>>> =
521      HashMap::new();
522    let mut nonencrypted_ports = HashSet::new();
523    let mut certified_keys_to_preload: HashMap<u16, Vec<Arc<CertifiedKey>>> = HashMap::new();
524    let mut used_sni_hostnames = HashSet::new();
525    let mut automatic_tls_used_sni_hostnames = HashSet::new();
526    let mut acme_tls_alpn_01_resolvers: HashMap<u16, TlsAlpn01Resolver> = HashMap::new();
527    let mut acme_tls_alpn_01_resolver_locks: HashMap<
528      u16,
529      Arc<tokio::sync::RwLock<Vec<crate::acme::TlsAlpn01DataLock>>>,
530    > = HashMap::new();
531    let acme_http_01_resolvers: Arc<tokio::sync::RwLock<Vec<crate::acme::Http01DataLock>>> =
532      Arc::new(tokio::sync::RwLock::new(Vec::new()));
533    let acme_default_directory = dirs::data_local_dir().and_then(|mut p| {
534      p.push("ferron-acme");
535      p.into_os_string().into_string().ok()
536    });
537    let memory_acme_account_cache_data = Arc::new(tokio::sync::RwLock::new(HashMap::new()));
538    let mut acme_configs = Vec::new();
539    let mut acme_on_demand_configs = Vec::new();
540    let (acme_on_demand_tx, acme_on_demand_rx) = async_channel::unbounded();
541    let on_demand_tls_ask_endpoint = match global_configuration
542      .as_ref()
543      .and_then(|c| get_value!("auto_tls_on_demand_ask", c))
544      .and_then(|v| v.as_str())
545      .map(|u| u.parse::<hyper::Uri>())
546    {
547      Some(Ok(uri)) => Some(uri),
548      Some(Err(err)) => Err(anyhow::anyhow!(
549        "Failed to parse automatic TLS on demand asking endpoint URI: {}",
550        err
551      ))?,
552      None => None,
553    };
554    let on_demand_tls_ask_endpoint_verify = !global_configuration
555      .as_ref()
556      .and_then(|c| get_value!("auto_tls_on_demand_ask_no_verification", c))
557      .and_then(|v| v.as_bool())
558      .unwrap_or(false);
559
560    // Iterate server configurations (TLS configuration)
561    for server_configuration in &server_configurations.inner {
562      if server_configuration.filters.is_global_non_host()
563        || (server_configuration.filters.is_global() && server_configuration.entries.is_empty())
564      {
565        // Don't add listeners from an empty global configuration or non-host global configuration
566        continue;
567      }
568
569      let on_demand_tls = get_value!("auto_tls_on_demand", server_configuration)
570        .and_then(|v| v.as_bool())
571        .unwrap_or(false);
572
573      let https_port = server_configuration.filters.port.or(default_https_port);
574
575      let sni_hostname = server_configuration.filters.hostname.clone().or_else(|| {
576        // !!! UNTESTED, many clients don't send SNI hostname when accessing via IP address anyway
577        match server_configuration.filters.ip {
578          Some(IpAddr::V4(address)) => Some(address.to_string()),
579          Some(IpAddr::V6(address)) => Some(format!("[{address}]")),
580          _ => None,
581        }
582      });
583
584      let is_sni_hostname_used = !https_port.is_none_or(|p| {
585        !used_sni_hostnames.contains(&(p, sni_hostname.clone()))
586          && !automatic_tls_used_sni_hostnames.contains(&(p, sni_hostname.clone()))
587      });
588      let is_auto_tls_sni_hostname_used =
589        https_port.is_some_and(|p| automatic_tls_used_sni_hostnames.contains(&(p, sni_hostname.clone())));
590
591      let mut automatic_tls_port = None;
592      if server_configuration.filters.port.is_none() {
593        if get_value!("auto_tls", server_configuration)
594          .and_then(|v| v.as_bool())
595          .unwrap_or(!is_localhost(
596            server_configuration.filters.ip.as_ref(),
597            server_configuration.filters.hostname.as_deref(),
598          ))
599        {
600          automatic_tls_port = default_https_port;
601        }
602        if let Some(http_port) = default_http_port {
603          nonencrypted_ports.insert(http_port);
604        }
605      }
606
607      if get_value!("auto_tls", server_configuration)
608        .and_then(|v| v.as_bool())
609        .unwrap_or(false)
610      {
611        automatic_tls_port = https_port;
612      } else if let Some(tls_entry) = get_entry!("tls", server_configuration) {
613        if let Some(https_port) = https_port {
614          if tls_entry.values.len() == 2 {
615            if let Some(cert_path) = tls_entry.values[0].as_str() {
616              if let Some(key_path) = tls_entry.values[1].as_str() {
617                automatic_tls_port = None;
618
619                if !is_sni_hostname_used {
620                  let certs = match load_certs(cert_path) {
621                    Ok(certs) => certs,
622                    Err(err) => Err(anyhow::anyhow!(format!(
623                      "Cannot load the \"{}\" TLS certificate: {}",
624                      cert_path, err
625                    )))?,
626                  };
627                  let key = match load_private_key(key_path) {
628                    Ok(key) => key,
629                    Err(err) => Err(anyhow::anyhow!(format!(
630                      "Cannot load the \"{}\" private key: {}",
631                      key_path, err
632                    )))?,
633                  };
634                  let signing_key = match crypto_provider.key_provider.load_private_key(key) {
635                    Ok(key) => key,
636                    Err(err) => Err(anyhow::anyhow!(format!(
637                      "Cannot load the \"{}\" private key: {}",
638                      key_path, err
639                    )))?,
640                  };
641                  let certified_key = Arc::new(CertifiedKey::new(certs, signing_key));
642                  if let Some(certified_keys) = certified_keys_to_preload.get_mut(&https_port) {
643                    certified_keys.push(certified_key.clone());
644                  } else {
645                    certified_keys_to_preload.insert(https_port, vec![certified_key.clone()]);
646                  }
647                  let resolver = Arc::new(OneCertifiedKeyResolver::new(certified_key));
648                  if let Some(sni_resolver) = tls_ports.get_mut(&https_port) {
649                    if let Some(sni_hostname) = &sni_hostname {
650                      sni_resolver.load_host_resolver(sni_hostname, resolver);
651                    } else {
652                      sni_resolver.load_fallback_resolver(resolver);
653                    }
654                  } else {
655                    let sni_resolver_list = Arc::new(tokio::sync::RwLock::new(Vec::new()));
656                    tls_port_locks.insert(https_port, sni_resolver_list.clone());
657                    let mut sni_resolver = CustomSniResolver::with_resolvers(sni_resolver_list);
658                    if let Some(sni_hostname) = &sni_hostname {
659                      sni_resolver.load_host_resolver(sni_hostname, resolver);
660                    } else {
661                      sni_resolver.load_fallback_resolver(resolver);
662                    }
663                    tls_ports.insert(https_port, sni_resolver);
664                  }
665                  used_sni_hostnames.insert((https_port, sni_hostname.clone()));
666                }
667              }
668            }
669          }
670        }
671      } else if let Some(http_port) = server_configuration.filters.port.or(default_http_port) {
672        nonencrypted_ports.insert(http_port);
673      }
674      if let Some(automatic_tls_port) = automatic_tls_port {
675        if !is_auto_tls_sni_hostname_used {
676          if sni_hostname.is_some() || on_demand_tls {
677            let is_wildcard_domain = sni_hostname.as_ref().is_some_and(|s| s.starts_with("*."));
678            let challenge_type_entry = get_entry!("auto_tls_challenge", server_configuration);
679            let challenge_type_str = challenge_type_entry
680              .and_then(|e| e.values.first())
681              .and_then(|v| v.as_str())
682              .unwrap_or("tls-alpn-01");
683            let challenge_params = challenge_type_entry
684              .and_then(|e| {
685                let mut props_str = HashMap::new();
686                for (prop_name, prop_value) in e.props.iter() {
687                  if let Some(prop_value) = prop_value.as_str() {
688                    props_str.insert(prop_name.to_string(), prop_value.to_string());
689                  }
690                }
691                if props_str.is_empty() {
692                  None
693                } else {
694                  Some(props_str)
695                }
696              })
697              .unwrap_or(HashMap::new());
698            if let Some(sni_hostname) = &sni_hostname {
699              if sni_hostname.parse::<IpAddr>().is_ok() {
700                if let Some(logging_tx) = &global_logger {
701                  logging_tx
702                    .send_blocking(LogMessage::new(
703                      format!("Ferron's automatic TLS functionality doesn't support IP address-based identifiers, skipping SNI host \"{sni_hostname}\"..."),
704                      true,
705                    ))
706                    .unwrap_or_default();
707                }
708                continue;
709              }
710            }
711            let challenge_type = match &*challenge_type_str.to_uppercase() {
712              "HTTP-01" => {
713                if let Some(sni_hostname) = &sni_hostname {
714                  if is_wildcard_domain && !on_demand_tls {
715                    if let Some(logging_tx) = &global_logger {
716                      logging_tx
717                        .send_blocking(LogMessage::new(
718                          format!("HTTP-01 ACME challenge doesn't support wildcard hostnames, skipping SNI host \"{sni_hostname}\"..."),
719                          true,
720                        ))
721                        .unwrap_or_default();
722                    }
723                    continue;
724                  }
725                }
726                ChallengeType::Http01
727              }
728              "TLS-ALPN-01" => {
729                if let Some(sni_hostname) = &sni_hostname {
730                  if is_wildcard_domain && !on_demand_tls {
731                    if let Some(logging_tx) = &global_logger {
732                      logging_tx
733                        .send_blocking(LogMessage::new(
734                          format!("TLS-ALPN-01 ACME challenge doesn't support wildcard hostnames, skipping SNI host \"{sni_hostname}\"..."),
735                          true,
736                        ))
737                        .unwrap_or_default();
738                    }
739                    continue;
740                  }
741                }
742                ChallengeType::TlsAlpn01
743              }
744              "DNS-01" => ChallengeType::Dns01,
745              unsupported => Err(anyhow::anyhow!("Unsupported ACME challenge type: {}", unsupported))?,
746            };
747            let dns_provider: Option<Arc<dyn ferron_common::dns::DnsProvider + Send + Sync>> =
748              if &*challenge_type_str.to_uppercase() != "DNS-01" {
749                None
750              } else if let Some(provider_name) = challenge_params.get("provider") {
751                Some(get_dns_provider(provider_name, &challenge_params)?)
752              } else {
753                Err(anyhow::anyhow!("No DNS provider specified"))?
754              };
755            let acme_cache_path_option = get_value!("auto_tls_cache", server_configuration)
756              .map_or(acme_default_directory.as_deref(), |v| {
757                if v.is_null() {
758                  None
759                } else if let Some(v) = v.as_str() {
760                  Some(v)
761                } else {
762                  acme_default_directory.as_deref()
763                }
764              })
765              .map(|path| path.to_owned());
766            let rustls_client_config = (if get_value!("auto_tls_no_verification", server_configuration)
767              .and_then(|v| v.as_bool())
768              .unwrap_or(false)
769            {
770              ClientConfig::builder_with_provider(crypto_provider.clone())
771                .with_safe_default_protocol_versions()?
772                .dangerous()
773                .with_custom_certificate_verifier(Arc::new(NoServerVerifier::new()))
774            } else if let Ok(client_config) = BuilderVerifierExt::with_platform_verifier(
775              ClientConfig::builder_with_provider(crypto_provider.clone()).with_safe_default_protocol_versions()?,
776            ) {
777              client_config
778            } else {
779              ClientConfig::builder_with_provider(crypto_provider.clone())
780                .with_safe_default_protocol_versions()?
781                .with_webpki_verifier(
782                  WebPkiServerVerifier::builder(Arc::new(rustls::RootCertStore {
783                    roots: webpki_roots::TLS_SERVER_ROOTS.to_vec(),
784                  }))
785                  .build()?,
786                )
787            })
788            .with_no_client_auth();
789            if on_demand_tls {
790              if &*challenge_type_str.to_uppercase() == "TLS-ALPN-01" {
791                // Add TLS-ALPN-01 resolver
792                let sni_resolver_list = Arc::new(tokio::sync::RwLock::new(Vec::new()));
793                acme_tls_alpn_01_resolver_locks.insert(automatic_tls_port, sni_resolver_list.clone());
794                let sni_resolver = TlsAlpn01Resolver::with_resolvers(sni_resolver_list);
795                acme_tls_alpn_01_resolvers.insert(automatic_tls_port, sni_resolver);
796              }
797
798              if let Some(sni_resolver) = tls_ports.get_mut(&automatic_tls_port) {
799                sni_resolver.load_fallback_sender(acme_on_demand_tx.clone(), automatic_tls_port);
800              } else {
801                let sni_resolver_list = Arc::new(tokio::sync::RwLock::new(Vec::new()));
802                tls_port_locks.insert(automatic_tls_port, sni_resolver_list.clone());
803                let mut sni_resolver = CustomSniResolver::with_resolvers(sni_resolver_list);
804                sni_resolver.load_fallback_sender(acme_on_demand_tx.clone(), automatic_tls_port);
805                tls_ports.insert(automatic_tls_port, sni_resolver);
806              }
807
808              let acme_on_demand_config = AcmeOnDemandConfig {
809                rustls_client_config,
810                challenge_type,
811                contact: if let Some(contact) =
812                  get_value!("auto_tls_contact", server_configuration).and_then(|v| v.as_str())
813                {
814                  vec![format!("mailto:{}", contact.to_string())]
815                } else {
816                  vec![]
817                },
818                directory: if let Some(directory) =
819                  get_value!("auto_tls_directory", server_configuration).and_then(|v| v.as_str())
820                {
821                  directory.to_string()
822                } else if get_value!("auto_tls_letsencrypt_production", server_configuration)
823                  .and_then(|v| v.as_bool())
824                  .unwrap_or(true)
825                {
826                  LetsEncrypt::Production.url().to_string()
827                } else {
828                  LetsEncrypt::Staging.url().to_string()
829                },
830                eab_key: if let Some(eab_key_entry) = get_entry!("auto_tls_eab_key", server_configuration) {
831                  if let Some(eab_key_id) = eab_key_entry.values.first().and_then(|v| v.as_str()) {
832                    if let Some(eab_key_hmac) = eab_key_entry.values.get(1).and_then(|v| v.as_str()) {
833                      match base64::engine::general_purpose::URL_SAFE_NO_PAD.decode(eab_key_hmac) {
834                        Ok(decoded_key) => {
835                          Some(Arc::new(ExternalAccountKey::new(eab_key_id.to_string(), &decoded_key)))
836                        }
837                        Err(err) => Err(anyhow::anyhow!("Failed to decode EAB key HMAC: {}", err))?,
838                      }
839                    } else {
840                      None
841                    }
842                  } else {
843                    None
844                  }
845                } else {
846                  None
847                },
848                profile: get_value!("auto_tls_profile", server_configuration)
849                  .and_then(|v| v.as_str().map(|s| s.to_string())),
850                cache_path: if let Some(acme_cache_path) = acme_cache_path_option.clone() {
851                  match PathBuf::from_str(&acme_cache_path) {
852                    Ok(pathbuf) => Some(pathbuf),
853                    Err(_) => Err(anyhow::anyhow!("Invalid ACME cache path"))?,
854                  }
855                } else {
856                  None
857                },
858                sni_resolver_lock: tls_port_locks
859                  .get(&automatic_tls_port)
860                  .cloned()
861                  .unwrap_or(Arc::new(tokio::sync::RwLock::new(Vec::new()))),
862                tls_alpn_01_resolver_lock: acme_tls_alpn_01_resolver_locks
863                  .get(&automatic_tls_port)
864                  .cloned()
865                  .unwrap_or(Arc::new(tokio::sync::RwLock::new(Vec::new()))),
866                http_01_resolver_lock: acme_http_01_resolvers.clone(),
867                dns_provider,
868                sni_hostname: sni_hostname.clone(),
869                port: automatic_tls_port,
870              };
871              acme_on_demand_configs.push(acme_on_demand_config);
872              automatic_tls_used_sni_hostnames.insert((automatic_tls_port, sni_hostname));
873            } else if let Some(sni_hostname) = sni_hostname {
874              let (account_cache_path, cert_cache_path) = if let Some(acme_cache_path) = acme_cache_path_option.clone()
875              {
876                let mut pathbuf = match PathBuf::from_str(&acme_cache_path) {
877                  Ok(pathbuf) => pathbuf,
878                  Err(_) => Err(anyhow::anyhow!("Invalid ACME cache path"))?,
879                };
880                let base_pathbuf = pathbuf.clone();
881                let append_hash = base64::engine::general_purpose::URL_SAFE_NO_PAD
882                  .encode(xxh3_128(format!("{automatic_tls_port}-{sni_hostname}").as_bytes()).to_be_bytes());
883                pathbuf.push(append_hash);
884                (Some(base_pathbuf), Some(pathbuf))
885              } else {
886                (None, None)
887              };
888              let certified_key_lock = Arc::new(tokio::sync::RwLock::new(None));
889              let tls_alpn_01_data_lock = Arc::new(tokio::sync::RwLock::new(None));
890              let http_01_data_lock = Arc::new(tokio::sync::RwLock::new(None));
891              let acme_config = AcmeConfig {
892                rustls_client_config,
893                domains: vec![sni_hostname.clone()],
894                challenge_type,
895                contact: if let Some(contact) =
896                  get_value!("auto_tls_contact", server_configuration).and_then(|v| v.as_str())
897                {
898                  vec![format!("mailto:{}", contact.to_string())]
899                } else {
900                  vec![]
901                },
902                directory: if let Some(directory) =
903                  get_value!("auto_tls_directory", server_configuration).and_then(|v| v.as_str())
904                {
905                  directory.to_string()
906                } else if get_value!("auto_tls_letsencrypt_production", server_configuration)
907                  .and_then(|v| v.as_bool())
908                  .unwrap_or(true)
909                {
910                  LetsEncrypt::Production.url().to_string()
911                } else {
912                  LetsEncrypt::Staging.url().to_string()
913                },
914                eab_key: if let Some(eab_key_entry) = get_entry!("auto_tls_eab_key", server_configuration) {
915                  if let Some(eab_key_id) = eab_key_entry.values.first().and_then(|v| v.as_str()) {
916                    if let Some(eab_key_hmac) = eab_key_entry.values.get(1).and_then(|v| v.as_str()) {
917                      match base64::engine::general_purpose::URL_SAFE_NO_PAD.decode(eab_key_hmac) {
918                        Ok(decoded_key) => {
919                          Some(Arc::new(ExternalAccountKey::new(eab_key_id.to_string(), &decoded_key)))
920                        }
921                        Err(err) => Err(anyhow::anyhow!("Failed to decode EAB key HMAC: {}", err))?,
922                      }
923                    } else {
924                      None
925                    }
926                  } else {
927                    None
928                  }
929                } else {
930                  None
931                },
932                profile: get_value!("auto_tls_profile", server_configuration)
933                  .and_then(|v| v.as_str().map(|s| s.to_string())),
934                account_cache: if let Some(account_cache_path) = account_cache_path {
935                  AcmeCache::File(account_cache_path)
936                } else {
937                  AcmeCache::Memory(memory_acme_account_cache_data.clone())
938                },
939                certificate_cache: if let Some(cert_cache_path) = cert_cache_path {
940                  AcmeCache::File(cert_cache_path)
941                } else {
942                  AcmeCache::Memory(Arc::new(tokio::sync::RwLock::new(HashMap::new())))
943                },
944                certified_key_lock: certified_key_lock.clone(),
945                tls_alpn_01_data_lock: tls_alpn_01_data_lock.clone(),
946                http_01_data_lock: http_01_data_lock.clone(),
947                dns_provider,
948                renewal_info: None,
949                account: None,
950              };
951              let acme_resolver = Arc::new(AcmeResolver::new(certified_key_lock));
952              acme_configs.push(acme_config);
953              match &*challenge_type_str.to_uppercase() {
954                "HTTP-01" => {
955                  acme_http_01_resolvers.blocking_write().push(http_01_data_lock);
956                }
957                "TLS-ALPN-01" => {
958                  if let Some(sni_resolver) = acme_tls_alpn_01_resolvers.get_mut(&automatic_tls_port) {
959                    sni_resolver.load_resolver(tls_alpn_01_data_lock);
960                  } else {
961                    let sni_resolver_list = Arc::new(tokio::sync::RwLock::new(Vec::new()));
962                    acme_tls_alpn_01_resolver_locks.insert(automatic_tls_port, sni_resolver_list.clone());
963                    let sni_resolver = TlsAlpn01Resolver::with_resolvers(sni_resolver_list);
964                    sni_resolver.load_resolver(tls_alpn_01_data_lock);
965                    acme_tls_alpn_01_resolvers.insert(automatic_tls_port, sni_resolver);
966                  }
967                }
968                _ => (),
969              }
970              if let Some(sni_resolver) = tls_ports.get_mut(&automatic_tls_port) {
971                sni_resolver.load_host_resolver(&sni_hostname, acme_resolver);
972              } else {
973                let sni_resolver_list = Arc::new(tokio::sync::RwLock::new(Vec::new()));
974                tls_port_locks.insert(automatic_tls_port, sni_resolver_list.clone());
975                let mut sni_resolver = CustomSniResolver::with_resolvers(sni_resolver_list);
976                sni_resolver.load_host_resolver(&sni_hostname, acme_resolver);
977                tls_ports.insert(automatic_tls_port, sni_resolver);
978              }
979              automatic_tls_used_sni_hostnames.insert((automatic_tls_port, Some(sni_hostname)));
980            }
981          } else if !server_configuration.filters.is_global() && !server_configuration.filters.is_global_non_host() {
982            if let Some(logging_tx) = &global_logger {
983              logging_tx
984                .send_blocking(LogMessage::new(
985                  "Skipping automatic TLS for a host without a SNI hostname...".to_string(),
986                  true,
987                ))
988                .unwrap_or_default();
989            }
990          }
991        }
992      }
993    }
994
995    if !acme_configs.is_empty() || !acme_on_demand_configs.is_empty() {
996      // Spawn a task to handle ACME certificate provisioning, one certificate at time
997
998      let acme_logger_option = global_logger.clone();
999      secondary_runtime_ref.spawn(async move {
1000        for acme_config in &mut acme_configs {
1001          // Install the certificates from the cache if they're valid
1002          check_certificate_validity_or_install_cached(acme_config, None)
1003            .await
1004            .unwrap_or_default();
1005        }
1006
1007        let mut existing_combinations = HashSet::new();
1008        for acme_on_demand_config in &mut acme_on_demand_configs {
1009          for cached_domain in get_cached_domains(acme_on_demand_config).await {
1010            let mut acme_config = convert_on_demand_config(
1011              acme_on_demand_config,
1012              cached_domain.clone(),
1013              memory_acme_account_cache_data.clone(),
1014            )
1015            .await;
1016
1017            existing_combinations.insert((cached_domain, acme_on_demand_config.port));
1018
1019            // Install the certificates from the cache if they're valid
1020            check_certificate_validity_or_install_cached(&mut acme_config, None)
1021              .await
1022              .unwrap_or_default();
1023
1024            acme_configs.push(acme_config);
1025          }
1026        }
1027
1028        // Wrap ACME configurations in a mutex
1029        let acme_configs_mutex = Arc::new(tokio::sync::Mutex::new(acme_configs));
1030
1031        let prevent_file_race_conditions_mutex = Arc::new(tokio::sync::Mutex::new(()));
1032
1033        if !acme_on_demand_configs.is_empty() {
1034          // On-demand TLS
1035          let acme_configs_mutex = acme_configs_mutex.clone();
1036          let acme_logger_option = acme_logger_option.clone();
1037          let acme_on_demand_configs = Arc::new(acme_on_demand_configs);
1038          tokio::spawn(async move {
1039            let mut existing_combinations = existing_combinations;
1040            while let Ok(received_data) = acme_on_demand_rx.recv().await {
1041              let on_demand_tls_ask_endpoint = on_demand_tls_ask_endpoint.clone();
1042              if let Some(on_demand_tls_ask_endpoint) = on_demand_tls_ask_endpoint {
1043                let mut url_parts = on_demand_tls_ask_endpoint.into_parts();
1044                if let Some(path_and_query) = url_parts.path_and_query {
1045                  let query = path_and_query.query();
1046                  let query = if let Some(query) = query {
1047                    format!("{}&domain={}", query, urlencoding::encode(&received_data.0))
1048                  } else {
1049                    format!("domain={}", urlencoding::encode(&received_data.0))
1050                  };
1051                  url_parts.path_and_query = Some(match format!("{}?{}", path_and_query.path(), query).parse() {
1052                    Ok(parsed) => parsed,
1053                    Err(err) => {
1054                      if let Some(acme_logger) = &acme_logger_option {
1055                        acme_logger
1056                          .send(LogMessage::new(
1057                            format!("Error while formatting the URL for on-demand TLS request: {err}"),
1058                            true,
1059                          ))
1060                          .await
1061                          .unwrap_or_default();
1062                      }
1063                      continue;
1064                    }
1065                  });
1066                } else {
1067                  url_parts.path_and_query = Some(
1068                    match format!("/?domain={}", urlencoding::encode(&received_data.0)).parse() {
1069                      Ok(parsed) => parsed,
1070                      Err(err) => {
1071                        if let Some(acme_logger) = &acme_logger_option {
1072                          acme_logger
1073                            .send(LogMessage::new(
1074                              format!("Error while formatting the URL for on-demand TLS request: {err}"),
1075                              true,
1076                            ))
1077                            .await
1078                            .unwrap_or_default();
1079                        }
1080                        continue;
1081                      }
1082                    },
1083                  );
1084                }
1085                let endpoint_url = match hyper::Uri::from_parts(url_parts) {
1086                  Ok(parsed) => parsed,
1087                  Err(err) => {
1088                    if let Some(acme_logger) = &acme_logger_option {
1089                      acme_logger
1090                        .send(LogMessage::new(
1091                          format!("Error while formatting the URL for on-demand TLS request: {err}"),
1092                          true,
1093                        ))
1094                        .await
1095                        .unwrap_or_default();
1096                    }
1097                    continue;
1098                  }
1099                };
1100                let ask_closure = async {
1101                  let client = hyper_util::client::legacy::Client::builder(hyper_util::rt::TokioExecutor::new())
1102                    .build::<_, http_body_util::Empty<hyper::body::Bytes>>(
1103                    hyper_rustls::HttpsConnectorBuilder::new()
1104                      .with_tls_config(
1105                        (if !on_demand_tls_ask_endpoint_verify {
1106                          ClientConfig::builder_with_provider(crypto_provider.clone())
1107                            .with_safe_default_protocol_versions()?
1108                            .dangerous()
1109                            .with_custom_certificate_verifier(Arc::new(NoServerVerifier::new()))
1110                        } else if let Ok(client_config) = BuilderVerifierExt::with_platform_verifier(
1111                          ClientConfig::builder_with_provider(crypto_provider.clone())
1112                            .with_safe_default_protocol_versions()?,
1113                        ) {
1114                          client_config
1115                        } else {
1116                          ClientConfig::builder_with_provider(crypto_provider.clone())
1117                            .with_safe_default_protocol_versions()?
1118                            .with_webpki_verifier(
1119                              WebPkiServerVerifier::builder(Arc::new(rustls::RootCertStore {
1120                                roots: webpki_roots::TLS_SERVER_ROOTS.to_vec(),
1121                              }))
1122                              .build()?,
1123                            )
1124                        })
1125                        .with_no_client_auth(),
1126                      )
1127                      .https_or_http()
1128                      .enable_http1()
1129                      .enable_http2()
1130                      .build(),
1131                  );
1132                  let request = hyper::Request::builder()
1133                    .method(hyper::Method::GET)
1134                    .uri(endpoint_url)
1135                    .body(http_body_util::Empty::<hyper::body::Bytes>::new())?;
1136                  let response = client.request(request).await?;
1137
1138                  Ok::<_, Box<dyn Error + Send + Sync>>(response.status().is_success())
1139                };
1140                match ask_closure.await {
1141                  Ok(true) => (),
1142                  Ok(false) => {
1143                    if let Some(acme_logger) = &acme_logger_option {
1144                      acme_logger
1145                        .send(LogMessage::new(
1146                          format!(
1147                            "The TLS certificate cannot be issued for \"{}\" hostname",
1148                            &received_data.0
1149                          ),
1150                          true,
1151                        ))
1152                        .await
1153                        .unwrap_or_default();
1154                    }
1155                    continue;
1156                  }
1157                  Err(err) => {
1158                    if let Some(acme_logger) = &acme_logger_option {
1159                      acme_logger
1160                        .send(LogMessage::new(
1161                          format!(
1162                            "Error while determining if the TLS certificate can be issued for \"{}\" hostname: {err}",
1163                            &received_data.0
1164                          ),
1165                          true,
1166                        ))
1167                        .await
1168                        .unwrap_or_default();
1169                    }
1170                    continue;
1171                  }
1172                }
1173              }
1174              if existing_combinations.contains(&received_data) {
1175                continue;
1176              } else {
1177                existing_combinations.insert(received_data.clone());
1178              }
1179              let (sni_hostname, port) = received_data;
1180              let acme_configs_mutex = acme_configs_mutex.clone();
1181              let acme_on_demand_configs = acme_on_demand_configs.clone();
1182              let memory_acme_account_cache_data = memory_acme_account_cache_data.clone();
1183              let prevent_file_race_conditions_mutex = prevent_file_race_conditions_mutex.clone();
1184              tokio::spawn(async move {
1185                for acme_on_demand_config in acme_on_demand_configs.iter() {
1186                  if match_hostname(acme_on_demand_config.sni_hostname.as_deref(), Some(&sni_hostname))
1187                    && acme_on_demand_config.port == port
1188                  {
1189                    let mutex_guard = prevent_file_race_conditions_mutex.lock().await;
1190                    add_domain_to_cache(acme_on_demand_config, &sni_hostname)
1191                      .await
1192                      .unwrap_or_default();
1193                    drop(mutex_guard);
1194
1195                    acme_configs_mutex.lock().await.push(
1196                      convert_on_demand_config(
1197                        acme_on_demand_config,
1198                        sni_hostname.clone(),
1199                        memory_acme_account_cache_data,
1200                      )
1201                      .await,
1202                    );
1203                    break;
1204                  }
1205                }
1206              });
1207            }
1208          });
1209        }
1210
1211        loop {
1212          for acme_config in &mut *acme_configs_mutex.lock().await {
1213            if let Err(acme_error) = provision_certificate(acme_config).await {
1214              if let Some(acme_logger) = &acme_logger_option {
1215                acme_logger
1216                  .send(LogMessage::new(
1217                    format!("Error while obtaining a TLS certificate: {acme_error}"),
1218                    true,
1219                  ))
1220                  .await
1221                  .unwrap_or_default();
1222              }
1223            }
1224          }
1225          tokio::time::sleep(Duration::from_secs(10)).await;
1226        }
1227      });
1228    }
1229
1230    // If HTTP/1.1 isn't enabled, don't listen to non-encrypted ports
1231    if !protocols.contains(&"h1") {
1232      nonencrypted_ports.clear();
1233    }
1234
1235    for tls_port in tls_ports.keys() {
1236      if nonencrypted_ports.contains(tls_port) {
1237        nonencrypted_ports.remove(tls_port);
1238      }
1239    }
1240
1241    // Create TLS server configurations
1242    let mut quic_tls_configs = HashMap::new();
1243    let mut tls_configs = HashMap::new();
1244    let mut acme_tls_alpn_01_configs = HashMap::new();
1245    for (tls_port, sni_resolver) in tls_ports.into_iter() {
1246      let enable_ocsp_stapling = global_configuration
1247        .as_ref()
1248        .and_then(|c| get_value!("ocsp_stapling", c))
1249        .and_then(|v| v.as_bool())
1250        .unwrap_or(true);
1251      let resolver: Arc<dyn ResolvesServerCert> = if enable_ocsp_stapling {
1252        // The `ocsp_stapler` crate is dependent on Tokio, so we create a stapler in the Tokio runtime...
1253        // If this wasn't wrapped in a Tokio runtime, creation of a OCSP stapler would just cause a panic.
1254        let stapler = secondary_runtime_ref.block_on(async move { ocsp_stapler::Stapler::new(Arc::new(sni_resolver)) });
1255        if let Some(certified_keys_to_preload) = certified_keys_to_preload.get(&tls_port) {
1256          for certified_key in certified_keys_to_preload {
1257            stapler.preload(certified_key.clone());
1258          }
1259        }
1260        Arc::new(stapler)
1261      } else {
1262        Arc::new(sni_resolver)
1263      };
1264      let mut tls_config = tls_config_builder_wants_server_cert
1265        .clone()
1266        .with_cert_resolver(resolver);
1267      if protocols.contains(&"h3") {
1268        // TLS configuration used for QUIC listene
1269        let mut quic_tls_config = tls_config.clone();
1270        quic_tls_config.max_early_data_size = u32::MAX;
1271        quic_tls_config.alpn_protocols.insert(0, b"h3-29".to_vec());
1272        quic_tls_config.alpn_protocols.insert(0, b"h3".to_vec());
1273        quic_tls_configs.insert(tls_port, Arc::new(quic_tls_config));
1274      }
1275      if protocols.contains(&"h1") {
1276        tls_config.alpn_protocols.insert(0, b"http/1.0".to_vec());
1277        tls_config.alpn_protocols.insert(0, b"http/1.1".to_vec());
1278      }
1279      if protocols.contains(&"h2") {
1280        tls_config.alpn_protocols.insert(0, b"h2".to_vec());
1281      }
1282      tls_configs.insert(tls_port, Arc::new(tls_config));
1283    }
1284    for (tls_port, sni_resolver) in acme_tls_alpn_01_resolvers.into_iter() {
1285      let mut tls_config = tls_config_builder_wants_server_cert
1286        .clone()
1287        .with_cert_resolver(Arc::new(sni_resolver));
1288      tls_config.alpn_protocols = vec![ACME_TLS_ALPN_NAME.to_vec()];
1289      acme_tls_alpn_01_configs.insert(tls_port, Arc::new(tls_config));
1290    }
1291
1292    let (listener_handler_tx, listener_handler_rx) = &**LISTENER_HANDLER_CHANNEL;
1293
1294    let mut tcp_listeners = TCP_LISTENERS
1295      .lock()
1296      .map_err(|_| anyhow::anyhow!("Can't access the TCP listeners"))?;
1297    let mut quic_listeners = QUIC_LISTENERS
1298      .lock()
1299      .map_err(|_| anyhow::anyhow!("Can't access the QUIC listeners"))?;
1300    let mut listened_socket_addresses = Vec::new();
1301    let mut quic_listened_socket_addresses = Vec::new();
1302    let listen_ip_addr = match global_configuration
1303      .as_deref()
1304      .and_then(|c| get_value!("listen_ip", c))
1305      .and_then(|v| v.as_str())
1306      .map_or(Ok(IpAddr::V6(Ipv6Addr::UNSPECIFIED)), |a| a.parse())
1307    {
1308      Ok(addr) => addr,
1309      Err(_) => Err(anyhow::anyhow!("Invalid IP address to listen to"))?,
1310    };
1311    for (tcp_port, encrypted) in nonencrypted_ports
1312      .iter()
1313      .map(|p| (*p, false))
1314      .chain(tls_configs.keys().map(|p| (*p, true)))
1315    {
1316      let socket_address = SocketAddr::new(listen_ip_addr, tcp_port);
1317      listened_socket_addresses.push((socket_address, encrypted));
1318    }
1319    for (quic_port, quic_tls_config) in quic_tls_configs.into_iter() {
1320      let socket_address = SocketAddr::new(listen_ip_addr, quic_port);
1321      quic_listened_socket_addresses.push((socket_address, quic_tls_config));
1322    }
1323
1324    let enable_uring = global_configuration
1325      .as_deref()
1326      .and_then(|c| get_value!("io_uring", c))
1327      .and_then(|v| v.as_bool())
1328      .unwrap_or(true);
1329    let mut uring_enabled_locked = URING_ENABLED
1330      .lock()
1331      .map_err(|_| anyhow::anyhow!("Can't access the enabled `io_uring` option"))?;
1332    let mut tcp_listener_socketaddrs_to_remove = Vec::new();
1333    let mut quic_listener_socketaddrs_to_remove = Vec::new();
1334    for (key, value) in &*tcp_listeners {
1335      if enable_uring != *uring_enabled_locked
1336        || (!listened_socket_addresses.contains(&(*key, true)) && !listened_socket_addresses.contains(&(*key, false)))
1337      {
1338        // Shut down the TCP listener
1339        value.cancel();
1340
1341        // Push the the TCP listener address to remove
1342        tcp_listener_socketaddrs_to_remove.push(*key);
1343      }
1344    }
1345    for (key, value) in &*quic_listeners {
1346      let mut contains = false;
1347      for key2 in &quic_listened_socket_addresses {
1348        if key2.0 == *key {
1349          contains = true;
1350          break;
1351        }
1352      }
1353      if enable_uring != *uring_enabled_locked || !contains {
1354        // Shut down the QUIC listener
1355        value.0.cancel();
1356
1357        // Push the the QUIC listener address to remove
1358        quic_listener_socketaddrs_to_remove.push(*key);
1359      }
1360    }
1361    *uring_enabled_locked = enable_uring;
1362    drop(uring_enabled_locked);
1363
1364    for key_to_remove in tcp_listener_socketaddrs_to_remove {
1365      // Remove the TCP listener
1366      tcp_listeners.remove(&key_to_remove);
1367    }
1368
1369    for key_to_remove in quic_listener_socketaddrs_to_remove {
1370      // Remove the QUIC listener
1371      quic_listeners.remove(&key_to_remove);
1372    }
1373
1374    // Spawn request handler threads
1375    let mut handler_shutdown_channels = Vec::new();
1376    for _ in 0..available_parallelism {
1377      handler_shutdown_channels.push(create_http_handler(
1378        server_configurations.clone(),
1379        listener_handler_rx.clone(),
1380        enable_uring,
1381        loggers.clone(),
1382        tls_configs.clone(),
1383        !quic_listened_socket_addresses.is_empty(),
1384        acme_tls_alpn_01_configs.clone(),
1385        acme_http_01_resolvers.clone(),
1386        enable_proxy_protocol,
1387      )?);
1388    }
1389
1390    // Error out, if server is configured to listen to no port
1391    if listened_socket_addresses.is_empty() && quic_listened_socket_addresses.is_empty() {
1392      Err(anyhow::anyhow!("The server is configured to listen to no port"))?
1393    }
1394
1395    let tcp_send_buffer_size = global_configuration
1396      .as_deref()
1397      .and_then(|c| get_value!("tcp_send_buffer", c))
1398      .and_then(|v| v.as_i128())
1399      .map(|v| v as usize);
1400    let tcp_recv_buffer_size = global_configuration
1401      .as_deref()
1402      .and_then(|c| get_value!("tcp_recv_buffer", c))
1403      .and_then(|v| v.as_i128())
1404      .map(|v| v as usize);
1405    for (socket_address, encrypted) in listened_socket_addresses {
1406      if let std::collections::hash_map::Entry::Vacant(e) = tcp_listeners.entry(socket_address) {
1407        // Create a TCP listener
1408        e.insert(create_tcp_listener(
1409          socket_address,
1410          encrypted,
1411          listener_handler_tx.clone(),
1412          enable_uring,
1413          global_logger.clone(),
1414          first_startup,
1415          (tcp_send_buffer_size, tcp_recv_buffer_size),
1416        )?);
1417      }
1418    }
1419
1420    // Drop TCP listener mutex guard
1421    drop(tcp_listeners);
1422
1423    for (socket_address, tls_config) in quic_listened_socket_addresses {
1424      if let Some(quic_listener_entry) = quic_listeners.get(&socket_address) {
1425        // Replace the TLS configuration in the QUIC listener
1426        let (_, tls_quic_listener) = quic_listener_entry;
1427        tls_quic_listener.send_blocking(tls_config).unwrap_or_default();
1428      } else {
1429        // Create a QUIC listener
1430        quic_listeners.insert(
1431          socket_address,
1432          create_quic_listener(
1433            socket_address,
1434            tls_config,
1435            listener_handler_tx.clone(),
1436            enable_uring,
1437            global_logger.clone(),
1438            first_startup,
1439          )?,
1440        );
1441      }
1442    }
1443
1444    // Drop QUIC listener mutex guard
1445    drop(quic_listeners);
1446
1447    let shutdown_result = handle_shutdown_signals(secondary_runtime_ref);
1448
1449    // Shut down request handler threads
1450    for shutdown in handler_shutdown_channels {
1451      shutdown.cancel();
1452    }
1453
1454    #[allow(unreachable_code)]
1455    Ok::<_, Box<dyn Error + Send + Sync>>(shutdown_result)
1456  };
1457
1458  match execute_rest() {
1459    Ok(to_restart) => Ok(to_restart),
1460    Err(err) => {
1461      if let Some(logging_tx) = global_logger_clone {
1462        logging_tx
1463          .send_blocking(LogMessage::new(err.to_string(), true))
1464          .unwrap_or_default();
1465      }
1466      std::thread::sleep(Duration::from_millis(100));
1467      Err(err)?
1468    }
1469  }
1470}
1471
1472fn obtain_configuration_adapters() -> (
1473  HashMap<String, Box<dyn ConfigurationAdapter + Send + Sync>>,
1474  Vec<&'static str>,
1475) {
1476  // Configuration adapters
1477  let mut configuration_adapters: HashMap<String, Box<dyn ConfigurationAdapter + Send + Sync>> = HashMap::new();
1478  let mut all_adapters = Vec::new();
1479
1480  // Configuration adapter registration macro
1481  macro_rules! register_configuration_adapter {
1482    ($name:literal, $adapter:expr) => {
1483      configuration_adapters.insert($name.to_string(), Box::new($adapter));
1484      all_adapters.push($name);
1485    };
1486  }
1487
1488  // Register configuration adapters
1489  register_configuration_adapter!("kdl", config::adapters::kdl::KdlConfigurationAdapter::new());
1490  #[cfg(feature = "config-yaml-legacy")]
1491  register_configuration_adapter!(
1492    "yaml-legacy",
1493    config::adapters::yaml_legacy::YamlLegacyConfigurationAdapter::new()
1494  );
1495  #[cfg(feature = "config-docker-auto")]
1496  register_configuration_adapter!(
1497    "docker-auto",
1498    config::adapters::docker_auto::DockerAutoConfigurationAdapter::new()
1499  );
1500
1501  (configuration_adapters, all_adapters)
1502}
1503
1504/// Determines the default configuration adapter
1505#[cfg(feature = "config-yaml-legacy")]
1506fn determine_default_configuration_adapter(path: &Path) -> &'static str {
1507  match path
1508    .extension()
1509    .and_then(|s| s.to_str())
1510    .map(|s| s.to_lowercase())
1511    .as_deref()
1512  {
1513    Some("yaml") | Some("yml") => "yaml-legacy",
1514    _ => "kdl",
1515  }
1516}
1517
1518/// Determines the default configuration adapter
1519#[cfg(not(feature = "config-yaml-legacy"))]
1520fn determine_default_configuration_adapter(_path: &Path) -> &'static str {
1521  "kdl"
1522}
1523
1524/// Parses the command-line arguments
1525fn parse_arguments(all_adapters: Vec<&'static str>) -> ArgMatches {
1526  Command::new("Ferron")
1527    .about("A fast, memory-safe web server written in Rust")
1528    .arg(
1529      Arg::new("config")
1530        .long("config")
1531        .short('c')
1532        .help("The path to the server configuration file")
1533        .action(ArgAction::Set)
1534        .default_value("./ferron.kdl")
1535        .value_parser(PathBuf::from_str),
1536    )
1537    .arg(
1538      Arg::new("config-adapter")
1539        .long("config-adapter")
1540        .help("The configuration adapter to use")
1541        .action(ArgAction::Set)
1542        .required(false)
1543        .value_parser(all_adapters),
1544    )
1545    .arg(
1546      Arg::new("module-config")
1547        .long("module-config")
1548        .help("Prints the used compile-time module configuration (`ferron-build.yaml` or `ferron-build-override.yaml` in the Ferron source) and exits")
1549        .action(ArgAction::SetTrue)
1550    )
1551    .arg(
1552      Arg::new("version")
1553        .long("version")
1554        .short('V')
1555        .help("Print version and build information")
1556        .action(ArgAction::SetTrue)
1557    )
1558    .get_matches()
1559}
1560
1561/// The main entry point of the application
1562fn main() {
1563  // Set the panic handler
1564  setup_panic!(Metadata::new("Ferron", env!("CARGO_PKG_VERSION"))
1565    .homepage("www.ferronweb.org")
1566    .support("- Send an email message to hello@ferron.sh"));
1567
1568  // Obtain the configuration adapters
1569  let (configuration_adapters, all_adapters) = obtain_configuration_adapters();
1570
1571  // Parse command-line arguments
1572  let args = parse_arguments(all_adapters);
1573
1574  if args.get_flag("module-config") {
1575    // Dump the used compile-time module configuration and exit
1576    println!("{}", ferron_load_modules::FERRON_BUILD_YAML);
1577    return;
1578  } else if args.get_flag("version") {
1579    // Print the server version and build information
1580    println!("Ferron {}", build::PKG_VERSION);
1581    println!("  Compiled on: {}", build::BUILD_TIME);
1582    println!("  Git commit: {}", build::COMMIT_HASH);
1583    println!("  Build target: {}", build::BUILD_TARGET);
1584    println!("  Rust version: {}", build::RUST_VERSION);
1585    println!("  Build host: {}", build::BUILD_OS);
1586    if shadow_rs::is_debug() {
1587      println!("WARNING: This is a debug build. It is not recommended for production use.");
1588    }
1589    return;
1590  }
1591
1592  // Start the server!
1593  let mut first_startup = true;
1594  loop {
1595    match before_starting_server(&args, &configuration_adapters, first_startup) {
1596      Ok(true) => {
1597        first_startup = false;
1598        println!("Reloading the server configuration...");
1599      }
1600      Ok(false) => break,
1601      Err(err) => {
1602        eprintln!("Error while running a server: {err}");
1603        std::process::exit(1);
1604      }
1605    };
1606  }
1607}