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;