Skip to content

Commit

Permalink
CN name mapping in PAM and NSS
Browse files Browse the repository at this point in the history
This maps the user's CN name to a full UPN in PAM
and NSS. This is enabled by default (although the
full upn is still accepted).

Signed-off-by: David Mulder <dmulder@samba.org>
  • Loading branch information
dmulder committed Oct 9, 2024
1 parent 0497245 commit 95c68fa
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 8 deletions.
18 changes: 13 additions & 5 deletions src/common/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@ use std::path::PathBuf;
use tracing::{debug, error};

use crate::constants::{
BROKER_APP_ID, DEFAULT_BROKER_SOCK_PATH, DEFAULT_CACHE_TIMEOUT, DEFAULT_CONFIG_PATH,
DEFAULT_CONN_TIMEOUT, DEFAULT_DB_PATH, DEFAULT_HELLO_ENABLED, DEFAULT_HOME_ALIAS,
DEFAULT_HOME_ATTR, DEFAULT_HOME_PREFIX, DEFAULT_HSM_PIN_PATH, DEFAULT_ID_ATTR_MAP,
DEFAULT_ODC_PROVIDER, DEFAULT_SELINUX, DEFAULT_SFA_FALLBACK_ENABLED, DEFAULT_SHELL,
DEFAULT_SOCK_PATH, DEFAULT_TASK_SOCK_PATH, DEFAULT_USE_ETC_SKEL, SERVER_CONFIG_PATH,
BROKER_APP_ID, CN_NAME_MAPPING, DEFAULT_BROKER_SOCK_PATH, DEFAULT_CACHE_TIMEOUT,
DEFAULT_CONFIG_PATH, DEFAULT_CONN_TIMEOUT, DEFAULT_DB_PATH, DEFAULT_HELLO_ENABLED,
DEFAULT_HOME_ALIAS, DEFAULT_HOME_ATTR, DEFAULT_HOME_PREFIX, DEFAULT_HSM_PIN_PATH,
DEFAULT_ID_ATTR_MAP, DEFAULT_ODC_PROVIDER, DEFAULT_SELINUX, DEFAULT_SFA_FALLBACK_ENABLED,
DEFAULT_SHELL, DEFAULT_SOCK_PATH, DEFAULT_TASK_SOCK_PATH, DEFAULT_USE_ETC_SKEL,
SERVER_CONFIG_PATH,
};
use crate::unix_config::{HomeAttr, HsmType};
use idmap::DEFAULT_IDMAP_RANGE;
Expand Down Expand Up @@ -401,6 +402,13 @@ impl HimmelblauConfig {
pub fn get_debug(&self) -> bool {
match_bool(self.config.get("global", "debug"), false)
}

pub fn get_cn_name_mapping(&self) -> bool {
match_bool(
self.config.get("global", "cn_name_mapping"),
CN_NAME_MAPPING,
)
}
}

impl fmt::Debug for HimmelblauConfig {
Expand Down
1 change: 1 addition & 0 deletions src/common/src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,4 @@ pub const DEFAULT_SFA_FALLBACK_ENABLED: bool = false;
pub const DEFAULT_ID_ATTR_MAP: IdAttr = IdAttr::Name;
pub const BROKER_APP_ID: &str = "29d9ed98-a469-4536-ade2-f981bc1d605e";
pub const BROKER_CLIENT_IDENT: &str = "38aa3b87-a06d-4817-b275-7a316988d93b";
pub const CN_NAME_MAPPING: bool = true;
7 changes: 7 additions & 0 deletions src/config/himmelblau.conf.example
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,13 @@
# configured. This is disabled by default.
# enable_sfa_fallback = false
#
# CN to UPN mapping allows users to simply enter the short form of their
# username (`dave` instead of `dave@example.com`). Himmelblau will only map CNs
# to the primary domain (the first domain listed in the `domains` option
# above). WARNING: CN mapping could mask local users, depending on your PAM
# configuration.
# cn_name_mapping = true
#
# authority_host = login.microsoftonline.com
#
# The location of the cache database
Expand Down
13 changes: 13 additions & 0 deletions src/glue/src/unix_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,38 @@ use himmelblau_unix_common::config::HimmelblauConfig;
use himmelblau_unix_common::constants::{DEFAULT_CONN_TIMEOUT, DEFAULT_SOCK_PATH};

pub struct KanidmUnixdConfig {
pub domains: Vec<String>,
pub unix_sock_timeout: u64,
pub sock_path: String,
pub cn_name_mapping: bool,
}

impl KanidmUnixdConfig {
pub fn new() -> Self {
KanidmUnixdConfig {
domains: vec![],
sock_path: DEFAULT_SOCK_PATH.to_string(),
unix_sock_timeout: DEFAULT_CONN_TIMEOUT * 2,
cn_name_mapping: false,
}
}

pub fn read_options_from_optional_config(self, config_path: &str) -> Result<Self, String> {
let config: HimmelblauConfig = HimmelblauConfig::new(Some(config_path))?;
Ok(KanidmUnixdConfig {
domains: config.get_configured_domains(),
sock_path: config.get_socket_path(),
unix_sock_timeout: config.get_connection_timeout() * 2,
cn_name_mapping: config.get_cn_name_mapping(),
})
}

pub fn map_cn_name(&self, account_id: &str) -> String {
if self.cn_name_mapping && !account_id.contains('@') && !self.domains.is_empty() {
return format!("{}@{}", account_id, self.domains[0]);
}
account_id.to_string()
}
}

impl Default for KanidmUnixdConfig {
Expand Down
10 changes: 7 additions & 3 deletions src/nss/src/implementation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ impl PasswdHooks for HimmelblauPasswd {
return Response::Unavail;
}
};
let req = ClientRequest::NssAccountByName(name);
let name = cfg.map_cn_name(&name);
let req = ClientRequest::NssAccountByName(name.clone());
let mut daemon_client = match DaemonClientBlocking::new(cfg.sock_path.as_str()) {
Ok(dc) => dc,
Err(_) => {
Expand All @@ -86,8 +87,11 @@ impl PasswdHooks for HimmelblauPasswd {
.call_and_wait(&req, cfg.unix_sock_timeout)
.map(|r| match r {
ClientResponse::NssAccount(opt) => opt
.map(passwd_from_nssuser)
.map(Response::Success)
.map(|nu| {
let mut passwd = passwd_from_nssuser(nu);
passwd.name = name;
Response::Success(passwd)
})
.unwrap_or_else(|| Response::NotFound),
_ => Response::NotFound,
})
Expand Down
3 changes: 3 additions & 0 deletions src/pam/src/pam/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,7 @@ impl PamHooks for PamKanidm {
Ok(cfg) => cfg,
Err(e) => return e,
};
let account_id = cfg.map_cn_name(&account_id);
let req = ClientRequest::PamAccountAllowed(account_id);
// PamResultCode::PAM_IGNORE

Expand Down Expand Up @@ -331,6 +332,7 @@ impl PamHooks for PamKanidm {
Ok(cfg) => cfg,
Err(e) => return e,
};
let account_id = cfg.map_cn_name(&account_id);

let mut timeout = cfg.unix_sock_timeout;
let mut daemon_client = match DaemonClientBlocking::new(cfg.sock_path.as_str()) {
Expand Down Expand Up @@ -553,6 +555,7 @@ impl PamHooks for PamKanidm {
Ok(cfg) => cfg,
Err(e) => return e,
};
let account_id = cfg.map_cn_name(&account_id);
let req = ClientRequest::PamAccountBeginSession(account_id);

let mut daemon_client = match DaemonClientBlocking::new(cfg.sock_path.as_str()) {
Expand Down

0 comments on commit 95c68fa

Please sign in to comment.