| 1 | //! Test client for gardmd authentication |
| 2 | //! |
| 3 | //! Usage: test-auth |
| 4 | //! Prompts for username and password, then tests authentication against gardmd. |
| 5 | |
| 6 | use anyhow::Result; |
| 7 | use gardm_ipc::{Request, Response, SOCKET_PATH}; |
| 8 | use std::io::{self, BufRead, BufReader, Write}; |
| 9 | use std::os::unix::net::UnixStream; |
| 10 | |
| 11 | fn main() -> Result<()> { |
| 12 | // Connect to daemon |
| 13 | let stream = UnixStream::connect(SOCKET_PATH)?; |
| 14 | let mut reader = BufReader::new(stream.try_clone()?); |
| 15 | let mut stream = stream; |
| 16 | |
| 17 | println!("Connected to gardmd at {}", SOCKET_PATH); |
| 18 | |
| 19 | // Get username |
| 20 | print!("Username: "); |
| 21 | io::stdout().flush()?; |
| 22 | let mut username = String::new(); |
| 23 | io::stdin().lock().read_line(&mut username)?; |
| 24 | let username = username.trim().to_string(); |
| 25 | |
| 26 | // Send CreateSession |
| 27 | let request = Request::CreateSession { username }; |
| 28 | send_request(&mut stream, &request)?; |
| 29 | |
| 30 | // Read response |
| 31 | let response = read_response(&mut reader)?; |
| 32 | println!("Response: {:?}", response); |
| 33 | |
| 34 | match response { |
| 35 | Response::AuthPrompt { prompt, echo } => { |
| 36 | // Get password |
| 37 | if echo { |
| 38 | print!("{} ", prompt); |
| 39 | io::stdout().flush()?; |
| 40 | let mut password = String::new(); |
| 41 | io::stdin().lock().read_line(&mut password)?; |
| 42 | send_auth(&mut stream, &mut reader, password.trim())?; |
| 43 | } else { |
| 44 | print!("{} ", prompt); |
| 45 | io::stdout().flush()?; |
| 46 | let password = rpassword::read_password()?; |
| 47 | send_auth(&mut stream, &mut reader, &password)?; |
| 48 | } |
| 49 | } |
| 50 | Response::Error { message } => { |
| 51 | eprintln!("Error: {}", message); |
| 52 | return Ok(()); |
| 53 | } |
| 54 | _ => { |
| 55 | eprintln!("Unexpected response: {:?}", response); |
| 56 | return Ok(()); |
| 57 | } |
| 58 | } |
| 59 | |
| 60 | Ok(()) |
| 61 | } |
| 62 | |
| 63 | fn send_request(stream: &mut UnixStream, request: &Request) -> Result<()> { |
| 64 | let json = serde_json::to_string(request)?; |
| 65 | writeln!(stream, "{}", json)?; |
| 66 | stream.flush()?; |
| 67 | Ok(()) |
| 68 | } |
| 69 | |
| 70 | fn read_response(reader: &mut BufReader<UnixStream>) -> Result<Response> { |
| 71 | let mut line = String::new(); |
| 72 | reader.read_line(&mut line)?; |
| 73 | let response: Response = serde_json::from_str(&line)?; |
| 74 | Ok(response) |
| 75 | } |
| 76 | |
| 77 | fn send_auth( |
| 78 | stream: &mut UnixStream, |
| 79 | reader: &mut BufReader<UnixStream>, |
| 80 | password: &str, |
| 81 | ) -> Result<()> { |
| 82 | let request = Request::Authenticate { |
| 83 | response: password.to_string(), |
| 84 | }; |
| 85 | send_request(stream, &request)?; |
| 86 | |
| 87 | let response = read_response(reader)?; |
| 88 | match response { |
| 89 | Response::Success => { |
| 90 | println!("Authentication successful!"); |
| 91 | } |
| 92 | Response::AuthError { message } => { |
| 93 | println!("Authentication failed: {}", message); |
| 94 | } |
| 95 | Response::Error { message } => { |
| 96 | println!("Error: {}", message); |
| 97 | } |
| 98 | _ => { |
| 99 | println!("Unexpected response: {:?}", response); |
| 100 | } |
| 101 | } |
| 102 | |
| 103 | Ok(()) |
| 104 | } |
| 105 |