From 8c64e98c8b018bdbd0d4028a394b4fabe90b196a Mon Sep 17 00:00:00 2001 From: Dominik George <dominik.george@teckids.org> Date: Tue, 11 May 2021 16:43:13 +0200 Subject: [PATCH] [NSS] Use client credentials if user token is unavailable --- src/nss.rs | 20 +++++++++++++++----- src/oauth.rs | 6 +++--- src/pam.rs | 2 +- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/nss.rs b/src/nss.rs index 66ab75f..c4be7f1 100644 --- a/src/nss.rs +++ b/src/nss.rs @@ -23,7 +23,7 @@ use crate::cache::get_cache; use crate::logging::setup_log; -use crate::oauth::get_data_jq; +use crate::oauth::{get_access_token_client, get_data_jq}; use serde::{Serialize, Deserialize}; use libc::{getpwuid, geteuid}; @@ -75,16 +75,26 @@ impl PasswdHooks for OidcPasswd { let mut cache = get_cache(); let user = get_current_user(); + let ctc; let token = match cache.load_user_token(&user) { Some(t) => t, None => { - // FIXME Implement fallback to system token - error!("Could not find a user token for {} to request NSS data", user); - return Response::Unavail; + // FIXME Implement caching of system token + debug!("Could not find a user token for {} to request NSS data; trying client credentials", user); + match get_access_token_client(&conf, "nss", "", "") { + Ok(ct) => { + ctc = ct.clone(); + &ctc + }, + Err(_) => { + error!("Failed to get access token with client credentials"); + return Response::Unavail; + } + } } }; - let data: Vec<PasswdHelper> = match get_data_jq(&conf, "nss", "passwd", token, true) { + let data: Vec<PasswdHelper> = match get_data_jq(&conf, "nss", "passwd", &token, true) { Ok(d) => d, Err(_) => { error!("Could not load JSON data for passwd"); diff --git a/src/oauth.rs b/src/oauth.rs index 385d41f..14d1882 100644 --- a/src/oauth.rs +++ b/src/oauth.rs @@ -49,7 +49,7 @@ fn full_key(parts: Vec<&str>) -> String { parts.join(".") } -fn get_client<E: Copy>(conf: Config, prefix: &str, error_value: E) -> Result<BasicClient, E> { +fn get_client<E: Copy>(conf: &Config, prefix: &str, error_value: E) -> Result<BasicClient, E> { let client_id = ClientId::new(get_or_error(&conf, &full_key(vec![prefix, "client_id"]), error_value)?); let client_secret = match get_optional(&conf, &full_key(vec![prefix, "client_secret"])) { Some(v) => Some(ClientSecret::new(v)), @@ -77,7 +77,7 @@ fn get_client<E: Copy>(conf: Config, prefix: &str, error_value: E) -> Result<Bas return Ok(client); } -pub fn get_access_token_client<E: Copy>(conf: Config, prefix: &str, error_value: E, unauth_value: E) -> Result<BasicTokenResponse, E> { +pub fn get_access_token_client<E: Copy>(conf: &Config, prefix: &str, error_value: E, unauth_value: E) -> Result<BasicTokenResponse, E> { let scopes: Vec<String> = match get_optional(&conf, &full_key(vec![prefix, "scopes"])) { Some(v) => v, None => vec![] @@ -105,7 +105,7 @@ pub fn get_access_token_client<E: Copy>(conf: Config, prefix: &str, error_value: } } -pub fn get_access_token_password<E: Copy>(conf: Config, prefix: &str, username: String, password: String, error_value: E, unauth_value: E) -> Result<BasicTokenResponse, E> { +pub fn get_access_token_password<E: Copy>(conf: &Config, prefix: &str, username: String, password: String, error_value: E, unauth_value: E) -> Result<BasicTokenResponse, E> { let scopes: Vec<String> = match get_optional(&conf, &full_key(vec![prefix, "scopes"])) { Some(v) => v, None => vec![] diff --git a/src/pam.rs b/src/pam.rs index 461d71c..2133f7f 100644 --- a/src/pam.rs +++ b/src/pam.rs @@ -87,7 +87,7 @@ impl PamServiceModule for PamOidc { }; debug!("Successfully got password"); - match get_access_token_password(conf, "pam", username.to_string(), password.to_string(), PamError::SERVICE_ERR, PamError::AUTH_ERR) { + match get_access_token_password(&conf, "pam", username.to_string(), password.to_string(), PamError::SERVICE_ERR, PamError::AUTH_ERR) { Ok(t) => { info!("Authenticated {} using Resource Owner Password Grant", username); get_cache().save_user_token(&username.to_string(), t.into()); -- GitLab