diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..8ee6cc2 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,25 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "libc" +version = "0.2.169" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" + +[[package]] +name = "pam-bindings" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95c337e922acb6ab9c3ddd1016fed13957a5bf14f51b6caa293ddc8dd47660ca" +dependencies = [ + "libc", +] + +[[package]] +name = "pam-honeypot" +version = "0.1.0" +dependencies = [ + "pam-bindings", +] diff --git a/Cargo.toml b/Cargo.toml index df91ec2..f303a78 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,4 +3,9 @@ name = "pam-honeypot" version = "0.1.0" edition = "2021" +[lib] +name = "pam_honeypot" +crate-type = ["cdylib"] + [dependencies] +pam-bindings = { version = "0.1.1" } diff --git a/conf/pam-honeypot b/conf/pam-honeypot new file mode 100644 index 0000000..e842046 --- /dev/null +++ b/conf/pam-honeypot @@ -0,0 +1 @@ +auth sufficient pam_honeypot.so user=Admin password=AdminPwdQ1 diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..6f073e4 --- /dev/null +++ b/flake.lock @@ -0,0 +1,58 @@ +{ + "nodes": { + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1735191716, + "narHash": "sha256-rwHLmGc/2OfudyjGnH8h5vQK2e5uJ6gt2GwPhWL9pPk=", + "path": "/nix/store/g421ks4gdcizmgacddxm2b7c6xabfhiv-source", + "rev": "1dd8f51e62c0ff199e551744ab46fc4fbe6f827a", + "type": "path" + }, + "original": { + "id": "nixpkgs", + "type": "indirect" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix index 3f3d50d..e8eeca3 100644 --- a/flake.nix +++ b/flake.nix @@ -2,34 +2,34 @@ description = "a653rs-router"; inputs = { - fenix = { - url = "github:nix-community/fenix"; - inputs.nixpkgs.follows = "nixpkgs"; - }; - flake-utils.url = "github:numtide/flake-utils"; + flake-utils.url = "github:numtide/flake-utils"; }; - outputs = { fenix, flake-utils, nixpkgs, ... }: flake-utils.lib.eachSystem [ "x86_64-linux" ] (system: - let - pkgs = import nixpkgs { inherit system; }; - rustToolchain = with fenix.packages.${system}; combine [ - latest.rustc - latest.cargo - latest.clippy - latest.rustfmt - latest.rust-src - latest.rust-analyzer - targets.aarch64-unknown-uefi.latest.rust-std - targets.i686-unknown-uefi.latest.rust-std - targets.x86_64-unknown-uefi.latest.rust-std - ]; - in + outputs = { - devShells.default = pkgs.mkShell { - packages = [ - rustToolchain - ]; - }; - } - ); + flake-utils, + nixpkgs, + ... + }: + flake-utils.lib.eachSystem [ "x86_64-linux" ] ( + system: + let + pkgs = import nixpkgs { inherit system; }; + in + { + devShells.default = pkgs.mkShell { + nativeBuildInputs = [ + pkgs.cargo + pkgs.clang + pkgs.clippy + pkgs.pam + pkgs.pkg-config + pkgs.rustc + pkgs.rustfmt + pkgs.rust-analyzer + pkgs.rustPlatform.bindgenHook + ]; + }; + } + ); } diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..dc03e9e --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,70 @@ +use std::{collections::HashMap, env::temp_dir, ffi::CStr, fs::File}; + +use pam::{ + constants::{PamResultCode, PAM_PROMPT_ECHO_ON}, + conv::Conv, + module::PamHooks, + pam_try, +}; + +struct PamHoneypot; + +impl PamHooks for PamHoneypot { + fn sm_authenticate( + pamh: &mut pam::module::PamHandle, + args: Vec<&CStr>, + _flags: pam::constants::PamFlag, + ) -> pam::constants::PamResultCode { + let args: Vec<_> = args.iter().map(|s| s.to_string_lossy()).collect(); + let args: HashMap<&str, &str> = args + .iter() + .map(|s| { + let mut parts = s.splitn(2, '='); + (parts.next().unwrap(), parts.next().unwrap_or("")) + }) + .collect(); + + let honey_user = match args.get("user") { + Some(user) => user, + _ => return PamResultCode::PAM_IGNORE, + }; + let honey_password = match args.get("password") { + Some(password) => password, + _ => return PamResultCode::PAM_IGNORE, + }; + + let user = pam_try!(pamh.get_user(None)); + if user != *honey_user { + return PamResultCode::PAM_IGNORE; + } + + let conv = match pamh.get_item::() { + Ok(Some(conv)) => conv, + Ok(_) => { + unreachable!("No conv available"); + } + Err(err) => { + return err; + } + }; + let password = pam_try!(conv.send(PAM_PROMPT_ECHO_ON, "Password")); + let password = match password { + Some(password) => Some(pam_try!(password.to_str(), PamResultCode::PAM_AUTH_ERR)), + _ => None, + }; + + if let Some(password) = password { + if *honey_password == password { + let mut tmp = temp_dir(); + tmp.push("honeypot"); + let _ = File::create(tmp); + + return PamResultCode::PAM_AUTH_ERR; + } + } + + PamResultCode::PAM_IGNORE + } +} + +pam::pam_hooks!(PamHoneypot); diff --git a/src/main.rs b/src/main.rs deleted file mode 100644 index e7a11a9..0000000 --- a/src/main.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - println!("Hello, world!"); -}