Fix error handling and add nixos test
This commit is contained in:
parent
c06b3a7142
commit
ef60878471
6 changed files with 335 additions and 20 deletions
244
Cargo.lock
generated
244
Cargo.lock
generated
|
@ -2,12 +2,65 @@
|
|||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "deranged"
|
||||
version = "0.3.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"
|
||||
dependencies = [
|
||||
"powerfmt",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hostname"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f9c7c7c8ac16c798734b8a24560c1362120597c40d5e1459f09498f8f6c8f2ba"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.169"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
|
||||
|
||||
[[package]]
|
||||
name = "num-conv"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
|
||||
|
||||
[[package]]
|
||||
name = "num_threads"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pam-bindings"
|
||||
version = "0.1.1"
|
||||
|
@ -21,5 +74,196 @@ dependencies = [
|
|||
name = "pam-honeypot"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"log",
|
||||
"pam-bindings",
|
||||
"syslog",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "powerfmt"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.92"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.38"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.217"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.217"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.93"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c786062daee0d6db1132800e623df74274a0a87322d8e183338e01b3d98d058"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syslog"
|
||||
version = "7.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "019f1500a13379b7d051455df397c75770de6311a7a188a699499502704d9f10"
|
||||
dependencies = [
|
||||
"hostname",
|
||||
"libc",
|
||||
"log",
|
||||
"time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.3.37"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21"
|
||||
dependencies = [
|
||||
"deranged",
|
||||
"itoa",
|
||||
"libc",
|
||||
"num-conv",
|
||||
"num_threads",
|
||||
"powerfmt",
|
||||
"serde",
|
||||
"time-core",
|
||||
"time-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time-core"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
|
||||
|
||||
[[package]]
|
||||
name = "time-macros"
|
||||
version = "0.2.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de"
|
||||
dependencies = [
|
||||
"num-conv",
|
||||
"time-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
|
||||
|
||||
[[package]]
|
||||
name = "windows"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be"
|
||||
dependencies = [
|
||||
"windows-core",
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_gnullvm",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||
|
|
|
@ -9,3 +9,5 @@ crate-type = ["cdylib"]
|
|||
|
||||
[dependencies]
|
||||
pam-bindings = { version = "0.1.1" }
|
||||
log = "0"
|
||||
syslog = "7.0.0"
|
||||
|
|
25
flake.nix
25
flake.nix
|
@ -2,7 +2,7 @@
|
|||
description = "a653rs-router";
|
||||
|
||||
inputs = {
|
||||
flake-utils.url = "github:numtide/flake-utils";
|
||||
flake-utils.url = "github:numtide/flake-utils";
|
||||
};
|
||||
|
||||
outputs =
|
||||
|
@ -16,9 +16,9 @@
|
|||
let
|
||||
pkgs = import nixpkgs { inherit system; };
|
||||
in
|
||||
{
|
||||
rec {
|
||||
devShells.default = pkgs.mkShell {
|
||||
nativeBuildInputs = [
|
||||
nativeBuildInputs = [
|
||||
pkgs.cargo
|
||||
pkgs.clang
|
||||
pkgs.clippy
|
||||
|
@ -31,10 +31,25 @@
|
|||
];
|
||||
};
|
||||
packages = {
|
||||
default = pkgs.callPackage ./default.nix {};
|
||||
default = pkgs.callPackage ./default.nix { };
|
||||
};
|
||||
checks = {
|
||||
vm = nixpkgs.lib.nixos.runTest (
|
||||
import ./test.nix {
|
||||
pkgs = import nixpkgs {
|
||||
inherit system;
|
||||
overlays = [
|
||||
(final: prev: {
|
||||
pam_honeypot = packages.default;
|
||||
})
|
||||
];
|
||||
};
|
||||
}
|
||||
);
|
||||
};
|
||||
}
|
||||
) // {
|
||||
)
|
||||
// {
|
||||
nixosModules = {
|
||||
default = ./module.nix;
|
||||
};
|
||||
|
|
15
module.nix
15
module.nix
|
@ -1,6 +1,13 @@
|
|||
{ pkgs, ... }:
|
||||
{ config, pkgs, ... }:
|
||||
{
|
||||
environment.etc."pam.d/pam_honeypot".text = ''
|
||||
auth optional ${pkgs.pam_honeypot}/lib/pam_honeypot.so user=Admin password=AdminPwdQ1
|
||||
'';
|
||||
security.pam.services.login.rules.auth.pam_honeypot = {
|
||||
enable = true;
|
||||
order = config.security.pam.services.login.rules.auth.unix.order - 10;
|
||||
control = "requisite";
|
||||
modulePath = "${pkgs.pam_honeypot}/lib/libpam_honeypot.so";
|
||||
args = [
|
||||
"user=Admin"
|
||||
"password=AdminPwdQ1"
|
||||
];
|
||||
};
|
||||
}
|
||||
|
|
40
src/lib.rs
40
src/lib.rs
|
@ -1,11 +1,14 @@
|
|||
use std::{collections::HashMap, env::temp_dir, ffi::CStr, fs::File};
|
||||
use std::{collections::HashMap, ffi::CStr};
|
||||
|
||||
use log::{debug, info, trace, warn};
|
||||
use pam::{
|
||||
constants::{PamResultCode, PAM_PROMPT_ECHO_ON},
|
||||
constants::{PamResultCode, PAM_PROMPT_ECHO_OFF},
|
||||
conv::Conv,
|
||||
items::User,
|
||||
module::PamHooks,
|
||||
pam_try,
|
||||
};
|
||||
use syslog::Facility;
|
||||
|
||||
struct PamHoneypot;
|
||||
|
||||
|
@ -15,12 +18,23 @@ impl PamHooks for PamHoneypot {
|
|||
args: Vec<&CStr>,
|
||||
_flags: pam::constants::PamFlag,
|
||||
) -> pam::constants::PamResultCode {
|
||||
let _ = syslog::init(
|
||||
Facility::LOG_USER,
|
||||
log::LevelFilter::Info,
|
||||
Some("pam_honeypot"),
|
||||
);
|
||||
|
||||
trace!("Running pam_honeypot");
|
||||
let args: Vec<_> = args.iter().map(|s| s.to_string_lossy()).collect();
|
||||
debug!("args = {args:?}");
|
||||
let args: HashMap<&str, &str> = args
|
||||
.iter()
|
||||
.map(|s| {
|
||||
let mut parts = s.splitn(2, '=');
|
||||
(parts.next().unwrap(), parts.next().unwrap_or(""))
|
||||
(
|
||||
parts.next().expect("Failed to parse arguments"),
|
||||
parts.next().unwrap_or(""),
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
|
||||
|
@ -28,13 +42,16 @@ impl PamHooks for PamHoneypot {
|
|||
Some(user) => user,
|
||||
_ => return PamResultCode::PAM_IGNORE,
|
||||
};
|
||||
debug!("honeypot user = {honey_user}");
|
||||
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 {
|
||||
trace!("Getting user from PAM");
|
||||
let user: User = pam_try!(pamh.get_item()).unwrap_or(User(c""));
|
||||
info!("Checking if entered username is honeypot user");
|
||||
if user.to_string_lossy() != *honey_user {
|
||||
return PamResultCode::PAM_IGNORE;
|
||||
}
|
||||
|
||||
|
@ -47,20 +64,21 @@ impl PamHooks for PamHoneypot {
|
|||
return err;
|
||||
}
|
||||
};
|
||||
let password = pam_try!(conv.send(PAM_PROMPT_ECHO_ON, "Password"));
|
||||
trace!("Getting password from PAM");
|
||||
let password = pam_try!(conv.send(PAM_PROMPT_ECHO_OFF, "Password: "));
|
||||
let password = match password {
|
||||
Some(password) => Some(pam_try!(password.to_str(), PamResultCode::PAM_AUTH_ERR)),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
if let Some(password) = password {
|
||||
trace!("Checking if password is honeypot password");
|
||||
if *honey_password == password {
|
||||
let mut tmp = temp_dir();
|
||||
tmp.push("honeypot");
|
||||
let _ = File::create(tmp);
|
||||
|
||||
return PamResultCode::PAM_AUTH_ERR;
|
||||
warn!("Someone tried to log in with the honeypot credentials");
|
||||
} else {
|
||||
info!("Entered username is not the honeypot user")
|
||||
}
|
||||
return PamResultCode::PAM_AUTH_ERR;
|
||||
}
|
||||
|
||||
PamResultCode::PAM_IGNORE
|
||||
|
|
29
test.nix
Normal file
29
test.nix
Normal file
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
{
|
||||
name = "pam_honeypot-test";
|
||||
hostPkgs = pkgs;
|
||||
node.pkgs = pkgs;
|
||||
nodes.machine =
|
||||
{ ... }:
|
||||
{
|
||||
imports = [ ./module.nix ];
|
||||
};
|
||||
testScript = ''
|
||||
machine.wait_for_unit("multi-user.target")
|
||||
machine.send_key("alt-f2")
|
||||
machine.wait_until_succeeds("[ $(fgconsole) = 2 ]")
|
||||
machine.wait_for_unit("getty@tty2.service")
|
||||
machine.wait_until_succeeds("pgrep -f 'agetty.*tty2'")
|
||||
machine.wait_until_tty_matches("2", "login: ")
|
||||
machine.send_chars("Admin\n")
|
||||
machine.wait_until_tty_matches("2", "login: Admin")
|
||||
machine.wait_until_succeeds("pgrep login")
|
||||
machine.wait_until_tty_matches("2", "Password: ")
|
||||
machine.send_chars("AdminPwdQ1\n")
|
||||
machine.wait_until_tty_matches("2", "login: ")
|
||||
machine.succeed("journalctl | grep 'log in with the honeypot credentials'")
|
||||
'';
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue