08354f7651
* Move client-core to common dir * Factor out socks5-client in its own crate * Possible sdk-socks5 integration * Update changelog * Remove socks5 client lib * Rename crate to include nym- prefix * Trim the socks5 wrapped message so that it's printable * Fix intellij auto refactoring * Post merge fixes
133 lines
3.6 KiB
Rust
133 lines
3.6 KiB
Rust
/// Client Authentication Methods
|
|
pub(crate) enum AuthenticationMethods {
|
|
/// No Authentication
|
|
NoAuth = 0x00,
|
|
// GssApi = 0x01, // question to DH: why is this commented?
|
|
/// Authenticate with a username / password
|
|
UserPass = 0x02,
|
|
/// Cannot authenticate
|
|
NoMethods = 0xFF,
|
|
}
|
|
|
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
/// A socks5 user with a matching password.
|
|
pub struct User {
|
|
pub username: String,
|
|
pub password: String,
|
|
}
|
|
|
|
#[derive(Clone, Debug)]
|
|
/// Allows configuration of access methods (no auth required, username/pass, reject all)
|
|
/// and keeps a list of users who have access if that method is enabled.
|
|
pub(crate) struct Authenticator {
|
|
allowed_users: Vec<User>,
|
|
pub(crate) auth_methods: Vec<u8>,
|
|
}
|
|
|
|
impl Authenticator {
|
|
pub(crate) fn new(auth_methods: Vec<u8>, allowed_users: Vec<User>) -> Authenticator {
|
|
Authenticator {
|
|
allowed_users,
|
|
auth_methods,
|
|
}
|
|
}
|
|
|
|
/// Check if username + password pair are valid
|
|
pub fn is_allowed(&self, user: &User) -> bool {
|
|
if self
|
|
.auth_methods
|
|
.contains(&(AuthenticationMethods::UserPass as u8))
|
|
{
|
|
self.allowed_users.contains(user)
|
|
} else {
|
|
false
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn constructor_works() {
|
|
let auth_methods = vec![
|
|
AuthenticationMethods::NoAuth as u8,
|
|
AuthenticationMethods::UserPass as u8,
|
|
];
|
|
|
|
let admin = User {
|
|
username: "foo".to_string(),
|
|
password: "bar".to_string(),
|
|
};
|
|
let allowed_users = vec![admin.clone()];
|
|
|
|
let authenticator = Authenticator::new(auth_methods, allowed_users);
|
|
|
|
assert!(authenticator.allowed_users.contains(&admin));
|
|
assert!(authenticator
|
|
.auth_methods
|
|
.contains(&(AuthenticationMethods::NoAuth as u8)));
|
|
assert!(authenticator
|
|
.auth_methods
|
|
.contains(&(AuthenticationMethods::UserPass as u8)));
|
|
}
|
|
|
|
mod without_user_and_password_auth_enabled {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn user_pass_authentication_fails() {
|
|
let auth_methods: Vec<u8> = Vec::new(); // it's empty
|
|
|
|
let admin = User {
|
|
username: "foo".to_string(),
|
|
password: "bar".to_string(),
|
|
};
|
|
|
|
let allowed_users = vec![admin.clone()];
|
|
|
|
let authenticator = Authenticator::new(auth_methods, allowed_users);
|
|
|
|
assert!(!authenticator.is_allowed(&admin));
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod with_user_and_password_auth_enabled {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn allowed_user_passes_authentication_check() {
|
|
let auth_methods = vec![AuthenticationMethods::UserPass as u8];
|
|
|
|
let admin = User {
|
|
username: "foo".to_string(),
|
|
password: "bar".to_string(),
|
|
};
|
|
|
|
let allowed_users = vec![admin.clone()];
|
|
|
|
let authenticator = Authenticator::new(auth_methods, allowed_users);
|
|
|
|
assert!(authenticator.is_allowed(&admin));
|
|
}
|
|
|
|
#[test]
|
|
fn disallowed_user_fails_authentication_check() {
|
|
let auth_methods = vec![AuthenticationMethods::UserPass as u8];
|
|
|
|
let bad_user = User {
|
|
username: "ashy".to_string(),
|
|
password: "slashy".to_string(),
|
|
};
|
|
|
|
let allowed_users = Vec::new();
|
|
|
|
let authenticator = Authenticator::new(auth_methods, allowed_users);
|
|
|
|
assert!(!authenticator.is_allowed(&bad_user));
|
|
}
|
|
}
|
|
}
|