aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/args.rs30
-rw-r--r--src/auth.rs44
2 files changed, 43 insertions, 31 deletions
diff --git a/src/args.rs b/src/args.rs
index 63799a0..3972995 100644
--- a/src/args.rs
+++ b/src/args.rs
@@ -77,8 +77,20 @@ fn parse_interface(src: &str) -> Result<IpAddr, std::net::AddrParseError> {
src.parse::<IpAddr>()
}
-/// Checks wether the auth string is valid, i.e. it follows the syntax username:password
+/// Parse a string of multiple authentication requirements
fn parse_auth(src: &str) -> Result<auth::RequiredAuth, ContextualError> {
+ let mut required_auth = auth::RequiredAuth::new();
+
+ for pair in src.split_whitespace().map(parse_single_auth) {
+ let (username, password) = pair?;
+ required_auth.insert(username.to_owned(), password);
+ }
+
+ Ok(required_auth)
+}
+
+/// Parse a single authentication requirement
+fn parse_single_auth(src: &str) -> Result<(String, auth::RequiredAuthPassword), ContextualError> {
let mut split = src.splitn(3, ':');
let invalid_auth_format = Err(ContextualError::InvalidAuthFormat);
@@ -119,10 +131,7 @@ fn parse_auth(src: &str) -> Result<auth::RequiredAuth, ContextualError> {
auth::RequiredAuthPassword::Plain(second_part.to_owned())
};
- Ok(auth::RequiredAuth {
- username: username.to_owned(),
- password,
- })
+ Ok((username.to_owned(), password))
}
/// Parses the command line arguments
@@ -172,16 +181,19 @@ mod tests {
fn create_required_auth(username: &str, password: &str, encrypt: &str) -> auth::RequiredAuth {
use auth::*;
use RequiredAuthPassword::*;
+ let mut required_auth = RequiredAuth::new();
- RequiredAuth {
- username: username.to_owned(),
- password: match encrypt {
+ required_auth.insert(
+ username.to_owned(),
+ match encrypt {
"plain" => Plain(password.to_owned()),
"sha256" => Sha256(hex::decode(password.to_owned()).unwrap()),
"sha512" => Sha512(hex::decode(password.to_owned()).unwrap()),
_ => panic!("Unknown encryption type"),
},
- }
+ );
+
+ required_auth
}
#[rstest_parametrize(
diff --git a/src/auth.rs b/src/auth.rs
index e526923..735929b 100644
--- a/src/auth.rs
+++ b/src/auth.rs
@@ -2,6 +2,7 @@ use actix_web::http::header;
use actix_web::middleware::{Middleware, Response};
use actix_web::{HttpRequest, HttpResponse, Result};
use sha2::{Digest, Sha256, Sha512};
+use std::collections::HashMap;
use crate::errors::{ContextualError};
@@ -22,12 +23,8 @@ pub enum RequiredAuthPassword {
Sha512(Vec<u8>),
}
-#[derive(Clone, Debug, PartialEq)]
/// Authentication structure to match `BasicAuthParams` against
-pub struct RequiredAuth {
- pub username: String,
- pub password: RequiredAuthPassword,
-}
+pub type RequiredAuth = HashMap<String, RequiredAuthPassword>;
/// Decode a HTTP basic auth string into a tuple of username and password.
pub fn parse_basic_auth(
@@ -57,20 +54,20 @@ pub fn parse_basic_auth(
/// Verify authentication
pub fn match_auth(basic_auth: BasicAuthParams, required_auth: &RequiredAuth) -> bool {
- if basic_auth.username != required_auth.username {
- return false;
- }
-
- match &required_auth.password {
- RequiredAuthPassword::Plain(ref required_password) => {
- basic_auth.password == *required_password
- }
- RequiredAuthPassword::Sha256(password_hash) => {
- compare_hash::<Sha256>(basic_auth.password, password_hash)
- }
- RequiredAuthPassword::Sha512(password_hash) => {
- compare_hash::<Sha512>(basic_auth.password, password_hash)
+ if let Some(password) = required_auth.get(&basic_auth.username) {
+ match &password {
+ RequiredAuthPassword::Plain(ref required_password) => {
+ basic_auth.password == *required_password
+ }
+ RequiredAuthPassword::Sha256(password_hash) => {
+ compare_hash::<Sha256>(basic_auth.password, password_hash)
+ }
+ RequiredAuthPassword::Sha512(password_hash) => {
+ compare_hash::<Sha512>(basic_auth.password, password_hash)
+ }
}
+ } else {
+ false
}
}
@@ -150,16 +147,19 @@ mod tests {
/// Helper function that creates a `RequiredAuth` structure and encrypt `password` if necessary
fn create_required_auth(username: &str, password: &str, encrypt: &str) -> RequiredAuth {
use RequiredAuthPassword::*;
+ let mut required_auth = RequiredAuth::new();
- RequiredAuth {
- username: username.to_owned(),
- password: match encrypt {
+ required_auth.insert(
+ username.to_owned(),
+ match encrypt {
"plain" => Plain(password.to_owned()),
"sha256" => Sha256(get_hash::<sha2::Sha256>(password.to_owned())),
"sha512" => Sha512(get_hash::<sha2::Sha512>(password.to_owned())),
_ => panic!("Unknown encryption type"),
},
- }
+ );
+
+ required_auth
}
#[rstest_parametrize(