diff --git a/src/backend.rs b/src/backend.rs index 5004610..8514428 100644 --- a/src/backend.rs +++ b/src/backend.rs @@ -1,18 +1,25 @@ use anyhow::Result; use libinjection::sqli; use log::{info, warn}; - -use crate::call::{Response, ResponseAuthenticate, ResponseDelete, ResponseRegister}; - use pbkdf2::{ password_hash::{rand_core::OsRng, PasswordHash, PasswordHasher, PasswordVerifier, SaltString}, Pbkdf2, }; +use crate::call::{Response, ResponseAuthenticate, ResponseDelete, ResponseRegister}; + pub struct Backend { db: sqlite::Connection, } +#[derive(Debug)] +pub struct Account { + id: i64, + username: String, + salt: String, + password: String, +} + fn is_sql_injection(string: &String) -> bool { match sqli(string) { Some((is_injection, _)) => is_injection, @@ -23,16 +30,33 @@ fn is_sql_injection(string: &String) -> bool { impl Backend { fn user_exists(&mut self, username: &String) -> Result { let mut statement = self.db.prepare(format!( - "SELECT id from Accounts WHERE username='{}';", + "SELECT id FROM Accounts WHERE username='{}';", username ))?; for _ in statement.iter() { + // yes, a for loop is useless, but don't wanna look + // too deep into the docs, and it works ^^ return Ok(true); } Ok(false) } + fn get_user(&mut self, username: &String) -> Result { + let mut statement = self.db.prepare(format!( + "SELECT * FROM Accounts WHERE username='{}';", + username + ))?; + statement.next()?; + + Ok(Account { + id: statement.read::("id").unwrap(), + username: statement.read::("username").unwrap(), + salt: statement.read::("salt").unwrap(), + password: statement.read::("password").unwrap(), + }) + } + pub fn register(&mut self, username: &String, password: &String) -> Result { if is_sql_injection(username) { warn!( @@ -70,12 +94,25 @@ impl Backend { return Ok(Response::Authenticate(ResponseAuthenticate::Rejected)); } - println!( - " Authentication Request: (Username: '{}' | Password: '{}')", - username, password - ); - println!(" -> Accepted"); - Ok(Response::Authenticate(ResponseAuthenticate::Success)) + if !self.user_exists(username)? { + warn!("Authentication failed, user `{}` not found", username); + return Ok(Response::Authenticate(ResponseAuthenticate::UserNotFound)); + } + + let account = self.get_user(username)?; + let hash = PasswordHash::new(&account.password) + .map_err(|_| anyhow::Error::msg("Failed to parse the password hash"))?; + + match Pbkdf2.verify_password(password.as_bytes(), &hash) { + Ok(_) => { + info!("Successfully authenticated `{}`", username); + Ok(Response::Authenticate(ResponseAuthenticate::Success)) + } + Err(_) => { + info!("Failed to authenticate `{}` (wrong password)", username); + Ok(Response::Authenticate(ResponseAuthenticate::WrongPassword)) + } + } } pub fn delete(&mut self, username: &String) -> Result {