diff --git a/docs-xml/generate-pathconf-entities.sh b/docs-xml/generate-pathconf-entities.sh index 1b689a8a23f..8d39c5034c0 100755 --- a/docs-xml/generate-pathconf-entities.sh +++ b/docs-xml/generate-pathconf-entities.sh @@ -19,4 +19,5 @@ echo " + " diff --git a/docs-xml/smbdotconf/himmelblaud/himmelblaudhsmpinpath.xml b/docs-xml/smbdotconf/himmelblaud/himmelblaudhsmpinpath.xml new file mode 100644 index 00000000000..8727127feb7 --- /dev/null +++ b/docs-xml/smbdotconf/himmelblaud/himmelblaudhsmpinpath.xml @@ -0,0 +1,13 @@ + + + Specifies the file path where the HSM PIN is stored. This PIN is used + for unlocking TPM objects required for Azure Entra ID authentication. The HSM + PIN is critical for ensuring secure communication and authentication within + the Himmelblaud daemon. + + +&pathconfig.HIMMELBLAUD_HSM_PIN_PATH; + diff --git a/dynconfig/dynconfig.c b/dynconfig/dynconfig.c index 415ccc53c52..69de711c4de 100644 --- a/dynconfig/dynconfig.c +++ b/dynconfig/dynconfig.c @@ -107,3 +107,4 @@ DEFINE_DYN_CONFIG_PARAM(NTP_SIGND_SOCKET_DIR) DEFINE_DYN_CONFIG_PARAM(PYTHONDIR) DEFINE_DYN_CONFIG_PARAM(PYTHONARCHDIR) DEFINE_DYN_CONFIG_PARAM(SCRIPTSBINDIR) +DEFINE_DYN_CONFIG_PARAM(HIMMELBLAUD_HSM_PIN_PATH) diff --git a/dynconfig/dynconfig.h b/dynconfig/dynconfig.h index 72028a8c2e1..d06636de827 100644 --- a/dynconfig/dynconfig.h +++ b/dynconfig/dynconfig.h @@ -58,3 +58,4 @@ DEFINE_DYN_CONFIG_PROTO(NTP_SIGND_SOCKET_DIR) DEFINE_DYN_CONFIG_PROTO(PYTHONDIR) DEFINE_DYN_CONFIG_PROTO(PYTHONARCHDIR) DEFINE_DYN_CONFIG_PROTO(SCRIPTSBINDIR) +DEFINE_DYN_CONFIG_PROTO(HIMMELBLAUD_HSM_PIN_PATH) diff --git a/dynconfig/wscript b/dynconfig/wscript index a784dac4e6c..c338fd34888 100644 --- a/dynconfig/wscript +++ b/dynconfig/wscript @@ -285,6 +285,13 @@ dynconfig = { 'HELPTEXT': 'Where to put the smbpasswd file', 'DELAY': True, }, + 'HIMMELBLAUD_HSM_PIN_PATH': { + 'STD-PATH': '${LOCALSTATEDIR}/lib/himmelblaud/hsm-pin', + 'FHS-PATH': '${LOCALSTATEDIR}/lib/himmelblaud/hsm-pin', + 'OPTION': '--with-himmelblaud-hsm-pin-path', + 'HELPTEXT': 'Where to store the hsm pin', + 'DELAY': True, + }, } def options(opt): diff --git a/lib/param/loadparm.c b/lib/param/loadparm.c index 01c8df0ed70..db434e66262 100644 --- a/lib/param/loadparm.c +++ b/lib/param/loadparm.c @@ -3166,6 +3166,9 @@ struct loadparm_context *loadparm_init(TALLOC_CTX *mem_ctx) "AD DC only"); /* Set the default Himmelblaud globals */ + lpcfg_do_global_parameter(lp_ctx, + "himmelblaud hsm pin path", + get_dyn_HIMMELBLAUD_HSM_PIN_PATH()); lpcfg_do_global_parameter(lp_ctx, "himmelblaud hello enabled", "false"); diff --git a/rust/himmelblaud/src/cache.rs b/rust/himmelblaud/src/cache.rs index 51047044939..ad1e44c9c5c 100644 --- a/rust/himmelblaud/src/cache.rs +++ b/rust/himmelblaud/src/cache.rs @@ -404,32 +404,6 @@ impl PrivateCache { }) } - pub(crate) fn hsm_pin_fetch_or_create( - &mut self, - ) -> Result> { - let hsm_pin = match self.cache.fetch_str("auth_value") { - Some(hsm_pin) => hsm_pin, - None => { - let auth_str = match AuthValue::generate() { - Ok(auth_str) => auth_str, - Err(e) => { - DBG_ERR!("Failed to create hsm pin: {:?}", e); - return Err(Box::new(NT_STATUS_UNSUCCESSFUL)); - } - }; - self.cache.store_bytes("auth_value", auth_str.as_bytes())?; - auth_str - } - }; - match AuthValue::try_from(hsm_pin.as_bytes()) { - Ok(auth_value) => Ok(auth_value), - Err(e) => { - DBG_ERR!("Invalid hsm pin: {:?}", e); - return Err(Box::new(NT_STATUS_UNSUCCESSFUL)); - } - } - } - pub(crate) fn loadable_machine_key_fetch_or_create( &mut self, hsm: &mut BoxedDynTpm, diff --git a/rust/himmelblaud/src/main.rs b/rust/himmelblaud/src/main.rs index 81cfeca493f..5b1f2a1917e 100644 --- a/rust/himmelblaud/src/main.rs +++ b/rust/himmelblaud/src/main.rs @@ -200,13 +200,21 @@ async fn main() -> ExitCode { }; // Check for and create the hsm pin if required. - let auth_value = match pcache.hsm_pin_fetch_or_create() { - Ok(auth_value) => auth_value, - Err(e) => { - DBG_ERR!("{:?}", e); + let hsm_pin_path = match lp.himmelblaud_hsm_pin_path() { + Ok(Some(hsm_pin_path)) => hsm_pin_path, + _ => { + DBG_ERR!("Failed loading hsm pin path."); return ExitCode::FAILURE; } }; + let auth_value = + match utils::hsm_pin_fetch_or_create(&hsm_pin_path).await { + Ok(auth_value) => auth_value, + Err(e) => { + DBG_ERR!("{:?}", e); + return ExitCode::FAILURE; + } + }; // Setup the HSM and its machine key let mut hsm: BoxedDynTpm = BoxedDynTpm::new(SoftTpm::new()); diff --git a/rust/himmelblaud/src/utils.rs b/rust/himmelblaud/src/utils.rs index 932232eaec7..ff0fcb4e2db 100644 --- a/rust/himmelblaud/src/utils.rs +++ b/rust/himmelblaud/src/utils.rs @@ -18,7 +18,13 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ +use dbg::{DBG_ERR, DBG_INFO}; +use kanidm_hsm_crypto::AuthValue; use ntstatus_gen::*; +use std::path::PathBuf; +use std::str::FromStr; +use tokio::fs::File; +use tokio::io::AsyncReadExt; pub fn split_username( username: &str, @@ -29,3 +35,47 @@ pub fn split_username( } Err(Box::new(NT_STATUS_INVALID_USER_PRINCIPAL_NAME)) } + +pub(crate) async fn hsm_pin_fetch_or_create( + hsm_pin_path: &str, +) -> Result> { + let auth_value = if !PathBuf::from_str(hsm_pin_path) + .map_err(|e| { + DBG_ERR!("Failed to create hsm pin: {:?}", e); + Box::new(NT_STATUS_UNSUCCESSFUL) + })? + .exists() + { + let auth_value = AuthValue::generate().map_err(|e| { + DBG_ERR!("Failed to create hsm pin: {:?}", e); + Box::new(NT_STATUS_UNSUCCESSFUL) + })?; + std::fs::write(hsm_pin_path, auth_value.clone()).map_err(|e| { + DBG_ERR!("Failed to write hsm pin: {:?}", e); + Box::new(NT_STATUS_UNSUCCESSFUL) + })?; + + DBG_INFO!("Generated new HSM pin"); + auth_value + } else { + let mut file = File::open(hsm_pin_path).await.map_err(|e| { + DBG_ERR!("Failed to read hsm pin: {:?}", e); + Box::new(NT_STATUS_UNSUCCESSFUL) + })?; + let mut auth_value = vec![]; + file.read_to_end(&mut auth_value).await.map_err(|e| { + DBG_ERR!("Failed to read hsm pin: {:?}", e); + Box::new(NT_STATUS_UNSUCCESSFUL) + })?; + std::str::from_utf8(&auth_value) + .map_err(|e| { + DBG_ERR!("Failed to read hsm pin: {:?}", e); + Box::new(NT_STATUS_UNSUCCESSFUL) + })? + .to_string() + }; + AuthValue::try_from(auth_value.as_bytes()).map_err(|e| { + DBG_ERR!("Invalid hsm pin: {:?}", e); + Box::new(NT_STATUS_UNSUCCESSFUL) + }) +} diff --git a/rust/param/src/lib.rs b/rust/param/src/lib.rs index 7b4bcaf5325..1632a2ed758 100644 --- a/rust/param/src/lib.rs +++ b/rust/param/src/lib.rs @@ -202,6 +202,7 @@ impl LoadParm { lpcfg_str!(cache_directory); lpcfg_str!(template_homedir); lpcfg_str!(template_shell); + lpcfg_str!(himmelblaud_hsm_pin_path); } unsafe impl Send for LoadParm {} diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index ae23d22f401..6a0f7321017 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -1005,6 +1005,9 @@ void loadparm_s3_init_globals(struct loadparm_context *lp_ctx, Globals.acl_claims_evaluation = ACL_CLAIMS_EVALUATION_AD_DC_ONLY; /* Set the default Himmelblaud globals */ + lpcfg_string_set(Globals.ctx, + &Globals.himmelblaud_hsm_pin_path, + get_dyn_HIMMELBLAUD_HSM_PIN_PATH()); Globals.himmelblaud_hello_enabled = false; Globals.himmelblaud_sfa_fallback = false;