126 lines
3.5 KiB
Rust
126 lines
3.5 KiB
Rust
//! Network services management (Tor, FIPS, etc.)
|
|
//!
|
|
//! Port of `net_services.c` / `net_services.h` from the C project.
|
|
|
|
use std::sync::Mutex;
|
|
use once_cell::sync::Lazy;
|
|
|
|
/// Network service status.
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
#[allow(dead_code)]
|
|
pub enum ServiceStatus {
|
|
Stopped,
|
|
Starting,
|
|
Running,
|
|
Error(String),
|
|
}
|
|
|
|
/// Network services state.
|
|
static G_NET_SERVICES: Lazy<Mutex<NetServicesState>> = Lazy::new(|| Mutex::new(NetServicesState::default()));
|
|
|
|
struct NetServicesState {
|
|
tor_status: ServiceStatus,
|
|
fips_status: ServiceStatus,
|
|
}
|
|
|
|
impl Default for NetServicesState {
|
|
fn default() -> Self {
|
|
NetServicesState {
|
|
tor_status: ServiceStatus::Stopped,
|
|
fips_status: ServiceStatus::Stopped,
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Initialize network services.
|
|
pub fn net_services_init() {
|
|
let mut state = G_NET_SERVICES.lock().unwrap();
|
|
state.tor_status = ServiceStatus::Stopped;
|
|
state.fips_status = ServiceStatus::Stopped;
|
|
}
|
|
|
|
/// Get Tor status.
|
|
pub fn net_services_get_tor_status() -> ServiceStatus {
|
|
let state = G_NET_SERVICES.lock().unwrap();
|
|
state.tor_status.clone()
|
|
}
|
|
|
|
/// Get FIPS status.
|
|
pub fn net_services_get_fips_status() -> ServiceStatus {
|
|
let state = G_NET_SERVICES.lock().unwrap();
|
|
state.fips_status.clone()
|
|
}
|
|
|
|
/// Start Tor.
|
|
pub fn net_services_start_tor() -> Result<(), Box<dyn std::error::Error>> {
|
|
let mut state = G_NET_SERVICES.lock().unwrap();
|
|
state.tor_status = ServiceStatus::Starting;
|
|
// TODO: actually start Tor
|
|
state.tor_status = ServiceStatus::Running;
|
|
println!("[net] Tor started");
|
|
Ok(())
|
|
}
|
|
|
|
/// Stop Tor.
|
|
pub fn net_services_stop_tor() {
|
|
let mut state = G_NET_SERVICES.lock().unwrap();
|
|
state.tor_status = ServiceStatus::Stopped;
|
|
println!("[net] Tor stopped");
|
|
}
|
|
|
|
/// Start FIPS.
|
|
pub fn net_services_start_fips() -> Result<(), Box<dyn std::error::Error>> {
|
|
let mut state = G_NET_SERVICES.lock().unwrap();
|
|
state.fips_status = ServiceStatus::Starting;
|
|
// TODO: actually start FIPS
|
|
state.fips_status = ServiceStatus::Running;
|
|
println!("[net] FIPS started");
|
|
Ok(())
|
|
}
|
|
|
|
/// Stop FIPS.
|
|
pub fn net_services_stop_fips() {
|
|
let mut state = G_NET_SERVICES.lock().unwrap();
|
|
state.fips_status = ServiceStatus::Stopped;
|
|
println!("[net] FIPS stopped");
|
|
}
|
|
|
|
/// Get the Tor SOCKS proxy endpoint.
|
|
///
|
|
/// Returns the SOCKS5 endpoint (e.g. "socks5h://127.0.0.1:9050") if Tor
|
|
/// is available, or None if Tor is not running. The "socks5h" prefix
|
|
/// tells the proxy to perform DNS resolution through Tor (remote DNS),
|
|
/// which is required for .onion hostnames.
|
|
///
|
|
/// Checks both the internal service status AND whether the SOCKS port
|
|
/// is actually reachable (e.g. a system Tor daemon started outside the
|
|
/// browser).
|
|
pub fn net_services_get_tor_socks_endpoint() -> Option<String> {
|
|
{
|
|
let state = G_NET_SERVICES.lock().unwrap();
|
|
if state.tor_status == ServiceStatus::Running {
|
|
return Some("socks5h://127.0.0.1:9050".to_string());
|
|
}
|
|
}
|
|
|
|
// Check if a system Tor is listening on the default SOCKS port.
|
|
if tor_socks_port_available() {
|
|
Some("socks5h://127.0.0.1:9050".to_string())
|
|
} else {
|
|
None
|
|
}
|
|
}
|
|
|
|
/// Check if Tor's SOCKS port (9050) is accepting connections.
|
|
fn tor_socks_port_available() -> bool {
|
|
use std::net::TcpStream;
|
|
use std::time::Duration;
|
|
match TcpStream::connect_timeout(
|
|
&"127.0.0.1:9050".parse().unwrap(),
|
|
Duration::from_millis(300),
|
|
) {
|
|
Ok(_) => true,
|
|
Err(_) => false,
|
|
}
|
|
}
|