1use rcgen::{CertificateParams, DistinguishedName, DnType, KeyPair};
8use std::fs;
9use std::path::Path;
10
11pub fn generate_certificate(
16 common_name: &str,
17) -> Result<(String, String, String), String> {
18 let mut params = CertificateParams::new(vec![common_name.to_string()])
19 .map_err(|e| format!("cert params: {}", e))?;
20
21 let mut dn = DistinguishedName::new();
23 dn.push(DnType::CommonName, common_name);
24 params.distinguished_name = dn;
25
26 let key_pair = KeyPair::generate()
28 .map_err(|e| format!("key gen: {}", e))?;
29
30 let cert = params
31 .self_signed(&key_pair)
32 .map_err(|e| format!("self-sign: {}", e))?;
33
34 let cert_pem = cert.pem();
35 let key_pem = key_pair.serialize_pem();
36
37 let fingerprint = pwr_core::crypto::sha256_hex(cert_pem.as_bytes());
39
40 Ok((cert_pem, key_pem, fingerprint))
41}
42
43pub fn save_certificate(
45 cert_path: &Path,
46 key_path: &Path,
47 cert_pem: &str,
48 key_pem: &str,
49) -> Result<(), String> {
50 if let Some(parent) = cert_path.parent() {
52 fs::create_dir_all(parent)
53 .map_err(|e| format!("mkdir {}: {}", parent.display(), e))?;
54 }
55 if let Some(parent) = key_path.parent() {
56 fs::create_dir_all(parent)
57 .map_err(|e| format!("mkdir {}: {}", parent.display(), e))?;
58 }
59
60 fs::write(cert_path, cert_pem)
62 .map_err(|e| format!("write cert: {}", e))?;
63
64 fs::write(key_path, key_pem)
66 .map_err(|e| format!("write key: {}", e))?;
67
68 #[cfg(unix)]
69 {
70 use std::os::unix::fs::PermissionsExt;
71 let mut perms = fs::metadata(key_path)
72 .map_err(|e| format!("stat key: {}", e))?
73 .permissions();
74 perms.set_mode(0o600);
75 fs::set_permissions(key_path, perms)
76 .map_err(|e| format!("chmod key: {}", e))?;
77 }
78
79 Ok(())
80}
81
82pub fn init_server(
84 config_path: &Path,
85 hostname: &str,
86) -> Result<(), String> {
87 use crate::config::{save_config, ServerConfig};
88
89 let (cert_pem, key_pem, fingerprint) = generate_certificate(hostname)?;
90
91 let cert_path = Path::new("/etc/pwr/server.crt");
92 let key_path = Path::new("/etc/pwr/server.key");
93
94 save_certificate(cert_path, key_path, &cert_pem, &key_pem)?;
95
96 let psk = pwr_core::crypto::generate_psk();
98 let psk_hex = pwr_core::crypto::psk_to_hex(&psk);
99
100 let mut config = ServerConfig::default();
101 config.auth_token = psk_hex.clone();
102 config.tls_cert_path = cert_path.to_path_buf();
103 config.tls_key_path = key_path.to_path_buf();
104
105 save_config(&config, config_path)?;
106
107 println!("Server initialized successfully.");
108 println!(" Config: {}", config_path.display());
109 println!(" Certificate: {}", cert_path.display());
110 println!(" Private key: {}", key_path.display());
111 println!(" PSK: {}", psk_hex);
112 println!(" Fingerprint: {}", fingerprint);
113 println!();
114 println!("Copy the PSK to your client config:");
115 println!(" pwr init --server-host {} --psk {}", hostname, psk_hex);
116
117 Ok(())
118}