Add shadow compatible password hashing

This commit is contained in:
Samuel Lorch 2023-10-26 13:08:17 +02:00
parent faf446d93a
commit 4c3ce8208a
6 changed files with 215 additions and 11 deletions

View file

@ -1,4 +1,3 @@
use serde_json::to_string;
use validator::Validate;
use super::definitions::config::Config;
@ -8,11 +7,14 @@ use std::{io, result::Result};
use custom_error::custom_error;
use pwhash::sha512_crypt;
custom_error! { pub ConfigError
IoError{source: io::Error} = "io error",
SerdeError{source: serde_json::Error} = "serde json error",
ValidatonError{source: validator::ValidationErrors} = "validation failed"
ValidatonError{source: validator::ValidationErrors} = "validation failed",
HashError{source: pwhash::error::Error} = "password hash generation",
UnsupportedVersionError = "unsupported config version",
}
pub const CURRENT_CONFIG_PATH: &str = "config.json";
@ -99,7 +101,7 @@ fn read_file_to_config(path: &str) -> Result<Config, ConfigError> {
let data = fs::read_to_string(path)?;
let conf: Config = serde_json::from_str(&data)?;
if conf.config_version != 1 {
// return Err("Unsupported config Version");
return Err(ConfigError::UnsupportedVersionError);
}
Ok(conf)
}
@ -112,12 +114,13 @@ fn write_config_to_file(path: &str, conf: Config) -> Result<(), ConfigError> {
pub fn generate_default_config(path: &str) -> Result<(), ConfigError> {
let mut conf = Config::default();
let hash = sha512_crypt::hash("nfsense")?;
conf.config_version = 1;
conf.system.users.insert(
"admin".to_string(),
crate::definitions::system::User {
comment: "Default Admin".to_string(),
hash: "".to_string(),
salt: "".to_string(),
hash: hash,
},
);
write_config_to_file(path, conf)

View file

@ -11,5 +11,4 @@ pub struct System {
pub struct User {
pub comment: String,
pub hash: String,
pub salt: String,
}

View file

@ -9,6 +9,7 @@ use axum::{middleware, Router};
use config_manager::ConfigManager;
use state::AppState;
use std::env;
use std::fs;
use tower_cookies::CookieManagerLayer;
use tracing::info;
use tracing_subscriber;
@ -29,7 +30,11 @@ async fn main() {
if args.len() > 1 && args[1] == "generate-default" {
info!("Generating default config...");
config_manager::generate_default_config(config_manager::CURRENT_CONFIG_PATH).unwrap();
config_manager::generate_default_config(config_manager::PENDING_CONFIG_PATH).unwrap();
fs::copy(
config_manager::CURRENT_CONFIG_PATH,
config_manager::PENDING_CONFIG_PATH,
)
.unwrap();
info!("Done! Exiting...");
return;
}

View file

@ -18,6 +18,9 @@ use axum::{
response::{IntoResponse, Response},
};
use pwhash::sha512_crypt;
use tracing::info;
use custom_error::custom_error;
custom_error! { AuthError
@ -65,22 +68,24 @@ async fn login_handler(
.users
.get(&payload.username.to_string())
{
// TODO use propper hash algorithm compatible with /etc/passwd
if payload.password == "nfsense" {
if sha512_crypt::verify(payload.password, &user.hash) {
let mut sessions = state.session_state.sessions.write().unwrap();
let id = Uuid::new_v4().to_string();
sessions.insert(
id.clone(),
Session {
username: payload.username,
username: payload.username.clone(),
},
);
cookies.add(Cookie::new(SESSION_COOKIE, id));
info!("user logged in: {:?}", payload.username);
return StatusCode::OK;
}
}
info!("user login failed: {:?}", payload.username);
StatusCode::UNAUTHORIZED
}
@ -96,6 +101,7 @@ async fn logout_handler(cookies: Cookies, state: State<AppState>) -> impl IntoRe
// cookies.remove(s.clone());
if let Some(session) = sessions.get(session_id) {
info!("user logged out: {:?}", session.username);
sessions.remove(session_id);
return StatusCode::OK;
}