Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add password auth as alternative to static-key #155

Open
chipsenkbeil opened this issue Nov 30, 2022 · 6 comments
Open

Add password auth as alternative to static-key #155

chipsenkbeil opened this issue Nov 30, 2022 · 6 comments
Labels
enhancement New feature or request
Milestone

Comments

@chipsenkbeil
Copy link
Owner

chipsenkbeil commented Nov 30, 2022

@chipsenkbeil chipsenkbeil added the enhancement New feature or request label Nov 30, 2022
@chipsenkbeil chipsenkbeil added this to the 0.20 milestone Nov 30, 2022
@chipsenkbeil
Copy link
Owner Author

NOTE: The pam-client and other crate that use the pam sys crate do NOT support OpenPAM. We'd have to write our own bindings!

@chipsenkbeil
Copy link
Owner Author

For windows, could use powershell to do this as well: https://serverfault.com/questions/596602/powershell-test-user-credentials-in-ad-with-password-reset

@chipsenkbeil
Copy link
Owner Author

For windows using the LogonUserW function:

use std::ptr;
use windows::{ErrorCode, Result};
use windows::win32::security::LogonUserW;
use windows::win32::windows_programming::CloseHandle;

fn authenticate_user(username: &str, password: &str) -> Result<bool> {
    let mut token_handle = ptr::null_mut();

    // NOTE: If we provide NULL to the domain, the username is expected to be in UPN
   //              format, which looks like User@DNSDomainName
   //
   //              We can instead provide a domain of "." for a local account
    let success = unsafe {
        LogonUserW(
            windows::wstring::from_str(username)?.as_ptr(),
            ptr::null_mut(),
            windows::wstring::from_str(password)?.as_ptr(),
            LogonUserW::LOGON32_LOGON_NETWORK,
            LogonUserW::LOGON32_PROVIDER_DEFAULT,
            &mut token_handle,
        ).is_ok()
    };
    let result = success.map_err(|error| error.code())?;
    if success {
        // authentication succeeded, do something with the token handle
        // (e.g. use it to impersonate the authenticated user)
        unsafe { CloseHandle(token_handle) };
    }
    Ok(result)
}

@chipsenkbeil
Copy link
Owner Author

For MacOS, we can use the security-framework crate:

use security_framework::{
    auth::*, base::SecKeychainItem, import::SecImportOptions, item::SecItem,
};
use std::os::raw::c_void;

fn authenticate(username: &str, password: &str) -> Result<(), String> {
    let auth_context = AuthContext::new()?;
    let auth_context = auth_context.set_option(AuthOption::UserName(username))?;
    let auth_context = auth_context.set_option(AuthOption::Password(password))?;
    let result = auth_context.evaluate()?;

    if result == AuthResult::Success {
        Ok(())
    } else {
        Err(format!("Authentication failed with result: {:?}", result))
    }
}

@chipsenkbeil
Copy link
Owner Author

chipsenkbeil commented Apr 9, 2023

The security-framework example isn't real (chatGPT failed me). I did figure out a way to do this from the commandline that works for a non-root user is dscl . -authonly {username} {password}. Providing this on the commandline is bad because it'll have the password visible and in the history! You can provide it without the password, but it doesn't appear that I can feed in the password over stdin?

Note that dscl /Login/Default -authonly {username} {password} also works and appears to be what . defaults to on my machine.

@chipsenkbeil
Copy link
Owner Author

I've now written https://crates.io/crates/pwcheck to do basic password authentication that leverages su for Unix systems including MacOS, and the LogonUserW via the windows crate for Windows.

It's a bit of a hack and may not be the best in terms of security, but it does work on all three platforms: Linux, MacOS, and Windows. It's untested on FreeBSD, NetBSD, and termux.

I'd like to move the authentication methods (outside of none) to a new crate, distant-auth, which will provide the methods we can use as features. This way, the static key can always be available and we can provide password as a feature to use the pwcheck crate.

Once pam is available, that can be made as a feature as well.

@chipsenkbeil chipsenkbeil modified the milestones: 0.20, 1.0 Jun 19, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant