Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions src/app/fprint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ pub async fn list_enrolled_fingers_dbus(
device: &DeviceProxy<'static>,
username: String,
) -> zbus::Result<Vec<String>> {
validate_username(&username)?;
device.list_enrolled_fingers(&username).await
}

Expand All @@ -31,6 +32,7 @@ pub async fn delete_fingerprint_dbus(
finger: String,
username: String,
) -> zbus::Result<()> {
validate_username(&username)?;
let device = DeviceProxy::builder(connection).path(path)?.build().await?;

device.claim(&username).await?;
Expand All @@ -44,6 +46,7 @@ pub async fn delete_fingers(
path: zbus::zvariant::OwnedObjectPath,
username: String,
) -> zbus::Result<()> {
validate_username(&username)?;
let device = DeviceProxy::builder(connection).path(path)?.build().await?;

device.claim(&username).await?;
Expand All @@ -60,6 +63,11 @@ pub async fn clear_all_fingers_dbus(
let mut last_error = None;

for username in usernames {
if let Err(e) = validate_username(&username) {
last_error = Some(e);
continue;
}

if let Err(e) = device.claim(&username).await {
last_error = Some(e);
continue;
Expand Down Expand Up @@ -101,6 +109,7 @@ where
S: Sink<Message> + Unpin + Send,
S::Error: std::fmt::Debug + Send,
{
validate_username(&username)?;
let device = DeviceProxy::builder(&connection)
.path(path)?
.build()
Expand Down Expand Up @@ -165,3 +174,51 @@ where

Ok(())
}

fn validate_username(username: &str) -> zbus::Result<()> {
if username.is_empty() {
return Err(zbus::Error::Failure("Username cannot be empty".to_string()));
}
if username.len() > 255 {
return Err(zbus::Error::Failure("Username is too long".to_string()));
}
if !username.chars().all(|c| c.is_alphanumeric() || c == '-' || c == '_' || c == '.') {
return Err(zbus::Error::Failure(format!(
"Invalid characters in username: {}",
username
)));
}
Ok(())
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_validate_username() {
// Valid usernames
assert!(validate_username("user").is_ok());
assert!(validate_username("user1").is_ok());
assert!(validate_username("user_name").is_ok());
assert!(validate_username("user-name").is_ok());
assert!(validate_username("user.name").is_ok());
assert!(validate_username("u").is_ok());
assert!(validate_username("123").is_ok());
assert!(validate_username("User").is_ok()); // Uppercase is allowed by our validation

// Invalid usernames
assert!(validate_username("").is_err());
assert!(validate_username("user name").is_err()); // space
assert!(validate_username("user/name").is_err()); // slash
assert!(validate_username("user@name").is_err()); // @
assert!(validate_username("user!name").is_err()); // !
assert!(validate_username("user?name").is_err()); // ?

let long_name = "a".repeat(256);
assert!(validate_username(&long_name).is_err());

let max_len_name = "a".repeat(255);
assert!(validate_username(&max_len_name).is_ok());
}
}
Loading