Skip to content
12 changes: 7 additions & 5 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,16 +51,16 @@ pub async fn prepare_ap_config<P: PlatformServices>(
) -> Result<WifiApConfigStatic, sunset::Error> {
let mut guard = config.lock().await;

if guard.wifi_pw.is_empty() {
if guard.wifi_ap_pw.is_empty() {
let pw = generate_wifi_password()?;
warn!("wifi_pw missing from config, generated new password");
guard.wifi_pw = pw;
guard.wifi_ap_pw = pw;
platform
.save_config(&guard)
.await
.map_err(|_| sunset::error::BadUsage.build())?;
}
info!("WIFI PSK: {}", guard.wifi_pw);
info!("WIFI PSK: {}", guard.wifi_ap_pw);

let mac = guard
.resolve_mac()
Expand All @@ -73,8 +73,10 @@ pub async fn prepare_ap_config<P: PlatformServices>(
print_hostkey_fingerprint(&guard.hostkey);

Ok(WifiApConfigStatic {
ssid: guard.wifi_ssid.clone(),
password: guard.wifi_pw.clone(),
ap_ssid: guard.wifi_ap_ssid.clone(),
ap_password: guard.wifi_ap_pw.clone(),
sta_ssid: guard.wifi_sta_ssid.clone(),
sta_password: guard.wifi_sta_pw.clone(),
channel: 1,
mac,
})
Expand Down
45 changes: 33 additions & 12 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,12 @@ pub struct SSHStampConfig {
pub pubkeys: [Option<Ed25519PubKey>; KEY_SLOTS],

/// `WiFi`
pub wifi_ssid: String<32>,
pub wifi_pw: String<63>,
/// Access Point Mode
pub wifi_ap_ssid: String<32>,
pub wifi_ap_pw: String<63>,
/// Station Mode
pub wifi_sta_ssid: String<32>,
pub wifi_sta_pw: String<63>,

/// Networking
/// MAC address. Special values:
Expand Down Expand Up @@ -103,9 +107,14 @@ impl SSHStampConfig {
pub fn new(default_mac: [u8; 6]) -> Result<Self> {
let hostkey = SignKey::generate(KeyType::Ed25519, None)?;

let wifi_ssid = Self::generate_wifi_ssid()?;
// Wifi Access Point Mode
let wifi_ap_ssid = Self::generate_wifi_ssid()?;
let wifi_ap_pw = Self::generate_wifi_password()?;
// Wifi Station Mode
let wifi_sta_ssid = Self::generate_wifi_ssid()?;
let wifi_sta_pw = Self::generate_wifi_password()?;

let mac = default_mac;
let wifi_pw = Self::generate_wifi_password()?;

let uart_pins = UartPins::default();
debug!(
Expand All @@ -116,8 +125,10 @@ impl SSHStampConfig {
Ok(SSHStampConfig {
hostkey,
pubkeys: Default::default(),
wifi_ssid,
wifi_pw,
wifi_ap_ssid,
wifi_ap_pw,
wifi_sta_ssid,
wifi_sta_pw,
mac,
ipv4_static: None,
#[cfg(feature = "ipv6")]
Expand Down Expand Up @@ -310,8 +321,12 @@ impl SSHEncode for SSHStampConfig {
enc_option(k.as_ref(), s)?;
}

self.wifi_ssid.as_str().enc(s)?;
self.wifi_pw.as_str().enc(s)?;
// Wifi Access Point Mode
self.wifi_ap_ssid.as_str().enc(s)?;
self.wifi_ap_pw.as_str().enc(s)?;
// Wifi Station Mode
self.wifi_sta_ssid.as_str().enc(s)?;
self.wifi_sta_pw.as_str().enc(s)?;
self.mac.enc(s)?;

enc_ipv4_config(self.ipv4_static.as_ref(), s)?;
Expand Down Expand Up @@ -341,8 +356,12 @@ impl<'de> SSHDecode<'de> for SSHStampConfig {
*k = dec_option(s)?;
}

let wifi_ssid = SSHDecode::dec(s)?;
let wifi_pw = SSHDecode::dec(s)?;
// Wifi Access Point Mode
let wifi_ap_ssid = SSHDecode::dec(s)?;
let wifi_ap_pw = SSHDecode::dec(s)?;
// Wifi Station Mode
let wifi_sta_ssid = SSHDecode::dec(s)?;
let wifi_sta_pw = SSHDecode::dec(s)?;

let mac = SSHDecode::dec(s)?;

Expand All @@ -361,8 +380,10 @@ impl<'de> SSHDecode<'de> for SSHStampConfig {
Ok(Self {
hostkey,
pubkeys,
wifi_ssid,
wifi_pw,
wifi_ap_ssid,
wifi_ap_pw,
wifi_sta_ssid,
wifi_sta_pw,
mac,
ipv4_static,
#[cfg(feature = "ipv6")]
Expand Down
94 changes: 78 additions & 16 deletions src/handle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -352,11 +352,17 @@ pub async fn session_env(
"SSH_STAMP_PUBKEY" => {
pubkey_env(a, config, ctx).await?;
}
"SSH_STAMP_WIFI_SSID" => {
wifi_ssid_env(a, config, ctx).await?;
"SSH_STAMP_WIFI_AP_SSID" => {
wifi_ap_ssid_env(a, config, ctx).await?;
}
"SSH_STAMP_WIFI_PSK" => {
wifi_psk_env(a, config, ctx).await?;
"SSH_STAMP_WIFI_AP_PSK" => {
wifi_ap_psk_env(a, config, ctx).await?;
}
"SSH_STAMP_WIFI_STA_SSID" => {
wifi_sta_ssid_env(a, config, ctx).await?;
}
"SSH_STAMP_WIFI_STA_PW" => {
wifi_sta_psk_env(a, config, ctx).await?;
}
"SSH_STAMP_WIFI_MAC_ADDRESS" => {
wifi_mac_address_env(a, config, ctx).await?;
Expand Down Expand Up @@ -414,57 +420,113 @@ pub async fn pubkey_env(
Ok(())
}

/// Handles `SSH_STAMP_WIFI_SSID` environment variable requests.
/// Handles `SSH_STAMP_WIFI_AP_SSID` environment variable requests.
///
/// # Errors
/// Returns an error if SSH protocol operations fail or if the SSID is invalid.
pub async fn wifi_ssid_env(
pub async fn wifi_ap_ssid_env(
a: sunset::event::ServEnvironmentRequest<'_, '_>,
config: &SunsetMutex<SSHStampConfig>,
ctx: &mut EventContext<'_>,
) -> Result<(), sunset::Error> {
let mut config_guard = config.lock().await;
if *ctx.auth_checked || config_guard.first_login {
if let Some(s) = env_parser::parse_wifi_ssid(a.value()?) {
config_guard.wifi_ssid = s;
debug!("Set wifi SSID from ENV");
config_guard.wifi_ap_ssid = s;
debug!("Set wifi Access Point SSID from ENV");
a.succeed()?;
*ctx.config_changed = true;
*ctx.needs_reset = true;
} else {
warn!("SSH_STAMP_WIFI_SSID invalid and/or too long");
warn!("SSH_STAMP_WIFI_AP_SSID invalid and/or too long");
a.fail()?;
}
} else {
warn!("SSH_STAMP_WIFI_SSID env received but not authenticated; rejecting");
warn!("SSH_STAMP_WIFI_AP_SSID env received but not authenticated; rejecting");
a.fail()?;
}
Ok(())
}

/// Handles `SSH_STAMP_WIFI_PSK` environment variable requests.
/// Handles `SSH_STAMP_WIFI_AP_PSK` environment variable requests.
///
/// # Errors
/// Returns an error if SSH protocol operations fail or if the PSK is invalid.
pub async fn wifi_psk_env(
pub async fn wifi_ap_psk_env(
a: sunset::event::ServEnvironmentRequest<'_, '_>,
config: &SunsetMutex<SSHStampConfig>,
ctx: &mut EventContext<'_>,
) -> Result<(), sunset::Error> {
let mut config_guard = config.lock().await;
if *ctx.auth_checked || config_guard.first_login {
if let Some(s) = env_parser::parse_wifi_psk(a.value()?) {
config_guard.wifi_ap_pw = s;
debug!("Set WIFI AP PSK from ENV");
a.succeed()?;
*ctx.config_changed = true;
*ctx.needs_reset = true;
} else {
warn!("SSH_STAMP_WIFI_AP_PSK invalid and/or not within 8-63 characters");
a.fail()?;
}
} else {
warn!("SSH_STAMP_WIFI_AP_PSK env received but not authenticated; rejecting");
a.fail()?;
}
Ok(())
}

/// Handles `SSH_STAMP_WIFI_STA_SSID` environment variable requests.
///
/// # Errors
/// Returns an error if SSH protocol operations fail or if the SSID is invalid.
pub async fn wifi_sta_ssid_env(
a: sunset::event::ServEnvironmentRequest<'_, '_>,
config: &SunsetMutex<SSHStampConfig>,
ctx: &mut EventContext<'_>,
) -> Result<(), sunset::Error> {
let mut config_guard = config.lock().await;
if *ctx.auth_checked || config_guard.first_login {
if let Some(s) = env_parser::parse_wifi_ssid(a.value()?) {
config_guard.wifi_sta_ssid = s;
debug!("Set wifi STATION SSID from ENV");
a.succeed()?;
*ctx.config_changed = true;
*ctx.needs_reset = true;
} else {
warn!("SSH_STAMP_WIFI_STA_SSID invalid and/or too long");
a.fail()?;
}
} else {
warn!("SSH_STAMP_WIFI_STA_SSID env received but not authenticated; rejecting");
a.fail()?;
}
Ok(())
}

/// Handles `SSH_STAMP_WIFI_STA_PSK` environment variable requests.
///
/// # Errors
/// Returns an error if SSH protocol operations fail or if the SSID is invalid.
pub async fn wifi_sta_psk_env(
a: sunset::event::ServEnvironmentRequest<'_, '_>,
config: &SunsetMutex<SSHStampConfig>,
ctx: &mut EventContext<'_>,
) -> Result<(), sunset::Error> {
let mut config_guard = config.lock().await;
if *ctx.auth_checked || config_guard.first_login {
if let Some(s) = env_parser::parse_wifi_psk(a.value()?) {
config_guard.wifi_pw = s;
debug!("Set WIFI PSK from ENV");
config_guard.wifi_sta_pw = s;
debug!("Set wifi STATION PSK from ENV");
a.succeed()?;
*ctx.config_changed = true;
*ctx.needs_reset = true;
} else {
warn!("SSH_STAMP_WIFI_PSK invalid and/or not within 8-63 characters");
warn!("SSH_STAMP_WIFI_STA_PSK invalid and/or not within 8-63 characters");
a.fail()?;
}
} else {
warn!("SSH_STAMP_WIFI_PSK env received but not authenticated; rejecting");
warn!("SSH_STAMP_WIFI_STA_PSK env received but not authenticated; rejecting");
a.fail()?;
}
Ok(())
Expand Down
10 changes: 5 additions & 5 deletions src/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,11 @@ where
match load(flash, buf) {
Ok(mut c) => {
debug!("Good existing config");
if c.wifi_ssid.as_str() == "ssh-stamp" {
debug!("Migrating insecure default SSID, regenerating randomly");
c.wifi_ssid = SSHStampConfig::generate_wifi_ssid()?;
if c.wifi_pw.is_empty() {
c.wifi_pw = SSHStampConfig::generate_wifi_password()?;
if c.wifi_ap_ssid.as_str() == "ssh-stamp" {
debug!("Migrating insecure default Access Point SSID, regenerating randomly");
c.wifi_ap_ssid = SSHStampConfig::generate_wifi_ssid()?;
if c.wifi_ap_pw.is_empty() {
c.wifi_ap_pw = SSHStampConfig::generate_wifi_password()?;
}
save(flash, buf, &c)?;
}
Expand Down
18 changes: 13 additions & 5 deletions ssh-stamp-esp32/src/bin/ssh-stamp-esp32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,11 +162,19 @@ async fn main(spawner: Spawner) -> ! {
let ap_config = app::prepare_ap_config(config, &platform)
.await
.expect("Failed to prepare AP config");
info!(
"Connect to the AP `{}` as a DHCP client with IP: {}",
ap_config.ssid.as_str(),
DEFAULT_IP
);
if ap_config.sta_ssid.as_str().is_empty() {
info!(
"Connect to the AP `{}` as a DHCP client with IP: {}",
ap_config.ap_ssid.as_str(),
DEFAULT_IP
);
} else {
info!(
"SSH Stamp has connected to Access Point {}. Connect to the same Access Point as a DHCP client with IP: {}",
ap_config.sta_ssid.as_str(),
DEFAULT_IP
);
}

let mut wifi = EspWifi::new(spawner, peripherals.WIFI, rng, DEFAULT_IP);
wifi.configure_ap(ap_config)
Expand Down
Loading
Loading