feat(backend): implemented the backend for authentication
This commit is contained in:
parent
3399e4034b
commit
9fc30d8d0a
|
@ -1,18 +1,25 @@
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use libinjection::sqli;
|
use libinjection::sqli;
|
||||||
use log::{info, warn};
|
use log::{info, warn};
|
||||||
|
|
||||||
use crate::call::{Response, ResponseAuthenticate, ResponseDelete, ResponseRegister};
|
|
||||||
|
|
||||||
use pbkdf2::{
|
use pbkdf2::{
|
||||||
password_hash::{rand_core::OsRng, PasswordHash, PasswordHasher, PasswordVerifier, SaltString},
|
password_hash::{rand_core::OsRng, PasswordHash, PasswordHasher, PasswordVerifier, SaltString},
|
||||||
Pbkdf2,
|
Pbkdf2,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::call::{Response, ResponseAuthenticate, ResponseDelete, ResponseRegister};
|
||||||
|
|
||||||
pub struct Backend {
|
pub struct Backend {
|
||||||
db: sqlite::Connection,
|
db: sqlite::Connection,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Account {
|
||||||
|
id: i64,
|
||||||
|
username: String,
|
||||||
|
salt: String,
|
||||||
|
password: String,
|
||||||
|
}
|
||||||
|
|
||||||
fn is_sql_injection(string: &String) -> bool {
|
fn is_sql_injection(string: &String) -> bool {
|
||||||
match sqli(string) {
|
match sqli(string) {
|
||||||
Some((is_injection, _)) => is_injection,
|
Some((is_injection, _)) => is_injection,
|
||||||
|
@ -23,16 +30,33 @@ fn is_sql_injection(string: &String) -> bool {
|
||||||
impl Backend {
|
impl Backend {
|
||||||
fn user_exists(&mut self, username: &String) -> Result<bool> {
|
fn user_exists(&mut self, username: &String) -> Result<bool> {
|
||||||
let mut statement = self.db.prepare(format!(
|
let mut statement = self.db.prepare(format!(
|
||||||
"SELECT id from Accounts WHERE username='{}';",
|
"SELECT id FROM Accounts WHERE username='{}';",
|
||||||
username
|
username
|
||||||
))?;
|
))?;
|
||||||
|
|
||||||
for _ in statement.iter() {
|
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);
|
return Ok(true);
|
||||||
}
|
}
|
||||||
Ok(false)
|
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> {
|
pub fn register(&mut self, username: &String, password: &String) -> Result<Response> {
|
||||||
if is_sql_injection(username) {
|
if is_sql_injection(username) {
|
||||||
warn!(
|
warn!(
|
||||||
|
@ -70,12 +94,25 @@ impl Backend {
|
||||||
return Ok(Response::Authenticate(ResponseAuthenticate::Rejected));
|
return Ok(Response::Authenticate(ResponseAuthenticate::Rejected));
|
||||||
}
|
}
|
||||||
|
|
||||||
println!(
|
if !self.user_exists(username)? {
|
||||||
"<Dummy> Authentication Request: (Username: '{}' | Password: '{}')",
|
warn!("Authentication failed, user `{}` not found", username);
|
||||||
username, password
|
return Ok(Response::Authenticate(ResponseAuthenticate::UserNotFound));
|
||||||
);
|
}
|
||||||
println!(" -> Accepted");
|
|
||||||
Ok(Response::Authenticate(ResponseAuthenticate::Success))
|
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> {
|
pub fn delete(&mut self, username: &String) -> Result<Response> {
|
||||||
|
|
Loading…
Reference in New Issue