From c9dfb848ed27480c62d7444af47c0dd17926d146 Mon Sep 17 00:00:00 2001 From: BanceDev Date: Mon, 23 Feb 2026 14:51:45 -0500 Subject: initial commit --- src/main.rs | 152 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 152 insertions(+) create mode 100644 src/main.rs (limited to 'src/main.rs') diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..bde0457 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,152 @@ +use pam::Client; +use xcb::Xid; +use xcb::x; +use xkbcommon::xkb; + +fn get_username() -> String { + std::env::var("USER") + .or_else(|_| std::env::var("LOGNAME")) + .unwrap_or_else(|_| "root".to_string()) +} + +fn authenticate(username: &str, password: &str) -> bool { + let mut client = match Client::with_password("login") { + Ok(c) => c, + Err(_) => return false, + }; + client + .conversation_mut() + .set_credentials(username, password); + client.authenticate().is_ok() && client.open_session().is_ok() +} + +fn main() -> xcb::Result<()> { + let username = get_username(); + let mut password_buf = String::new(); + + // make keymap + let context = xkb::Context::new(xkb::CONTEXT_NO_FLAGS); + let keymap = xkb::Keymap::new_from_names( + &context, + "", // rules + "", // model + "", // layout + "", // variant + None, // options + xkb::KEYMAP_COMPILE_NO_FLAGS, + ) + .expect("Failed to create keymap"); + let mut state = xkb::State::new(&keymap); + + let (conn, screen_num) = xcb::Connection::connect(None)?; + + let setup = conn.get_setup(); + let screen = setup.roots().nth(screen_num as usize).unwrap(); + + let window: x::Window = conn.generate_id(); + + let cookie = conn.send_request_checked(&x::CreateWindow { + depth: x::COPY_FROM_PARENT as u8, + wid: window, + parent: screen.root(), + x: 0, + y: 0, + width: screen.width_in_pixels(), + height: screen.height_in_pixels(), + border_width: 0, + class: x::WindowClass::InputOutput, + visual: screen.root_visual(), + value_list: &[ + x::Cw::BackPixel(screen.black_pixel()), + x::Cw::OverrideRedirect(true), + x::Cw::EventMask( + x::EventMask::EXPOSURE + | x::EventMask::KEY_PRESS + | x::EventMask::BUTTON_PRESS + | x::EventMask::POINTER_MOTION, + ), + ], + }); + conn.check_request(cookie)?; + + conn.send_request(&x::MapWindow { window }); + conn.flush()?; + + let grab_keyboard = conn.send_request(&x::GrabKeyboard { + owner_events: false, + grab_window: window, + time: x::CURRENT_TIME, + pointer_mode: x::GrabMode::Async, + keyboard_mode: x::GrabMode::Async, + }); + + let reply = conn.wait_for_reply(grab_keyboard)?; + if reply.status() != x::GrabStatus::Success { + eprintln!("Failed to grab keyboard"); + return Ok(()); + } + + let grab_pointer = conn.send_request(&x::GrabPointer { + owner_events: false, + grab_window: window, + event_mask: x::EventMask::BUTTON_PRESS | x::EventMask::POINTER_MOTION, + pointer_mode: x::GrabMode::Async, + keyboard_mode: x::GrabMode::Async, + confine_to: x::Window::none(), + cursor: x::Cursor::none(), + time: x::CURRENT_TIME, + }); + + let reply = conn.wait_for_reply(grab_pointer)?; + if reply.status() != x::GrabStatus::Success { + eprintln!("Failed to grab pointer"); + return Ok(()); + } + + // We enter the main event loop + loop { + match conn.wait_for_event()? { + xcb::Event::X(x::Event::KeyPress(ev)) => { + let keycode = ev.detail(); + state.update_key(keycode.into(), xkb::KeyDirection::Down); + + let keysym = state.key_get_one_sym(keycode.into()); + let c = xkb::keysym_to_utf8(keysym); + match keycode { + 36 => { + if authenticate(&username, &password_buf) { + conn.send_request(&x::UngrabKeyboard { + time: x::CURRENT_TIME, + }); + conn.send_request(&x::UngrabPointer { + time: x::CURRENT_TIME, + }); + conn.flush()?; + break Ok(()); + } else { + eprintln!("Authentication failed"); + password_buf.clear(); + } + } + // Backspace (22) + 22 => { + password_buf.pop(); + } + // Escape (9) — clear buffer + 9 => { + password_buf.clear(); + } + + _ => { + password_buf.push_str(&c); + } + } + } + xcb::Event::X(x::Event::KeyRelease(ev)) => { + let keycode = ev.detail(); + state.update_key(keycode.into(), xkb::KeyDirection::Up); + } + _ => {} + } + } +} -- cgit v1.2.3-59-g8ed1b