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

190
Cargo.lock generated
View file

@ -119,6 +119,32 @@ version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
[[package]]
name = "block-buffer"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4"
dependencies = [
"generic-array",
]
[[package]]
name = "blowfish"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32fa6a061124e37baba002e496d203e23ba3d7b73750be82dbfbc92913048a5b"
dependencies = [
"byteorder",
"cipher",
"opaque-debug",
]
[[package]]
name = "byteorder"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "bytes"
version = "1.5.0"
@ -140,6 +166,15 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "cipher"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12f8e7987cbd042a63249497f41aed09f8e65add917ea6566effbc56578d6801"
dependencies = [
"generic-array",
]
[[package]]
name = "cookie"
version = "0.17.0"
@ -151,6 +186,25 @@ dependencies = [
"version_check",
]
[[package]]
name = "cpufeatures"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fbc60abd742b35f2492f808e1abbb83d45f72db402e14c55057edc9c7b1e9e4"
dependencies = [
"libc",
]
[[package]]
name = "crypto-mac"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bff07008ec701e8028e2ceb8f83f0e4274ee62bd2dbdc4fefff2e9a91824081a"
dependencies = [
"generic-array",
"subtle",
]
[[package]]
name = "custom_error"
version = "1.9.2"
@ -166,6 +220,15 @@ dependencies = [
"powerfmt",
]
[[package]]
name = "digest"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066"
dependencies = [
"generic-array",
]
[[package]]
name = "fnv"
version = "1.0.7"
@ -227,6 +290,16 @@ dependencies = [
"slab",
]
[[package]]
name = "generic-array"
version = "0.14.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
dependencies = [
"typenum",
"version_check",
]
[[package]]
name = "getrandom"
version = "0.2.10"
@ -250,6 +323,16 @@ version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7"
[[package]]
name = "hmac"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1441c6b1e930e2817404b5046f1f989899143a12bf92de603b69f4e0aee1e15"
dependencies = [
"crypto-mac",
"digest",
]
[[package]]
name = "http"
version = "0.2.9"
@ -404,6 +487,17 @@ version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94"
[[package]]
name = "md-5"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b5a279bb9607f9f53c22d496eade00d138d1bdcccd07d74650387cf94942a15"
dependencies = [
"block-buffer",
"digest",
"opaque-debug",
]
[[package]]
name = "memchr"
version = "2.6.4"
@ -444,6 +538,7 @@ dependencies = [
"custom_error",
"ipnet",
"macaddr",
"pwhash",
"serde",
"serde_json",
"tokio",
@ -490,6 +585,12 @@ version = "1.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
[[package]]
name = "opaque-debug"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
[[package]]
name = "overload"
version = "0.1.1"
@ -563,6 +664,12 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
[[package]]
name = "ppv-lite86"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
[[package]]
name = "proc-macro-error"
version = "1.0.4"
@ -596,6 +703,21 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "pwhash"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "419a3ad8fa9f9d445e69d9b185a24878ae6e6f55c96e4512f4a0e28cd3bc5c56"
dependencies = [
"blowfish",
"byteorder",
"hmac",
"md-5",
"rand",
"sha-1",
"sha2",
]
[[package]]
name = "quote"
version = "1.0.33"
@ -605,6 +727,36 @@ dependencies = [
"proc-macro2",
]
[[package]]
name = "rand"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
"rand_chacha",
"rand_core",
]
[[package]]
name = "rand_chacha"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
"rand_core",
]
[[package]]
name = "rand_core"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
"getrandom",
]
[[package]]
name = "redox_syscall"
version = "0.4.1"
@ -720,6 +872,32 @@ dependencies = [
"serde",
]
[[package]]
name = "sha-1"
version = "0.9.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6"
dependencies = [
"block-buffer",
"cfg-if",
"cpufeatures",
"digest",
"opaque-debug",
]
[[package]]
name = "sha2"
version = "0.9.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800"
dependencies = [
"block-buffer",
"cfg-if",
"cpufeatures",
"digest",
"opaque-debug",
]
[[package]]
name = "sharded-slab"
version = "0.1.7"
@ -773,6 +951,12 @@ dependencies = [
"windows-sys",
]
[[package]]
name = "subtle"
version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
[[package]]
name = "syn"
version = "1.0.109"
@ -1012,6 +1196,12 @@ version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed"
[[package]]
name = "typenum"
version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
[[package]]
name = "unicode-bidi"
version = "0.3.13"

View file

@ -10,6 +10,7 @@ axum = "0.6.20"
custom_error = "1.9.2"
ipnet = { version = "2.8.0", features = ["serde"] }
macaddr = { version = "1.0.1", features = ["serde"] }
pwhash = "1.0.0"
serde = { version = "1.0.189", features = ["derive"] }
serde_json = "1.0.107"
tokio = { version = "1.33.0", features = ["full"] }

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;
}