Skip to content
Snippets Groups Projects
Verified Commit 1cda1af8 authored by Nik | Klampfradler's avatar Nik | Klampfradler
Browse files

[NSS] Implement conversion and return of passwd results

parent 4c48c5f2
No related branches found
No related tags found
No related merge requests found
...@@ -26,6 +26,8 @@ use crate::logging::setup_log; ...@@ -26,6 +26,8 @@ use crate::logging::setup_log;
use crate::oauth::get_data; use crate::oauth::get_data;
use std::collections::HashMap; use std::collections::HashMap;
use serde_json::value::Value; use serde_json::value::Value;
use std::fmt;
use std::convert::TryInto;
use libc::{getpwuid, geteuid}; use libc::{getpwuid, geteuid};
use std::ffi::CStr; use std::ffi::CStr;
...@@ -55,6 +57,51 @@ fn get_current_user() -> String { ...@@ -55,6 +57,51 @@ fn get_current_user() -> String {
euser.to_str().ok().unwrap().to_string() euser.to_str().ok().unwrap().to_string()
} }
// FIXME Provide more specific error types and messages
#[derive(Debug, Clone)]
struct TransformMappingError {
msg: String,
field: String
}
impl fmt::Display for TransformMappingError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Invalid mapping configuration: field={} - {}", self.field, self.msg)
}
}
fn transform_ent(conf: &Config, row: &mut HashMap<String, Value>, map_name: &str) -> Result<(), TransformMappingError> {
let mapping: HashMap<String, HashMap<String, Value>> = get_optional(&conf, &("nss.maps.".to_string() + map_name)).unwrap_or_default();
for (field, rule) in &mapping {
let type_: String = rule.get("type").ok_or(TransformMappingError { field: field.to_string(), msg: "No type".to_string() })?.as_str().unwrap().to_string();
let value: &Value = rule.get("value").ok_or(TransformMappingError { field: field.to_string(), msg: "No value".to_string() })?;
if type_ == "static" {
row.insert(field.to_string(), value.clone());
} else if type_ == "rename" {
let old_value: Value = row.remove(&value.as_str().unwrap().to_string()).ok_or(TransformMappingError { field: field.to_string(), msg: "No value to rename".to_string() })?;
row.insert(field.to_string(), old_value);
} else {
return Err(TransformMappingError { field: field.to_string(), msg: (&("Unknown type ".to_string() + &type_)).to_string() });
};
}
Ok(())
}
fn map_to_passwd(conf: &Config, row: &mut HashMap<String, Value>) -> Result<Passwd, TransformMappingError> {
transform_ent(&conf, row, "passwd")?;
Ok(Passwd {
name: row.get("name").ok_or(TransformMappingError { field: "name".to_string(), msg: "No value in JSON data".to_string() })?.as_str().unwrap().to_string(),
passwd: row.get("passwd").ok_or(TransformMappingError { field: "passwd".to_string(), msg: "No value in JSON data".to_string() })?.as_str().unwrap().to_string(),
uid: row.get("uid").ok_or(TransformMappingError { field: "uid".to_string(), msg: "No value in JSON data".to_string() })?.as_u64().ok_or(TransformMappingError { field: "uid".to_string(), msg: "Invalid integer".to_string() })?.try_into().or(Err(TransformMappingError { field: "uid".to_string(), msg: "Overflow converting to u32".to_string() }))?,
gid: row.get("gid").ok_or(TransformMappingError { field: "gid".to_string(), msg: "No value in JSON data".to_string() })?.as_u64().ok_or(TransformMappingError { field: "gid".to_string(), msg: "Invalid integer".to_string() })?.try_into().or(Err(TransformMappingError { field: "gid".to_string(), msg: "Overflow converting to u32".to_string() }))?,
gecos: row.get("gecos").ok_or(TransformMappingError { field: "gecos".to_string(), msg: "No value in JSON data".to_string() })?.as_str().unwrap().to_string(),
dir: row.get("dir").ok_or(TransformMappingError { field: "dir".to_string(), msg: "No value in JSON data".to_string() })?.as_str().unwrap().to_string(),
shell: row.get("shell").ok_or(TransformMappingError { field: "shell".to_string(), msg: "No value in JSON data".to_string() })?.as_str().unwrap().to_string(),
})
}
struct OidcPasswd; struct OidcPasswd;
impl PasswdHooks for OidcPasswd { impl PasswdHooks for OidcPasswd {
...@@ -72,29 +119,20 @@ impl PasswdHooks for OidcPasswd { ...@@ -72,29 +119,20 @@ impl PasswdHooks for OidcPasswd {
} }
}; };
let data: Vec<HashMap<String, Value>> = match get_data(conf, "nss", "passwd", token, "") { let mut data: Vec<HashMap<String, Value>> = match get_data(&conf, "nss", "passwd", token, "") {
Ok(d) => d, Ok(d) => d,
Err(_) => return Response::Unavail Err(_) => return Response::Unavail
}; };
for ent in &data {
for (k, v) in ent { let mut passwd_vec: Vec<Passwd> = Vec::new();
debug!("{} {}", k, v); for row in &mut data {
} match map_to_passwd(&conf, row) {
Ok(p) => passwd_vec.push(p),
Err(e) => error!("Error converting JSON to passwd entry: {}", e)
};
} }
Response::Success( Response::Success(passwd_vec)
vec![
Passwd {
name: "test".to_string(),
passwd: "x".to_string(),
uid: 1005,
gid: 1005,
gecos: "Test Account".to_string(),
dir: "/home/test".to_string(),
shell: "/bin/bash".to_string(),
}
]
)
} }
fn get_entry_by_uid(uid: libc::uid_t) -> Response<Passwd> { fn get_entry_by_uid(uid: libc::uid_t) -> Response<Passwd> {
......
...@@ -133,7 +133,7 @@ pub fn get_access_token_password<E: Copy>(conf: Config, prefix: &str, username: ...@@ -133,7 +133,7 @@ pub fn get_access_token_password<E: Copy>(conf: Config, prefix: &str, username:
} }
} }
pub fn get_data<T: for<'de> Deserialize<'de>, E: Copy>(conf: Config, prefix: &str, endpoint: &str, token: &BasicTokenResponse, error_value: E) -> Result<T, E> { pub fn get_data<T: for<'de> Deserialize<'de>, E: Copy>(conf: &Config, prefix: &str, endpoint: &str, token: &BasicTokenResponse, error_value: E) -> Result<T, E> {
let access_token = token.access_token().secret(); let access_token = token.access_token().secret();
let endpoint_url: String = get_or_error(&conf, &full_key(prefix, &(endpoint.to_string() + "_url")), error_value)?; let endpoint_url: String = get_or_error(&conf, &full_key(prefix, &(endpoint.to_string() + "_url")), error_value)?;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment