feat(backend): implemented the backend for authentication
This commit is contained in:
parent
3399e4034b
commit
9fc30d8d0a
|
@ -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<bool> {
|
||||
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<Account> {
|
||||
let mut statement = self.db.prepare(format!(
|
||||
"SELECT * FROM Accounts WHERE username='{}';",
|
||||
username
|
||||
))?;
|
||||
statement.next()?;
|
||||
|
||||
Ok(Account {
|
||||
id: statement.read::<i64, _>("id").unwrap(),
|
||||
username: statement.read::<String, _>("username").unwrap(),
|
||||
salt: statement.read::<String, _>("salt").unwrap(),
|
||||
password: statement.read::<String, _>("password").unwrap(),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn register(&mut self, username: &String, password: &String) -> Result<Response> {
|
||||
if is_sql_injection(username) {
|
||||
warn!(
|
||||
|
@ -70,13 +94,26 @@ impl Backend {
|
|||
return Ok(Response::Authenticate(ResponseAuthenticate::Rejected));
|
||||
}
|
||||
|
||||
println!(
|
||||
"<Dummy> Authentication Request: (Username: '{}' | Password: '{}')",
|
||||
username, password
|
||||
);
|
||||
println!(" -> Accepted");
|
||||
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<Response> {
|
||||
if is_sql_injection(username) {
|
||||
|
|
Loading…
Reference in New Issue