74 lines
2.2 KiB
Rust
74 lines
2.2 KiB
Rust
use crate::repository::PasswordDirectory;
|
|
use common::request::Request;
|
|
use log::{error, info};
|
|
use std::io::{Error, Read, Write};
|
|
|
|
pub const RESPONSE_NO: [u8; 4] = [0x0, 0x2, b'N', b'O'];
|
|
pub const RESPONSE_OK: [u8; 4] = [0x0, 0x2, b'O', b'K'];
|
|
|
|
pub struct Handler<S: Read + Write> {
|
|
stream: S,
|
|
repository: PasswordDirectory,
|
|
}
|
|
|
|
impl<S: Read + Write> Handler<S> {
|
|
pub fn new(stream: S, repository: PasswordDirectory) -> Handler<S> {
|
|
Handler { stream, repository }
|
|
}
|
|
|
|
fn communicate(&mut self) -> Result<(), Error> {
|
|
let request = Request::from_stream(&mut self.stream)?;
|
|
|
|
if self.repository.check_auth(&request) {
|
|
self.stream.write_all(&RESPONSE_OK)?;
|
|
info!("userid: {}, service: {}, realm: {} - OK", request.userid, request.service, request.realm);
|
|
} else {
|
|
self.stream.write_all(&RESPONSE_NO)?;
|
|
info!("userid: {}, service: {}, realm: {} - FAIL", request.userid, request.service, request.realm);
|
|
}
|
|
|
|
|
|
Ok(())
|
|
}
|
|
|
|
pub fn handle_client(&mut self) {
|
|
if let Err(error) = self.communicate() {
|
|
error!("{error}");
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use crate::handler::{Handler, RESPONSE_OK};
|
|
use crate::repository::PasswordDirectory;
|
|
use common::request::Request;
|
|
use std::io::Cursor;
|
|
|
|
const TEST_PATH: &str = "../test_passwords";
|
|
|
|
#[test]
|
|
fn it_handles_a_request() {
|
|
let repository = PasswordDirectory::new(TEST_PATH);
|
|
|
|
let request = Request::new("bp", "some-rad-password", "ignore-this", "also-ignore-this");
|
|
|
|
let mut cursor = Cursor::new(Vec::new());
|
|
|
|
request.write_to_stream(&mut cursor).unwrap();
|
|
|
|
// Figure out where the response should end up
|
|
let response_position: usize = cursor.position().try_into().unwrap();
|
|
|
|
// Rewind and have the handler deal with the request
|
|
cursor.set_position(0);
|
|
Handler::new(&mut cursor, repository).handle_client();
|
|
|
|
// Extract the response, which should come after the
|
|
// request in the cursor buffer
|
|
let response = cursor.into_inner().split_off(response_position);
|
|
|
|
assert_eq!(response, RESPONSE_OK);
|
|
}
|
|
}
|