Skip to content
Snippets Groups Projects
pam.rs 3.58 KiB
Newer Older
/* Copyright 2021 Dominik George <dominik.george@teckids.org>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

Nik | Klampfradler's avatar
Nik | Klampfradler committed
use crate::config::{
    argv_to_config,
    get_optional,
Nik | Klampfradler's avatar
Nik | Klampfradler committed
};
use config::Config;

use crate::oauth::get_access_token_password;
use crate::logging::setup_log;
Nik | Klampfradler's avatar
Nik | Klampfradler committed
use pamsm::{PamServiceModule, Pam, PamFlag, PamError, PamLibExt};

fn pam_sm_prepare(argv: &Vec<String>) -> Config {
    let conf_args = argv_to_config(argv);
    let conf = get_config(Some(conf_args));

    let mut log_level = log::LevelFilter::Error;
    if get_optional(&conf, "pam.debug").unwrap_or_default() {
        log_level = log::LevelFilter::Debug;
    }
    setup_log(log_level);

    return conf;
}

Nik | Klampfradler's avatar
Nik | Klampfradler committed
struct PamOidc;

impl PamServiceModule for PamOidc {
    fn authenticate(pamh: Pam, _: PamFlag, argv: Vec<String>) -> PamError {
        let conf = pam_sm_prepare(&argv);
Nik | Klampfradler's avatar
Nik | Klampfradler committed
        if conf.get_str("pam.flow").unwrap() == "password" {
            debug!("Starting Resource Owner Password Credentials OAuth flow");

Nik | Klampfradler's avatar
Nik | Klampfradler committed
            let username = match pamh.get_user(None) {
                Ok(Some(u)) => match u.to_str() {
                    Ok(u) => u,
                    _ => {
                        error!("Could not convert user name to string, aborting");
                        return PamError::CRED_INSUFFICIENT;
                    },
                },
                Ok(None) => {
                    error!("No username supplied");
                    return PamError::CRED_INSUFFICIENT;
                },
                Err(e) => {
                    error!("Error getting user name: {}", e);
                    return e;
Nik | Klampfradler's avatar
Nik | Klampfradler committed
                },
            };
            debug!("Successfully got user name");

Nik | Klampfradler's avatar
Nik | Klampfradler committed
            let password = match pamh.get_authtok(None) {
                Ok(Some(p)) => match p.to_str() {
                    Ok(p) => p,
                    _ => {
                        error!("Could not convert password to string");
                        return PamError::CRED_INSUFFICIENT;
                    },
                },
                Ok(None) => {
                    error!("No password supplied");
                    return PamError::CRED_INSUFFICIENT;
                },
                Err(e) => {
                    error!("Error getting password: {}", e);
                    return e;
Nik | Klampfradler's avatar
Nik | Klampfradler committed
                },
            };
            debug!("Successfully got password");
            match get_access_token_password(conf, "pam", username.to_string(), password.to_string(), PamError::SERVICE_ERR, PamError::AUTH_ERR) {
                    info!("Authenticated {} using Resource Owner Password Grant", username);
                    CACHE.save_user_token(&username.to_string(), t.into());
                    return PamError::SUCCESS;
                },
                Err(e) => {
                    error!("Error in legacy authentication: {}", e);
                    return e;
                },
        error!("Unknown flow for authentication");
Nik | Klampfradler's avatar
Nik | Klampfradler committed
        return PamError::SERVICE_ERR;
    }
}

pam_module!(PamOidc);