diff --git a/bin/core/src/connection/client.rs b/bin/core/src/connection/client.rs index 6c915497d..4f164de51 100644 --- a/bin/core/src/connection/client.rs +++ b/bin/core/src/connection/client.rs @@ -93,7 +93,7 @@ impl PeripheryConnectionArgs<'_> { /// to implement passkey support for backward compatibility async fn handle_login( handler: &mut super::WebsocketHandler<'_, TungsteniteWebsocket>, - // deprecated. + // for legacy auth passkey: &str, ) -> anyhow::Result<()> { // Get the required auth type @@ -107,61 +107,7 @@ async fn handle_login( // Noise auth &[0] => handler.login::().await, // Passkey auth - &[1] => { - let res = async { - let mut passkey = if passkey.is_empty() { - core_config() - .passkey - .as_deref() - .context("Periphery requires passkey auth")? - .as_bytes() - .to_vec() - } else { - passkey.as_bytes().to_vec() - }; - passkey.push(MessageState::Successful.as_byte()); - - handler - .socket - .send(passkey.into()) - .await - .context("Failed to send passkey")?; - - // Receive login state message and return based on value - let state_msg = handler.socket.recv_bytes().await.context( - "Failed to receive authentication state message", - )?; - let state = state_msg.last().context( - "Authentication state message did not contain state byte", - )?; - match MessageState::from_byte(*state) { - MessageState::Successful => anyhow::Ok(()), - _ => Err(deserialize_error_bytes( - &state_msg[..(state_msg.len() - 1)], - )), - } - } - .await; - if let Err(e) = res { - let mut bytes = serialize_error_bytes(&e); - bytes.push(MessageState::Failed.as_byte()); - if let Err(e) = handler - .socket - .send(bytes.into()) - .await - .context("Failed to send login failed to client") - { - // Log additional error - warn!("{e:#}"); - } - // Close socket - let _ = handler.socket.close(None).await; - // Return the original error - Err(e) - } else { - Ok(()) - } - } + &[1] => handle_passkey_login(handler, passkey).await, other => { return Err(anyhow!( "Receieved invalid login type pattern: {other:?}" @@ -170,6 +116,68 @@ async fn handle_login( } } +async fn handle_passkey_login( + handler: &mut super::WebsocketHandler<'_, TungsteniteWebsocket>, + // for legacy auth + passkey: &str, +) -> anyhow::Result<()> { + let res = async { + let mut passkey = if passkey.is_empty() { + core_config() + .passkey + .as_deref() + .context("Periphery requires passkey auth")? + .as_bytes() + .to_vec() + } else { + passkey.as_bytes().to_vec() + }; + passkey.push(MessageState::Successful.as_byte()); + + handler + .socket + .send(passkey.into()) + .await + .context("Failed to send passkey")?; + + // Receive login state message and return based on value + let state_msg = handler + .socket + .recv_bytes() + .await + .context("Failed to receive authentication state message")?; + let state = state_msg.last().context( + "Authentication state message did not contain state byte", + )?; + match MessageState::from_byte(*state) { + MessageState::Successful => anyhow::Ok(()), + _ => Err(deserialize_error_bytes( + &state_msg[..(state_msg.len() - 1)], + )), + } + } + .await; + if let Err(e) = res { + let mut bytes = serialize_error_bytes(&e); + bytes.push(MessageState::Failed.as_byte()); + if let Err(e) = handler + .socket + .send(bytes.into()) + .await + .context("Failed to send login failed to client") + { + // Log additional error + warn!("{e:#}"); + } + // Close socket + let _ = handler.socket.close(None).await; + // Return the original error + Err(e) + } else { + Ok(()) + } +} + async fn connect_websocket( url: &str, ) -> anyhow::Result<(TungsteniteWebsocket, HeaderValue)> { diff --git a/bin/periphery/src/connection/server.rs b/bin/periphery/src/connection/server.rs index 495e3617e..c933c6675 100644 --- a/bin/periphery/src/connection/server.rs +++ b/bin/periphery/src/connection/server.rs @@ -123,94 +123,102 @@ async fn handle_login( match (&config.core_public_key, &config.passkeys) { (Some(_), _) | (_, None) => { + // Send login type [0] (Noise auth) handler .socket - // Noise handshake auth: [0] .send(Bytes::from_owner([0])) .await .context("Failed to send login type indicator")?; handler.login::().await } (None, Some(passkeys)) => { - warn!( - "Authenticating using Passkeys. Set 'core_public_key' (PERIPHERY_CORE_PUBLIC_KEY) instead to enhance security." - ); - let res = async { - // Send login type - handler - .socket - // Passkey auth: [1] - .send(Bytes::from_owner([1])) - .await - .context("Failed to send login type indicator")?; + handle_passkey_login(handler, passkeys).await + } + } +} - // Receieve passkey - let bytes = handler - .socket - .recv_bytes() - .await - .context("Failed to receive passkey from Core")?; - let passkey = match MessageState::from_byte( - *bytes.last().context("passkey message is empty")?, - ) { - MessageState::Successful => &bytes[..(bytes.len() - 1)], - _ => { - return Err(deserialize_error_bytes( - &bytes[..(bytes.len() - 1)], - )); - } - }; +async fn handle_passkey_login( + handler: &mut WebsocketHandler<'_, AxumWebsocket>, + passkeys: &[String], +) -> anyhow::Result<()> { + warn!( + "Authenticating using Passkeys. Set 'core_public_key' (PERIPHERY_CORE_PUBLIC_KEY) instead to enhance security." + ); + let res = async { + // Send login type + handler + .socket + // Passkey auth: [1] + .send(Bytes::from_owner([1])) + .await + .context("Failed to send login type indicator")?; - if passkeys.iter().any(|expected_passkey| { - expected_passkey.as_bytes() == passkey - }) { - handler - .socket - .send(MessageState::Successful.into()) - .await - .context("Failed to send login type indicator")?; - Ok(()) - } else { - let e = anyhow!("Invalid passkey"); - let mut bytes = serialize_error_bytes(&e); - bytes.push(MessageState::Failed.as_byte()); - if let Err(e) = handler - .socket - .send(bytes.into()) - .await - .context("Failed to send login failed") - { - // Log additional error - warn!("{e:#}"); - // Close socket - let _ = handler.socket.close(None).await; - } - // Return the original error - Err(e) - } + // Receieve passkey + let bytes = handler + .socket + .recv_bytes() + .await + .context("Failed to receive passkey from Core")?; + let passkey = match MessageState::from_byte( + *bytes.last().context("passkey message is empty")?, + ) { + MessageState::Successful => &bytes[..(bytes.len() - 1)], + _ => { + return Err(deserialize_error_bytes( + &bytes[..(bytes.len() - 1)], + )); } - .await; - if let Err(e) = res { - let mut bytes = serialize_error_bytes(&e); - bytes.push(MessageState::Failed.as_byte()); - if let Err(e) = handler - .socket - .send(bytes.into()) - .await - .context("Failed to send login failed to client") - { - // Log additional error - warn!("{e:#}"); - } + }; + + if passkeys + .iter() + .any(|expected_passkey| expected_passkey.as_bytes() == passkey) + { + handler + .socket + .send(MessageState::Successful.into()) + .await + .context("Failed to send login type indicator")?; + Ok(()) + } else { + let e = anyhow!("Invalid passkey"); + let mut bytes = serialize_error_bytes(&e); + bytes.push(MessageState::Failed.as_byte()); + if let Err(e) = handler + .socket + .send(bytes.into()) + .await + .context("Failed to send login failed") + { + // Log additional error + warn!("{e:#}"); // Close socket let _ = handler.socket.close(None).await; - // Return the original error - Err(e) - } else { - Ok(()) } + // Return the original error + Err(e) } } + .await; + if let Err(e) = res { + let mut bytes = serialize_error_bytes(&e); + bytes.push(MessageState::Failed.as_byte()); + if let Err(e) = handler + .socket + .send(bytes.into()) + .await + .context("Failed to send login failed to client") + { + // Log additional error + warn!("{e:#}"); + } + // Close socket + let _ = handler.socket.close(None).await; + // Return the original error + Err(e) + } else { + Ok(()) + } } async fn guard_request_by_ip(