diff --git a/Cargo.lock b/Cargo.lock index 38b5c82..b241c0e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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" diff --git a/Cargo.toml b/Cargo.toml index 6c776aa..d27ab4d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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"] } diff --git a/src/config_manager.rs b/src/config_manager.rs index cee98ee..79c2db2 100644 --- a/src/config_manager.rs +++ b/src/config_manager.rs @@ -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 { 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) diff --git a/src/definitions/system.rs b/src/definitions/system.rs index f0e4384..48f01ff 100644 --- a/src/definitions/system.rs +++ b/src/definitions/system.rs @@ -11,5 +11,4 @@ pub struct System { pub struct User { pub comment: String, pub hash: String, - pub salt: String, } diff --git a/src/main.rs b/src/main.rs index 893b3e6..cf69770 100644 --- a/src/main.rs +++ b/src/main.rs @@ -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; } diff --git a/src/web/auth.rs b/src/web/auth.rs index 15d521a..526c1a2 100644 --- a/src/web/auth.rs +++ b/src/web/auth.rs @@ -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) -> 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; }