#password #user-name #security #validate #macos #account #pam

pwcheck

Provides a function to validate a username & password on Linux, MacOS, and Windows

3 unstable releases

0.2.1 May 18, 2023
0.2.0 May 18, 2023
0.1.0 May 18, 2023

#400 in Authentication

MIT/Apache

29KB
302 lines

pwcheck

Crates.io Docs.rs CI RustC 1.64+

Provides a singular function to check and validate the password of a local user account on Linux, MacOS, and Windows.

Currently does not work on Linux using musl due to https://github.com/1wilkens/pam/issues/25. Will result in SIGSEGV!

Install

[dependencies]
pwcheck = "0.2"

Dependencies

  • On Linux, this leverages PAM bindings and therefore requires PAM developer headersto be available.
    • Debian/Ubuntu: apt install libpam0g-dev
    • Fedora/CentOS: dnf install pam-devel (you may also need dnf install clang if you get stddef.h not found)
  • On MacOS, this leverages dscl, and does not need anything additional.
  • On Windows, this leverages windows-rs and does not need anything additional.

Usage

use pwcheck::*;

fn main() {
    // Check if some username/password combo is valid
    match pwcheck("username", "password") {
        PwcheckResult::Ok => println!("Correct username & password!"),
        PwcheckResult::WrongPassword => println!("Incorrect username & password!"),
        PwcheckResult::Err(x) => println!("Encountered error: {x}"),
    }
}

How It Works

Linux

On Linux platforms, this leverages PAM with the login service to perform authentication in a non-interactive fashion via a username and password.

You can specify a different service with the Linux module's implementation:

use pwcheck::PwcheckResult;

fn main() {
    #[cfg(target_os = "linux")]
    {
        use pwcheck::linux::{Method, pwcheck};
        match pwcheck(Method::Pam {
            username: "username",
            password: "password",
            service: "my-service",
        }) {
            PwcheckResult::Ok => println!("Correct username & password!"),
            PwcheckResult::WrongPassword => println!("Incorrect username & password!"),
            PwcheckResult::Err(x) => println!("Encountered error: {x}"),
        }
    }
}

Note that PAM authentication will only work for a username and password if either:

a. The username matches the one performing the authentication b. The user doing authentication has elevated permissions

In other words, an ordinary user cannot authenticate the username and password of a different user. This will instead return an error about a wrong password.

MacOS

On MacOS platforms, this leverages executing dscl to authenticate the user using the datasource "." (local directory).

You can specify a different datasource with the MacOS module's implementation:

use pwcheck::PwcheckResult;

fn main() {
    #[cfg(target_os = "macos")]
    {
        use pwcheck::macos::{Method, pwcheck};
        match pwcheck::macos::pwcheck(Method::Dscl {
            username: "username", 
            password: "password", 
            datasource: "/Login/Default", 
            timeout: None,
        }) {
            PwcheckResult::Ok => println!("Correct username & password!"),
            PwcheckResult::WrongPassword => println!("Incorrect username & password!"),
            PwcheckResult::Err(x) => println!("Encountered error: {x}"),
        }
    }
}

Windows

On Windows platforms, this leverages the LogonUserW function to attempt to log a user on to the local computer.

You can execute the Windows module implementation directly like below:

use pwcheck::PwcheckResult;

fn main() {
    #[cfg(windows)]
    {
        use pwcheck::windows::{Method, pwcheck};
        match pwcheck::windows::pwcheck(Method::LogonUserW {
            username: "username", 
            password: "password", 
        }) {
            PwcheckResult::Ok => println!("Correct username & password!"),
            PwcheckResult::WrongPassword => println!("Incorrect username & password!"),
            PwcheckResult::Err(x) => println!("Encountered error: {x}"),
        }
    }
}

Note that this function requires the running program to have the SeTcbPrivilege privilege set in order to log in as a user other than the user that started the program. So it's safe to use this to validate the account of the user running this program, but otherwise it needs a very high-level permission to validate the password, typically something you'd see from running the program as an administrator.

License

This project is licensed under either of

Apache License, Version 2.0, (LICENSE-APACHE or apache-license) MIT license (LICENSE-MIT or mit-license) at your option.

Dependencies

~0–38MB
~534K SLoC