From d01fed8aa57d90ff133324b0a89cfaf228be8bab Mon Sep 17 00:00:00 2001 From: David Mulder Date: Thu, 28 Aug 2025 13:09:36 -0600 Subject: [PATCH] Remove previous himmelblau integration attempt This was a project attempting to integrate Himmelblau into Samba, but it has been abandoned. Signed-off-by: David Mulder Reviewed-by: Andreas Schneider Autobuild-User(master): David Mulder Autobuild-Date(master): Tue Nov 4 09:09:40 UTC 2025 on atb-devel-224 --- docs-xml/generate-pathconf-entities.sh | 1 - .../himmelblaud/himmelblaudhelloenabled.xml | 18 - .../himmelblaud/himmelblaudhsmpinpath.xml | 13 - .../himmelblaud/himmelblaudsfafallback.xml | 17 - dynconfig/dynconfig.c | 1 - dynconfig/dynconfig.h | 1 - dynconfig/wscript | 7 - lib/param/loadparm.c | 11 - rust/.cargo/config.toml | 5 - rust/.gitignore | 14 - rust/Cargo.lock | 2899 ----------------- rust/Cargo.toml | 12 - rust/build.rs | 19 - rust/chelps/Cargo.toml | 8 - rust/chelps/src/lib.rs | 154 - rust/config/Cargo.toml | 12 - rust/config/additions.h | 8 - rust/config/build.rs | 20 - rust/config/src/lib.rs | 52 - rust/dbg/Cargo.toml | 16 - rust/dbg/build.rs | 25 - rust/dbg/src/lib.rs | 217 -- rust/himmelblaud/Cargo.toml | 32 - rust/himmelblaud/build.rs | 3 - rust/himmelblaud/src/cache.rs | 658 ---- rust/himmelblaud/src/constants.rs | 1 - rust/himmelblaud/src/himmelblaud.rs | 295 -- .../src/himmelblaud/himmelblaud_getgrent.rs | 154 - .../src/himmelblaud/himmelblaud_getgrgid.rs | 147 - .../src/himmelblaud/himmelblaud_getgrnam.rs | 159 - .../src/himmelblaud/himmelblaud_getpwent.rs | 210 -- .../src/himmelblaud/himmelblaud_getpwnam.rs | 232 -- .../src/himmelblaud/himmelblaud_getpwuid.rs | 156 - .../himmelblaud/himmelblaud_pam_acct_mgmt.rs | 47 - .../src/himmelblaud/himmelblaud_pam_auth.rs | 794 ----- rust/himmelblaud/src/main.rs | 476 --- rust/himmelblaud/src/utils.rs | 149 - rust/idmap/Cargo.toml | 15 - rust/idmap/build.rs | 33 - rust/idmap/src/lib.rs | 227 -- rust/idmap/src/murmurhash3.c | 114 - rust/idmap/src/murmurhash3.h | 21 - rust/idmap/src/sss_idmap.c | 1909 ----------- rust/idmap/src/sss_idmap.h | 1100 ------- rust/idmap/src/sss_idmap_conv.c | 570 ---- rust/idmap/src/sss_idmap_private.h | 84 - rust/idmap/src/util.h | 46 - rust/nss/Cargo.toml | 21 - rust/nss/build.rs | 18 - rust/nss/src/lib.rs | 185 -- rust/ntstatus_gen/Cargo.toml | 6 - rust/ntstatus_gen/src/lib.rs | 24 - rust/pam/Cargo.toml | 23 - rust/pam/build.rs | 10 - rust/pam/src/lib.rs | 43 - rust/pam/src/pam/constants.rs | 118 - rust/pam/src/pam/conv.rs | 112 - rust/pam/src/pam/items.rs | 101 - rust/pam/src/pam/macros.rs | 140 - rust/pam/src/pam/mod.rs | 615 ---- rust/pam/src/pam/module.rs | 361 -- rust/param/Cargo.toml | 15 - rust/param/build.rs | 53 - rust/param/src/lib.rs | 201 -- rust/rustfmt.toml | 2 - rust/sock/Cargo.toml | 16 - rust/sock/src/lib.rs | 141 - rust/sock/src/proto.rs | 116 - rust/talloc/Cargo.toml | 13 - rust/talloc/build.rs | 38 - rust/talloc/src/lib.rs | 56 - rust/tdb/Cargo.toml | 16 - rust/tdb/build.rs | 35 - rust/tdb/src/lib.rs | 260 -- rust/version/Cargo.toml | 18 - rust/version/build.rs | 29 - rust/version/include/includes.h | 0 rust/version/src/lib.rs | 40 - rust/wscript_build | 19 +- script/autobuild.py | 7 +- source3/param/loadparm.c | 7 - wscript | 12 - 82 files changed, 2 insertions(+), 14031 deletions(-) delete mode 100644 docs-xml/smbdotconf/himmelblaud/himmelblaudhelloenabled.xml delete mode 100644 docs-xml/smbdotconf/himmelblaud/himmelblaudhsmpinpath.xml delete mode 100644 docs-xml/smbdotconf/himmelblaud/himmelblaudsfafallback.xml delete mode 100644 rust/.cargo/config.toml delete mode 100644 rust/.gitignore delete mode 100644 rust/Cargo.lock delete mode 100644 rust/build.rs delete mode 100644 rust/chelps/Cargo.toml delete mode 100644 rust/chelps/src/lib.rs delete mode 100644 rust/config/Cargo.toml delete mode 100644 rust/config/additions.h delete mode 100644 rust/config/build.rs delete mode 100644 rust/config/src/lib.rs delete mode 100644 rust/dbg/Cargo.toml delete mode 100644 rust/dbg/build.rs delete mode 100644 rust/dbg/src/lib.rs delete mode 100644 rust/himmelblaud/Cargo.toml delete mode 100644 rust/himmelblaud/build.rs delete mode 100644 rust/himmelblaud/src/cache.rs delete mode 100644 rust/himmelblaud/src/constants.rs delete mode 100644 rust/himmelblaud/src/himmelblaud.rs delete mode 100644 rust/himmelblaud/src/himmelblaud/himmelblaud_getgrent.rs delete mode 100644 rust/himmelblaud/src/himmelblaud/himmelblaud_getgrgid.rs delete mode 100644 rust/himmelblaud/src/himmelblaud/himmelblaud_getgrnam.rs delete mode 100644 rust/himmelblaud/src/himmelblaud/himmelblaud_getpwent.rs delete mode 100644 rust/himmelblaud/src/himmelblaud/himmelblaud_getpwnam.rs delete mode 100644 rust/himmelblaud/src/himmelblaud/himmelblaud_getpwuid.rs delete mode 100644 rust/himmelblaud/src/himmelblaud/himmelblaud_pam_acct_mgmt.rs delete mode 100644 rust/himmelblaud/src/himmelblaud/himmelblaud_pam_auth.rs delete mode 100644 rust/himmelblaud/src/main.rs delete mode 100644 rust/himmelblaud/src/utils.rs delete mode 100644 rust/idmap/Cargo.toml delete mode 100644 rust/idmap/build.rs delete mode 100644 rust/idmap/src/lib.rs delete mode 100644 rust/idmap/src/murmurhash3.c delete mode 100644 rust/idmap/src/murmurhash3.h delete mode 100644 rust/idmap/src/sss_idmap.c delete mode 100644 rust/idmap/src/sss_idmap.h delete mode 100644 rust/idmap/src/sss_idmap_conv.c delete mode 100644 rust/idmap/src/sss_idmap_private.h delete mode 100644 rust/idmap/src/util.h delete mode 100644 rust/nss/Cargo.toml delete mode 100644 rust/nss/build.rs delete mode 100644 rust/nss/src/lib.rs delete mode 100644 rust/ntstatus_gen/Cargo.toml delete mode 100644 rust/ntstatus_gen/src/lib.rs delete mode 100644 rust/pam/Cargo.toml delete mode 100644 rust/pam/build.rs delete mode 100644 rust/pam/src/lib.rs delete mode 100644 rust/pam/src/pam/constants.rs delete mode 100644 rust/pam/src/pam/conv.rs delete mode 100644 rust/pam/src/pam/items.rs delete mode 100644 rust/pam/src/pam/macros.rs delete mode 100755 rust/pam/src/pam/mod.rs delete mode 100755 rust/pam/src/pam/module.rs delete mode 100644 rust/param/Cargo.toml delete mode 100644 rust/param/build.rs delete mode 100644 rust/param/src/lib.rs delete mode 100644 rust/rustfmt.toml delete mode 100644 rust/sock/Cargo.toml delete mode 100644 rust/sock/src/lib.rs delete mode 100644 rust/sock/src/proto.rs delete mode 100644 rust/talloc/Cargo.toml delete mode 100644 rust/talloc/build.rs delete mode 100644 rust/talloc/src/lib.rs delete mode 100644 rust/tdb/Cargo.toml delete mode 100644 rust/tdb/build.rs delete mode 100644 rust/tdb/src/lib.rs delete mode 100644 rust/version/Cargo.toml delete mode 100644 rust/version/build.rs delete mode 100644 rust/version/include/includes.h delete mode 100644 rust/version/src/lib.rs diff --git a/docs-xml/generate-pathconf-entities.sh b/docs-xml/generate-pathconf-entities.sh index 8d39c5034c0..1b689a8a23f 100755 --- a/docs-xml/generate-pathconf-entities.sh +++ b/docs-xml/generate-pathconf-entities.sh @@ -19,5 +19,4 @@ echo " - " diff --git a/docs-xml/smbdotconf/himmelblaud/himmelblaudhelloenabled.xml b/docs-xml/smbdotconf/himmelblaud/himmelblaudhelloenabled.xml deleted file mode 100644 index b148362862f..00000000000 --- a/docs-xml/smbdotconf/himmelblaud/himmelblaudhelloenabled.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - This parameter controls Hello enrollment and authentication to - Azure Entra ID. By default, it is disabled to prevent security risks, - such as on hosts exposing the SSH port. Administrators should enable - this setting only when Hello enrollment is appropriate for their - environment. - - - - -no -yes - diff --git a/docs-xml/smbdotconf/himmelblaud/himmelblaudhsmpinpath.xml b/docs-xml/smbdotconf/himmelblaud/himmelblaudhsmpinpath.xml deleted file mode 100644 index 8727127feb7..00000000000 --- a/docs-xml/smbdotconf/himmelblaud/himmelblaudhsmpinpath.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - 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/docs-xml/smbdotconf/himmelblaud/himmelblaudsfafallback.xml b/docs-xml/smbdotconf/himmelblaud/himmelblaudsfafallback.xml deleted file mode 100644 index 1b30d0a87c9..00000000000 --- a/docs-xml/smbdotconf/himmelblaud/himmelblaudsfafallback.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - This parameter is designed to control whether Himmelblaud should fallback to - Single Factor Authentication (SFA) if Multi-Factor Authentication (MFA) isn't - available. This normally is possible during a short window during which MFA - enrollment is available to a new user. - - - - -no -yes - diff --git a/dynconfig/dynconfig.c b/dynconfig/dynconfig.c index 69de711c4de..415ccc53c52 100644 --- a/dynconfig/dynconfig.c +++ b/dynconfig/dynconfig.c @@ -107,4 +107,3 @@ 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 d06636de827..72028a8c2e1 100644 --- a/dynconfig/dynconfig.h +++ b/dynconfig/dynconfig.h @@ -58,4 +58,3 @@ 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 2d7d79006fd..5d7633b047b 100644 --- a/dynconfig/wscript +++ b/dynconfig/wscript @@ -285,13 +285,6 @@ 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 8aea8f8499b..69baf4b7054 100644 --- a/lib/param/loadparm.c +++ b/lib/param/loadparm.c @@ -3284,17 +3284,6 @@ struct loadparm_context *loadparm_init(TALLOC_CTX *mem_ctx) "acl claims evaluation", "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"); - lpcfg_do_global_parameter(lp_ctx, - "himmelblaud sfa fallback", - "false"); - lpcfg_do_global_parameter(lp_ctx, "server smb encryption over quic", "yes"); diff --git a/rust/.cargo/config.toml b/rust/.cargo/config.toml deleted file mode 100644 index 29bbcafd56a..00000000000 --- a/rust/.cargo/config.toml +++ /dev/null @@ -1,5 +0,0 @@ -[source.crates-io] -replace-with = "vendored-sources" - -[source.vendored-sources] -directory = "../bin/default/rust/vendor" diff --git a/rust/.gitignore b/rust/.gitignore deleted file mode 100644 index eadb94ca271..00000000000 --- a/rust/.gitignore +++ /dev/null @@ -1,14 +0,0 @@ -# ---> Rust -# Generated by Cargo -# will have compiled files and executables -debug/ -target/ - -# These are backup files generated by rustfmt -**/*.rs.bk - -# MSVC Windows builds of rustc generate these, which store debugging information -*.pdb - -vendor/ -tags diff --git a/rust/Cargo.lock b/rust/Cargo.lock deleted file mode 100644 index 9a2af4b9f87..00000000000 --- a/rust/Cargo.lock +++ /dev/null @@ -1,2899 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "addr2line" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - -[[package]] -name = "ahash" -version = "0.8.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" -dependencies = [ - "cfg-if", - "getrandom", - "once_cell", - "version_check", - "zerocopy", -] - -[[package]] -name = "aho-corasick" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" -dependencies = [ - "memchr", -] - -[[package]] -name = "anstream" -version = "0.6.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" -dependencies = [ - "anstyle", - "anstyle-parse", - "anstyle-query", - "anstyle-wincon", - "colorchoice", - "is_terminal_polyfill", - "utf8parse", -] - -[[package]] -name = "anstyle" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" - -[[package]] -name = "anstyle-parse" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" -dependencies = [ - "utf8parse", -] - -[[package]] -name = "anstyle-query" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" -dependencies = [ - "windows-sys 0.52.0", -] - -[[package]] -name = "anstyle-wincon" -version = "3.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" -dependencies = [ - "anstyle", - "windows-sys 0.52.0", -] - -[[package]] -name = "argon2" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c3610892ee6e0cbce8ae2700349fcf8f98adb0dbfbee85aec3c9179d29cc072" -dependencies = [ - "base64ct", - "blake2", - "cpufeatures", - "password-hash", -] - -[[package]] -name = "atomic-waker" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" - -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi 0.1.19", - "libc", - "winapi", -] - -[[package]] -name = "autocfg" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" - -[[package]] -name = "backtrace" -version = "0.3.73" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", -] - -[[package]] -name = "base64" -version = "0.21.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" - -[[package]] -name = "base64" -version = "0.22.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" - -[[package]] -name = "base64ct" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" - -[[package]] -name = "base64urlsafedata" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a56894edf5cd1efa7068d7454adeb7ce0b3da4ffa5ab08cfc06165bbc62f0c7" -dependencies = [ - "base64 0.21.7", - "paste", - "serde", -] - -[[package]] -name = "bindgen" -version = "0.69.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0" -dependencies = [ - "bitflags 2.6.0", - "cexpr", - "clang-sys", - "itertools", - "lazy_static", - "lazycell", - "log", - "prettyplease", - "proc-macro2", - "quote", - "regex", - "rustc-hash", - "shlex", - "syn 2.0.72", - "which", -] - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" - -[[package]] -name = "blake2" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" -dependencies = [ - "digest", -] - -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", -] - -[[package]] -name = "bumpalo" -version = "3.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" - -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - -[[package]] -name = "bytes" -version = "1.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" - -[[package]] -name = "cbindgen" -version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da6bc11b07529f16944307272d5bd9b22530bc7d05751717c9d416586cedab49" -dependencies = [ - "clap 3.2.25", - "heck", - "indexmap 1.9.3", - "log", - "proc-macro2", - "quote", - "serde", - "serde_json", - "syn 1.0.109", - "tempfile", - "toml", -] - -[[package]] -name = "cc" -version = "1.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "504bdec147f2cc13c8b57ed9401fd8a147cc66b67ad5cb241394244f2c947549" - -[[package]] -name = "cexpr" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" -dependencies = [ - "nom", -] - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "chelps" -version = "4.21.0" - -[[package]] -name = "clang-sys" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" -dependencies = [ - "glob", - "libc", - "libloading", -] - -[[package]] -name = "clap" -version = "3.2.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" -dependencies = [ - "atty", - "bitflags 1.3.2", - "clap_lex 0.2.4", - "indexmap 1.9.3", - "strsim 0.10.0", - "termcolor", - "textwrap", -] - -[[package]] -name = "clap" -version = "4.5.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c937d4061031a6d0c8da4b9a4f98a172fc2976dfb1c19213a9cf7d0d3c837e36" -dependencies = [ - "clap_builder", -] - -[[package]] -name = "clap_builder" -version = "4.5.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85379ba512b21a328adf887e85f7742d12e96eb31f3ef077df4ffc26b506ffed" -dependencies = [ - "anstream", - "anstyle", - "clap_lex 0.7.2", - "strsim 0.11.1", -] - -[[package]] -name = "clap_lex" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" -dependencies = [ - "os_str_bytes", -] - -[[package]] -name = "clap_lex" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" - -[[package]] -name = "colorchoice" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" - -[[package]] -name = "compact_jwt" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b6493b1c78b7c33fbbb00d8d60d633439fd0c0e44826fb4834efc28121ef266" -dependencies = [ - "base64 0.21.7", - "base64urlsafedata", - "hex", - "kanidm-hsm-crypto", - "openssl", - "openssl-kdf", - "serde", - "serde_json", - "tracing", - "url", - "uuid", -] - -[[package]] -name = "config" -version = "4.21.0" -dependencies = [ - "bindgen", - "libc", -] - -[[package]] -name = "cookie" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ddef33a339a91ea89fb53151bd0a4689cfce27055c291dfa69945475d22c747" -dependencies = [ - "percent-encoding", - "time", - "version_check", -] - -[[package]] -name = "cookie_store" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4934e6b7e8419148b6ef56950d277af8561060b56afd59e2aadf98b59fce6baa" -dependencies = [ - "cookie", - "idna 0.5.0", - "log", - "publicsuffix", - "serde", - "serde_derive", - "serde_json", - "time", - "url", -] - -[[package]] -name = "core-foundation" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "core-foundation-sys" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" - -[[package]] -name = "cpufeatures" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" -dependencies = [ - "libc", -] - -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "typenum", -] - -[[package]] -name = "cssparser" -version = "0.31.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b3df4f93e5fbbe73ec01ec8d3f68bba73107993a5b1e7519273c32db9b0d5be" -dependencies = [ - "cssparser-macros", - "dtoa-short", - "itoa", - "phf 0.11.2", - "smallvec", -] - -[[package]] -name = "cssparser-macros" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" -dependencies = [ - "quote", - "syn 2.0.72", -] - -[[package]] -name = "dbg" -version = "4.21.0" -dependencies = [ - "bindgen", - "chelps", - "paste", - "tempfile", -] - -[[package]] -name = "deranged" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" -dependencies = [ - "powerfmt", -] - -[[package]] -name = "derive_more" -version = "0.99.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.72", -] - -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer", - "crypto-common", - "subtle", -] - -[[package]] -name = "dtoa" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcbb2bf8e87535c23f7a8a321e364ce21462d0ff10cb6407820e8e96dfff6653" - -[[package]] -name = "dtoa-short" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd1511a7b6a56299bd043a9c167a6d2bfb37bf84a6dfceaba651168adfb43c87" -dependencies = [ - "dtoa", -] - -[[package]] -name = "ego-tree" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a68a4904193147e0a8dec3314640e6db742afd5f6e634f428a6af230d9b3591" - -[[package]] -name = "either" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" - -[[package]] -name = "encoding_rs" -version = "0.8.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "equivalent" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" - -[[package]] -name = "errno" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] - -[[package]] -name = "fastrand" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - -[[package]] -name = "form_urlencoded" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" -dependencies = [ - "percent-encoding", -] - -[[package]] -name = "futf" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df420e2e84819663797d1ec6544b13c5be84629e7bb00dc960d6917db2987843" -dependencies = [ - "mac", - "new_debug_unreachable", -] - -[[package]] -name = "futures" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-channel" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" -dependencies = [ - "futures-core", - "futures-sink", -] - -[[package]] -name = "futures-core" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" - -[[package]] -name = "futures-executor" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-io" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" - -[[package]] -name = "futures-macro" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.72", -] - -[[package]] -name = "futures-sink" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" - -[[package]] -name = "futures-task" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" - -[[package]] -name = "futures-util" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" -dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-macro", - "futures-sink", - "futures-task", - "memchr", - "pin-project-lite", - "pin-utils", - "slab", -] - -[[package]] -name = "fxhash" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" -dependencies = [ - "byteorder", -] - -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", -] - -[[package]] -name = "getopts" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" -dependencies = [ - "unicode-width", -] - -[[package]] -name = "getrandom" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - -[[package]] -name = "gimli" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" - -[[package]] -name = "glob" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" - -[[package]] -name = "h2" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa82e28a107a8cc405f0839610bdc9b15f1e25ec7d696aa5cf173edbcb1486ab" -dependencies = [ - "atomic-waker", - "bytes", - "fnv", - "futures-core", - "futures-sink", - "http", - "indexmap 2.3.0", - "slab", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" - -[[package]] -name = "hashbrown" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" - -[[package]] -name = "heck" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" - -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - -[[package]] -name = "hermit-abi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - -[[package]] -name = "himmelblaud" -version = "4.21.0" -dependencies = [ - "bytes", - "chelps", - "clap 4.5.14", - "dbg", - "futures", - "idmap", - "kanidm-hsm-crypto", - "libc", - "libhimmelblau", - "ntstatus_gen", - "param", - "serde", - "serde_json", - "sock", - "talloc", - "tdb", - "tempfile", - "tokio", - "tokio-util", - "version", -] - -[[package]] -name = "home" -version = "0.5.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" -dependencies = [ - "windows-sys 0.52.0", -] - -[[package]] -name = "hostname" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9c7c7c8ac16c798734b8a24560c1362120597c40d5e1459f09498f8f6c8f2ba" -dependencies = [ - "cfg-if", - "libc", - "windows", -] - -[[package]] -name = "html5ever" -version = "0.27.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c13771afe0e6e846f1e67d038d4cb29998a6779f93c809212e4e9c32efd244d4" -dependencies = [ - "log", - "mac", - "markup5ever", - "proc-macro2", - "quote", - "syn 2.0.72", -] - -[[package]] -name = "http" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - -[[package]] -name = "http-body" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" -dependencies = [ - "bytes", - "http", -] - -[[package]] -name = "http-body-util" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" -dependencies = [ - "bytes", - "futures-util", - "http", - "http-body", - "pin-project-lite", -] - -[[package]] -name = "httparse" -version = "1.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" - -[[package]] -name = "hyper" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" -dependencies = [ - "bytes", - "futures-channel", - "futures-util", - "h2", - "http", - "http-body", - "httparse", - "itoa", - "pin-project-lite", - "smallvec", - "tokio", - "want", -] - -[[package]] -name = "hyper-rustls" -version = "0.27.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" -dependencies = [ - "futures-util", - "http", - "hyper", - "hyper-util", - "rustls", - "rustls-pki-types", - "tokio", - "tokio-rustls", - "tower-service", -] - -[[package]] -name = "hyper-tls" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" -dependencies = [ - "bytes", - "http-body-util", - "hyper", - "hyper-util", - "native-tls", - "tokio", - "tokio-native-tls", - "tower-service", -] - -[[package]] -name = "hyper-util" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cde7055719c54e36e95e8719f95883f22072a48ede39db7fc17a4e1d5281e9b9" -dependencies = [ - "bytes", - "futures-channel", - "futures-util", - "http", - "http-body", - "hyper", - "pin-project-lite", - "socket2", - "tokio", - "tower", - "tower-service", - "tracing", -] - -[[package]] -name = "idmap" -version = "4.21.0" -dependencies = [ - "bindgen", - "cc", - "chelps", - "dbg", - "libc", -] - -[[package]] -name = "idna" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" -dependencies = [ - "unicode-bidi", - "unicode-normalization", -] - -[[package]] -name = "idna" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" -dependencies = [ - "unicode-bidi", - "unicode-normalization", -] - -[[package]] -name = "indexmap" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown 0.12.3", -] - -[[package]] -name = "indexmap" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3fc2e30ba82dd1b3911c8de1ffc143c74a914a14e99514d7637e3099df5ea0" -dependencies = [ - "equivalent", - "hashbrown 0.14.5", -] - -[[package]] -name = "ipnet" -version = "2.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" - -[[package]] -name = "is_terminal_polyfill" -version = "1.70.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" - -[[package]] -name = "itertools" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" -dependencies = [ - "either", -] - -[[package]] -name = "itoa" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" - -[[package]] -name = "js-sys" -version = "0.3.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" -dependencies = [ - "wasm-bindgen", -] - -[[package]] -name = "kanidm-hsm-crypto" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10b3ed8e86cda3da4f274c677a3057d567bd7b715a0feb06a656e55cc75faf5e" -dependencies = [ - "argon2", - "hex", - "openssl", - "serde", - "tracing", - "zeroize", -] - -[[package]] -name = "lazy_static" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" - -[[package]] -name = "lazycell" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" - -[[package]] -name = "libc" -version = "0.2.155" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" - -[[package]] -name = "libhimmelblau" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9bf69727a5d6f3e1e3685569791a7b591e23f811aa6dea5362b274516ee5696" -dependencies = [ - "base64 0.22.1", - "cbindgen", - "compact_jwt", - "hostname", - "kanidm-hsm-crypto", - "openssl", - "os-release", - "paste", - "regex", - "reqwest", - "scraper", - "serde", - "serde_json", - "tokio", - "tracing", - "tracing-subscriber", - "urlencoding", - "uuid", - "zeroize", -] - -[[package]] -name = "libloading" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" -dependencies = [ - "cfg-if", - "windows-targets 0.52.6", -] - -[[package]] -name = "libnss" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c4bc0291fc787d67c56e9ed79b80780e53bfb9be173177f301ee666cec1021b" -dependencies = [ - "lazy_static", - "libc", - "paste", -] - -[[package]] -name = "linux-raw-sys" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" - -[[package]] -name = "lock_api" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" -dependencies = [ - "autocfg", - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" - -[[package]] -name = "mac" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" - -[[package]] -name = "markup5ever" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16ce3abbeba692c8b8441d036ef91aea6df8da2c6b6e21c7e14d3c18e526be45" -dependencies = [ - "log", - "phf 0.11.2", - "phf_codegen 0.11.2", - "string_cache", - "string_cache_codegen", - "tendril", -] - -[[package]] -name = "memchr" -version = "2.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" - -[[package]] -name = "mime" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" - -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - -[[package]] -name = "miniz_oxide" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" -dependencies = [ - "adler", -] - -[[package]] -name = "mio" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4569e456d394deccd22ce1c1913e6ea0e54519f577285001215d33557431afe4" -dependencies = [ - "hermit-abi 0.3.9", - "libc", - "wasi", - "windows-sys 0.52.0", -] - -[[package]] -name = "native-tls" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" -dependencies = [ - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - -[[package]] -name = "new_debug_unreachable" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" - -[[package]] -name = "nom" -version = "7.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" -dependencies = [ - "memchr", - "minimal-lexical", -] - -[[package]] -name = "nss_himmelblau" -version = "4.21.0" -dependencies = [ - "libc", - "libnss", - "ntstatus_gen", - "param", - "sock", - "version", -] - -[[package]] -name = "ntstatus_gen" -version = "4.21.0" - -[[package]] -name = "nu-ansi-term" -version = "0.46.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" -dependencies = [ - "overload", - "winapi", -] - -[[package]] -name = "num-conv" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" - -[[package]] -name = "object" -version = "0.36.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27b64972346851a39438c60b341ebc01bba47464ae329e55cf343eb93964efd9" -dependencies = [ - "memchr", -] - -[[package]] -name = "once_cell" -version = "1.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" - -[[package]] -name = "openssl" -version = "0.10.66" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" -dependencies = [ - "bitflags 2.6.0", - "cfg-if", - "foreign-types", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-kdf" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "feda4b74ded511c6d8543db00166f70f572ca7e5eb72f4817bf08628b5bbc1f4" -dependencies = [ - "foreign-types", - "libc", - "openssl", - "openssl-sys", - "pkg-config", - "thiserror", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.72", -] - -[[package]] -name = "openssl-probe" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" - -[[package]] -name = "openssl-sys" -version = "0.9.103" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - -[[package]] -name = "os-release" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82f29ae2f71b53ec19cc23385f8e4f3d90975195aa3d09171ba3bef7159bec27" -dependencies = [ - "lazy_static", -] - -[[package]] -name = "os_str_bytes" -version = "6.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1" - -[[package]] -name = "overload" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" - -[[package]] -name = "pam_himmelblau" -version = "4.21.0" -dependencies = [ - "chelps", - "dbg", - "libc", - "param", - "pkg-config", - "sock", -] - -[[package]] -name = "param" -version = "4.21.0" -dependencies = [ - "bindgen", - "chelps", - "dbg", - "ntstatus_gen", - "paste", -] - -[[package]] -name = "parking_lot" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-targets 0.52.6", -] - -[[package]] -name = "password-hash" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166" -dependencies = [ - "base64ct", - "rand_core", - "subtle", -] - -[[package]] -name = "paste" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" - -[[package]] -name = "percent-encoding" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" - -[[package]] -name = "phf" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" -dependencies = [ - "phf_shared 0.10.0", -] - -[[package]] -name = "phf" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" -dependencies = [ - "phf_macros", - "phf_shared 0.11.2", -] - -[[package]] -name = "phf_codegen" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb1c3a8bc4dd4e5cfce29b44ffc14bedd2ee294559a294e2a4d4c9e9a6a13cd" -dependencies = [ - "phf_generator 0.10.0", - "phf_shared 0.10.0", -] - -[[package]] -name = "phf_codegen" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8d39688d359e6b34654d328e262234662d16cc0f60ec8dcbe5e718709342a5a" -dependencies = [ - "phf_generator 0.11.2", - "phf_shared 0.11.2", -] - -[[package]] -name = "phf_generator" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" -dependencies = [ - "phf_shared 0.10.0", - "rand", -] - -[[package]] -name = "phf_generator" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" -dependencies = [ - "phf_shared 0.11.2", - "rand", -] - -[[package]] -name = "phf_macros" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" -dependencies = [ - "phf_generator 0.11.2", - "phf_shared 0.11.2", - "proc-macro2", - "quote", - "syn 2.0.72", -] - -[[package]] -name = "phf_shared" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" -dependencies = [ - "siphasher", -] - -[[package]] -name = "phf_shared" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" -dependencies = [ - "siphasher", -] - -[[package]] -name = "pin-project" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.72", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "pkg-config" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" - -[[package]] -name = "powerfmt" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" - -[[package]] -name = "ppv-lite86" -version = "0.2.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" -dependencies = [ - "zerocopy", -] - -[[package]] -name = "precomputed-hash" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" - -[[package]] -name = "prettyplease" -version = "0.2.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e" -dependencies = [ - "proc-macro2", - "syn 2.0.72", -] - -[[package]] -name = "proc-macro2" -version = "1.0.86" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "psl-types" -version = "2.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33cb294fe86a74cbcf50d4445b37da762029549ebeea341421c7c70370f86cac" - -[[package]] -name = "publicsuffix" -version = "2.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96a8c1bda5ae1af7f99a2962e49df150414a43d62404644d98dd5c3a93d07457" -dependencies = [ - "idna 0.3.0", - "psl-types", -] - -[[package]] -name = "quote" -version = "1.0.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom", -] - -[[package]] -name = "redox_syscall" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" -dependencies = [ - "bitflags 2.6.0", -] - -[[package]] -name = "regex" -version = "1.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" - -[[package]] -name = "reqwest" -version = "0.12.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7d6d2a27d57148378eb5e111173f4276ad26340ecc5c49a4a2152167a2d6a37" -dependencies = [ - "base64 0.22.1", - "bytes", - "cookie", - "cookie_store", - "encoding_rs", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "http-body-util", - "hyper", - "hyper-rustls", - "hyper-tls", - "hyper-util", - "ipnet", - "js-sys", - "log", - "mime", - "native-tls", - "once_cell", - "percent-encoding", - "pin-project-lite", - "rustls-pemfile", - "serde", - "serde_json", - "serde_urlencoded", - "sync_wrapper", - "system-configuration", - "tokio", - "tokio-native-tls", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "winreg", -] - -[[package]] -name = "ring" -version = "0.17.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" -dependencies = [ - "cc", - "cfg-if", - "getrandom", - "libc", - "spin", - "untrusted", - "windows-sys 0.52.0", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" - -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - -[[package]] -name = "rustix" -version = "0.38.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" -dependencies = [ - "bitflags 2.6.0", - "errno", - "libc", - "linux-raw-sys", - "windows-sys 0.52.0", -] - -[[package]] -name = "rustls" -version = "0.23.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c58f8c84392efc0a126acce10fa59ff7b3d2ac06ab451a33f2741989b806b044" -dependencies = [ - "once_cell", - "rustls-pki-types", - "rustls-webpki", - "subtle", - "zeroize", -] - -[[package]] -name = "rustls-pemfile" -version = "2.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "196fe16b00e106300d3e45ecfcb764fa292a535d7326a29a5875c579c7417425" -dependencies = [ - "base64 0.22.1", - "rustls-pki-types", -] - -[[package]] -name = "rustls-pki-types" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0" - -[[package]] -name = "rustls-webpki" -version = "0.102.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e6b52d4fda176fd835fdc55a835d4a89b8499cad995885a21149d5ad62f852e" -dependencies = [ - "ring", - "rustls-pki-types", - "untrusted", -] - -[[package]] -name = "ryu" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" - -[[package]] -name = "schannel" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" -dependencies = [ - "windows-sys 0.52.0", -] - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "scraper" -version = "0.19.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "761fb705fdf625482d2ed91d3f0559dcfeab2798fe2771c69560a774865d0802" -dependencies = [ - "ahash", - "cssparser", - "ego-tree", - "getopts", - "html5ever", - "once_cell", - "selectors", - "tendril", -] - -[[package]] -name = "security-framework" -version = "2.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" -dependencies = [ - "bitflags 2.6.0", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75da29fe9b9b08fe9d6b22b5b4bcbc75d8db3aa31e639aa56bb62e9d46bfceaf" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "selectors" -version = "0.25.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eb30575f3638fc8f6815f448d50cb1a2e255b0897985c8c59f4d37b72a07b06" -dependencies = [ - "bitflags 2.6.0", - "cssparser", - "derive_more", - "fxhash", - "log", - "new_debug_unreachable", - "phf 0.10.1", - "phf_codegen 0.10.0", - "precomputed-hash", - "servo_arc", - "smallvec", -] - -[[package]] -name = "serde" -version = "1.0.205" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e33aedb1a7135da52b7c21791455563facbbcc43d0f0f66165b42c21b3dfb150" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.205" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "692d6f5ac90220161d6774db30c662202721e64aed9058d2c394f451261420c1" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.72", -] - -[[package]] -name = "serde_json" -version = "1.0.122" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784b6203951c57ff748476b126ccb5e8e2959a5c19e5c617ab1956be3dbc68da" -dependencies = [ - "itoa", - "memchr", - "ryu", - "serde", -] - -[[package]] -name = "serde_urlencoded" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" -dependencies = [ - "form_urlencoded", - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "servo_arc" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d036d71a959e00c77a63538b90a6c2390969f9772b096ea837205c6bd0491a44" -dependencies = [ - "stable_deref_trait", -] - -[[package]] -name = "sharded-slab" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" -dependencies = [ - "lazy_static", -] - -[[package]] -name = "shlex" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" - -[[package]] -name = "signal-hook-registry" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" -dependencies = [ - "libc", -] - -[[package]] -name = "siphasher" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" - -[[package]] -name = "slab" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] - -[[package]] -name = "smallvec" -version = "1.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" - -[[package]] -name = "sock" -version = "4.21.0" -dependencies = [ - "chelps", - "dbg", - "libc", - "libnss", - "ntstatus_gen", - "param", - "serde", - "serde_json", -] - -[[package]] -name = "socket2" -version = "0.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] - -[[package]] -name = "spin" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" - -[[package]] -name = "stable_deref_trait" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" - -[[package]] -name = "string_cache" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" -dependencies = [ - "new_debug_unreachable", - "once_cell", - "parking_lot", - "phf_shared 0.10.0", - "precomputed-hash", - "serde", -] - -[[package]] -name = "string_cache_codegen" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988" -dependencies = [ - "phf_generator 0.10.0", - "phf_shared 0.10.0", - "proc-macro2", - "quote", -] - -[[package]] -name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - -[[package]] -name = "strsim" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" - -[[package]] -name = "subtle" -version = "2.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" - -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "2.0.72" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "sync_wrapper" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" - -[[package]] -name = "system-configuration" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" -dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "system-configuration-sys", -] - -[[package]] -name = "system-configuration-sys" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "talloc" -version = "4.21.0" -dependencies = [ - "bindgen", - "chelps", - "config", -] - -[[package]] -name = "tdb" -version = "4.21.0" -dependencies = [ - "bindgen", - "chelps", - "config", - "dbg", - "libc", - "ntstatus_gen", -] - -[[package]] -name = "tempfile" -version = "3.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" -dependencies = [ - "cfg-if", - "fastrand", - "once_cell", - "rustix", - "windows-sys 0.59.0", -] - -[[package]] -name = "tendril" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d24a120c5fc464a3458240ee02c299ebcb9d67b5249c8848b09d639dca8d7bb0" -dependencies = [ - "futf", - "mac", - "utf-8", -] - -[[package]] -name = "termcolor" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "textwrap" -version = "0.16.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9" - -[[package]] -name = "thiserror" -version = "1.0.63" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.63" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.72", -] - -[[package]] -name = "thread_local" -version = "1.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" -dependencies = [ - "cfg-if", - "once_cell", -] - -[[package]] -name = "time" -version = "0.3.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" -dependencies = [ - "deranged", - "itoa", - "num-conv", - "powerfmt", - "serde", - "time-core", - "time-macros", -] - -[[package]] -name = "time-core" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" - -[[package]] -name = "time-macros" -version = "0.2.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" -dependencies = [ - "num-conv", - "time-core", -] - -[[package]] -name = "tinyvec" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - -[[package]] -name = "tokio" -version = "1.39.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daa4fb1bc778bd6f04cbfc4bb2d06a7396a8f299dc33ea1900cedaa316f467b1" -dependencies = [ - "backtrace", - "bytes", - "libc", - "mio", - "parking_lot", - "pin-project-lite", - "signal-hook-registry", - "socket2", - "tokio-macros", - "windows-sys 0.52.0", -] - -[[package]] -name = "tokio-macros" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.72", -] - -[[package]] -name = "tokio-native-tls" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" -dependencies = [ - "native-tls", - "tokio", -] - -[[package]] -name = "tokio-rustls" -version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" -dependencies = [ - "rustls", - "rustls-pki-types", - "tokio", -] - -[[package]] -name = "tokio-util" -version = "0.7.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" -dependencies = [ - "bytes", - "futures-core", - "futures-sink", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "toml" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" -dependencies = [ - "serde", -] - -[[package]] -name = "tower" -version = "0.4.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" -dependencies = [ - "futures-core", - "futures-util", - "pin-project", - "pin-project-lite", - "tokio", - "tower-layer", - "tower-service", -] - -[[package]] -name = "tower-layer" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" - -[[package]] -name = "tower-service" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" - -[[package]] -name = "tracing" -version = "0.1.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" -dependencies = [ - "pin-project-lite", - "tracing-attributes", - "tracing-core", -] - -[[package]] -name = "tracing-attributes" -version = "0.1.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.72", -] - -[[package]] -name = "tracing-core" -version = "0.1.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" -dependencies = [ - "once_cell", - "valuable", -] - -[[package]] -name = "tracing-log" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" -dependencies = [ - "log", - "once_cell", - "tracing-core", -] - -[[package]] -name = "tracing-subscriber" -version = "0.3.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" -dependencies = [ - "nu-ansi-term", - "sharded-slab", - "smallvec", - "thread_local", - "tracing-core", - "tracing-log", -] - -[[package]] -name = "try-lock" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" - -[[package]] -name = "typenum" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" - -[[package]] -name = "unicode-bidi" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" - -[[package]] -name = "unicode-ident" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" - -[[package]] -name = "unicode-normalization" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" -dependencies = [ - "tinyvec", -] - -[[package]] -name = "unicode-width" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" - -[[package]] -name = "untrusted" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" - -[[package]] -name = "url" -version = "2.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" -dependencies = [ - "form_urlencoded", - "idna 0.5.0", - "percent-encoding", - "serde", -] - -[[package]] -name = "urlencoding" -version = "2.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" - -[[package]] -name = "utf-8" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" - -[[package]] -name = "utf8parse" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" - -[[package]] -name = "uuid" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" -dependencies = [ - "getrandom", - "serde", -] - -[[package]] -name = "valuable" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" - -[[package]] -name = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - -[[package]] -name = "version" -version = "4.21.0" -dependencies = [ - "bindgen", - "cc", - "chelps", - "libc", -] - -[[package]] -name = "version_check" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" - -[[package]] -name = "want" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" -dependencies = [ - "try-lock", -] - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "wasm-bindgen" -version = "0.2.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" -dependencies = [ - "cfg-if", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" -dependencies = [ - "bumpalo", - "log", - "once_cell", - "proc-macro2", - "quote", - "syn 2.0.72", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" -dependencies = [ - "cfg-if", - "js-sys", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.72", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" - -[[package]] -name = "web-sys" -version = "0.3.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "which" -version = "4.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" -dependencies = [ - "either", - "home", - "once_cell", - "rustix", -] - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-util" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" -dependencies = [ - "windows-sys 0.59.0", -] - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "windows" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" -dependencies = [ - "windows-core", - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-core" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" -dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.5", -] - -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-sys" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", -] - -[[package]] -name = "windows-targets" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" -dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm 0.52.6", - "windows_x86_64_msvc 0.52.6", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" - -[[package]] -name = "winreg" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5" -dependencies = [ - "cfg-if", - "windows-sys 0.48.0", -] - -[[package]] -name = "zerocopy" -version = "0.7.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" -dependencies = [ - "byteorder", - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.7.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.72", -] - -[[package]] -name = "zeroize" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" -dependencies = [ - "zeroize_derive", -] - -[[package]] -name = "zeroize_derive" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.72", -] diff --git a/rust/Cargo.toml b/rust/Cargo.toml index c32050b9dd0..4ed73e6a384 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -7,18 +7,6 @@ version = "4.21.0" [workspace] resolver = "2" members = [ - "chelps", "config", "dbg", "himmelblaud", "idmap", - "nss", "ntstatus_gen", "pam", - "param", "sock", "talloc", "tdb", "version", ] [workspace.dependencies] -param = { path = "param" } -dbg = { path = "dbg" } -chelps = { path = "chelps" } -sock = { path = "sock" } -ntstatus_gen = { path = "ntstatus_gen" } -tdb = { path = "tdb" } -idmap = { path = "idmap" } -libc = "0.2.155" -config = { path = "config" } diff --git a/rust/build.rs b/rust/build.rs deleted file mode 100644 index fc0dfaf20eb..00000000000 --- a/rust/build.rs +++ /dev/null @@ -1,19 +0,0 @@ -use std::env; - -fn main() { - if let Some(vers) = version::samba_version_string() { - println!("cargo:rustc-env=CARGO_PKG_VERSION={}", vers); - } - println!( - "cargo:rustc-env=CARGO_PKG_VERSION_MAJOR={}", - version::SAMBA_VERSION_MAJOR - ); - println!( - "cargo:rustc-env=CARGO_PKG_VERSION_MINOR={}", - version::SAMBA_VERSION_MINOR - ); - println!( - "cargo:rustc-env=CARGO_PKG_VERSION_PATCH={}", - version::SAMBA_VERSION_RELEASE - ); -} diff --git a/rust/chelps/Cargo.toml b/rust/chelps/Cargo.toml deleted file mode 100644 index 80dfe1c8f9b..00000000000 --- a/rust/chelps/Cargo.toml +++ /dev/null @@ -1,8 +0,0 @@ -[package] -name = "chelps" -edition.workspace = true -license.workspace = true -homepage.workspace = true -version.workspace = true - -[dependencies] diff --git a/rust/chelps/src/lib.rs b/rust/chelps/src/lib.rs deleted file mode 100644 index 79be4f03e5e..00000000000 --- a/rust/chelps/src/lib.rs +++ /dev/null @@ -1,154 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - C conversion helper functions and macros - - Copyright (C) David Mulder 2024 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -use std::ffi::{CStr, CString}; -use std::os::raw::c_char; -use std::ptr; - -pub unsafe fn wrap_c_char(input: *const c_char) -> Option { - if input.is_null() { - return None; - } - - let c_str = unsafe { CStr::from_ptr(input) }; - match c_str.to_str() { - Ok(output) => Some(output.to_string()), - Err(_) => None, - } -} - -pub fn wrap_string(input: &str) -> *mut c_char { - match CString::new(input.to_string()) { - Ok(msg) => msg.into_raw(), - Err(_) => ptr::null_mut(), - } -} - -pub unsafe fn string_free(input: *mut c_char) { - if !input.is_null() { - unsafe { - let _ = CString::from_raw(input); - } - } -} - -#[macro_export] -macro_rules! function { - () => {{ - fn f() {} - fn type_name_of(_: T) -> &'static str { - std::any::type_name::() - } - let name = type_name_of(f); - - let base_name = match name.rfind("::") { - Some(pos) => &name[..pos], - None => name, - }; - let parts: Vec<&str> = base_name - .split("::") - .filter(|&p| p != "{{closure}}") - .collect(); - parts.join("::") - }}; -} - -#[cfg(test)] -mod tests { - use super::*; - use std::ffi::CString; - use std::ptr; - - #[test] - fn test_wrap_c_char_non_null() { - let original = "Hello, world!"; - let c_string = CString::new(original).expect("CString::new failed"); - let c_ptr = c_string.as_ptr(); - - let result = unsafe { wrap_c_char(c_ptr) }; - assert_eq!(result, Some(original.to_string())); - } - - #[test] - fn test_wrap_c_char_null() { - let result = unsafe { wrap_c_char(ptr::null()) }; - assert!(result.is_none()); - } - - #[test] - fn test_wrap_c_char_invalid_utf8() { - let invalid_utf8 = vec![0xff, 0xff, 0xff, 0xff]; - let c_string = CString::new(invalid_utf8).expect("CString::new failed"); - let c_ptr = c_string.as_ptr(); - - let result = unsafe { wrap_c_char(c_ptr) }; - assert!(result.is_none()); - } - - #[test] - fn test_wrap_string() { - let original = "Hello, world!"; - let c_ptr = wrap_string(original); - - let c_str = unsafe { CStr::from_ptr(c_ptr) }; - let result = c_str.to_str().expect("CStr::to_str failed"); - - assert_eq!(result, original); - - // Clean up the allocated memory - unsafe { string_free(c_ptr) }; - } - - #[test] - fn test_wrap_string_empty() { - let original = ""; - let c_ptr = wrap_string(original); - - let c_str = unsafe { CStr::from_ptr(c_ptr) }; - let result = c_str.to_str().expect("CStr::to_str failed"); - - assert_eq!(result, original); - - // Clean up the allocated memory - unsafe { string_free(c_ptr) }; - } - - #[test] - fn test_wrap_string_null_pointer() { - let c_ptr = wrap_string("\0"); - assert!(c_ptr.is_null()); - } - - #[test] - fn test_string_free_null() { - unsafe { string_free(ptr::null_mut()) }; - // No assertion needed, just ensuring no crash occurs - } - - #[test] - fn test_string_free_non_null() { - let original = "Hello, world!"; - let c_ptr = wrap_string(original); - - unsafe { string_free(c_ptr) }; - // No assertion needed, just ensuring the memory was freed without a crash - } -} diff --git a/rust/config/Cargo.toml b/rust/config/Cargo.toml deleted file mode 100644 index e61ab953d2d..00000000000 --- a/rust/config/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "config" -edition.workspace = true -license.workspace = true -homepage.workspace = true -version.workspace = true - -[dependencies] -libc.workspace = true - -[build-dependencies] -bindgen = "0.69.4" diff --git a/rust/config/additions.h b/rust/config/additions.h deleted file mode 100644 index 96a49509ac4..00000000000 --- a/rust/config/additions.h +++ /dev/null @@ -1,8 +0,0 @@ -#include "../../bin/default/include/config.h" -#ifndef USING_SYSTEM_TDB -#define USING_SYSTEM_TDB 0 -#endif - -#ifndef USING_SYSTEM_TALLOC -#define USING_SYSTEM_TALLOC 0 -#endif diff --git a/rust/config/build.rs b/rust/config/build.rs deleted file mode 100644 index b1c1549dc70..00000000000 --- a/rust/config/build.rs +++ /dev/null @@ -1,20 +0,0 @@ -use std::env; -use std::path::PathBuf; - -fn main() { - let header = "../../bin/default/include/config.h"; - println!("cargo:rerun-if-changed={}", header); - let additions_header = "./additions.h"; - println!("cargo:rerun-if-changed={}", additions_header); - - let bindings = bindgen::Builder::default() - .header(additions_header) - .header(header) - .generate() - .expect("Failed generating config bindings!"); - - let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); - bindings - .write_to_file(out_path.join("bindings.rs")) - .expect("Couldn't write bindings!"); -} diff --git a/rust/config/src/lib.rs b/rust/config/src/lib.rs deleted file mode 100644 index a8546eecf65..00000000000 --- a/rust/config/src/lib.rs +++ /dev/null @@ -1,52 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Samba config imported into Rust - - Copyright (C) David Mulder 2024 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#![allow(non_upper_case_globals)] -#![allow(non_camel_case_types)] -#![allow(non_snake_case)] -#![allow(dead_code)] -#![allow(clippy::upper_case_acronyms)] -include!(concat!(env!("OUT_DIR"), "/bindings.rs")); - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_using_system_tdb() { - // This test just ensures that USING_SYSTEM_TDB is available from the - // config. None of the other options are really used at the moment. - assert!( - USING_SYSTEM_TDB == 0 || USING_SYSTEM_TDB == 1, - "Unexpected value for USING_SYSTEM_TDB: {}", - USING_SYSTEM_TDB - ); - } - - #[test] - fn test_using_system_talloc() { - assert!( - USING_SYSTEM_TALLOC == 0 || USING_SYSTEM_TALLOC == 1, - "Unexpected value for USING_SYSTEM_TALLOC: {}", - USING_SYSTEM_TALLOC - ); - } -} diff --git a/rust/dbg/Cargo.toml b/rust/dbg/Cargo.toml deleted file mode 100644 index e1c6284bcc7..00000000000 --- a/rust/dbg/Cargo.toml +++ /dev/null @@ -1,16 +0,0 @@ -[package] -name = "dbg" -edition.workspace = true -license.workspace = true -homepage.workspace = true -version.workspace = true - -[build-dependencies] -bindgen = "0.69.4" - -[dependencies] -chelps.workspace = true - -[dev-dependencies] -tempfile = "3.12.0" -paste = "1.0.15" diff --git a/rust/dbg/build.rs b/rust/dbg/build.rs deleted file mode 100644 index 149df6bb430..00000000000 --- a/rust/dbg/build.rs +++ /dev/null @@ -1,25 +0,0 @@ -use std::env; -use std::path::PathBuf; - -fn main() { - let bindings = bindgen::Builder::default() - .header("../../lib/util/debug.h") - .parse_callbacks(Box::new(bindgen::CargoCallbacks::new())) - .generate() - .expect("Unable to generate bindings"); - - let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); - bindings - .write_to_file(out_path.join("bindings.rs")) - .expect("Couldn't write bindings!"); - - let mut src_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()); - src_dir.push("../../bin/default/lib/util"); - println!( - "cargo:rustc-link-search=native={}", - src_dir.to_str().unwrap() - ); - println!("cargo:rustc-link-lib=samba-debug-private-samba"); - println!("cargo:rustc-link-lib=samba-util"); - println!("cargo:rustc-env=LD_LIBRARY_PATH=../../bin/shared:../../bin/shared/private/"); -} diff --git a/rust/dbg/src/lib.rs b/rust/dbg/src/lib.rs deleted file mode 100644 index 26c513e2029..00000000000 --- a/rust/dbg/src/lib.rs +++ /dev/null @@ -1,217 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Parameter loading functions - - Copyright (C) David Mulder 2024 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -pub mod ffi { - #![allow(non_upper_case_globals)] - #![allow(non_camel_case_types)] - #![allow(non_snake_case)] - #![allow(dead_code)] - #![allow(clippy::upper_case_acronyms)] - include!(concat!(env!("OUT_DIR"), "/bindings.rs")); -} - -pub const MAX_DEBUG_LEVEL: u32 = ffi::MAX_DEBUG_LEVEL; -pub const DBGLVL_ERR: u32 = ffi::DBGLVL_ERR; -pub const DBGLVL_WARNING: u32 = ffi::DBGLVL_WARNING; -pub const DBGLVL_NOTICE: u32 = ffi::DBGLVL_NOTICE; -pub const DBGLVL_INFO: u32 = ffi::DBGLVL_INFO; -pub const DBGLVL_DEBUG: u32 = ffi::DBGLVL_DEBUG; - -pub const DEBUG_DEFAULT_STDERR: ffi::debug_logtype = - ffi::debug_logtype_DEBUG_DEFAULT_STDERR; -pub const DEBUG_DEFAULT_STDOUT: ffi::debug_logtype = - ffi::debug_logtype_DEBUG_DEFAULT_STDOUT; -pub const DEBUG_FILE: ffi::debug_logtype = ffi::debug_logtype_DEBUG_FILE; -pub const DEBUG_STDOUT: ffi::debug_logtype = ffi::debug_logtype_DEBUG_STDOUT; -pub const DEBUG_STDERR: ffi::debug_logtype = ffi::debug_logtype_DEBUG_STDERR; -pub const DEBUG_CALLBACK: ffi::debug_logtype = - ffi::debug_logtype_DEBUG_CALLBACK; - -pub fn debug_set_logfile(name: &str) { - let name_cstr = chelps::wrap_string(name); - unsafe { - ffi::debug_set_logfile(name_cstr); - chelps::string_free(name_cstr); - } -} - -pub fn setup_logging(prog_name: &str, new_logtype: ffi::debug_logtype) { - let prog_name_cstr = chelps::wrap_string(prog_name); - unsafe { - ffi::setup_logging(prog_name_cstr, new_logtype); - chelps::string_free(prog_name_cstr); - } -} - -pub fn dbgflush() { - unsafe { - ffi::dbgflush(); - } -} - -#[macro_export] -macro_rules! debuglevel_set { - ($level:expr) => {{ - unsafe { - $crate::ffi::debuglevel_set_class( - $crate::ffi::DBGC_ALL as usize, - $level as i32, - ) - } - }}; -} - -#[macro_export] -macro_rules! DBG_PREFIX { - ($level:expr $(, $arg:expr)* $(,)?) => {{ - if $level <= $crate::ffi::MAX_DEBUG_LEVEL { - let location = format!("{}:{}", file!(), line!()); - let location_cstr = chelps::wrap_string(&location); - let function = chelps::function!(); - let function_msg = format!("{}: ", function); - let function_cstr = chelps::wrap_string(&function); - let function_msg_cstr = chelps::wrap_string(&function_msg); - // Always append a newline to the debug, otherwise it won't flush - // to the log. - let msg = format!("{}\n", format!($($arg),*)); - let msg_cstr = chelps::wrap_string(&msg); - unsafe { - let _ = $crate::ffi::debuglevel_get_class($crate::ffi::DBGC_CLASS as usize) >= ($level as i32) - && $crate::ffi::dbghdrclass($level as i32, - $crate::ffi::DBGC_CLASS as i32, - location_cstr, - function_cstr) - && $crate::ffi::dbgtext(function_msg_cstr) - && $crate::ffi::dbgtext(msg_cstr); - chelps::string_free(location_cstr); - chelps::string_free(function_cstr); - chelps::string_free(function_msg_cstr); - chelps::string_free(msg_cstr); - } - } - }} -} - -#[macro_export] -macro_rules! DBG_ERR { - ($msg:expr $(, $arg:expr)* $(,)?) => {{ - $crate::DBG_PREFIX!($crate::ffi::DBGLVL_ERR, $msg, $($arg),*) - }} -} - -#[macro_export] -macro_rules! DBG_WARNING { - ($msg:expr $(, $arg:expr)* $(,)?) => {{ - $crate::DBG_PREFIX!($crate::ffi::DBGLVL_WARNING, $msg, $($arg),*) - }} -} - -#[macro_export] -macro_rules! DBG_NOTICE { - ($msg:expr $(, $arg:expr)* $(,)?) => {{ - $crate::DBG_PREFIX!($crate::ffi::DBGLVL_NOTICE, $msg, $($arg),*) - }} -} - -#[macro_export] -macro_rules! DBG_INFO { - ($msg:expr $(, $arg:expr)* $(,)?) => {{ - $crate::DBG_PREFIX!($crate::ffi::DBGLVL_INFO, $msg, $($arg),*) - }} -} - -#[macro_export] -macro_rules! DBG_DEBUG { - ($msg:expr $(, $arg:expr)* $(,)?) => {{ - $crate::DBG_PREFIX!($crate::ffi::DBGLVL_DEBUG, $msg, $($arg),*) - }} -} - -#[cfg(test)] -mod tests { - use super::*; - use paste::paste; - use std::fs::File; - use std::io::Read; - use tempfile::NamedTempFile; - - #[test] - fn test_debug_constants() { - assert_eq!(MAX_DEBUG_LEVEL, ffi::MAX_DEBUG_LEVEL); - assert_eq!(DBGLVL_ERR, ffi::DBGLVL_ERR); - assert_eq!(DBGLVL_WARNING, ffi::DBGLVL_WARNING); - assert_eq!(DBGLVL_NOTICE, ffi::DBGLVL_NOTICE); - assert_eq!(DBGLVL_INFO, ffi::DBGLVL_INFO); - assert_eq!(DBGLVL_DEBUG, ffi::DBGLVL_DEBUG); - - assert_eq!( - DEBUG_DEFAULT_STDERR, - ffi::debug_logtype_DEBUG_DEFAULT_STDERR - ); - assert_eq!( - DEBUG_DEFAULT_STDOUT, - ffi::debug_logtype_DEBUG_DEFAULT_STDOUT - ); - assert_eq!(DEBUG_FILE, ffi::debug_logtype_DEBUG_FILE); - assert_eq!(DEBUG_STDOUT, ffi::debug_logtype_DEBUG_STDOUT); - assert_eq!(DEBUG_STDERR, ffi::debug_logtype_DEBUG_STDERR); - assert_eq!(DEBUG_CALLBACK, ffi::debug_logtype_DEBUG_CALLBACK); - } - - macro_rules! test_dbg_macro { - ($level:ident) => { - paste! { - #[test] - fn []() { - let logfile = NamedTempFile::new().expect("Failed to create temporary file"); - let logfile = logfile.path().to_str().unwrap(); - setup_logging("test_program", DEBUG_FILE); - debug_set_logfile(logfile); - - let logfile_output = concat!("This is a ", stringify!($level), " message"); - - debuglevel_set!([]); - - []!("{}\n", logfile_output); - dbgflush(); - - let mut file = File::open(logfile).expect("Failed to open logfile"); - let mut logfile_contents = String::new(); - file.read_to_string(&mut logfile_contents) - .expect("Failed to read logfile"); - assert!( - logfile_contents.contains(logfile_output), - "Test data missing from logfile: {}", - logfile_contents - ); - } - } - }; - } - - test_dbg_macro!(DEBUG); - // Multiple re-inits of the debug env cause it to fail, so we can't - // reliably test all of these in one go. - //test_dbg_macro!(INFO); - //test_dbg_macro!(NOTICE); - //test_dbg_macro!(WARNING); - //test_dbg_macro!(ERR); -} diff --git a/rust/himmelblaud/Cargo.toml b/rust/himmelblaud/Cargo.toml deleted file mode 100644 index dedde9e1f76..00000000000 --- a/rust/himmelblaud/Cargo.toml +++ /dev/null @@ -1,32 +0,0 @@ -[package] -name = "himmelblaud" -edition.workspace = true -license.workspace = true -homepage.workspace = true -version.workspace = true - -[dependencies] -libhimmelblau = "0.2.9" -ntstatus_gen.workspace = true -param = { workspace = true } -sock = { workspace = true } -tdb = { workspace = true } -dbg = { workspace = true } -chelps.workspace = true -clap = "4.5.9" -kanidm-hsm-crypto = "0.2.0" -serde_json = "1.0.120" -tokio = { version = "1.38.1", features = [ "rt", "macros" ] } -tokio-util = { version = "0.7.11", features = ["codec"] } -bytes = "1.6.1" -futures = "0.3.30" -serde = "1.0.204" -idmap = { workspace = true } -libc = { workspace = true } -talloc = { version = "4.21.0", path = "../talloc" } - -[build-dependencies] -version = { path = "../version" } - -[dev-dependencies] -tempfile = "3.12.0" diff --git a/rust/himmelblaud/build.rs b/rust/himmelblaud/build.rs deleted file mode 100644 index da232e3c90e..00000000000 --- a/rust/himmelblaud/build.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - println!("cargo:rustc-env=LD_LIBRARY_PATH=../../bin/shared:../../bin/shared/private/"); -} diff --git a/rust/himmelblaud/src/cache.rs b/rust/himmelblaud/src/cache.rs deleted file mode 100644 index 764753d0037..00000000000 --- a/rust/himmelblaud/src/cache.rs +++ /dev/null @@ -1,658 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Himmelblau daemon cache - - Copyright (C) David Mulder 2024 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -use dbg::DBG_ERR; -use himmelblau::error::MsalError; -use himmelblau::graph::DirectoryObject; -use himmelblau::UserToken; -use kanidm_hsm_crypto::{ - AuthValue, BoxedDynTpm, LoadableIdentityKey, LoadableMachineKey, - LoadableMsOapxbcRsaKey, Tpm, -}; -use libc::uid_t; -use ntstatus_gen::*; -use serde::{Deserialize, Serialize}; -use serde_json::{from_slice as json_from_slice, to_vec as json_to_vec}; -use std::collections::HashSet; -use tdb::Tdb; - -struct BasicCache { - tdb: Tdb, -} - -impl BasicCache { - fn new(cache_path: &str) -> Result> { - let tdb = - Tdb::open(cache_path, None, None, None, None).map_err(|e| { - DBG_ERR!("{:?}", e); - Box::new(NT_STATUS_FILE_INVALID) - })?; - Ok(BasicCache { tdb }) - } - - fn fetch_str(&self, key: &str) -> Option { - let key = key.to_string().to_lowercase(); - let exists = match self.tdb.exists(&key) { - Ok(exists) => exists, - Err(e) => { - DBG_ERR!("Failed to fetch {}: {:?}", key, e); - false - } - }; - if exists { - match self.tdb.fetch(&key) { - Ok(val) => Some(val), - Err(e) => { - DBG_ERR!("Failed to fetch {}: {:?}", key, e); - None - } - } - } else { - None - } - } - - fn fetch<'a, T>(&self, key: &str) -> Option - where - T: for<'de> Deserialize<'de>, - { - let key = key.to_string().to_lowercase(); - match self.fetch_str(&key) { - Some(val) => match json_from_slice::(val.as_bytes()) { - Ok(res) => Some(res), - Err(e) => { - DBG_ERR!("Failed to decode {}: {:?}", key, e); - None - } - }, - None => { - return None; - } - } - } - - fn store_bytes( - &mut self, - key: &str, - val: &[u8], - ) -> Result<(), Box> { - let key = key.to_string().to_lowercase(); - match self.tdb.transaction_start() { - Ok(start) => { - if !start { - DBG_ERR!("Failed to start the database transaction."); - return Err(Box::new(NT_STATUS_UNSUCCESSFUL)); - } - } - Err(e) => { - DBG_ERR!("Failed to start the database transaction: {:?}", e); - return Err(Box::new(NT_STATUS_UNSUCCESSFUL)); - } - }; - - let res = match self.tdb.store(&key, val, None) { - Ok(res) => Some(res), - Err(e) => { - DBG_ERR!("Unable to persist {}: {:?}", key, e); - None - } - }; - - let res = match res { - Some(res) => res, - None => { - let _ = self.tdb.transaction_cancel(); - return Err(Box::new(NT_STATUS_UNSUCCESSFUL)); - } - }; - if !res { - DBG_ERR!("Unable to persist {}", key); - let _ = self.tdb.transaction_cancel(); - return Err(Box::new(NT_STATUS_UNSUCCESSFUL)); - } - - let success = match self.tdb.transaction_commit() { - Ok(success) => success, - Err(e) => { - DBG_ERR!("Failed to commit the database transaction: {:?}", e); - return Err(Box::new(NT_STATUS_UNSUCCESSFUL)); - } - }; - if !success { - DBG_ERR!("Failed to commit the database transaction."); - let _ = self.tdb.transaction_cancel(); - return Err(Box::new(NT_STATUS_UNSUCCESSFUL)); - } - - Ok(()) - } - - fn store(&mut self, key: &str, val: T) -> Result<(), Box> - where - T: Serialize, - { - let key = key.to_string().to_lowercase(); - let val_bytes = match json_to_vec(&val) { - Ok(val_bytes) => val_bytes, - Err(e) => { - DBG_ERR!("Unable to serialize {}: {:?}", key, e); - return Err(Box::new(NT_STATUS_UNSUCCESSFUL)); - } - }; - self.store_bytes(&key, &val_bytes) - } - - fn keys(&self) -> Result, Box> { - self.tdb.keys().map_err(|e| { - DBG_ERR!("{:?}", e); - Box::new(NT_STATUS_UNSUCCESSFUL) - }) - } -} - -#[derive(Clone, Debug, Serialize, Deserialize)] -pub(crate) struct UserEntry { - pub(crate) upn: String, - pub(crate) uuid: String, - pub(crate) name: String, -} - -impl TryFrom<&UserToken> for UserEntry { - type Error = MsalError; - - fn try_from(token: &UserToken) -> Result { - Ok(UserEntry { - upn: token.spn()?, - uuid: token.uuid()?.to_string(), - name: token.id_token.name.clone(), - }) - } -} - -pub(crate) struct UserCache { - cache: BasicCache, -} - -impl UserCache { - pub(crate) fn new(cache_path: &str) -> Result> { - Ok(UserCache { - cache: BasicCache::new(cache_path)?, - }) - } - - pub(crate) fn fetch(&mut self, upn: &str) -> Option { - self.cache.fetch::(upn) - } - - pub(crate) fn fetch_all( - &mut self, - ) -> Result, Box> { - let keys = self.cache.keys()?; - let mut res = Vec::new(); - for upn in keys { - let entry = match self.cache.fetch::(&upn) { - Some(entry) => entry, - None => { - DBG_ERR!("Unable to fetch user {}", upn); - return Err(Box::new(NT_STATUS_UNSUCCESSFUL)); - } - }; - res.push(entry); - } - Ok(res) - } - - pub(crate) fn store( - &mut self, - entry: UserEntry, - ) -> Result<(), Box> { - let key = entry.upn.clone(); - self.cache.store::(&key, entry) - } -} - -pub(crate) struct UidCache { - cache: BasicCache, -} - -impl UidCache { - pub(crate) fn new(cache_path: &str) -> Result> { - Ok(UidCache { - cache: BasicCache::new(cache_path)?, - }) - } - - pub(crate) fn store( - &mut self, - uid: uid_t, - upn: &str, - ) -> Result<(), Box> { - let key = format!("{}", uid); - let upn = upn.to_string().to_lowercase(); - self.cache.store_bytes(&key, upn.as_bytes()) - } - - pub(crate) fn fetch(&mut self, uid: uid_t) -> Option { - let key = format!("{}", uid); - self.cache.fetch_str(&key) - } -} - -#[derive(Clone, Debug, Serialize, Deserialize)] -pub(crate) struct GroupEntry { - pub(crate) uuid: String, - members: HashSet, -} - -impl From for GroupEntry { - fn from(obj: DirectoryObject) -> Self { - GroupEntry { - uuid: obj.id.clone(), - members: HashSet::new(), - } - } -} - -impl GroupEntry { - pub(crate) fn add_member(&mut self, member: &str) { - // Only ever use lowercase names, otherwise the group - // memberships will have duplicates. - self.members.insert(member.to_lowercase()); - } - - pub(crate) fn remove_member(&mut self, member: &str) { - // Only ever use lowercase names, otherwise the group - // memberships will have duplicates. - self.members.remove(&member.to_lowercase()); - } - - pub(crate) fn into_with_member(obj: DirectoryObject, member: &str) -> Self { - let mut g: GroupEntry = obj.into(); - g.add_member(member); - g - } - - pub(crate) fn members(&self) -> Vec { - self.members.clone().into_iter().collect::>() - } -} - -impl GroupEntry { - pub fn new(uuid: &str) -> Self { - GroupEntry { - uuid: uuid.to_string(), - members: HashSet::new(), - } - } -} - -pub(crate) struct GroupCache { - cache: BasicCache, -} - -impl GroupCache { - pub(crate) fn new(cache_path: &str) -> Result> { - Ok(GroupCache { - cache: BasicCache::new(cache_path)?, - }) - } - - pub(crate) fn fetch(&mut self, uuid: &str) -> Option { - self.cache.fetch::(uuid) - } - - pub(crate) fn fetch_all( - &mut self, - ) -> Result, Box> { - let keys = self.cache.keys()?; - let mut res = Vec::new(); - for uuid in keys { - let entry = match self.cache.fetch::(&uuid) { - Some(entry) => entry, - None => { - DBG_ERR!("Unable to fetch group {}", uuid); - return Err(Box::new(NT_STATUS_UNSUCCESSFUL)); - } - }; - res.push(entry); - } - Ok(res) - } - - pub(crate) fn merge_groups( - &mut self, - member: &str, - mut entries: Vec, - ) -> Result<(), Box> { - // We need to ensure the member is removed from non-intersecting - // groups, otherwise we don't honor group membership removals. - let group_uuids: HashSet = entries - .clone() - .into_iter() - .map(|g| g.uuid.clone()) - .collect(); - let existing_group_uuids = { - let cache = &self.cache; - match cache.keys() { - Ok(keys) => keys, - Err(e) => { - DBG_ERR!("Unable to fetch groups: {:?}", e); - return Err(Box::new(NT_STATUS_UNSUCCESSFUL)); - } - } - }; - let existing_group_uuids: HashSet = - existing_group_uuids.into_iter().collect(); - let difference: HashSet = existing_group_uuids - .difference(&group_uuids) - .cloned() - .collect(); - for group_uuid in &difference { - if let Some(mut group) = - self.cache.fetch::(&group_uuid).clone() - { - group.remove_member(member); - if let Err(e) = - self.cache.store::(&group.uuid.clone(), group) - { - DBG_ERR!("Unable to store membership change: {:?}", e); - return Err(Box::new(NT_STATUS_UNSUCCESSFUL)); - } - } - } - - // Ensure the member is added to the listed groups - for group in &mut entries { - group.add_member(member); - } - - // Now add the new entries, merging with existing memberships - for group in entries { - match self.cache.fetch::(&group.uuid) { - Some(mut existing_group) => { - // Merge with an existing entry - existing_group.add_member(member); - if let Err(e) = self.cache.store::( - &existing_group.uuid.clone(), - existing_group, - ) { - DBG_ERR!("Unable to store membership change: {:?}", e); - return Err(Box::new(NT_STATUS_UNSUCCESSFUL)); - } - } - None => { - if let Err(e) = self - .cache - .store::(&group.uuid.clone(), group) - { - DBG_ERR!("Unable to store membership change: {:?}", e); - return Err(Box::new(NT_STATUS_UNSUCCESSFUL)); - } - } - } - } - Ok(()) - } -} - -pub(crate) struct PrivateCache { - cache: BasicCache, -} - -impl PrivateCache { - pub(crate) fn new(cache_path: &str) -> Result> { - Ok(PrivateCache { - cache: BasicCache::new(cache_path)?, - }) - } - - pub(crate) fn loadable_machine_key_fetch_or_create( - &mut self, - hsm: &mut BoxedDynTpm, - auth_value: &AuthValue, - ) -> Result> { - match self - .cache - .fetch::("loadable_machine_key") - { - Some(loadable_machine_key) => Ok(loadable_machine_key), - None => { - // No machine key found - create one, and store it. - let loadable_machine_key = - match hsm.machine_key_create(&auth_value) { - Ok(loadable_machine_key) => loadable_machine_key, - Err(e) => { - DBG_ERR!( - "Unable to create hsm loadable \ - machine key: {:?}", - e - ); - return Err(Box::new(NT_STATUS_UNSUCCESSFUL)); - } - }; - - self.cache.store::( - "loadable_machine_key", - loadable_machine_key.clone(), - )?; - - Ok(loadable_machine_key) - } - } - } - - pub(crate) fn loadable_transport_key_fetch( - &mut self, - realm: &str, - ) -> Option { - let transport_key_tag = format!("{}/transport", realm); - self.cache - .fetch::(&transport_key_tag) - } - - pub(crate) fn loadable_cert_key_fetch( - &mut self, - realm: &str, - ) -> Option { - let cert_key_tag = format!("{}/certificate", realm); - self.cache.fetch::(&cert_key_tag) - } - - pub(crate) fn loadable_hello_key_fetch( - &mut self, - account_id: &str, - ) -> Option { - let hello_key_tag = format!("{}/hello", account_id); - self.cache.fetch::(&hello_key_tag) - } - - pub(crate) fn loadable_cert_key_store( - &mut self, - realm: &str, - cert_key: LoadableIdentityKey, - ) -> Result<(), Box> { - let cert_key_tag = format!("{}/certificate", realm); - self.cache - .store::(&cert_key_tag, cert_key) - } - - pub(crate) fn loadable_hello_key_store( - &mut self, - account_id: &str, - hello_key: LoadableIdentityKey, - ) -> Result<(), Box> { - let hello_key_tag = format!("{}/hello", account_id); - self.cache - .store::(&hello_key_tag, hello_key) - } - - pub(crate) fn loadable_transport_key_store( - &mut self, - realm: &str, - transport_key: LoadableMsOapxbcRsaKey, - ) -> Result<(), Box> { - let transport_key_tag = format!("{}/transport", realm); - self.cache - .store::(&transport_key_tag, transport_key) - } - - pub(crate) fn device_id(&mut self, realm: &str) -> Option { - let device_id_tag = format!("{}/device_id", realm); - self.cache.fetch_str(&device_id_tag) - } - - pub(crate) fn device_id_store( - &mut self, - realm: &str, - device_id: &str, - ) -> Result<(), Box> { - let device_id_tag = format!("{}/device_id", realm); - self.cache.store_bytes(&device_id_tag, device_id.as_bytes()) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use kanidm_hsm_crypto::soft::SoftTpm; - use std::str::FromStr; - use tempfile::tempdir; - - #[test] - fn test_basic_cache_new() { - let dir = tempdir().unwrap(); - let cache_path = dir.path().join("test.tdb"); - let cache = BasicCache::new(cache_path.to_str().unwrap()); - assert!(cache.is_ok()); - } - - #[test] - fn test_basic_cache_store_fetch_str() { - let dir = tempdir().unwrap(); - let cache_path = dir.path().join("test.tdb"); - let mut cache = BasicCache::new(cache_path.to_str().unwrap()).unwrap(); - - let key = "test_key"; - let value = "test_value"; - cache.store_bytes(key, value.as_bytes()).unwrap(); - let fetched_value = cache.fetch_str(key).unwrap(); - assert_eq!(fetched_value, value); - } - - #[test] - fn test_basic_cache_store_fetch() { - let dir = tempdir().unwrap(); - let cache_path = dir.path().join("test.tdb"); - let mut cache = BasicCache::new(cache_path.to_str().unwrap()).unwrap(); - - let key = "test_key"; - let value = UserEntry { - upn: "user@test.com".to_string(), - uuid: "f63a43c7-b783-4da9-acb4-89f8ebfc49e9".to_string(), - name: "Test User".to_string(), - }; - - cache.store(key, &value).unwrap(); - let fetched_value: Option = cache.fetch(key); - assert!(fetched_value.is_some()); - let fetched_value = fetched_value.unwrap(); - assert_eq!(fetched_value.upn, value.upn); - assert_eq!(fetched_value.uuid, value.uuid); - assert_eq!(fetched_value.name, value.name); - } - - #[test] - fn test_user_cache_store_fetch() { - let dir = tempdir().unwrap(); - let cache_path = dir.path().join("test.tdb"); - let mut cache = UserCache::new(cache_path.to_str().unwrap()).unwrap(); - - let entry = UserEntry { - upn: "user@test.com".to_string(), - uuid: "f63a43c7-b783-4da9-acb4-89f8ebfc49e9".to_string(), - name: "Test User".to_string(), - }; - - cache.store(entry.clone()).unwrap(); - let fetched_entry = cache.fetch(&entry.upn); - assert!(fetched_entry.is_some()); - let fetched_entry = fetched_entry.unwrap(); - assert_eq!(fetched_entry.upn, entry.upn); - assert_eq!(fetched_entry.uuid, entry.uuid); - assert_eq!(fetched_entry.name, entry.name); - } - - #[test] - fn test_uid_cache_store_fetch() { - let dir = tempdir().unwrap(); - let cache_path = dir.path().join("test.tdb"); - let mut cache = UidCache::new(cache_path.to_str().unwrap()).unwrap(); - - let uid: uid_t = 1000; - let upn = "user@test.com"; - - cache.store(uid, upn).unwrap(); - let fetched_upn = cache.fetch(uid); - assert!(fetched_upn.is_some()); - assert_eq!(fetched_upn.unwrap(), upn); - } - - #[test] - fn test_group_cache_store_fetch() { - let dir = tempdir().unwrap(); - let cache_path = dir.path().join("test.tdb"); - let mut cache = GroupCache::new(cache_path.to_str().unwrap()).unwrap(); - - let mut group = GroupEntry { - uuid: "5f8be63a-a379-4324-9f42-9ea40bed9d7f".to_string(), - members: HashSet::new(), - }; - group.add_member("user@test.com"); - - cache.cache.store(&group.uuid, &group).unwrap(); - let fetched_group = cache.fetch(&group.uuid); - assert!(fetched_group.is_some()); - let fetched_group = fetched_group.unwrap(); - assert_eq!(fetched_group.uuid, group.uuid); - assert!(fetched_group.members.contains("user@test.com")); - } - - #[test] - fn test_private_cache_loadable_machine_key_fetch_or_create() { - let dir = tempdir().unwrap(); - let cache_path = dir.path().join("test.tdb"); - let mut cache = - PrivateCache::new(cache_path.to_str().unwrap()).unwrap(); - - let mut hsm = BoxedDynTpm::new(SoftTpm::new()); - let auth_str = AuthValue::generate().expect("Failed to create hex pin"); - let auth_value = AuthValue::from_str(&auth_str) - .expect("Unable to create auth value"); - - let result = - cache.loadable_machine_key_fetch_or_create(&mut hsm, &auth_value); - assert!(result.is_ok()); - - let fetched_key = cache - .cache - .fetch::("loadable_machine_key"); - assert!(fetched_key.is_some()); - } -} diff --git a/rust/himmelblaud/src/constants.rs b/rust/himmelblaud/src/constants.rs deleted file mode 100644 index e2a36473c6d..00000000000 --- a/rust/himmelblaud/src/constants.rs +++ /dev/null @@ -1 +0,0 @@ -pub const DEFAULT_ODC_PROVIDER: &str = "odc.officeapps.live.com"; diff --git a/rust/himmelblaud/src/himmelblaud.rs b/rust/himmelblaud/src/himmelblaud.rs deleted file mode 100644 index 36541d80c1b..00000000000 --- a/rust/himmelblaud/src/himmelblaud.rs +++ /dev/null @@ -1,295 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Himmelblau daemon - - Copyright (C) David Mulder 2024 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -use crate::cache::{GroupCache, PrivateCache, UidCache, UserCache}; -#[cfg(not(test))] -use crate::himmelblaud::himmelblaud_pam_auth::AuthSession; -use bytes::{BufMut, BytesMut}; -use dbg::{DBG_DEBUG, DBG_ERR, DBG_WARNING}; -use futures::{SinkExt, StreamExt}; -use himmelblau::graph::Graph; -use himmelblau::BrokerClientApplication; -use idmap::Idmap; -use kanidm_hsm_crypto::{BoxedDynTpm, MachineKey}; -use param::LoadParm; -use sock::{PamAuthResponse, Request, Response}; -use std::error::Error; -use std::io; -use std::io::{Error as IoError, ErrorKind}; -use std::sync::Arc; -use tokio::net::UnixStream; -use tokio::sync::Mutex; -use tokio_util::codec::{Decoder, Encoder, Framed}; - -#[cfg(not(test))] -pub(crate) struct Resolver { - realm: String, - tenant_id: String, - lp: LoadParm, - idmap: Idmap, - graph: Graph, - pcache: PrivateCache, - user_cache: UserCache, - uid_cache: UidCache, - group_cache: GroupCache, - hsm: Mutex, - machine_key: MachineKey, - client: Arc>, -} - -#[cfg(not(test))] -impl Resolver { - pub(crate) fn new( - realm: &str, - tenant_id: &str, - lp: LoadParm, - idmap: Idmap, - graph: Graph, - pcache: PrivateCache, - user_cache: UserCache, - uid_cache: UidCache, - group_cache: GroupCache, - hsm: BoxedDynTpm, - machine_key: MachineKey, - client: BrokerClientApplication, - ) -> Self { - Resolver { - realm: realm.to_string(), - tenant_id: tenant_id.to_string(), - lp, - idmap, - graph, - pcache, - user_cache, - uid_cache, - group_cache, - hsm: Mutex::new(hsm), - machine_key, - client: Arc::new(Mutex::new(client)), - } - } -} - -// The test environment is unable to communicate with Entra ID, therefore -// we alter the resolver to only test the cache interactions. - -#[cfg(test)] -pub(crate) struct Resolver { - realm: String, - tenant_id: String, - lp: LoadParm, - idmap: Idmap, - pcache: PrivateCache, - user_cache: UserCache, - uid_cache: UidCache, - group_cache: GroupCache, -} - -#[cfg(test)] -impl Resolver { - pub(crate) fn new( - realm: &str, - tenant_id: &str, - lp: LoadParm, - idmap: Idmap, - pcache: PrivateCache, - user_cache: UserCache, - uid_cache: UidCache, - group_cache: GroupCache, - ) -> Self { - Resolver { - realm: realm.to_string(), - tenant_id: tenant_id.to_string(), - lp, - idmap, - pcache, - user_cache, - uid_cache, - group_cache, - } - } -} - -struct ClientCodec; - -impl Decoder for ClientCodec { - type Error = io::Error; - type Item = Request; - - fn decode( - &mut self, - src: &mut BytesMut, - ) -> Result, Self::Error> { - match serde_json::from_slice::(src) { - Ok(msg) => { - src.clear(); - Ok(Some(msg)) - } - _ => Ok(None), - } - } -} - -impl Encoder for ClientCodec { - type Error = io::Error; - - fn encode( - &mut self, - msg: Response, - dst: &mut BytesMut, - ) -> Result<(), Self::Error> { - DBG_DEBUG!("Attempting to send response -> {:?} ...", msg); - let data = serde_json::to_vec(&msg).map_err(|e| { - DBG_ERR!("socket encoding error -> {:?}", e); - io::Error::new(ErrorKind::Other, "JSON encode error") - })?; - dst.put(data.as_slice()); - Ok(()) - } -} - -impl ClientCodec { - fn new() -> Self { - ClientCodec - } -} - -pub(crate) async fn handle_client( - stream: UnixStream, - resolver: Arc>, -) -> Result<(), Box> { - DBG_DEBUG!("Accepted connection"); - - let Ok(_ucred) = stream.peer_cred() else { - return Err(Box::new(IoError::new( - ErrorKind::Other, - "Unable to verify peer credentials.", - ))); - }; - - let mut reqs = Framed::new(stream, ClientCodec::new()); - #[cfg(not(test))] - let mut pam_auth_session_state = None; - - while let Some(Ok(req)) = reqs.next().await { - let mut resolver = resolver.lock().await; - let resp = match req { - #[cfg(not(test))] - Request::PamAuthenticateInit(account_id) => { - DBG_DEBUG!("pam authenticate init"); - - match &pam_auth_session_state { - Some(_) => { - DBG_WARNING!( - "Attempt to init \ - auth session while current \ - session is active" - ); - pam_auth_session_state = None; - Response::Error - } - None => { - let (auth_session, resp) = - resolver.pam_auth_init(&account_id)?; - pam_auth_session_state = Some(auth_session); - resp - } - } - } - #[cfg(not(test))] - Request::PamAuthenticateStep(pam_next_req) => { - DBG_DEBUG!("pam authenticate step"); - match &mut pam_auth_session_state { - Some(AuthSession::InProgress { - account_id, - cred_handler, - }) => { - let resp = resolver - .pam_auth_step( - account_id, - cred_handler, - pam_next_req, - ) - .await?; - match resp { - Response::PamAuthStepResponse( - PamAuthResponse::Success, - ) => { - pam_auth_session_state = - Some(AuthSession::Success); - } - Response::PamAuthStepResponse( - PamAuthResponse::Denied, - ) => { - pam_auth_session_state = - Some(AuthSession::Denied); - } - _ => {} - } - resp - } - _ => { - DBG_WARNING!( - "Attempt to \ - continue auth session \ - while current session is \ - inactive" - ); - Response::Error - } - } - } - Request::NssAccounts => resolver.getpwent().await?, - Request::NssAccountByName(account_id) => { - resolver.getpwnam(&account_id).await? - } - Request::NssAccountByUid(uid) => resolver.getpwuid(uid).await?, - Request::NssGroups => resolver.getgrent().await?, - Request::NssGroupByName(grp_id) => { - resolver.getgrnam(&grp_id).await? - } - Request::NssGroupByGid(gid) => resolver.getgrgid(gid).await?, - #[cfg(not(test))] - Request::PamAccountAllowed(account_id) => { - resolver.pam_acct_mgmt(&account_id).await? - } - Request::PamAccountBeginSession(_account_id) => Response::Success, - #[cfg(test)] - _ => Response::Error, - }; - reqs.send(resp).await?; - reqs.flush().await?; - DBG_DEBUG!("flushed response!"); - } - - DBG_DEBUG!("Disconnecting client ..."); - Ok(()) -} - -mod himmelblaud_getgrent; -mod himmelblaud_getgrgid; -mod himmelblaud_getgrnam; -mod himmelblaud_getpwent; -mod himmelblaud_getpwnam; -mod himmelblaud_getpwuid; -#[cfg(not(test))] -mod himmelblaud_pam_acct_mgmt; -#[cfg(not(test))] -mod himmelblaud_pam_auth; diff --git a/rust/himmelblaud/src/himmelblaud/himmelblaud_getgrent.rs b/rust/himmelblaud/src/himmelblaud/himmelblaud_getgrent.rs deleted file mode 100644 index 67e02eed463..00000000000 --- a/rust/himmelblaud/src/himmelblaud/himmelblaud_getgrent.rs +++ /dev/null @@ -1,154 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Himmelblau daemon implementation for nss getgrent - - Copyright (C) David Mulder 2024 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -use crate::himmelblaud::Resolver; -use dbg::DBG_ERR; -use ntstatus_gen::*; -use sock::{Group, Response}; - -impl Resolver { - pub(crate) async fn getgrent(&mut self) -> Result> { - let group_entries = self.group_cache.fetch_all()?; - let mut res = Vec::new(); - for entry in group_entries { - let name = entry.uuid.clone(); - let gid = self - .idmap - .gen_to_unix(&self.tenant_id, &entry.uuid) - .map_err(|e| { - DBG_ERR!("{:?}", e); - Box::new(NT_STATUS_NO_SUCH_GROUP) - })?; - let group = Group { - name, - passwd: "x".to_string(), - gid, - members: entry.members(), - }; - res.push(group); - } - Ok(Response::NssGroups(res)) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::cache::GroupEntry; - use crate::{GroupCache, PrivateCache, UidCache, UserCache}; - use idmap::Idmap; - use param::LoadParm; - use std::collections::HashSet; - use tempfile::tempdir; - - #[tokio::test] - async fn test_getgrent() { - // Create a temporary directory for the cache - let dir = tempdir().unwrap(); - - // Initialize the caches - let private_cache_path = dir - .path() - .join("himmelblau.tdb") - .to_str() - .unwrap() - .to_string(); - let pcache = PrivateCache::new(&private_cache_path).unwrap(); - let user_cache_path = dir - .path() - .join("himmelblau_users.tdb") - .to_str() - .unwrap() - .to_string(); - let user_cache = UserCache::new(&user_cache_path).unwrap(); - let uid_cache_path = dir - .path() - .join("uid_cache.tdb") - .to_str() - .unwrap() - .to_string(); - let uid_cache = UidCache::new(&uid_cache_path).unwrap(); - let group_cache_path = dir - .path() - .join("himmelblau_groups.tdb") - .to_str() - .unwrap() - .to_string(); - let mut group_cache = GroupCache::new(&group_cache_path).unwrap(); - - // Insert dummy GroupEntries into the cache - let group_uuid1 = "c490c3ea-fd98-4d45-b6aa-2a3520f804fa"; - let group_uuid2 = "f7a51b58-84de-42a3-b5b1-967b17c04f89"; - let dummy_group1 = GroupEntry::new(group_uuid1); - let dummy_group2 = GroupEntry::new(group_uuid2); - group_cache - .merge_groups("user1@test.com", vec![dummy_group1.clone()]) - .unwrap(); - group_cache - .merge_groups("user2@test.com", vec![dummy_group2.clone()]) - .unwrap(); - - // Initialize the Idmap with dummy configuration - let realm = "test.com"; - let tenant_id = "89a61bb7-d1b9-4356-a1e0-75d88e06f14e"; - let mut idmap = Idmap::new().unwrap(); - idmap - .add_gen_domain(realm, tenant_id, (1000, 2000)) - .unwrap(); - - // Initialize dummy configuration - let lp = LoadParm::new(None).expect("Failed loading default config"); - - // Initialize the Resolver - let mut resolver = Resolver { - realm: realm.to_string(), - tenant_id: tenant_id.to_string(), - lp, - idmap, - pcache, - user_cache, - uid_cache, - group_cache, - }; - - // Test the getgrent function - let result = resolver.getgrent().await.unwrap(); - - match result { - Response::NssGroups(mut groups) => { - groups.sort_by(|a, b| a.name.cmp(&b.name)); - assert_eq!(groups.len(), 2); - - let group1 = &groups[0]; - assert_eq!(group1.name, dummy_group1.uuid); - assert_eq!(group1.gid, 1388); - assert_eq!(group1.members, vec!["user1@test.com".to_string()]); - - let group2 = &groups[1]; - assert_eq!(group2.name, dummy_group2.uuid); - assert_eq!(group2.gid, 1593); - assert_eq!(group2.members, vec!["user2@test.com".to_string()]); - } - other => { - panic!("Expected NssGroups with a list of groups: {:?}", other) - } - } - } -} diff --git a/rust/himmelblaud/src/himmelblaud/himmelblaud_getgrgid.rs b/rust/himmelblaud/src/himmelblaud/himmelblaud_getgrgid.rs deleted file mode 100644 index f921446a653..00000000000 --- a/rust/himmelblaud/src/himmelblaud/himmelblaud_getgrgid.rs +++ /dev/null @@ -1,147 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Himmelblau daemon implementation for nss getgrgid - - Copyright (C) David Mulder 2024 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -use crate::himmelblaud::Resolver; -use libc::gid_t; -use ntstatus_gen::NTSTATUS; -use sock::{Group, Response}; - -impl Resolver { - pub(crate) async fn getgrgid( - &mut self, - gid: gid_t, - ) -> Result> { - if let Some(uuid) = self.uid_cache.fetch(gid) { - if let Some(entry) = self.group_cache.fetch(&uuid) { - return Ok(Response::NssGroup(Some(Group { - name: entry.uuid.clone(), - passwd: "x".to_string(), - gid, - members: entry.members(), - }))); - } - } - Ok(Response::NssGroup(None)) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::cache::GroupEntry; - use crate::{GroupCache, PrivateCache, UidCache, UserCache}; - use idmap::Idmap; - use param::LoadParm; - use std::collections::HashSet; - use tempfile::tempdir; - - #[tokio::test] - async fn test_getgrgid() { - // Create a temporary directory for the cache - let dir = tempdir().unwrap(); - - // Initialize the caches - let private_cache_path = dir - .path() - .join("himmelblau.tdb") - .to_str() - .unwrap() - .to_string(); - let pcache = PrivateCache::new(&private_cache_path).unwrap(); - let user_cache_path = dir - .path() - .join("himmelblau_users.tdb") - .to_str() - .unwrap() - .to_string(); - let user_cache = UserCache::new(&user_cache_path).unwrap(); - let uid_cache_path = dir - .path() - .join("uid_cache.tdb") - .to_str() - .unwrap() - .to_string(); - let mut uid_cache = UidCache::new(&uid_cache_path).unwrap(); - let group_cache_path = dir - .path() - .join("himmelblau_groups.tdb") - .to_str() - .unwrap() - .to_string(); - let mut group_cache = GroupCache::new(&group_cache_path).unwrap(); - - // Initialize the Idmap with dummy configuration - let realm = "test.com"; - let tenant_id = "89a61bb7-d1b9-4356-a1e0-75d88e06f14e"; - let mut idmap = Idmap::new().unwrap(); - idmap - .add_gen_domain(realm, tenant_id, (1000, 2000)) - .unwrap(); - - // Insert a dummy GroupEntry into the cache - let group_uuid = "c490c3ea-fd98-4d45-b6aa-2a3520f804fa".to_string(); - let dummy_gid = idmap - .gen_to_unix(tenant_id, &group_uuid) - .expect("Failed to map group gid"); - // Store the calculated gid -> uuid map in the cache - uid_cache - .store(dummy_gid, &group_uuid) - .expect("Failed to store group gid"); - let dummy_group = GroupEntry::new(&group_uuid); - group_cache - .merge_groups("user1@test.com", vec![dummy_group.clone()]) - .unwrap(); - - // Initialize dummy configuration - let lp = LoadParm::new(None).expect("Failed loading default config"); - - // Initialize the Resolver - let mut resolver = Resolver { - realm: realm.to_string(), - tenant_id: tenant_id.to_string(), - lp, - idmap, - pcache, - user_cache, - uid_cache, - group_cache, - }; - - // Test the getgrgid function with a gid that exists - let result = resolver.getgrgid(dummy_gid).await.unwrap(); - - match result { - Response::NssGroup(Some(group)) => { - assert_eq!(group.name, dummy_group.uuid); - assert_eq!(group.gid, dummy_gid); - assert_eq!(group.members, vec!["user1@test.com".to_string()]); - } - other => panic!("Expected NssGroup with Some(group): {:?}", other), - } - - // Test the getgrgid function with a gid that does not exist - let nonexistent_gid: gid_t = 1600; - let result = resolver.getgrgid(nonexistent_gid).await.unwrap(); - match result { - Response::NssGroup(None) => {} // This is the expected result - _ => panic!("Expected NssGroup with None"), - } - } -} diff --git a/rust/himmelblaud/src/himmelblaud/himmelblaud_getgrnam.rs b/rust/himmelblaud/src/himmelblaud/himmelblaud_getgrnam.rs deleted file mode 100644 index 16b1de58365..00000000000 --- a/rust/himmelblaud/src/himmelblaud/himmelblaud_getgrnam.rs +++ /dev/null @@ -1,159 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Himmelblau daemon implementation for nss getgrnam - - Copyright (C) David Mulder 2024 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -use crate::himmelblaud::Resolver; -use dbg::DBG_ERR; -use ntstatus_gen::*; -use sock::{Group, Response}; - -impl Resolver { - pub(crate) async fn getgrnam( - &mut self, - grp_id: &str, - ) -> Result> { - let entry = match self.group_cache.fetch(grp_id) { - Some(entry) => entry, - None => return Ok(Response::NssGroup(None)), - }; - let gid = self - .idmap - .gen_to_unix(&self.tenant_id, &entry.uuid) - .map_err(|e| { - DBG_ERR!("{:?}", e); - Box::new(NT_STATUS_INVALID_TOKEN) - })?; - // Store the calculated gid -> uuid map in the cache - self.uid_cache.store(gid, &entry.uuid)?; - let group = Group { - name: entry.uuid.clone(), - passwd: "x".to_string(), - gid, - members: entry.members(), - }; - return Ok(Response::NssGroup(Some(group))); - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::cache::GroupEntry; - use crate::{GroupCache, PrivateCache, UidCache, UserCache}; - use idmap::Idmap; - use param::LoadParm; - use std::collections::HashSet; - use tempfile::tempdir; - - #[tokio::test] - async fn test_getgrnam() { - // Create a temporary directory for the cache - let dir = tempdir().unwrap(); - - // Initialize the caches - let private_cache_path = dir - .path() - .join("himmelblau.tdb") - .to_str() - .unwrap() - .to_string(); - let pcache = PrivateCache::new(&private_cache_path).unwrap(); - let user_cache_path = dir - .path() - .join("himmelblau_users.tdb") - .to_str() - .unwrap() - .to_string(); - let user_cache = UserCache::new(&user_cache_path).unwrap(); - let uid_cache_path = dir - .path() - .join("uid_cache.tdb") - .to_str() - .unwrap() - .to_string(); - let uid_cache = UidCache::new(&uid_cache_path).unwrap(); - let group_cache_path = dir - .path() - .join("himmelblau_groups.tdb") - .to_str() - .unwrap() - .to_string(); - let mut group_cache = GroupCache::new(&group_cache_path).unwrap(); - - // Insert a dummy GroupEntry into the cache - let group_uuid = "c490c3ea-fd98-4d45-b6aa-2a3520f804fa"; - let dummy_group = GroupEntry::new(group_uuid); - group_cache - .merge_groups("user1@test.com", vec![dummy_group.clone()]) - .unwrap(); - group_cache - .merge_groups("user2@test.com", vec![dummy_group.clone()]) - .unwrap(); - - // Initialize the Idmap with dummy configuration - let realm = "test.com"; - let tenant_id = "89a61bb7-d1b9-4356-a1e0-75d88e06f14e"; - let mut idmap = Idmap::new().unwrap(); - idmap - .add_gen_domain(realm, tenant_id, (1000, 2000)) - .unwrap(); - - // Initialize dummy configuration - let lp = LoadParm::new(None).expect("Failed loading default config"); - - // Initialize the Resolver - let mut resolver = Resolver { - realm: realm.to_string(), - tenant_id: tenant_id.to_string(), - lp, - idmap, - pcache, - user_cache, - uid_cache, - group_cache, - }; - - // Test the getgrnam function with a group that exists - let result = resolver.getgrnam(group_uuid).await.unwrap(); - - match result { - Response::NssGroup(Some(mut group)) => { - group.members.sort(); - assert_eq!(group.name, dummy_group.uuid); - assert_eq!(group.gid, 1388); - assert_eq!( - group.members, - vec![ - "user1@test.com".to_string(), - "user2@test.com".to_string() - ] - ); - } - other => panic!("Expected NssGroup with Some(group): {:?}", other), - } - - // Test the getgrnam function with a group that does not exist - let nonexistent_group_uuid = "2ea8f1d4-1b94-4003-865b-cb247a8a1f5d"; - let result = resolver.getgrnam(nonexistent_group_uuid).await.unwrap(); - match result { - Response::NssGroup(None) => {} // This is the expected result - _ => panic!("Expected NssGroup with None"), - } - } -} diff --git a/rust/himmelblaud/src/himmelblaud/himmelblaud_getpwent.rs b/rust/himmelblaud/src/himmelblaud/himmelblaud_getpwent.rs deleted file mode 100644 index e8f7d9406ea..00000000000 --- a/rust/himmelblaud/src/himmelblaud/himmelblaud_getpwent.rs +++ /dev/null @@ -1,210 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Himmelblau daemon implementation for nss getpwent - - Copyright (C) David Mulder 2024 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -use crate::himmelblaud::Resolver; -use crate::utils::split_username; -use dbg::DBG_ERR; -use ntstatus_gen::*; -use sock::{Passwd, Response}; - -impl Resolver { - pub(crate) async fn getpwent(&mut self) -> Result> { - let user_entries = self.user_cache.fetch_all()?; - let template_homedir = self - .lp - .template_homedir() - .map_err(|e| { - DBG_ERR!("{:?}", e); - Box::new(NT_STATUS_NOT_A_DIRECTORY) - })? - .ok_or_else(|| { - DBG_ERR!("Failed to discover template homedir. Is it set?"); - Box::new(NT_STATUS_NOT_A_DIRECTORY) - })?; - let shell = self - .lp - .template_shell() - .map_err(|e| { - DBG_ERR!("{:?}", e); - Box::new(NT_STATUS_NOT_A_DIRECTORY) - })? - .ok_or_else(|| { - DBG_ERR!("Failed to discover template shell. Is it set?"); - Box::new(NT_STATUS_NOT_A_DIRECTORY) - })?; - let mut res = Vec::new(); - for entry in user_entries { - let uid = self - .idmap - .gen_to_unix(&self.tenant_id, &entry.upn) - .map_err(|e| { - DBG_ERR!("{:?}", e); - Box::new(NT_STATUS_INVALID_TOKEN) - })?; - let upn = entry.upn.clone(); - let (cn, domain) = match split_username(&upn) { - Ok(res) => res, - Err(e) => { - DBG_ERR!( - "Failed to parse user upn '{}': {:?}", - &entry.upn, - e - ); - return Err(Box::new( - NT_STATUS_INVALID_USER_PRINCIPAL_NAME, - )); - } - }; - let homedir = template_homedir - .clone() - .replace("%D", &domain) - .replace("%U", &cn); - let passwd = Passwd { - name: entry.upn.clone(), - passwd: "x".to_string(), - uid, - gid: uid, - gecos: entry.name, - dir: homedir, - shell: shell.clone(), - }; - res.push(passwd); - } - Ok(Response::NssAccounts(res)) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::cache::UserEntry; - use crate::{GroupCache, PrivateCache, UidCache, UserCache}; - use idmap::Idmap; - use param::LoadParm; - use std::collections::HashSet; - use tempfile::tempdir; - - #[tokio::test] - async fn test_getpwent() { - // Create a temporary directory for the cache - let dir = tempdir().unwrap(); - - // Initialize the caches - let private_cache_path = dir - .path() - .join("himmelblau.tdb") - .to_str() - .unwrap() - .to_string(); - let pcache = PrivateCache::new(&private_cache_path).unwrap(); - let user_cache_path = dir - .path() - .join("himmelblau_users.tdb") - .to_str() - .unwrap() - .to_string(); - let mut user_cache = UserCache::new(&user_cache_path).unwrap(); - let uid_cache_path = dir - .path() - .join("uid_cache.tdb") - .to_str() - .unwrap() - .to_string(); - let uid_cache = UidCache::new(&uid_cache_path).unwrap(); - let group_cache_path = dir - .path() - .join("himmelblau_groups.tdb") - .to_str() - .unwrap() - .to_string(); - let group_cache = GroupCache::new(&group_cache_path).unwrap(); - - // Insert dummy UserEntrys into the cache - let dummy_user = UserEntry { - upn: "user1@test.com".to_string(), - uuid: "731e9af3-668d-4033-afd1-9f09b9120cc7".to_string(), - name: "User One".to_string(), - }; - user_cache - .store(dummy_user.clone()) - .expect("Failed storing user in cache"); - - let dummy_user2 = UserEntry { - upn: "user2@test.com".to_string(), - uuid: "7be6c0c5-5763-4633-aecf-f8c460b338fd".to_string(), - name: "User Two".to_string(), - }; - user_cache - .store(dummy_user2.clone()) - .expect("Failed storing user in cache"); - - // Initialize the Idmap with dummy configuration - let realm = "test.com"; - let tenant_id = "89a61bb7-d1b9-4356-a1e0-75d88e06f14e"; - let mut idmap = Idmap::new().unwrap(); - idmap - .add_gen_domain(realm, tenant_id, (1000, 2000)) - .unwrap(); - - // Initialize dummy configuration for LoadParm - let lp = LoadParm::new(None).expect("Failed loading default config"); - - // Initialize the Resolver - let mut resolver = Resolver { - realm: realm.to_string(), - tenant_id: tenant_id.to_string(), - lp, - idmap, - pcache, - user_cache, - uid_cache, - group_cache, - }; - - // Test the getpwent function - let result = resolver.getpwent().await.unwrap(); - - match result { - Response::NssAccounts(accounts) => { - assert_eq!(accounts.len(), 2); - - let account1 = &accounts[0]; - assert_eq!(account1.name, dummy_user.upn); - assert_eq!(account1.uid, 1316); - assert_eq!(account1.gid, 1316); - assert_eq!(account1.gecos, dummy_user.name); - assert_eq!(account1.dir, "/home/test.com/user1"); - assert_eq!(account1.shell, "/bin/false"); - - let account2 = &accounts[1]; - assert_eq!(account2.name, dummy_user2.upn); - assert_eq!(account2.uid, 1671); - assert_eq!(account2.gid, 1671); - assert_eq!(account2.gecos, dummy_user2.name); - assert_eq!(account2.dir, "/home/test.com/user2"); - assert_eq!(account2.shell, "/bin/false"); - } - other => panic!( - "Expected NssAccounts with a list of accounts: {:?}", - other - ), - } - } -} diff --git a/rust/himmelblaud/src/himmelblaud/himmelblaud_getpwnam.rs b/rust/himmelblaud/src/himmelblaud/himmelblaud_getpwnam.rs deleted file mode 100644 index 40a7bffcbdc..00000000000 --- a/rust/himmelblaud/src/himmelblaud/himmelblaud_getpwnam.rs +++ /dev/null @@ -1,232 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Himmelblau daemon implementation for nss getpwnam - - Copyright (C) David Mulder 2024 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -use crate::cache::GroupEntry; -use crate::himmelblaud::Resolver; -use crate::utils::split_username; -use dbg::{DBG_ERR, DBG_WARNING}; -use ntstatus_gen::*; -use sock::{Passwd, Response}; - -impl Resolver { - pub(crate) fn create_passwd_from_upn( - &mut self, - upn: &str, - gecos: &str, - ) -> Result> { - let template_homedir = self - .lp - .template_homedir() - .map_err(|e| { - DBG_ERR!("{:?}", e); - Box::new(NT_STATUS_NOT_A_DIRECTORY) - })? - .ok_or_else(|| { - DBG_ERR!("Failed to discover template homedir. Is it set?"); - Box::new(NT_STATUS_NOT_A_DIRECTORY) - })?; - let shell = self - .lp - .template_shell() - .map_err(|e| { - DBG_ERR!("{:?}", e); - Box::new(NT_STATUS_NOT_A_DIRECTORY) - })? - .ok_or_else(|| { - DBG_ERR!("Failed to discover template shell. Is it set?"); - Box::new(NT_STATUS_NOT_A_DIRECTORY) - })?; - let uid = - self.idmap.gen_to_unix(&self.tenant_id, &upn).map_err(|e| { - DBG_ERR!("{:?}", e); - Box::new(NT_STATUS_INVALID_TOKEN) - })?; - // Store the calculated uid -> upn map in the cache - self.uid_cache.store(uid, &upn)?; - // Store the primary group (which is a fake group matching the user upn) - let mut group = GroupEntry::new(upn); - group.add_member(upn); - self.group_cache.merge_groups(upn, vec![group])?; - let (cn, domain) = match split_username(&upn) { - Ok(res) => res, - Err(e) => { - DBG_ERR!("Failed to parse user upn '{}': {:?}", upn, e); - return Err(Box::new(NT_STATUS_INVALID_USER_PRINCIPAL_NAME)); - } - }; - let homedir = template_homedir - .clone() - .replace("%D", &domain) - .replace("%U", &cn); - let passwd = Passwd { - name: upn.to_string(), - passwd: "x".to_string(), - uid, - gid: uid, - gecos: gecos.to_string(), - dir: homedir, - shell: shell.clone(), - }; - return Ok(passwd); - } - - pub(crate) async fn getpwnam( - &mut self, - account_id: &str, - ) -> Result> { - // We first try to fetch the user from the cache, so that we - // get the gecos. Otherwise we can just create a passwd entry - // based on whether the upn exists in Entra ID. - let entry = match self.user_cache.fetch(account_id) { - Some(entry) => entry, - #[cfg(not(test))] - None => { - // Check if the user exists in Entra ID - let exists = match self - .client - .lock() - .await - .check_user_exists(&account_id) - .await - { - Ok(exists) => exists, - Err(e) => { - DBG_WARNING!("{:?}", e); - return Ok(Response::NssAccount(None)); - } - }; - if exists { - return Ok(Response::NssAccount(Some( - self.create_passwd_from_upn(account_id, "")?, - ))); - } - return Ok(Response::NssAccount(None)); - } - #[cfg(test)] - None => return Ok(Response::NssAccount(None)), - }; - return Ok(Response::NssAccount(Some( - self.create_passwd_from_upn(&entry.upn, &entry.name)?, - ))); - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::cache::UserEntry; - use crate::{GroupCache, PrivateCache, UidCache, UserCache}; - use idmap::Idmap; - use param::LoadParm; - use tempfile::tempdir; - - #[tokio::test] - async fn test_getpwnam() { - // Create a temporary directory for the cache - let dir = tempdir().unwrap(); - - // Initialize the caches - let private_cache_path = dir - .path() - .join("himmelblau.tdb") - .to_str() - .unwrap() - .to_string(); - let pcache = PrivateCache::new(&private_cache_path).unwrap(); - let user_cache_path = dir - .path() - .join("himmelblau_users.tdb") - .to_str() - .unwrap() - .to_string(); - let mut user_cache = UserCache::new(&user_cache_path).unwrap(); - let uid_cache_path = dir - .path() - .join("uid_cache.tdb") - .to_str() - .unwrap() - .to_string(); - let uid_cache = UidCache::new(&uid_cache_path).unwrap(); - let group_cache_path = dir - .path() - .join("himmelblau_groups.tdb") - .to_str() - .unwrap() - .to_string(); - let group_cache = GroupCache::new(&group_cache_path).unwrap(); - - // Insert a dummy UserEntry into the cache - let dummy_user = UserEntry { - upn: "user1@test.com".to_string(), - uuid: "731e9af3-668d-4033-afd1-9f09b9120cc7".to_string(), - name: "User One".to_string(), - }; - let _ = user_cache.store(dummy_user.clone()); - - // Initialize the Idmap with dummy configuration - let realm = "test.com"; - let tenant_id = "89a61bb7-d1b9-4356-a1e0-75d88e06f14e"; - let mut idmap = Idmap::new().unwrap(); - idmap - .add_gen_domain(realm, tenant_id, (1000, 2000)) - .unwrap(); - - // Initialize dummy configuration for LoadParm - let lp = LoadParm::new(None).expect("Failed loading default config"); - - // Initialize the Resolver - let mut resolver = Resolver { - realm: realm.to_string(), - tenant_id: tenant_id.to_string(), - lp, - idmap, - pcache, - user_cache, - uid_cache, - group_cache, - }; - - // Test the getpwnam function with a user that exists in the cache - let result = resolver.getpwnam(&dummy_user.upn).await.unwrap(); - - match result { - Response::NssAccount(Some(account)) => { - assert_eq!(account.name, dummy_user.upn); - assert_eq!(account.uid, 1316); - assert_eq!(account.gid, 1316); - assert_eq!(account.gecos, dummy_user.name); - assert_eq!(account.dir, "/home/test.com/user1"); - assert_eq!(account.shell, "/bin/false"); - } - other => { - panic!("Expected NssAccount with Some(account): {:?}", other) - } - } - - // Test the getpwnam function with a user that does not exist in the cache - let nonexistent_user_upn = "nonexistent@test.com"; - let result = resolver.getpwnam(nonexistent_user_upn).await.unwrap(); - - match result { - Response::NssAccount(None) => {} // This is the expected result - other => panic!("Expected NssAccount with None: {:?}", other), - } - } -} diff --git a/rust/himmelblaud/src/himmelblaud/himmelblaud_getpwuid.rs b/rust/himmelblaud/src/himmelblaud/himmelblaud_getpwuid.rs deleted file mode 100644 index f93f55cff1e..00000000000 --- a/rust/himmelblaud/src/himmelblaud/himmelblaud_getpwuid.rs +++ /dev/null @@ -1,156 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Himmelblau daemon implementation for nss getpwuid - - Copyright (C) David Mulder 2024 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -use crate::himmelblaud::Resolver; -use libc::uid_t; -use ntstatus_gen::NTSTATUS; -use sock::Response; - -impl Resolver { - pub(crate) async fn getpwuid( - &mut self, - uid: uid_t, - ) -> Result> { - if let Some(upn) = self.uid_cache.fetch(uid) { - if let Some(entry) = self.user_cache.fetch(&upn) { - Ok(Response::NssAccount(Some( - self.create_passwd_from_upn(&entry.upn, &entry.name)?, - ))) - } else { - Ok(Response::NssAccount(Some( - self.create_passwd_from_upn(&upn, "")?, - ))) - } - } else { - Ok(Response::NssAccount(None)) - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::cache::UserEntry; - use crate::{GroupCache, PrivateCache, UidCache, UserCache}; - use idmap::Idmap; - use param::LoadParm; - use tempfile::tempdir; - - #[tokio::test] - async fn test_getpwuid() { - // Create a temporary directory for the cache - let dir = tempdir().unwrap(); - - // Initialize the caches - let private_cache_path = dir - .path() - .join("himmelblau.tdb") - .to_str() - .unwrap() - .to_string(); - let pcache = PrivateCache::new(&private_cache_path).unwrap(); - let user_cache_path = dir - .path() - .join("himmelblau_users.tdb") - .to_str() - .unwrap() - .to_string(); - let mut user_cache = UserCache::new(&user_cache_path).unwrap(); - let uid_cache_path = dir - .path() - .join("uid_cache.tdb") - .to_str() - .unwrap() - .to_string(); - let mut uid_cache = UidCache::new(&uid_cache_path).unwrap(); - let group_cache_path = dir - .path() - .join("himmelblau_groups.tdb") - .to_str() - .unwrap() - .to_string(); - let group_cache = GroupCache::new(&group_cache_path).unwrap(); - - // Insert a dummy UserEntry into the cache - let dummy_user = UserEntry { - upn: "user1@test.com".to_string(), - uuid: "731e9af3-668d-4033-afd1-9f09b9120cc7".to_string(), - name: "User One".to_string(), - }; - let _ = user_cache.store(dummy_user.clone()); - - // Initialize the Idmap with dummy configuration - let realm = "test.com"; - let tenant_id = "89a61bb7-d1b9-4356-a1e0-75d88e06f14e"; - let mut idmap = Idmap::new().unwrap(); - idmap - .add_gen_domain(realm, tenant_id, (1000, 2000)) - .unwrap(); - - let uid = idmap - .gen_to_unix(tenant_id, &dummy_user.upn) - .expect("Failed to generate uid for user"); - // Store the calculated uid -> upn map in the cache - uid_cache - .store(uid, &dummy_user.upn) - .expect("Failed storing generated uid in the cache"); - - // Initialize dummy configuration for LoadParm - let lp = LoadParm::new(None).expect("Failed loading default config"); - - // Initialize the Resolver - let mut resolver = Resolver { - realm: realm.to_string(), - tenant_id: tenant_id.to_string(), - lp, - idmap, - pcache, - user_cache, - uid_cache, - group_cache, - }; - - // Test the getpwuid function with a uid that exists in the cache - let result = resolver.getpwuid(uid).await.unwrap(); - - match result { - Response::NssAccount(Some(account)) => { - assert_eq!(account.name, dummy_user.upn); - assert_eq!(account.uid, uid); - assert_eq!(account.gid, uid); - assert_eq!(account.gecos, dummy_user.name); - assert_eq!(account.dir, "/home/test.com/user1"); - assert_eq!(account.shell, "/bin/false"); - } - other => { - panic!("Expected NssAccount with Some(account): {:?}", other) - } - } - - // Test the getpwuid function with a uid that does not exist in the cache - let nonexistent_uid = 9999; - let result = resolver.getpwuid(nonexistent_uid).await.unwrap(); - - match result { - Response::NssAccount(None) => {} // This is the expected result - other => panic!("Expected NssAccount with None: {:?}", other), - } - } -} diff --git a/rust/himmelblaud/src/himmelblaud/himmelblaud_pam_acct_mgmt.rs b/rust/himmelblaud/src/himmelblaud/himmelblaud_pam_acct_mgmt.rs deleted file mode 100644 index 98209eee573..00000000000 --- a/rust/himmelblaud/src/himmelblaud/himmelblaud_pam_acct_mgmt.rs +++ /dev/null @@ -1,47 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Himmelblau daemon implementation for pam_acct_mgmt - - Copyright (C) David Mulder 2024 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -use crate::himmelblaud::Resolver; -use dbg::DBG_WARNING; -use ntstatus_gen::*; -use sock::Response; - -impl Resolver { - pub(crate) async fn pam_acct_mgmt( - &self, - account_id: &str, - ) -> Result> { - // Check if the user exists in Entra ID - // TODO: If we're offline, check the cache instead - match self - .client - .lock() - .await - .check_user_exists(&account_id) - .await - { - Ok(exists) => Ok(Response::PamStatus(Some(exists))), - Err(e) => { - DBG_WARNING!("{:?}", e); - Ok(Response::PamStatus(None)) - } - } - } -} diff --git a/rust/himmelblaud/src/himmelblaud/himmelblaud_pam_auth.rs b/rust/himmelblaud/src/himmelblaud/himmelblaud_pam_auth.rs deleted file mode 100644 index c1cd64f8fd6..00000000000 --- a/rust/himmelblaud/src/himmelblaud/himmelblaud_pam_auth.rs +++ /dev/null @@ -1,794 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Himmelblau daemon implementation for PAM_AUTH - - Copyright (C) David Mulder 2024 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -use crate::cache::{GroupEntry, UserEntry}; -use crate::himmelblaud::Resolver; -use dbg::{DBG_DEBUG, DBG_ERR, DBG_INFO, DBG_WARNING}; -use himmelblau::error::{ - MsalError, AUTH_PENDING, DEVICE_AUTH_FAIL, REQUIRES_MFA, -}; -use himmelblau::{ - DeviceAuthorizationResponse, EnrollAttrs, MFAAuthContinue, - UserToken as UnixUserToken, -}; -use ntstatus_gen::*; -use serde::{Deserialize, Serialize}; -use sock::{PamAuthRequest, PamAuthResponse, Response}; -use std::env; -use std::thread::sleep; -use std::time::Duration; - -#[derive(Debug, Serialize, Deserialize, Clone)] -pub struct GroupToken { - pub name: String, - pub spn: String, - pub object_id: String, - pub gidnumber: u32, -} - -#[derive(Debug, Serialize, Deserialize, Clone)] -pub struct UserToken { - pub name: String, - pub spn: String, - pub object_id: String, - pub gidnumber: u32, - pub displayname: String, - pub shell: Option, - pub groups: Vec, -} - -pub(crate) enum AuthCredHandler { - MFA { flow: MFAAuthContinue }, - DeviceAuthorizationGrant { flow: DeviceAuthorizationResponse }, - SetupPin { token: UnixUserToken }, - None, -} - -pub(crate) enum AuthSession { - InProgress { - account_id: String, - cred_handler: AuthCredHandler, - }, - Success, - Denied, -} - -impl Resolver { - pub(crate) fn pam_auth_init( - &mut self, - account_id: &str, - ) -> Result<(AuthSession, Response), Box> { - let auth_session = AuthSession::InProgress { - account_id: account_id.to_string(), - cred_handler: AuthCredHandler::None, - }; - let hello_key = self.pcache.loadable_hello_key_fetch(account_id); - // Skip Hello authentication if it is disabled by config - let hello_enabled = - self.lp.himmelblaud_hello_enabled().map_err(|e| { - DBG_ERR!("{:?}", e); - Box::new(NT_STATUS_LOGON_FAILURE) - })?; - if !self.is_domain_joined() || hello_key.is_none() || !hello_enabled { - // Send a password request to the client - Ok(( - auth_session, - Response::PamAuthStepResponse(PamAuthResponse::Password), - )) - } else { - // Send a pin request to the client - Ok(( - auth_session, - Response::PamAuthStepResponse(PamAuthResponse::Pin), - )) - } - } - - pub(crate) async fn pam_auth_step( - &mut self, - account_id: &str, - cred_handler: &mut AuthCredHandler, - pam_next_req: PamAuthRequest, - ) -> Result> { - macro_rules! enroll_and_obtain_enrolled_token { - ($token:ident) => {{ - if !self.is_domain_joined() { - DBG_DEBUG!("Device is not enrolled. Enrolling now."); - self.join_domain(&$token) - .await - .map_err(|e| { - DBG_ERR!("Failed to join domain: {:?}", e); - Box::new(NT_STATUS_LOGON_FAILURE) - })?; - } - let mut tpm = self.hsm.lock().await; - let mtoken2 = self - .client - .lock() - .await - .acquire_token_by_refresh_token( - &$token.refresh_token, - vec!["User.Read"], - Some("https://graph.microsoft.com".to_string()), - &mut tpm, - &self.machine_key, - ) - .await; - match mtoken2 { - Ok(token) => token, - Err(e) => { - DBG_ERR!("{:?}", e); - match e { - MsalError::AcquireTokenFailed(err_resp) => { - if err_resp.error_codes.contains(&DEVICE_AUTH_FAIL) { - /* A device authentication failure may happen - * if Azure hasn't finished replicating the new - * device object. Wait 5 seconds and try again. */ - DBG_INFO!("Azure hasn't finished replicating the device..."); - DBG_INFO!("Retrying in 5 seconds"); - sleep(Duration::from_secs(5)); - self.client - .lock() - .await - .acquire_token_by_refresh_token( - &$token.refresh_token, - vec!["User.Read"], - Some("https://graph.microsoft.com".to_string()), - &mut tpm, - &self.machine_key, - ) - .await - .map_err(|e| { - DBG_ERR!("{:?}", e); - Box::new(NT_STATUS_NOT_FOUND) - })? - } else { - return Err(Box::new(NT_STATUS_NOT_FOUND)); - } - } - _ => return Err(Box::new(NT_STATUS_NOT_FOUND)), - } - } - } - }}; - } - macro_rules! auth_and_validate_hello_key { - ($hello_key:ident, $cred:ident) => {{ - let token = { - let mut tpm = self.hsm.lock().await; - self - .client - .lock() - .await - .acquire_token_by_hello_for_business_key( - account_id, - &$hello_key, - vec!["User.Read"], - Some("https://graph.microsoft.com".to_string()), - &mut tpm, - &self.machine_key, - &$cred, - ) - .await - .map_err(|e| { - DBG_ERR!( - "Failed to authenticate with hello key: {:?}", - e - ); - Box::new(NT_STATUS_LOGON_FAILURE) - })? - }; - - self.token_validate(account_id, &token).await - }}; - } - match (&mut *cred_handler, pam_next_req) { - ( - AuthCredHandler::SetupPin { token }, - PamAuthRequest::SetupPin { pin }, - ) => { - let hello_key = { - let mut tpm = self.hsm.lock().await; - match self - .client - .lock() - .await - .provision_hello_for_business_key( - &token, - &mut tpm, - &self.machine_key, - &pin, - ) - .await - { - Ok(hello_key) => hello_key, - Err(e) => { - return Ok(Response::PamAuthStepResponse( - PamAuthResponse::SetupPin { - msg: format!( - "Failed to provision hello key: {:?}\n{}", - e, - "Create a PIN to use in place of passwords." - ), - } - )); - } - } - }; - self.pcache - .loadable_hello_key_store(account_id, hello_key.clone()) - .map_err(|e| { - DBG_ERR!("Failed to provision hello key: {:?}", e); - Box::new(NT_STATUS_LOGON_FAILURE) - })?; - - auth_and_validate_hello_key!(hello_key, pin) - } - (_, PamAuthRequest::Pin { pin }) => { - let hello_key = self - .pcache - .loadable_hello_key_fetch(account_id) - .ok_or_else(|| { - DBG_ERR!("Authentication failed. Hello key missing."); - Box::new(NT_STATUS_LOGON_FAILURE) - })?; - - auth_and_validate_hello_key!(hello_key, pin) - } - (_, PamAuthRequest::Password { cred }) => { - // Always attempt to force MFA when enrolling the device, otherwise - // the device object will not have the MFA claim. If we are already - // enrolled but creating a new Hello Pin, we follow the same process, - // since only an enrollment token can be exchanged for a PRT (which - // will be needed to enroll the Hello Pin). - let mresp = self - .client - .lock() - .await - .initiate_acquire_token_by_mfa_flow_for_device_enrollment( - account_id, &cred, - ) - .await; - // We need to wait to handle the response until after we've released - // the lock on the client, otherwise we will deadlock. - let resp = match mresp { - Ok(resp) => resp, - Err(e) => { - // If SFA is disabled, we need to skip the SFA fallback. - let sfa_enabled = self - .lp - .himmelblaud_sfa_fallback() - .map_err(|e| { - DBG_ERR!("{:?}", e); - Box::new(NT_STATUS_LOGON_FAILURE) - })?; - macro_rules! init_dag { - ($msg:expr) => {{ - DBG_WARNING!( - "SFA auth failed, falling back to DAG: {}", - $msg - ); - // We've exhausted alternatives, and must perform a DAG - let resp = self - .client - .lock() - .await - .initiate_device_flow_for_device_enrollment() - .await - .map_err(|e| { - DBG_ERR!("{:?}", e); - Box::new(NT_STATUS_LOGON_FAILURE) - })?; - let msg = match &resp.message { - Some(msg) => msg.to_string(), - None => format!("Using a browser on another \ - device, visit:\n{}\nAnd enter the code:\n{}", - resp.verification_uri, resp.user_code), - }; - let polling_interval = match resp.interval { - Some(polling_interval) => polling_interval, - None => 5, - }; - *cred_handler = AuthCredHandler::DeviceAuthorizationGrant { - flow: resp, - }; - return Ok(Response::PamAuthStepResponse( - PamAuthResponse::MFAPoll { - msg, - polling_interval, - } - )); - }} - } - let token = if sfa_enabled { - DBG_WARNING!( - "MFA auth failed, falling back to SFA: {:?}", - e - ); - // Again, we need to wait to handle the response until after - // we've released the write lock on the client, otherwise we - // will deadlock. - match self - .client - .lock() - .await - .acquire_token_by_username_password_for_device_enrollment( - account_id, &cred, - ) - .await - { - Ok(token) => token, - Err(e) => { - DBG_ERR!("{:?}", e); - match e { - MsalError::AcquireTokenFailed( - err_resp, - ) => { - if err_resp - .error_codes - .contains(&REQUIRES_MFA) - { - init_dag!( - err_resp.error_description - ); - } - return Err(Box::new( - NT_STATUS_LOGON_FAILURE, - )); - } - _ => { - return Err(Box::new( - NT_STATUS_LOGON_FAILURE, - )) - } - } - } - } - } else { - init_dag!( - "SFA fallback is disabled by configuration" - ) - }; - let token2 = enroll_and_obtain_enrolled_token!(token); - return self.token_validate(account_id, &token2).await; - } - }; - match resp.mfa_method.as_str() { - "PhoneAppOTP" | "OneWaySMS" | "ConsolidatedTelephony" => { - let msg = resp.msg.clone(); - *cred_handler = AuthCredHandler::MFA { flow: resp }; - return Ok(Response::PamAuthStepResponse( - PamAuthResponse::MFACode { msg }, - )); - } - _ => { - let msg = resp.msg.clone(); - let polling_interval = - resp.polling_interval.ok_or_else(|| { - DBG_ERR!("Invalid response from the server"); - Box::new(NT_STATUS_LOGON_FAILURE) - })?; - *cred_handler = AuthCredHandler::MFA { flow: resp }; - return Ok(Response::PamAuthStepResponse( - PamAuthResponse::MFAPoll { - msg, - // pam expects a polling_interval in - // seconds, not milliseconds. - polling_interval: polling_interval / 1000, - }, - )); - } - } - } - ( - AuthCredHandler::DeviceAuthorizationGrant { flow }, - PamAuthRequest::MFAPoll { .. }, - ) => { - let token = match self - .client - .lock() - .await - .acquire_token_by_device_flow(flow.clone()) - .await - { - Err(MsalError::AcquireTokenFailed(ref resp)) => { - if resp.error_codes.contains(&AUTH_PENDING) { - DBG_DEBUG!( - "Polling for acquire_token_by_device_flow" - ); - return Ok(Response::PamAuthStepResponse( - PamAuthResponse::MFAPollWait, - )); - } else { - DBG_ERR!("{}", resp.error_description); - return Err(Box::new(NT_STATUS_LOGON_FAILURE)); - } - } - Err(e) => { - DBG_ERR!("{:?}", e); - return Err(Box::new(NT_STATUS_LOGON_FAILURE)); - } - Ok(token) => token, - }; - let token2 = enroll_and_obtain_enrolled_token!(token); - match self.token_validate(account_id, &token2).await { - Ok(Response::PamAuthStepResponse( - PamAuthResponse::Success, - )) => { - let mfa = token2.amr_mfa().map_err(|e| { - DBG_ERR!("{:?}", e); - Box::new(NT_STATUS_NOT_FOUND) - })?; - // If the DAG didn't obtain an MFA amr, and SFA fallback - // is disabled, we need to reject the authentication - // attempt here. - let sfa_enabled = self - .lp - .himmelblaud_sfa_fallback() - .map_err(|e| { - DBG_ERR!("{:?}", e); - Box::new(NT_STATUS_LOGON_FAILURE) - })?; - if !mfa && !sfa_enabled { - DBG_INFO!( - "A DAG produced an SFA token, yet SFA \ - fallback is disabled by configuration" - ); - return Ok(Response::PamAuthStepResponse( - PamAuthResponse::Denied, - )); - } - // STOP! If the DAG doesn't hold an MFA amr, then we - // need to bail out here and refuse Hello enrollment - // (we can't enroll in Hello with an SFA token). - // Also skip Hello enrollment if it is disabled by config - let hello_enabled = self - .lp - .himmelblaud_hello_enabled() - .map_err(|e| { - DBG_ERR!("{:?}", e); - Box::new(NT_STATUS_LOGON_FAILURE) - })?; - if !mfa || !hello_enabled { - if !mfa { - DBG_INFO!( - "Skipping Hello enrollment because \ - the token doesn't contain an MFA amr" - ); - } else if !hello_enabled { - DBG_INFO!( - "Skipping Hello enrollment \ - because it is disabled" - ); - } - return Ok(Response::PamAuthStepResponse( - PamAuthResponse::Success, - )); - } - - // Setup Windows Hello - *cred_handler = AuthCredHandler::SetupPin { token }; - return Ok(Response::PamAuthStepResponse( - PamAuthResponse::SetupPin { - msg: format!( - "Set up a PIN\n {}{}", - "A Hello PIN is a fast, secure way to sign", - "in to your device, apps, and services." - ), - }, - )); - } - Ok(auth_result) => Ok(auth_result), - Err(e) => Err(e), - } - } - ( - AuthCredHandler::MFA { ref mut flow }, - PamAuthRequest::MFACode { cred }, - ) => { - let token = self - .client - .lock() - .await - .acquire_token_by_mfa_flow( - account_id, - Some(&cred), - None, - flow, - ) - .await - .map_err(|e| { - DBG_ERR!("{:?}", e); - Box::new(NT_STATUS_NOT_FOUND) - })?; - let token2 = enroll_and_obtain_enrolled_token!(token); - match self.token_validate(account_id, &token2).await { - Ok(Response::PamAuthStepResponse( - PamAuthResponse::Success, - )) => { - // Skip Hello enrollment if it is disabled by config - let hello_enabled = self - .lp - .himmelblaud_hello_enabled() - .map_err(|e| { - DBG_ERR!("{:?}", e); - Box::new(NT_STATUS_LOGON_FAILURE) - })?; - if !hello_enabled { - DBG_INFO!("Skipping Hello enrollment because it is disabled"); - return Ok(Response::PamAuthStepResponse( - PamAuthResponse::Success, - )); - } - - // Setup Windows Hello - *cred_handler = AuthCredHandler::SetupPin { token }; - return Ok(Response::PamAuthStepResponse( - PamAuthResponse::SetupPin { - msg: format!( - "Set up a PIN\n {}{}", - "A Hello PIN is a fast, secure way to sign", - "in to your device, apps, and services." - ), - }, - )); - } - Ok(auth_result) => Ok(auth_result), - Err(e) => Err(e), - } - } - ( - AuthCredHandler::MFA { flow }, - PamAuthRequest::MFAPoll { poll_attempt }, - ) => { - let max_poll_attempts = - flow.max_poll_attempts.ok_or_else(|| { - DBG_ERR!("Invalid response from the server"); - Box::new(NT_STATUS_LOGON_FAILURE) - })?; - if poll_attempt > max_poll_attempts { - DBG_ERR!("MFA polling timed out"); - return Err(Box::new(NT_STATUS_LOGON_FAILURE)); - } - let token = match self - .client - .lock() - .await - .acquire_token_by_mfa_flow( - account_id, - None, - Some(poll_attempt), - flow, - ) - .await - { - Ok(token) => token, - Err(e) => match e { - MsalError::MFAPollContinue => { - return Ok(Response::PamAuthStepResponse( - PamAuthResponse::MFAPollWait, - )); - } - e => { - DBG_ERR!("{:?}", e); - return Err(Box::new(NT_STATUS_NOT_FOUND)); - } - }, - }; - let token2 = enroll_and_obtain_enrolled_token!(token); - match self.token_validate(account_id, &token2).await { - Ok(Response::PamAuthStepResponse( - PamAuthResponse::Success, - )) => { - // Skip Hello enrollment if it is disabled by config - let hello_enabled = self - .lp - .himmelblaud_hello_enabled() - .map_err(|e| { - DBG_ERR!("{:?}", e); - Box::new(NT_STATUS_LOGON_FAILURE) - })?; - if !hello_enabled { - DBG_INFO!("Skipping Hello enrollment because it is disabled"); - return Ok(Response::PamAuthStepResponse( - PamAuthResponse::Success, - )); - } - - // Setup Windows Hello - *cred_handler = AuthCredHandler::SetupPin { token }; - return Ok(Response::PamAuthStepResponse( - PamAuthResponse::SetupPin { - msg: format!( - "Set up a PIN\n {}{}", - "A Hello PIN is a fast, secure way to sign", - "in to your device, apps, and services." - ), - }, - )); - } - Ok(auth_result) => Ok(auth_result), - Err(e) => Err(e), - } - } - _ => { - DBG_ERR!( - "Unexpected AuthCredHandler and PamAuthRequest pairing" - ); - Err(Box::new(NT_STATUS_NOT_IMPLEMENTED)) - } - } - } - - async fn token_validate( - &mut self, - account_id: &str, - token: &UnixUserToken, - ) -> Result> { - match &token.access_token { - Some(access_token) => { - /* MFA can respond with different user than requested. - * Azure resource names are case insensitive. - */ - let spn = token.spn().map_err(|e| { - DBG_ERR!("Failed fetching user spn: {:?}", e); - Box::new(NT_STATUS_LOGON_FAILURE) - })?; - if account_id.to_string().to_lowercase() - != spn.to_string().to_lowercase() - { - DBG_ERR!( - "Authenticated user {} does not match requested user {}", - spn, account_id - ); - return Ok(Response::PamAuthStepResponse( - PamAuthResponse::Denied, - )); - } - DBG_INFO!( - "Authentication successful for user '{}'", - account_id - ); - - // Store the user in the cache - let user_entry: UserEntry = token.try_into().map_err(|e| { - DBG_ERR!("{:?}", e); - Box::new(NT_STATUS_LOGON_FAILURE) - })?; - self.user_cache.store(user_entry).map_err(|e| { - DBG_ERR!("{:?}", e); - Box::new(NT_STATUS_LOGON_FAILURE) - })?; - - // Get the users groups, and store those groups in the cache - let groups: Vec = self - .graph - .request_user_groups(access_token) - .await - .map_err(|e| { - DBG_ERR!("{:?}", e); - Box::new(NT_STATUS_LOGON_FAILURE) - })? - .into_iter() - .map(|g| GroupEntry::into_with_member(g, account_id)) - .collect(); - self.group_cache.merge_groups(account_id, groups).map_err( - |e| { - DBG_ERR!("{:?}", e); - Box::new(NT_STATUS_LOGON_FAILURE) - }, - )?; - - Ok(Response::PamAuthStepResponse(PamAuthResponse::Success)) - } - None => { - DBG_INFO!("Authentication failed for user '{}'", account_id); - Err(Box::new(NT_STATUS_NOT_FOUND)) - } - } - } - - async fn join_domain( - &mut self, - token: &UnixUserToken, - ) -> Result<(), Box> { - /* If not already joined, join the domain now. */ - let attrs = EnrollAttrs::new( - self.realm.clone(), - None, - Some(env::consts::OS.to_string()), - None, - None, - ) - .map_err(|e| { - DBG_ERR!("{:?}", e); - Box::new(NT_STATUS_LOGON_FAILURE) - })?; - let mut tpm = self.hsm.lock().await; - match self - .client - .lock() - .await - .enroll_device( - &token.refresh_token, - attrs, - &mut tpm, - &self.machine_key, - ) - .await - { - Ok(( - new_loadable_transport_key, - new_loadable_cert_key, - device_id, - )) => { - DBG_INFO!("Joined domain {} ({})", self.realm, device_id); - // Store the new_loadable_cert_key in the keystore - self.pcache - .loadable_cert_key_store(&self.realm, new_loadable_cert_key) - .map_err(|e| { - DBG_ERR!("{:?}", e); - Box::new(NT_STATUS_LOGON_FAILURE) - })?; - // Store the new_loadable_transport_key - self.pcache - .loadable_transport_key_store( - &self.realm, - new_loadable_transport_key, - ) - .map_err(|e| { - DBG_ERR!("{:?}", e); - Box::new(NT_STATUS_LOGON_FAILURE) - })?; - // Store the device_id - self.pcache - .device_id_store(&self.realm, &device_id) - .map_err(|e| { - DBG_ERR!("{:?}", e); - Box::new(NT_STATUS_LOGON_FAILURE) - })?; - Ok(()) - } - Err(e) => { - DBG_ERR!("{:?}", e); - Err(Box::new(NT_STATUS_LOGON_FAILURE)) - } - } - } - - fn is_domain_joined(&mut self) -> bool { - /* If we have access to tpm keys, and the domain device_id is - * configured, we'll assume we are domain joined. */ - let device_id = self.pcache.device_id(&self.realm); - if device_id.is_none() { - return false; - } - let transport_key = - self.pcache.loadable_transport_key_fetch(&self.realm); - if transport_key.is_none() { - return false; - } - let cert_key = self.pcache.loadable_cert_key_fetch(&self.realm); - if cert_key.is_none() { - return false; - } - true - } -} diff --git a/rust/himmelblaud/src/main.rs b/rust/himmelblaud/src/main.rs deleted file mode 100644 index 835ba8c10dc..00000000000 --- a/rust/himmelblaud/src/main.rs +++ /dev/null @@ -1,476 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Himmelblau daemon - - Copyright (C) David Mulder 2024 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -// Ignore unused/dead code when running cargo test -#![cfg_attr(test, allow(unused_imports))] -#![cfg_attr(test, allow(dead_code))] - -use clap::{Arg, ArgAction, Command}; -use dbg::*; -use himmelblau::graph::Graph; -use himmelblau::BrokerClientApplication; -use idmap::Idmap; -use kanidm_hsm_crypto::soft::SoftTpm; -use kanidm_hsm_crypto::{BoxedDynTpm, Tpm}; -use libc::umask; -use param::LoadParm; -use std::path::{Path, PathBuf}; -use std::process::ExitCode; -use std::sync::atomic::{AtomicBool, Ordering}; -use std::sync::Arc; -use tokio::net::UnixListener; -use tokio::signal::unix::{signal, SignalKind}; -use tokio::sync::Mutex; - -mod constants; -use constants::DEFAULT_ODC_PROVIDER; -mod cache; -mod himmelblaud; -use cache::{GroupCache, PrivateCache, UidCache, UserCache}; -mod utils; - -#[cfg(not(test))] -#[tokio::main(flavor = "current_thread")] -async fn main() -> ExitCode { - let clap_args = Command::new("himmelblaud") - .version(env!("CARGO_PKG_VERSION")) - .about("Samba Himmelblau Authentication Daemon") - .arg( - Arg::new("debuglevel") - .help("Set debug level") - .short('d') - .long("debuglevel") - .value_parser( - clap::value_parser!(u16).range(0..(MAX_DEBUG_LEVEL as i64)), - ) - .action(ArgAction::Set), - ) - .arg( - Arg::new("debug-stdout") - .help("Send debug output to standard output") - .long("debug-stdout") - .action(ArgAction::SetTrue), - ) - .arg( - Arg::new("configfile") - .help("Use alternative configuration file") - .short('s') - .long("configfile") - .action(ArgAction::Set), - ) - .get_matches(); - - let stop_now = Arc::new(AtomicBool::new(false)); - let terminate_now = Arc::clone(&stop_now); - let quit_now = Arc::clone(&stop_now); - let interrupt_now = Arc::clone(&stop_now); - - let frame = talloc::talloc_stackframe!(); - - async { - // Set the command line debug level - if let Some(debuglevel) = clap_args.get_one::("debuglevel") { - debuglevel_set!(*debuglevel); - } - - // Initialize the LoadParm from the command line specified config file - let lp = match LoadParm::new( - clap_args - .get_one::("configfile") - .map(|x| x.as_str()), - ) { - Ok(lp) => lp, - Err(e) => { - eprintln!("Failed loading smb.conf: {:?}", e); - talloc::TALLOC_FREE!(frame); - return ExitCode::FAILURE; - } - }; - - // Check that the realm is configured. This the bare minimum for - // himmelblaud, since a device join can happen at authentication time, - // but we need to know the permitted enrollment domain. - let realm = match lp.realm() { - Ok(Some(realm)) => realm, - _ => { - eprintln!( - "The realm MUST be set in the \ - smb.conf to start himmelblaud" - ); - talloc::TALLOC_FREE!(frame); - return ExitCode::FAILURE; - } - }; - - // Setup logging, either to the configured logfile, or to stdout, depending - // on what is specified on the command line. - match clap_args.get_flag("debug-stdout") { - true => setup_logging(env!("CARGO_PKG_NAME"), DEBUG_STDOUT), - false => { - setup_logging(env!("CARGO_PKG_NAME"), DEBUG_FILE); - match lp.logfile() { - Ok(Some(logfile)) => debug_set_logfile(&logfile), - _ => { - eprintln!("Failed to determine logfile name"); - talloc::TALLOC_FREE!(frame); - return ExitCode::FAILURE; - } - } - } - } - - // Determine the unix socket path - let sock_dir_str = match lp.winbindd_socket_directory() { - Ok(Some(sock_dir)) => sock_dir, - _ => { - talloc::TALLOC_FREE!(frame); - return ExitCode::FAILURE; - } - }; - let sock_dir = Path::new(&sock_dir_str); - let mut sock_path_buf = PathBuf::from(sock_dir); - sock_path_buf.push("hb_pipe"); - let sock_path = match sock_path_buf.to_str() { - Some(sock_path) => sock_path, - None => { - talloc::TALLOC_FREE!(frame); - return ExitCode::FAILURE; - } - }; - if sock_path_buf.exists() { - DBG_DEBUG!("Cleaning up socket from previous invocations"); - if let Err(_) = std::fs::remove_file(sock_path) { - DBG_ERR!("Failed removing socket"); - } - } - - // Initialize the Himmelblau cache - let private_cache_path = match lp.private_path("himmelblau.tdb") { - Ok(Some(private_cache_path)) => private_cache_path, - _ => { - DBG_ERR!("Failed to determine private cache path"); - talloc::TALLOC_FREE!(frame); - return ExitCode::FAILURE; - } - }; - let mut private_dir = Path::new(&private_cache_path).to_path_buf(); - private_dir.pop(); - if !private_dir.exists() { - DBG_ERR!( - "The private directory '{}' does not exist", - private_dir.display() - ); - talloc::TALLOC_FREE!(frame); - return ExitCode::FAILURE; - } - let mut pcache = match PrivateCache::new(&private_cache_path) { - Ok(cache) => cache, - Err(e) => { - DBG_ERR!( - "Failed to open the himmelblau private cache: {:?}", - e - ); - talloc::TALLOC_FREE!(frame); - return ExitCode::FAILURE; - } - }; - - let cache_dir = match lp.cache_directory() { - Ok(Some(cache_dir)) => cache_dir, - _ => { - DBG_ERR!("Failed to determine cache directory"); - talloc::TALLOC_FREE!(frame); - return ExitCode::FAILURE; - } - }; - if !Path::new(&cache_dir).exists() { - DBG_ERR!("The cache directory '{}' does not exist", cache_dir); - talloc::TALLOC_FREE!(frame); - return ExitCode::FAILURE; - } - - let user_cache_path = Path::new(&cache_dir) - .join("himmelblau_users.tdb") - .display() - .to_string(); - let user_cache = match UserCache::new(&user_cache_path) { - Ok(cache) => cache, - Err(e) => { - DBG_ERR!("Failed to open the himmelblau user cache: {:?}", e); - talloc::TALLOC_FREE!(frame); - return ExitCode::FAILURE; - } - }; - - let uid_cache_path = Path::new(&cache_dir) - .join("himmelblau_uid_map.tdb") - .display() - .to_string(); - let uid_cache = match UidCache::new(&uid_cache_path) { - Ok(cache) => cache, - Err(e) => { - DBG_ERR!("Failed to open the himmelblau uid cache: {:?}", e); - talloc::TALLOC_FREE!(frame); - return ExitCode::FAILURE; - } - }; - - let group_cache_path = Path::new(&cache_dir) - .join("himmelblau_groups.tdb") - .display() - .to_string(); - let group_cache = match GroupCache::new(&group_cache_path) { - Ok(cache) => cache, - Err(e) => { - DBG_ERR!("Failed to open the himmelblau group cache: {:?}", e); - talloc::TALLOC_FREE!(frame); - return ExitCode::FAILURE; - } - }; - - // Check for and create the hsm pin if required. - 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."); - talloc::TALLOC_FREE!(frame); - return ExitCode::FAILURE; - } - }; - let mut hsm_pin_dir = Path::new(&hsm_pin_path).to_path_buf(); - hsm_pin_dir.pop(); - if !hsm_pin_dir.exists() { - DBG_ERR!( - "The hsm pin directory '{}' does not exist", - hsm_pin_dir.display() - ); - talloc::TALLOC_FREE!(frame); - 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); - talloc::TALLOC_FREE!(frame); - return ExitCode::FAILURE; - } - }; - - // Setup the HSM and its machine key - let mut hsm: BoxedDynTpm = BoxedDynTpm::new(SoftTpm::new()); - - let loadable_machine_key = match pcache - .loadable_machine_key_fetch_or_create(&mut hsm, &auth_value) - { - Ok(lmk) => lmk, - Err(e) => { - DBG_ERR!("{:?}", e); - talloc::TALLOC_FREE!(frame); - return ExitCode::FAILURE; - } - }; - - let res = hsm.machine_key_load(&auth_value, &loadable_machine_key); - let machine_key = match res { - Ok(machine_key) => machine_key, - Err(e) => { - DBG_ERR!("Unable to load machine root key: {:?}", e); - DBG_INFO!("This can occur if you have changed your HSM pin."); - DBG_INFO!( - "To proceed, run `tdbtool erase {}`", - private_cache_path - ); - DBG_INFO!("The host will forget domain enrollments."); - talloc::TALLOC_FREE!(frame); - return ExitCode::FAILURE; - } - }; - - // Get the transport key for a joined domain - let loadable_transport_key = - pcache.loadable_transport_key_fetch(&realm); - - // Get the certificate key for a joined domain - let loadable_cert_key = pcache.loadable_cert_key_fetch(&realm); - - // Contact the odc provider to get the authority host and tenant id - let graph = match Graph::new(DEFAULT_ODC_PROVIDER, &realm).await { - Ok(graph) => graph, - Err(e) => { - DBG_ERR!("Failed initializing the graph: {:?}", e); - talloc::TALLOC_FREE!(frame); - return ExitCode::FAILURE; - } - }; - let authority_host = graph.authority_host(); - let tenant_id = graph.tenant_id(); - let authority = format!("https://{}/{}", authority_host, tenant_id); - - let client = match BrokerClientApplication::new( - Some(&authority), - loadable_transport_key, - loadable_cert_key, - ) { - Ok(client) => client, - Err(e) => { - DBG_ERR!("Failed initializing the broker: {:?}", e); - talloc::TALLOC_FREE!(frame); - return ExitCode::FAILURE; - } - }; - - let mut idmap = match Idmap::new() { - Ok(idmap) => idmap, - Err(e) => { - DBG_ERR!("Failed initializing the idmapper: {:?}", e); - talloc::TALLOC_FREE!(frame); - return ExitCode::FAILURE; - } - }; - // Configure the idmap range - let (low, high) = match lp.idmap_range(&realm) { - Ok(res) => res, - Err(e) => { - DBG_ERR!("Failed fetching idmap range: {:?}", e); - talloc::TALLOC_FREE!(frame); - return ExitCode::FAILURE; - } - }; - if let Err(e) = idmap.add_gen_domain(&realm, &tenant_id, (low, high)) { - DBG_ERR!("Failed adding the domain idmap range: {:?}", e); - talloc::TALLOC_FREE!(frame); - return ExitCode::FAILURE; - } - - let resolver = Arc::new(Mutex::new(himmelblaud::Resolver::new( - &realm, - &tenant_id, - lp, - idmap, - graph, - pcache, - user_cache, - uid_cache, - group_cache, - hsm, - machine_key, - client, - ))); - - // Set the umask while we open the path for most clients. - let before = unsafe { umask(0) }; - // Listen for incoming requests from PAM and NSS - let listener = match UnixListener::bind(sock_path) { - Ok(listener) => listener, - Err(e) => { - DBG_ERR!("Failed setting up the socket listener: {:?}", e); - talloc::TALLOC_FREE!(frame); - return ExitCode::FAILURE; - } - }; - // Undo umask changes. - let _ = unsafe { umask(before) }; - - let server = tokio::spawn(async move { - while !stop_now.load(Ordering::Relaxed) { - let resolver_ref = resolver.clone(); - match listener.accept().await { - Ok((socket, _addr)) => { - tokio::spawn(async move { - if let Err(e) = himmelblaud::handle_client( - socket, - resolver_ref.clone(), - ) - .await - { - DBG_ERR!( - "handle_client error occurred: {:?}", - e - ); - } - }); - } - Err(e) => { - DBG_ERR!("Error while handling connection: {:?}", e); - } - } - } - }); - - let terminate_task = tokio::spawn(async move { - match signal(SignalKind::terminate()) { - Ok(mut stream) => { - stream.recv().await; - terminate_now.store(true, Ordering::Relaxed); - } - Err(e) => { - DBG_ERR!("Failed registering terminate signal: {}", e); - } - }; - }); - - let quit_task = tokio::spawn(async move { - match signal(SignalKind::quit()) { - Ok(mut stream) => { - stream.recv().await; - quit_now.store(true, Ordering::Relaxed); - } - Err(e) => { - DBG_ERR!("Failed registering quit signal: {}", e); - } - }; - }); - - let interrupt_task = tokio::spawn(async move { - match signal(SignalKind::interrupt()) { - Ok(mut stream) => { - stream.recv().await; - interrupt_now.store(true, Ordering::Relaxed); - } - Err(e) => { - DBG_ERR!("Failed registering interrupt signal: {}", e); - } - }; - }); - - DBG_INFO!("Server started ..."); - - tokio::select! { - _ = server => { - DBG_DEBUG!("Main listener task is terminating"); - }, - _ = terminate_task => { - DBG_DEBUG!("Received signal to terminate"); - }, - _ = quit_task => { - DBG_DEBUG!("Received signal to quit"); - }, - _ = interrupt_task => { - DBG_DEBUG!("Received signal to interrupt"); - } - } - - talloc::TALLOC_FREE!(frame); - ExitCode::SUCCESS - } - .await -} diff --git a/rust/himmelblaud/src/utils.rs b/rust/himmelblaud/src/utils.rs deleted file mode 100644 index b452b4844d0..00000000000 --- a/rust/himmelblaud/src/utils.rs +++ /dev/null @@ -1,149 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Himmelblau daemon common utilities - - Copyright (C) David Mulder 2024 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - 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, -) -> Result<(String, String), Box> { - let tup: Vec<&str> = username.split('@').collect(); - if tup.len() == 2 { - return Ok((tup[0].to_string(), tup[1].to_string())); - } - 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) - }) -} - -#[cfg(test)] -mod tests { - use super::*; - use std::io::Write; - use tempfile::tempdir; - use tokio::fs; - - #[test] - fn test_split_username_success() { - let username = "user@domain.com"; - let result = split_username(username); - assert!(result.is_ok()); - let (user, domain) = result.unwrap(); - assert_eq!(user, "user"); - assert_eq!(domain, "domain.com"); - } - - #[test] - fn test_split_username_failure() { - let username = "invalid_username"; - let result = split_username(username); - assert!(result.is_err()); - assert_eq!(*result.unwrap_err(), NT_STATUS_INVALID_USER_PRINCIPAL_NAME); - } - - #[tokio::test] - async fn test_hsm_pin_fetch_or_create_generate() { - let dir = tempdir().unwrap(); - let path = dir.path().join("hsm_pin"); - - let result = hsm_pin_fetch_or_create(path.to_str().unwrap()).await; - assert!(result.is_ok()); - - // Verify that the file is created and contains a valid auth value - let saved_pin = fs::read(path).await.expect("Auth value missing"); - AuthValue::try_from(saved_pin.as_slice()) - .expect("Failed parsing auth value"); - } - - #[tokio::test] - async fn test_hsm_pin_fetch_or_create_invalid_path() { - let result = hsm_pin_fetch_or_create("invalid_path\0").await; - assert!(result.is_err()); - match result { - Err(e) => assert_eq!(*e, NT_STATUS_UNSUCCESSFUL), - Ok(_) => panic!("Expected error but got success"), - } - } - - #[tokio::test] - async fn test_hsm_pin_fetch_or_create_invalid_auth_value() { - let dir = tempdir().unwrap(); - let path = dir.path().join("hsm_pin"); - - // Write invalid content to the file - let mut file = std::fs::File::create(&path).unwrap(); - file.write_all(b"invalid_auth_value").unwrap(); - - // Test reading the invalid file - let result = hsm_pin_fetch_or_create(path.to_str().unwrap()).await; - assert!(result.is_err()); - match result { - Err(e) => assert_eq!(*e, NT_STATUS_UNSUCCESSFUL), - Ok(_) => panic!("Expected error but got success"), - } - } -} diff --git a/rust/idmap/Cargo.toml b/rust/idmap/Cargo.toml deleted file mode 100644 index 8df127f0507..00000000000 --- a/rust/idmap/Cargo.toml +++ /dev/null @@ -1,15 +0,0 @@ -[package] -name = "idmap" -edition.workspace = true -license.workspace = true -homepage.workspace = true -version.workspace = true - -[dependencies] -chelps.workspace = true -dbg.workspace = true -libc.workspace = true - -[build-dependencies] -cc = "1.0.97" -bindgen = "0.69.4" diff --git a/rust/idmap/build.rs b/rust/idmap/build.rs deleted file mode 100644 index c1a9f35e31a..00000000000 --- a/rust/idmap/build.rs +++ /dev/null @@ -1,33 +0,0 @@ -use std::env; -use std::path::Path; -use std::path::PathBuf; - -fn main() { - cc::Build::new() - .file("src/sss_idmap.c") - .file("src/sss_idmap_conv.c") - .file("src/murmurhash3.c") - .include(Path::new("../../bin/default/include")) - .warnings(false) - .compile("sss_idmap"); - - let bindings = bindgen::Builder::default() - .blocklist_function("qgcvt") - .blocklist_function("qgcvt_r") - .blocklist_function("qfcvt") - .blocklist_function("qfcvt_r") - .blocklist_function("qecvt") - .blocklist_function("qecvt_r") - .blocklist_function("strtold") - .header("src/sss_idmap.h") - .parse_callbacks(Box::new(bindgen::CargoCallbacks::new())) - .generate() - .expect("Unable to generate bindings"); - - let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); - bindings - .write_to_file(out_path.join("bindings.rs")) - .expect("Couldn't write bindings!"); - println!("cargo:rustc-link-lib=utf8proc"); - println!("cargo:rustc-env=LD_LIBRARY_PATH=../../bin/shared/private/"); -} diff --git a/rust/idmap/src/lib.rs b/rust/idmap/src/lib.rs deleted file mode 100644 index 7e9e236649a..00000000000 --- a/rust/idmap/src/lib.rs +++ /dev/null @@ -1,227 +0,0 @@ -/* - Himmelblaud - - ID-mapping library - - Copyright (C) David Mulder 2024 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -use dbg::DBG_ERR; -use std::ffi::CString; -use std::fmt; -use std::ptr; -use std::sync::{Arc, Mutex}; - -mod ffi { - #![allow(non_upper_case_globals)] - #![allow(non_camel_case_types)] - #![allow(non_snake_case)] - #![allow(dead_code)] - include!(concat!(env!("OUT_DIR"), "/bindings.rs")); -} - -#[derive(PartialEq, Eq)] -pub struct IdmapError(u32); - -pub const IDMAP_SUCCESS: IdmapError = - IdmapError(ffi::idmap_error_code_IDMAP_SUCCESS); -pub const IDMAP_NOT_IMPLEMENTED: IdmapError = - IdmapError(ffi::idmap_error_code_IDMAP_NOT_IMPLEMENTED); -pub const IDMAP_ERROR: IdmapError = - IdmapError(ffi::idmap_error_code_IDMAP_ERROR); -pub const IDMAP_OUT_OF_MEMORY: IdmapError = - IdmapError(ffi::idmap_error_code_IDMAP_OUT_OF_MEMORY); -pub const IDMAP_NO_DOMAIN: IdmapError = - IdmapError(ffi::idmap_error_code_IDMAP_NO_DOMAIN); -pub const IDMAP_CONTEXT_INVALID: IdmapError = - IdmapError(ffi::idmap_error_code_IDMAP_CONTEXT_INVALID); -pub const IDMAP_SID_INVALID: IdmapError = - IdmapError(ffi::idmap_error_code_IDMAP_SID_INVALID); -pub const IDMAP_SID_UNKNOWN: IdmapError = - IdmapError(ffi::idmap_error_code_IDMAP_SID_UNKNOWN); -pub const IDMAP_NO_RANGE: IdmapError = - IdmapError(ffi::idmap_error_code_IDMAP_NO_RANGE); -pub const IDMAP_BUILTIN_SID: IdmapError = - IdmapError(ffi::idmap_error_code_IDMAP_BUILTIN_SID); -pub const IDMAP_OUT_OF_SLICES: IdmapError = - IdmapError(ffi::idmap_error_code_IDMAP_OUT_OF_SLICES); -pub const IDMAP_COLLISION: IdmapError = - IdmapError(ffi::idmap_error_code_IDMAP_COLLISION); -pub const IDMAP_EXTERNAL: IdmapError = - IdmapError(ffi::idmap_error_code_IDMAP_EXTERNAL); -pub const IDMAP_NAME_UNKNOWN: IdmapError = - IdmapError(ffi::idmap_error_code_IDMAP_NAME_UNKNOWN); -pub const IDMAP_NO_REVERSE: IdmapError = - IdmapError(ffi::idmap_error_code_IDMAP_NO_REVERSE); -pub const IDMAP_ERR_LAST: IdmapError = - IdmapError(ffi::idmap_error_code_IDMAP_ERR_LAST); - -impl fmt::Display for IdmapError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "IdmapError({:#x})", self.0) - } -} - -impl fmt::Debug for IdmapError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "IdmapError({:#x})", self.0) - } -} - -impl std::error::Error for IdmapError {} - -pub struct Idmap { - ctx: Arc>, -} - -impl Idmap { - pub fn new() -> Result { - let mut ctx = ptr::null_mut(); - unsafe { - match IdmapError(ffi::sss_idmap_init( - None, - ptr::null_mut(), - None, - &mut ctx, - )) { - IDMAP_SUCCESS => Ok(Idmap { - ctx: Arc::new(Mutex::new(ctx)), - }), - e => Err(e), - } - } - } - - pub fn add_gen_domain( - &mut self, - domain_name: &str, - tenant_id: &str, - range: (u32, u32), - ) -> Result<(), IdmapError> { - let ctx = self.ctx.lock().map_err(|e| { - DBG_ERR!("Failed obtaining write lock on sss_idmap_ctx: {}", e); - IDMAP_ERROR - })?; - let domain_name_cstr = - CString::new(domain_name).map_err(|_| IDMAP_OUT_OF_MEMORY)?; - let tenant_id_cstr = - CString::new(tenant_id).map_err(|_| IDMAP_OUT_OF_MEMORY)?; - let mut idmap_range = ffi::sss_idmap_range { - min: range.0, - max: range.1, - }; - unsafe { - match IdmapError(ffi::sss_idmap_add_gen_domain_ex( - *ctx, - domain_name_cstr.as_ptr(), - tenant_id_cstr.as_ptr(), - &mut idmap_range, - ptr::null_mut(), - None, - None, - ptr::null_mut(), - 0, - false, - )) { - IDMAP_SUCCESS => Ok(()), - e => Err(e), - } - } - } - - pub fn gen_to_unix( - &self, - tenant_id: &str, - input: &str, - ) -> Result { - let ctx = self.ctx.lock().map_err(|e| { - DBG_ERR!("Failed obtaining write lock on sss_idmap_ctx: {}", e); - IDMAP_ERROR - })?; - let tenant_id_cstr = - CString::new(tenant_id).map_err(|_| IDMAP_OUT_OF_MEMORY)?; - let input_cstr = CString::new(input.to_lowercase()) - .map_err(|_| IDMAP_OUT_OF_MEMORY)?; - unsafe { - let mut id: u32 = 0; - match IdmapError(ffi::sss_idmap_gen_to_unix( - *ctx, - tenant_id_cstr.as_ptr(), - input_cstr.as_ptr(), - &mut id, - )) { - IDMAP_SUCCESS => Ok(id), - e => Err(e), - } - } - } -} - -impl Drop for Idmap { - fn drop(&mut self) { - match self.ctx.lock() { - Ok(ctx) => unsafe { - let _ = ffi::sss_idmap_free(*ctx); - }, - Err(e) => { - DBG_ERR!( - "Failed obtaining write lock on sss_idmap_ctx during drop: {}", - e - ); - } - } - } -} - -unsafe impl Send for Idmap {} -unsafe impl Sync for Idmap {} - -#[cfg(test)] -mod tests { - use crate::Idmap; - use std::collections::HashMap; - pub const DEFAULT_IDMAP_RANGE: (u32, u32) = (200000, 2000200000); - - #[test] - fn sssd_idmapping() { - let domain = "contoso.onmicrosoft.com"; - let tenant_id = "d7af6c1b-0497-40fe-9d17-07e6b0f8332e"; - let mut idmap = Idmap::new().expect("Idmap initialization failed"); - - idmap - .add_gen_domain(domain, tenant_id, DEFAULT_IDMAP_RANGE) - .expect("Failed initializing test domain idmapping"); - - // Verify we always get the same mapping for various users - let mut usermap: HashMap = HashMap::new(); - usermap.insert("tux@contoso.onmicrosoft.com".to_string(), 1912749799); - usermap.insert("admin@contoso.onmicrosoft.com".to_string(), 297515919); - usermap.insert("dave@contoso.onmicrosoft.com".to_string(), 132631922); - usermap.insert("joe@contoso.onmicrosoft.com".to_string(), 361591965); - usermap.insert("georg@contoso.onmicrosoft.com".to_string(), 866887005); - - for (username, expected_uid) in &usermap { - let uid = idmap.gen_to_unix(tenant_id, username).expect(&format!( - "Failed converting username {} to uid", - username - )); - assert_eq!( - uid, *expected_uid, - "Uid for {} did not match", - username - ); - } - } -} diff --git a/rust/idmap/src/murmurhash3.c b/rust/idmap/src/murmurhash3.c deleted file mode 100644 index f0ccd929627..00000000000 --- a/rust/idmap/src/murmurhash3.c +++ /dev/null @@ -1,114 +0,0 @@ -/* This file is based on the public domain MurmurHash3 from Austin Appleby: - * http://code.google.com/p/smhasher/source/browse/trunk/MurmurHash3.cpp - * - * We use only the 32 bit variant because the 2 produce different result while - * we need to produce the same result regardless of the architecture as - * clients can be both 64 or 32 bit at the same time. - */ - -#include -#include -#include - -#include "config.h" -#include "murmurhash3.h" -#include "util.h" - -static uint32_t rotl(uint32_t x, int8_t r) -{ - return (x << r) | (x >> (32 - r)); -} - -/* slower than original but is endian neutral and handles platforms that - * do only aligned reads */ -__attribute__((always_inline)) -static inline uint32_t getblock(const uint8_t *p, int i) -{ - uint32_t r; - size_t size = sizeof(uint32_t); - - memcpy(&r, &p[i * size], size); - - return le32toh(r); -} - -/* - * Finalization mix - force all bits of a hash block to avalanche - */ - -__attribute__((always_inline)) -static inline uint32_t fmix(uint32_t h) -{ - h ^= h >> 16; - h *= 0x85ebca6b; - h ^= h >> 13; - h *= 0xc2b2ae35; - h ^= h >> 16; - - return h; -} - - -uint32_t murmurhash3(const char *key, int len, uint32_t seed) -{ - const uint8_t *blocks; - const uint8_t *tail; - int nblocks; - uint32_t h1; - uint32_t k1; - uint32_t c1; - uint32_t c2; - int i; - - blocks = (const uint8_t *)key; - nblocks = len / 4; - h1 = seed; - c1 = 0xcc9e2d51; - c2 = 0x1b873593; - - /* body */ - - for (i = 0; i < nblocks; i++) { - - k1 = getblock(blocks, i); - - k1 *= c1; - k1 = rotl(k1, 15); - k1 *= c2; - - h1 ^= k1; - h1 = rotl(h1, 13); - h1 = h1 * 5 + 0xe6546b64; - } - - /* tail */ - - tail = (const uint8_t *)key + nblocks * 4; - - k1 = 0; - - switch (len & 3) { - case 3: - k1 ^= tail[2] << 16; - SSS_ATTRIBUTE_FALLTHROUGH; - case 2: - k1 ^= tail[1] << 8; - SSS_ATTRIBUTE_FALLTHROUGH; - case 1: - k1 ^= tail[0]; - k1 *= c1; - k1 = rotl(k1, 15); - k1 *= c2; - h1 ^= k1; - break; - default: - break; - } - - /* finalization */ - - h1 ^= len; - h1 = fmix(h1); - - return h1; -} diff --git a/rust/idmap/src/murmurhash3.h b/rust/idmap/src/murmurhash3.h deleted file mode 100644 index 27671831c47..00000000000 --- a/rust/idmap/src/murmurhash3.h +++ /dev/null @@ -1,21 +0,0 @@ -/* This file is based on the public domain MurmurHash3 from Austin Appleby: - * http://code.google.com/p/smhasher/source/browse/trunk/MurmurHash3.cpp - * - * We use only the 32 bit variant because the 2 produce different result while - * we need to produce the same result regardless of the architecture as - * clients can be both 64 or 32 bit at the same time. - */ - -#ifndef _SHARED_MURMURHASH3_H_ -#define _SHARED_MURMURHASH3_H_ - -/* CAUTION: - * This file is also used in sss_client (pam, nss). Therefore it have to be - * minimalist and cannot include DEBUG macros or header file util.h. - */ - -#include - -uint32_t murmurhash3(const char *key, int len, uint32_t seed); - -#endif /* _SHARED_MURMURHASH3_H_ */ diff --git a/rust/idmap/src/sss_idmap.c b/rust/idmap/src/sss_idmap.c deleted file mode 100644 index 4da1d0df4e5..00000000000 --- a/rust/idmap/src/sss_idmap.c +++ /dev/null @@ -1,1909 +0,0 @@ -/* - SSSD - - ID-mapping library - - Authors: - Sumit Bose - - Copyright (C) 2012 Red Hat - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include -#include -#include -#include -#include - -#include "sss_idmap.h" -#include "sss_idmap_private.h" -#include "murmurhash3.h" - -#define SID_FMT "%s-%"PRIu32 -#define SID_STR_MAX_LEN 1024 - -/* Hold all parameters for unix<->sid mapping relevant for - * given slice. */ -struct idmap_range_params { - uint32_t min_id; - uint32_t max_id; - char *range_id; - - uint32_t first_rid; - struct idmap_range_params *next; -}; - -struct idmap_domain_info { - char *name; - char *sid; - struct idmap_range_params range_params; - struct idmap_domain_info *next; - bool external_mapping; - - struct idmap_range_params *helpers; - bool auto_add_ranges; - bool helpers_owner; - - idmap_offset_func *offset_func; - idmap_rev_offset_func *rev_offset_func; - void *offset_func_pvt; - - idmap_store_cb cb; - void *pvt; -}; - -static void *default_alloc(size_t size, void *pvt) -{ - return malloc(size); -} - -static void default_free(void *ptr, void *pvt) -{ - free(ptr); -} - -static char *idmap_strdup(struct sss_idmap_ctx *ctx, const char *str) -{ - char *new = NULL; - size_t len; - - CHECK_IDMAP_CTX(ctx, NULL); - - len = strlen(str) + 1; - - new = ctx->alloc_func(len, ctx->alloc_pvt); - if (new == NULL) { - return NULL; - } - - memcpy(new, str, len); - - return new; -} - -static bool ranges_eq(const struct idmap_range_params *a, - const struct idmap_range_params *b) -{ - if (a == NULL || b == NULL) { - return false; - } - - if (a->first_rid == b->first_rid - && a->min_id == b->min_id - && a->max_id == b->max_id) { - return true; - } - - return false; -} - -static enum idmap_error_code -construct_range(struct sss_idmap_ctx *ctx, - const struct idmap_range_params *src, - char *id, - struct idmap_range_params **_dst) -{ - struct idmap_range_params *dst; - - if (src == NULL || id == NULL || _dst == NULL) { - return IDMAP_ERROR; - } - - dst = ctx->alloc_func(sizeof(struct idmap_range_params), ctx->alloc_pvt); - if (dst == NULL) { - return IDMAP_OUT_OF_MEMORY; - } - - dst->min_id = src->min_id; - dst->max_id = src->max_id; - dst->first_rid = src->first_rid; - dst->next = NULL; - dst->range_id = id; - - *_dst = dst; - return IDMAP_SUCCESS; -} - -static bool id_is_in_range(uint32_t id, - struct idmap_range_params *rp, - uint32_t *rid) -{ - if (id == 0 || rp == NULL) { - return false; - } - - if (id >= rp->min_id && id <= rp->max_id) { - if (rid != NULL) { - *rid = rp->first_rid + (id - rp->min_id); - } - - return true; - } - - return false; -} - -const char *idmap_error_string(enum idmap_error_code err) -{ - switch (err) { - case IDMAP_SUCCESS: - return "IDMAP operation successful"; - break; - case IDMAP_NOT_IMPLEMENTED: - return "IDMAP Function is not yet implemented"; - break; - case IDMAP_ERROR: - return "IDMAP general error"; - break; - case IDMAP_OUT_OF_MEMORY: - return "IDMAP operation ran out of memory"; - break; - case IDMAP_NO_DOMAIN: - return "IDMAP domain not found"; - break; - case IDMAP_CONTEXT_INVALID: - return "IDMAP context is invalid"; - break; - case IDMAP_SID_INVALID: - return "IDMAP SID is invalid"; - break; - case IDMAP_SID_UNKNOWN: - return "IDMAP SID not found"; - break; - case IDMAP_NO_RANGE: - return "IDMAP range not found"; - break; - case IDMAP_BUILTIN_SID: - return "IDMAP SID from BUILTIN domain"; - break; - case IDMAP_OUT_OF_SLICES: - return "IDMAP not more free slices"; - break; - case IDMAP_COLLISION: - return "IDMAP new range collides with existing one"; - break; - case IDMAP_EXTERNAL: - return "IDMAP ID managed externally"; - break; - case IDMAP_NAME_UNKNOWN: - return "IDMAP domain with the given name not found"; - break; - case IDMAP_NO_REVERSE: - return "IDMAP cannot revert id to original source"; - break; - case IDMAP_UTF8_ERROR: - return "IDMAP failed to modify UTF8 string"; - break; - default: - return "IDMAP unknown error code"; - } -} - -bool is_domain_sid(const char *sid) -{ - const char *p; - long long a; - char *endptr; - size_t c; - - if (sid == NULL || strncmp(sid, DOM_SID_PREFIX, DOM_SID_PREFIX_LEN) != 0) { - return false; - } - - p = sid + DOM_SID_PREFIX_LEN; - c = 0; - - do { - errno = 0; - a = strtoull(p, &endptr, 10); - if (errno != 0 || a > UINT32_MAX) { - return false; - } - - if (*endptr == '-') { - p = endptr + 1; - } else if (*endptr != '\0') { - return false; - } - c++; - } while(c < 3 && *endptr != '\0'); - - if (c != 3 || *endptr != '\0') { - return false; - } - - return true; -} - -enum idmap_error_code sss_idmap_init(idmap_alloc_func *alloc_func, - void *alloc_pvt, - idmap_free_func *free_func, - struct sss_idmap_ctx **_ctx) -{ - struct sss_idmap_ctx *ctx; - - if (alloc_func == NULL) { - alloc_func = default_alloc; - } - - ctx = alloc_func(sizeof(struct sss_idmap_ctx), alloc_pvt); - if (ctx == NULL) { - return IDMAP_OUT_OF_MEMORY; - } - memset(ctx, 0, sizeof(struct sss_idmap_ctx)); - - ctx->alloc_func = alloc_func; - ctx->alloc_pvt = alloc_pvt; - ctx->free_func = (free_func == NULL) ? default_free : free_func; - - /* Set default values. */ - ctx->idmap_opts.autorid_mode = SSS_IDMAP_DEFAULT_AUTORID; - ctx->idmap_opts.idmap_lower = SSS_IDMAP_DEFAULT_LOWER; - ctx->idmap_opts.idmap_upper = SSS_IDMAP_DEFAULT_UPPER; - ctx->idmap_opts.rangesize = SSS_IDMAP_DEFAULT_RANGESIZE; - ctx->idmap_opts.extra_slice_init = SSS_IDMAP_DEFAULT_EXTRA_SLICE_INIT; - - *_ctx = ctx; - - return IDMAP_SUCCESS; -} - -static void free_helpers(struct sss_idmap_ctx *ctx, - struct idmap_range_params *helpers, - bool helpers_owner) -{ - struct idmap_range_params *it = helpers; - struct idmap_range_params *tmp; - - if (helpers_owner == false) { - return; - } - - while (it != NULL) { - tmp = it->next; - - ctx->free_func(it->range_id, ctx->alloc_pvt); - ctx->free_func(it, ctx->alloc_pvt); - - it = tmp; - } -} - -static struct idmap_range_params* -get_helper_by_id(struct idmap_range_params *helpers, const char *id) -{ - struct idmap_range_params *it; - - for (it = helpers; it != NULL; it = it->next) { - if (strcmp(it->range_id, id) == 0) { - return it; - } - } - - return NULL; -} - -static void sss_idmap_free_domain(struct sss_idmap_ctx *ctx, - struct idmap_domain_info *dom) -{ - if (ctx == NULL || dom == NULL) { - return; - } - - ctx->free_func(dom->range_params.range_id, ctx->alloc_pvt); - - free_helpers(ctx, dom->helpers, dom->helpers_owner); - - ctx->free_func(dom->name, ctx->alloc_pvt); - ctx->free_func(dom->sid, ctx->alloc_pvt); - ctx->free_func(dom, ctx->alloc_pvt); -} - -enum idmap_error_code sss_idmap_free(struct sss_idmap_ctx *ctx) -{ - struct idmap_domain_info *dom; - struct idmap_domain_info *next; - - CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID); - - next = ctx->idmap_domain_info; - while (next) { - dom = next; - next = dom->next; - sss_idmap_free_domain(ctx, dom); - } - - ctx->free_func(ctx, ctx->alloc_pvt); - - return IDMAP_SUCCESS; -} - -static enum idmap_error_code sss_idmap_free_ptr(struct sss_idmap_ctx *ctx, - void *ptr) -{ - CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID); - - if (ptr != NULL) { - ctx->free_func(ptr, ctx->alloc_pvt); - } - - return IDMAP_SUCCESS; -} - -enum idmap_error_code sss_idmap_free_sid(struct sss_idmap_ctx *ctx, - char *sid) -{ - return sss_idmap_free_ptr(ctx, sid); -} - -enum idmap_error_code sss_idmap_free_dom_sid(struct sss_idmap_ctx *ctx, - struct sss_dom_sid *dom_sid) -{ - return sss_idmap_free_ptr(ctx, dom_sid); -} - -enum idmap_error_code sss_idmap_free_smb_sid(struct sss_idmap_ctx *ctx, - struct dom_sid *smb_sid) -{ - return sss_idmap_free_ptr(ctx, smb_sid); -} - -enum idmap_error_code sss_idmap_free_bin_sid(struct sss_idmap_ctx *ctx, - uint8_t *bin_sid) -{ - return sss_idmap_free_ptr(ctx, bin_sid); -} - -static bool check_overlap(struct idmap_range_params *range, - id_t min, id_t max) -{ - return ((range->min_id <= min && range->max_id >= max) - || (range->min_id >= min && range->min_id <= max) - || (range->max_id >= min && range->max_id <= max)); -} - -static bool check_dom_overlap(struct idmap_range_params *prim_range, - /* struct idmap_range_params *sec_ranges, */ - id_t min, - id_t max) -{ - return check_overlap(prim_range, min, max); -} - -enum idmap_error_code sss_idmap_calculate_range(struct sss_idmap_ctx *ctx, - const char *range_id, - id_t *slice_num, - struct sss_idmap_range *_range) -{ - id_t max_slices; - id_t orig_slice; - id_t new_slice = 0; - id_t min; - id_t max; - id_t idmap_lower; - id_t idmap_upper; - id_t rangesize; - bool autorid_mode; - uint32_t hash_val; - struct idmap_domain_info *dom; - - CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID); - - idmap_lower = ctx->idmap_opts.idmap_lower; - idmap_upper = ctx->idmap_opts.idmap_upper; - rangesize = ctx->idmap_opts.rangesize; - autorid_mode = ctx->idmap_opts.autorid_mode; - - max_slices = (idmap_upper - idmap_lower) / rangesize; - - if (slice_num && *slice_num != -1) { - /* The slice is being set explicitly. - * This may happen at system startup when we're loading - * previously-determined slices. In the future, we may also - * permit configuration to select the slice for a domain - * explicitly. - */ - new_slice = *slice_num; - min = (rangesize * new_slice) + idmap_lower; - max = min + rangesize - 1; - for (dom = ctx->idmap_domain_info; dom != NULL; dom = dom->next) { - if (check_dom_overlap(&dom->range_params,min, max)) { - /* This range overlaps one already registered - * Fail, because the slice was manually configured - */ - return IDMAP_COLLISION; - } - } - } else { - /* If slice is -1, we're being asked to pick a new slice */ - - if (autorid_mode) { - /* In autorid compatibility mode, always start at 0 and find the - * first free value. - */ - orig_slice = 0; - } else { - /* Hash the range identifier string */ - hash_val = murmurhash3(range_id, strlen(range_id), 0xdeadbeef); - - /* Now get take the modulus of the hash val and the max_slices - * to determine its optimal position in the range. - */ - new_slice = hash_val % max_slices; - orig_slice = new_slice; - } - - min = (rangesize * new_slice) + idmap_lower; - max = min + rangesize - 1; - /* Verify that this slice is not already in use */ - do { - for (dom = ctx->idmap_domain_info; dom != NULL; dom = dom->next) { - - if (check_dom_overlap(&dom->range_params, - min, max)) { - /* This range overlaps one already registered - * We'll try the next available slot - */ - new_slice++; - if (new_slice >= max_slices) { - /* loop around to the beginning if necessary */ - new_slice = 0; - } - - min = (rangesize * new_slice) + idmap_lower; - max = min + rangesize - 1; - break; - } - } - - /* Keep trying until dom is NULL (meaning we got to the end - * without matching) or we have run out of slices and gotten - * back to the first one we tried. - */ - } while (dom && new_slice != orig_slice); - - if (dom) { - /* We looped all the way through and found no empty slots */ - return IDMAP_OUT_OF_SLICES; - } - } - - _range->min = (rangesize * new_slice) + idmap_lower; - _range->max = _range->min + rangesize - 1; - - if (slice_num) { - *slice_num = new_slice; - } - - return IDMAP_SUCCESS; -} - -enum idmap_error_code sss_idmap_check_collision_ex(const char *o_name, - const char *o_sid, - struct sss_idmap_range *o_range, - uint32_t o_first_rid, - const char *o_range_id, - bool o_external_mapping, - const char *n_name, - const char *n_sid, - struct sss_idmap_range *n_range, - uint32_t n_first_rid, - const char *n_range_id, - bool n_external_mapping) -{ - bool names_equal; - bool sids_equal; - - /* TODO: if both ranges have the same ID check if an update is - * needed. */ - - /* Check if ID ranges overlap. - * ID ranges with external mapping may overlap. */ - if ((!n_external_mapping && !o_external_mapping) - && ((n_range->min >= o_range->min - && n_range->min <= o_range->max) - || (n_range->max >= o_range->min - && n_range->max <= o_range->max))) { - return IDMAP_COLLISION; - } - - names_equal = (strcasecmp(n_name, o_name) == 0); - sids_equal = ((n_sid == NULL && o_sid == NULL) - || (n_sid != NULL && o_sid != NULL - && strcasecmp(n_sid, o_sid) == 0)); - - /* check if domain name and SID are consistent */ - if ((names_equal && !sids_equal) || (!names_equal && sids_equal)) { - return IDMAP_COLLISION; - } - - /* check if external_mapping is consistent */ - if (names_equal && sids_equal - && n_external_mapping != o_external_mapping) { - return IDMAP_COLLISION; - } - - /* check if RID ranges overlap */ - if (names_equal && sids_equal - && n_external_mapping == false - && n_first_rid >= o_first_rid - && n_first_rid <= o_first_rid + (o_range->max - o_range->min)) { - return IDMAP_COLLISION; - } - - return IDMAP_SUCCESS; -} - -enum idmap_error_code sss_idmap_check_collision(struct sss_idmap_ctx *ctx, - char *n_name, char *n_sid, - struct sss_idmap_range *n_range, - uint32_t n_first_rid, - char *n_range_id, - bool n_external_mapping) -{ - struct idmap_domain_info *dom; - enum idmap_error_code err; - struct sss_idmap_range range; - - for (dom = ctx->idmap_domain_info; dom != NULL; dom = dom->next) { - - range.min = dom->range_params.min_id; - range.max = dom->range_params.max_id; - - err = sss_idmap_check_collision_ex(dom->name, dom->sid, - &range, - dom->range_params.first_rid, - dom->range_params.range_id, - dom->external_mapping, - n_name, n_sid, n_range, n_first_rid, - n_range_id, n_external_mapping); - if (err != IDMAP_SUCCESS) { - return err; - } - } - return IDMAP_SUCCESS; -} - -static enum -idmap_error_code dom_check_collision(struct idmap_domain_info *dom_list, - struct idmap_domain_info *new_dom) -{ - struct idmap_domain_info *dom; - enum idmap_error_code err; - struct sss_idmap_range range; - struct sss_idmap_range new_dom_range = { new_dom->range_params.min_id, - new_dom->range_params.max_id }; - - for (dom = dom_list; dom != NULL; dom = dom->next) { - range.min = dom->range_params.min_id; - range.max = dom->range_params.max_id; - - err = sss_idmap_check_collision_ex(dom->name, dom->sid, - &range, - dom->range_params.first_rid, - dom->range_params.range_id, - dom->external_mapping, - new_dom->name, new_dom->sid, - &new_dom_range, - new_dom->range_params.first_rid, - new_dom->range_params.range_id, - new_dom->external_mapping); - if (err != IDMAP_SUCCESS) { - return err; - } - } - return IDMAP_SUCCESS; -} - -static char* -generate_sec_slice_name(struct sss_idmap_ctx *ctx, - const char *domain_sid, uint32_t rid) -{ - const char *SEC_SLICE_NAME_FMT = "%s-%"PRIu32; - char *slice_name; - int len, len2; - - len = snprintf(NULL, 0, SEC_SLICE_NAME_FMT, domain_sid, rid); - if (len <= 0) { - return NULL; - } - - slice_name = ctx->alloc_func(len + 1, ctx->alloc_pvt); - if (slice_name == NULL) { - return NULL; - } - - len2 = snprintf(slice_name, len + 1, SEC_SLICE_NAME_FMT, domain_sid, - rid); - if (len != len2) { - ctx->free_func(slice_name, ctx->alloc_pvt); - return NULL; - } - - return slice_name; -} - -static enum idmap_error_code -generate_slice(struct sss_idmap_ctx *ctx, char *slice_name, uint32_t first_rid, - struct idmap_range_params **_slice) -{ - struct idmap_range_params *slice; - struct sss_idmap_range tmp_range; - enum idmap_error_code err; - - slice = ctx->alloc_func(sizeof(struct idmap_range_params), ctx->alloc_pvt); - if (slice == NULL) { - return IDMAP_OUT_OF_MEMORY; - } - - slice->next = NULL; - - err = sss_idmap_calculate_range(ctx, slice_name, NULL, &tmp_range); - if (err != IDMAP_SUCCESS) { - ctx->free_func(slice, ctx->alloc_pvt); - return err; - } - - slice->min_id = tmp_range.min; - slice->max_id = tmp_range.max; - slice->range_id = slice_name; - slice->first_rid = first_rid; - - *_slice = slice; - return IDMAP_SUCCESS; -} - -static enum idmap_error_code -get_helpers(struct sss_idmap_ctx *ctx, - const char *domain_sid, - uint32_t first_rid, - struct idmap_range_params **_sec_slices) -{ - struct idmap_range_params *prev = NULL; - struct idmap_range_params *sec_slices = NULL; - static enum idmap_error_code err; - struct idmap_range_params *slice; - char *secondary_name; - - for (int i = 0; i < ctx->idmap_opts.extra_slice_init; i++) { - secondary_name = generate_sec_slice_name(ctx, domain_sid, first_rid); - if (secondary_name == NULL) { - err = IDMAP_OUT_OF_MEMORY; - goto fail; - } - - err = generate_slice(ctx, secondary_name, first_rid, &slice); - if (err != IDMAP_SUCCESS) { - goto fail; - } - - first_rid += ctx->idmap_opts.rangesize; - - if (prev != NULL) { - prev->next = slice; - } - - if (sec_slices == NULL) { - sec_slices = slice; - } - - prev = slice; - } - - *_sec_slices = sec_slices; - return IDMAP_SUCCESS; - -fail: - ctx->free_func(secondary_name, ctx->alloc_pvt); - - /* Free already generated helpers. */ - free_helpers(ctx, sec_slices, true); - - return err; -} - -enum idmap_error_code sss_idmap_add_gen_domain_ex(struct sss_idmap_ctx *ctx, - const char *domain_name, - const char *domain_id, - struct sss_idmap_range *range, - const char *range_id, - idmap_offset_func *offset_func, - idmap_rev_offset_func *rev_offset_func, - void *offset_func_pvt, - uint32_t shift, - bool external_mapping) -{ - struct idmap_domain_info *dom = NULL; - enum idmap_error_code err; - - CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID); - - if (domain_name == NULL || domain_id == NULL) { - return IDMAP_NO_DOMAIN; - } - - if (range == NULL) { - return IDMAP_NO_RANGE; - } - - dom = ctx->alloc_func(sizeof(struct idmap_domain_info), ctx->alloc_pvt); - if (dom == NULL) { - return IDMAP_OUT_OF_MEMORY; - } - memset(dom, 0, sizeof(struct idmap_domain_info)); - - dom->name = idmap_strdup(ctx, domain_name); - if (dom->name == NULL) { - err = IDMAP_OUT_OF_MEMORY; - goto fail; - } - - dom->sid = idmap_strdup(ctx, domain_id); - if (dom->sid == NULL) { - err = IDMAP_OUT_OF_MEMORY; - goto fail; - } - - dom->range_params.min_id = range->min; - dom->range_params.max_id = range->max; - - if (range_id != NULL) { - dom->range_params.range_id = idmap_strdup(ctx, range_id); - if (dom->range_params.range_id == NULL) { - err = IDMAP_OUT_OF_MEMORY; - goto fail; - } - } - - dom->range_params.first_rid = shift; - dom->external_mapping = external_mapping; - - dom->offset_func = offset_func; - dom->rev_offset_func = rev_offset_func; - dom->offset_func_pvt = offset_func_pvt; - - err = dom_check_collision(ctx->idmap_domain_info, dom); - if (err != IDMAP_SUCCESS) { - goto fail; - } - - dom->next = ctx->idmap_domain_info; - ctx->idmap_domain_info = dom; - - return IDMAP_SUCCESS; - -fail: - sss_idmap_free_domain(ctx, dom); - - return err; -} - -enum idmap_error_code sss_idmap_add_domain_ex(struct sss_idmap_ctx *ctx, - const char *domain_name, - const char *domain_sid, - struct sss_idmap_range *range, - const char *range_id, - uint32_t rid, - bool external_mapping) -{ - struct idmap_domain_info *dom = NULL; - enum idmap_error_code err; - - CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID); - - if (domain_name == NULL) { - return IDMAP_NO_DOMAIN; - } - - if (range == NULL) { - return IDMAP_NO_RANGE; - } - - /* For algorithmic mapping a valid domain SID is required, for external - * mapping it may be NULL, but if set it should be valid. */ - if ((!external_mapping && !is_domain_sid(domain_sid)) - || (external_mapping - && domain_sid != NULL - && !is_domain_sid(domain_sid))) { - return IDMAP_SID_INVALID; - } - - dom = ctx->alloc_func(sizeof(struct idmap_domain_info), ctx->alloc_pvt); - if (dom == NULL) { - return IDMAP_OUT_OF_MEMORY; - } - memset(dom, 0, sizeof(struct idmap_domain_info)); - - dom->name = idmap_strdup(ctx, domain_name); - if (dom->name == NULL) { - err = IDMAP_OUT_OF_MEMORY; - goto fail; - } - - if (domain_sid != NULL) { - dom->sid = idmap_strdup(ctx, domain_sid); - if (dom->sid == NULL) { - err = IDMAP_OUT_OF_MEMORY; - goto fail; - } - } - - dom->range_params.min_id = range->min; - dom->range_params.max_id = range->max; - - if (range_id != NULL) { - dom->range_params.range_id = idmap_strdup(ctx, range_id); - if (dom->range_params.range_id == NULL) { - err = IDMAP_OUT_OF_MEMORY; - goto fail; - } - } - - dom->range_params.first_rid = rid; - dom->external_mapping = external_mapping; - - err = dom_check_collision(ctx->idmap_domain_info, dom); - if (err != IDMAP_SUCCESS) { - goto fail; - } - - dom->next = ctx->idmap_domain_info; - ctx->idmap_domain_info = dom; - - return IDMAP_SUCCESS; - -fail: - sss_idmap_free_domain(ctx, dom); - - return err; -} - -enum idmap_error_code -sss_idmap_add_auto_domain_ex(struct sss_idmap_ctx *ctx, - const char *domain_name, - const char *domain_sid, - struct sss_idmap_range *range, - const char *range_id, - uint32_t rid, - bool external_mapping, - idmap_store_cb cb, - void *pvt) -{ - enum idmap_error_code err; - - err = sss_idmap_add_domain_ex(ctx, domain_name, domain_sid, range, - range_id, rid, external_mapping); - if (err != IDMAP_SUCCESS) { - return err; - } - - if (external_mapping) { - /* There's no point in generating secondary ranges if external_mapping - is enabled. */ - ctx->idmap_domain_info->auto_add_ranges = false; - return IDMAP_SUCCESS; - } - - if ((range->max - range->min + 1) != ctx->idmap_opts.rangesize) { - /* Range of primary slice is not equal to the value of - ldap_idmap_range_size option. */ - return IDMAP_ERROR; - } - - /* No additional secondary ranges should be added if no sec ranges are - predeclared. */ - if (ctx->idmap_opts.extra_slice_init == 0) { - ctx->idmap_domain_info->auto_add_ranges = false; - return IDMAP_SUCCESS; - } - - /* Add size of primary slice for first_rid of secondary slices. */ - rid += ctx->idmap_opts.rangesize; - err = get_helpers(ctx, domain_sid, rid, - &ctx->idmap_domain_info->helpers); - if (err == IDMAP_SUCCESS) { - ctx->idmap_domain_info->auto_add_ranges = true; - ctx->idmap_domain_info->helpers_owner = true; - } else { - /* Running out of slices for secondary mapping is a non-fatal - * problem. */ - if (err == IDMAP_OUT_OF_SLICES) { - err = IDMAP_SUCCESS; - } - ctx->idmap_domain_info->auto_add_ranges = false; - } - - ctx->idmap_domain_info->cb = cb; - ctx->idmap_domain_info->pvt = pvt; - - return err; -} - -enum idmap_error_code sss_idmap_add_domain(struct sss_idmap_ctx *ctx, - const char *domain_name, - const char *domain_sid, - struct sss_idmap_range *range) -{ - return sss_idmap_add_domain_ex(ctx, domain_name, domain_sid, range, NULL, - 0, false); -} - -static bool sss_idmap_sid_is_builtin(const char *sid) -{ - if (strncmp(sid, "S-1-5-32-", 9) == 0) { - return true; - } - - return false; -} - -static bool parse_rid(const char *sid, size_t dom_prefix_len, long long *_rid) -{ - long long rid; - char *endptr; - - errno = 0; - /* Use suffix of sid - part after domain and following '-' */ - rid = strtoull(sid + dom_prefix_len + 1, &endptr, 10); - if (errno != 0 || rid > UINT32_MAX || *endptr != '\0') { - return false; - } - - *_rid = rid; - return true; -} - -static bool is_from_dom(const char *domain_id, const char *id) -{ - if (domain_id == NULL) { - return false; - } - - return strcmp(domain_id, id) == 0; -} - -static bool is_sid_from_dom(const char *dom_sid, const char *sid, - size_t *_dom_sid_len) -{ - size_t dom_sid_len; - - if (dom_sid == NULL) { - return false; - } - - dom_sid_len = strlen(dom_sid); - *_dom_sid_len = dom_sid_len; - - if (strlen(sid) < dom_sid_len || sid[dom_sid_len] != '-') { - return false; - } - - return strncmp(sid, dom_sid, dom_sid_len) == 0; -} - -static bool comp_id(struct idmap_range_params *range_params, long long rid, - uint32_t *_id) -{ - uint32_t id; - - if (rid >= range_params->first_rid - && ((UINT32_MAX - range_params->min_id) > - (rid - range_params->first_rid))) { - id = range_params->min_id + (rid - range_params->first_rid); - if (id <= range_params->max_id) { - *_id = id; - return true; - } - } - return false; -} - -static enum idmap_error_code -get_range(struct sss_idmap_ctx *ctx, - struct idmap_range_params *helpers, - const char *dom_sid, - long long rid, - struct idmap_range_params **_range) -{ - char *secondary_name = NULL; - enum idmap_error_code err; - int first_rid; - struct idmap_range_params *range; - struct idmap_range_params *helper; - - first_rid = (rid / ctx->idmap_opts.rangesize) * ctx->idmap_opts.rangesize; - - secondary_name = generate_sec_slice_name(ctx, dom_sid, first_rid); - if (secondary_name == NULL) { - err = IDMAP_OUT_OF_MEMORY; - goto error; - } - - helper = get_helper_by_id(helpers, secondary_name); - if (helper != NULL) { - /* Utilize helper's range. */ - err = construct_range(ctx, helper, secondary_name, &range); - } else { - /* Have to generate a whole new range. */ - err = generate_slice(ctx, secondary_name, first_rid, &range); - } - - if (err != IDMAP_SUCCESS) { - goto error; - } - - *_range = range; - return IDMAP_SUCCESS; - -error: - ctx->free_func(secondary_name, ctx->alloc_pvt); - return err; -} - -static enum idmap_error_code -spawn_dom(struct sss_idmap_ctx *ctx, - struct idmap_domain_info *parent, - struct idmap_range_params *range) -{ - struct sss_idmap_range tmp; - static enum idmap_error_code err; - struct idmap_domain_info *it; - - tmp.min = range->min_id; - tmp.max = range->max_id; - - err = sss_idmap_add_domain_ex(ctx, - parent->name, - parent->sid, - &tmp, range->range_id, - range->first_rid, false); - if (err != IDMAP_SUCCESS) { - return err; - } - - it = ctx->idmap_domain_info; - while (it != NULL) { - /* Find the newly added domain. */ - if (ranges_eq(&it->range_params, range)) { - - /* Share helpers. */ - it->helpers = parent->helpers; - it->auto_add_ranges = parent->auto_add_ranges; - - /* Share call back for storing domains */ - it->cb = parent->cb; - it->pvt = parent->pvt; - break; - } - - it = it->next; - } - - if (it == NULL) { - /* Failed to find just added domain. */ - return IDMAP_ERROR; - } - - /* Store mapping for newly created domain. */ - if (it->cb != NULL) { - err = it->cb(it->name, - it->sid, - it->range_params.range_id, - it->range_params.min_id, - it->range_params.max_id, - it->range_params.first_rid, - it->pvt); - if (err != IDMAP_SUCCESS) { - return err; - } - } - - return IDMAP_SUCCESS; -} - -static enum idmap_error_code -add_dom_for_sid(struct sss_idmap_ctx *ctx, - struct idmap_domain_info *matched_dom, - const char *sid, - uint32_t *_id) -{ - enum idmap_error_code err; - long long rid; - struct idmap_range_params *range = NULL; - - if (parse_rid(sid, strlen(matched_dom->sid), &rid) == false) { - err = IDMAP_SID_INVALID; - goto done; - } - - err = get_range(ctx, matched_dom->helpers, matched_dom->sid, rid, &range); - if (err != IDMAP_SUCCESS) { - goto done; - } - - err = spawn_dom(ctx, matched_dom, range); - if (err != IDMAP_SUCCESS) { - goto done; - } - - if (!comp_id(range, rid, _id)) { - err = IDMAP_ERROR; - goto done; - } - - err = IDMAP_SUCCESS; - -done: - if (range != NULL) { - ctx->free_func(range->range_id, ctx->alloc_pvt); - } - ctx->free_func(range, ctx->alloc_pvt); - return err; -} - -enum idmap_error_code offset_identity(void *pvt, uint32_t range_size, - const char *input, long long *offset) -{ - long long out; - char *endptr; - - if (input == NULL || offset == NULL) { - return IDMAP_ERROR; - } - - errno = 0; - out = strtoull(input, &endptr, 10); - if (errno != 0 || out >= range_size || *endptr != '\0' - || endptr == input) { - return IDMAP_ERROR; - } - - *offset = out; - - return IDMAP_SUCCESS; -} - -enum idmap_error_code rev_offset_identity(struct sss_idmap_ctx *ctx, void *pvt, - uint32_t id, char **_out) -{ - char *out; - int len; - int ret; - - len = snprintf(NULL, 0, "%"PRIu32, id); - if (len <= 0 || len > SID_STR_MAX_LEN) { - return IDMAP_ERROR; - } - - out = ctx->alloc_func(len + 1, ctx->alloc_pvt); - if (out == NULL) { - return IDMAP_OUT_OF_MEMORY; - } - - ret = snprintf(out, len + 1, "%"PRIu32, id); - if (ret != len) { - ctx->free_func(out, ctx->alloc_pvt); - return IDMAP_ERROR; - } - - *_out = out; - return IDMAP_SUCCESS; -} - -static char *normalize_casefold(const char *input, bool normalize, - bool casefold) -{ - if (casefold) { - return (char *) utf8proc_NFKC_Casefold((const utf8proc_uint8_t *) input); - } - - if (normalize) { - return (char *) utf8proc_NFKC((const utf8proc_uint8_t *) input); - } - - return NULL; -} - -struct offset_murmurhash3_data offset_murmurhash3_data_default = - { .seed = 0xdeadbeef, - .normalize = true, - .casefold = false }; - -enum idmap_error_code offset_murmurhash3(void *pvt, uint32_t range_size, - const char *input, long long *offset) -{ - struct offset_murmurhash3_data *offset_murmurhash3_data; - long long out; - char *tmp = NULL; - const char *val; - - if (input == NULL || offset == NULL) { - return IDMAP_ERROR; - } - - if (pvt != NULL) { - offset_murmurhash3_data = (struct offset_murmurhash3_data *) pvt; - } else { - offset_murmurhash3_data = &offset_murmurhash3_data_default; - } - - if (offset_murmurhash3_data->normalize || offset_murmurhash3_data->casefold) { - tmp = normalize_casefold(input, offset_murmurhash3_data->normalize, - offset_murmurhash3_data->casefold); - if (tmp == NULL) { - return IDMAP_UTF8_ERROR; - } - } - - val = (tmp == NULL) ? input : tmp; - - out = murmurhash3(val, strlen(val), offset_murmurhash3_data->seed); - free(tmp); - - out %= range_size; - - *offset = out; - - return IDMAP_SUCCESS; -} - -enum idmap_error_code sss_idmap_gen_to_unix(struct sss_idmap_ctx *ctx, - const char *domain_id, - const char *input, - uint32_t *_id) -{ - struct idmap_domain_info *idmap_domain_info; - struct idmap_domain_info *matched_dom = NULL; - long long offset; - uint32_t range_size; - enum idmap_error_code err; - idmap_offset_func *offset_func = offset_murmurhash3; - void *offset_func_pvt = NULL; - - if (domain_id == NULL || input == NULL || _id == NULL) { - return IDMAP_ERROR; - } - - CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID); - - idmap_domain_info = ctx->idmap_domain_info; - - if (idmap_domain_info->offset_func != NULL) { - offset_func = idmap_domain_info->offset_func; - if (idmap_domain_info->offset_func_pvt != NULL) { - offset_func_pvt = idmap_domain_info->offset_func_pvt; - } - } - - /* Try primary slices */ - while (idmap_domain_info != NULL) { - - if (is_from_dom(idmap_domain_info->sid, domain_id)) { - - if (idmap_domain_info->external_mapping == true) { - return IDMAP_EXTERNAL; - } - - range_size = 1 + (idmap_domain_info->range_params.max_id - idmap_domain_info->range_params.min_id); - err = offset_func(offset_func_pvt, range_size, input, &offset); - if (err != IDMAP_SUCCESS) { - return err; - } - - if (offset >= range_size) { - return IDMAP_ERROR; - } - - if (comp_id(&idmap_domain_info->range_params, offset, _id)) { - return IDMAP_SUCCESS; - } - - matched_dom = idmap_domain_info; - } - - idmap_domain_info = idmap_domain_info->next; - } - - return matched_dom ? IDMAP_NO_RANGE : IDMAP_NO_DOMAIN; -} - -enum idmap_error_code sss_idmap_unix_to_gen(struct sss_idmap_ctx *ctx, - uint32_t id, - char **_out) -{ - struct idmap_domain_info *idmap_domain_info; - uint32_t offset; - - CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID); - - idmap_domain_info = ctx->idmap_domain_info; - - while (idmap_domain_info != NULL) { - if (id_is_in_range(id, &idmap_domain_info->range_params, &offset)) { - - if (idmap_domain_info->external_mapping == true - || idmap_domain_info->sid == NULL) { - return IDMAP_EXTERNAL; - } - - if (idmap_domain_info->rev_offset_func == NULL) { - return IDMAP_NO_REVERSE; - } - - return idmap_domain_info->rev_offset_func(ctx, - idmap_domain_info->offset_func_pvt, - offset, _out); - } - - idmap_domain_info = idmap_domain_info->next; - } - - return IDMAP_NO_DOMAIN; -} - -enum idmap_error_code sss_idmap_sid_to_unix(struct sss_idmap_ctx *ctx, - const char *sid, - uint32_t *_id) -{ - struct idmap_domain_info *idmap_domain_info; - struct idmap_domain_info *matched_dom = NULL; - size_t dom_len; - long long rid; - - if (sid == NULL || _id == NULL) { - return IDMAP_ERROR; - } - - CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID); - - idmap_domain_info = ctx->idmap_domain_info; - - if (sss_idmap_sid_is_builtin(sid)) { - return IDMAP_BUILTIN_SID; - } - - /* Try primary slices */ - while (idmap_domain_info != NULL) { - - if (is_sid_from_dom(idmap_domain_info->sid, sid, &dom_len)) { - - if (idmap_domain_info->external_mapping == true) { - return IDMAP_EXTERNAL; - } - - if (parse_rid(sid, dom_len, &rid) == false) { - return IDMAP_SID_INVALID; - } - - if (comp_id(&idmap_domain_info->range_params, rid, _id)) { - return IDMAP_SUCCESS; - } - - matched_dom = idmap_domain_info; - } - - idmap_domain_info = idmap_domain_info->next; - } - - if (matched_dom != NULL && matched_dom->auto_add_ranges) { - return add_dom_for_sid(ctx, matched_dom, sid, _id); - } - - return matched_dom ? IDMAP_NO_RANGE : IDMAP_NO_DOMAIN; -} - -enum idmap_error_code sss_idmap_check_sid_unix(struct sss_idmap_ctx *ctx, - const char *sid, - uint32_t id) -{ - struct idmap_domain_info *idmap_domain_info; - size_t dom_len; - bool no_range = false; - - if (sid == NULL) { - return IDMAP_ERROR; - } - - CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID); - - if (ctx->idmap_domain_info == NULL) { - return IDMAP_NO_DOMAIN; - } - - idmap_domain_info = ctx->idmap_domain_info; - - if (sss_idmap_sid_is_builtin(sid)) { - return IDMAP_BUILTIN_SID; - } - - while (idmap_domain_info != NULL) { - if (idmap_domain_info->sid != NULL) { - dom_len = strlen(idmap_domain_info->sid); - if (strlen(sid) > dom_len && sid[dom_len] == '-' - && strncmp(sid, idmap_domain_info->sid, dom_len) == 0) { - - if (id >= idmap_domain_info->range_params.min_id - && id <= idmap_domain_info->range_params.max_id) { - return IDMAP_SUCCESS; - } - - no_range = true; - } - } - - idmap_domain_info = idmap_domain_info->next; - } - - return no_range ? IDMAP_NO_RANGE : IDMAP_SID_UNKNOWN; -} - -static enum idmap_error_code generate_sid(struct sss_idmap_ctx *ctx, - const char *dom_sid, - uint32_t rid, - char **_sid) -{ - char *sid; - int len; - int ret; - - len = snprintf(NULL, 0, SID_FMT, dom_sid, rid); - if (len <= 0 || len > SID_STR_MAX_LEN) { - return IDMAP_ERROR; - } - - sid = ctx->alloc_func(len + 1, ctx->alloc_pvt); - if (sid == NULL) { - return IDMAP_OUT_OF_MEMORY; - } - - ret = snprintf(sid, len + 1, SID_FMT, dom_sid, rid); - if (ret != len) { - ctx->free_func(sid, ctx->alloc_pvt); - return IDMAP_ERROR; - } - - *_sid = sid; - return IDMAP_SUCCESS; -} - -enum idmap_error_code sss_idmap_unix_to_sid(struct sss_idmap_ctx *ctx, - uint32_t id, - char **_sid) -{ - struct idmap_domain_info *idmap_domain_info; - uint32_t rid; - enum idmap_error_code err; - - CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID); - - idmap_domain_info = ctx->idmap_domain_info; - - while (idmap_domain_info != NULL) { - if (id_is_in_range(id, &idmap_domain_info->range_params, &rid)) { - - if (idmap_domain_info->external_mapping == true - || idmap_domain_info->sid == NULL) { - return IDMAP_EXTERNAL; - } - - return generate_sid(ctx, idmap_domain_info->sid, rid, _sid); - } - - idmap_domain_info = idmap_domain_info->next; - } - - /* Check secondary ranges. */ - idmap_domain_info = ctx->idmap_domain_info; - while (idmap_domain_info != NULL) { - - for (struct idmap_range_params *it = idmap_domain_info->helpers; - it != NULL; - it = it->next) { - - if (idmap_domain_info->helpers_owner == false) { - /* Checking helpers on owner is sufficient. */ - continue; - } - - if (id_is_in_range(id, it, &rid)) { - - if (idmap_domain_info->external_mapping == true - || idmap_domain_info->sid == NULL) { - return IDMAP_EXTERNAL; - } - - err = spawn_dom(ctx, idmap_domain_info, it); - if (err != IDMAP_SUCCESS) { - return err; - } - - return generate_sid(ctx, idmap_domain_info->sid, rid, _sid); - } - } - - idmap_domain_info = idmap_domain_info->next; - } - - return IDMAP_NO_DOMAIN; -} - -enum idmap_error_code sss_idmap_dom_sid_to_unix(struct sss_idmap_ctx *ctx, - struct sss_dom_sid *dom_sid, - uint32_t *id) -{ - enum idmap_error_code err; - char *sid; - - CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID); - - err = sss_idmap_dom_sid_to_sid(ctx, dom_sid, &sid); - if (err != IDMAP_SUCCESS) { - goto done; - } - - err = sss_idmap_sid_to_unix(ctx, sid, id); - -done: - ctx->free_func(sid, ctx->alloc_pvt); - - return err; -} - -enum idmap_error_code sss_idmap_bin_sid_to_unix(struct sss_idmap_ctx *ctx, - uint8_t *bin_sid, - size_t length, - uint32_t *id) -{ - enum idmap_error_code err; - char *sid; - - CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID); - - err = sss_idmap_bin_sid_to_sid(ctx, bin_sid, length, &sid); - if (err != IDMAP_SUCCESS) { - goto done; - } - - err = sss_idmap_sid_to_unix(ctx, sid, id); - -done: - ctx->free_func(sid, ctx->alloc_pvt); - - return err; -} - -enum idmap_error_code sss_idmap_smb_sid_to_unix(struct sss_idmap_ctx *ctx, - struct dom_sid *smb_sid, - uint32_t *id) -{ - enum idmap_error_code err; - char *sid; - - CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID); - - err = sss_idmap_smb_sid_to_sid(ctx, smb_sid, &sid); - if (err != IDMAP_SUCCESS) { - goto done; - } - - err = sss_idmap_sid_to_unix(ctx, sid, id); - -done: - ctx->free_func(sid, ctx->alloc_pvt); - - return err; -} - -enum idmap_error_code sss_idmap_check_dom_sid_to_unix(struct sss_idmap_ctx *ctx, - struct sss_dom_sid *dom_sid, - uint32_t id) -{ - enum idmap_error_code err; - char *sid; - - CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID); - - err = sss_idmap_dom_sid_to_sid(ctx, dom_sid, &sid); - if (err != IDMAP_SUCCESS) { - goto done; - } - - err = sss_idmap_check_sid_unix(ctx, sid, id); - -done: - ctx->free_func(sid, ctx->alloc_pvt); - - return err; -} - -enum idmap_error_code sss_idmap_check_bin_sid_unix(struct sss_idmap_ctx *ctx, - uint8_t *bin_sid, - size_t length, - uint32_t id) -{ - enum idmap_error_code err; - char *sid; - - CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID); - - err = sss_idmap_bin_sid_to_sid(ctx, bin_sid, length, &sid); - if (err != IDMAP_SUCCESS) { - goto done; - } - - err = sss_idmap_check_sid_unix(ctx, sid, id); - -done: - ctx->free_func(sid, ctx->alloc_pvt); - - return err; -} - -enum idmap_error_code sss_idmap_check_smb_sid_unix(struct sss_idmap_ctx *ctx, - struct dom_sid *smb_sid, - uint32_t id) -{ - enum idmap_error_code err; - char *sid; - - CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID); - - err = sss_idmap_smb_sid_to_sid(ctx, smb_sid, &sid); - if (err != IDMAP_SUCCESS) { - goto done; - } - - err = sss_idmap_check_sid_unix(ctx, sid, id); - -done: - ctx->free_func(sid, ctx->alloc_pvt); - - return err; -} -enum idmap_error_code sss_idmap_unix_to_dom_sid(struct sss_idmap_ctx *ctx, - uint32_t id, - struct sss_dom_sid **_dom_sid) -{ - enum idmap_error_code err; - char *sid = NULL; - struct sss_dom_sid *dom_sid = NULL; - - CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID); - - err = sss_idmap_unix_to_sid(ctx, id, &sid); - if (err != IDMAP_SUCCESS) { - goto done; - } - - err = sss_idmap_sid_to_dom_sid(ctx, sid, &dom_sid); - if (err != IDMAP_SUCCESS) { - goto done; - } - - *_dom_sid = dom_sid; - err = IDMAP_SUCCESS; - -done: - ctx->free_func(sid, ctx->alloc_pvt); - if (err != IDMAP_SUCCESS) { - ctx->free_func(dom_sid, ctx->alloc_pvt); - } - - return err; -} - -enum idmap_error_code sss_idmap_unix_to_bin_sid(struct sss_idmap_ctx *ctx, - uint32_t id, - uint8_t **_bin_sid, - size_t *_length) -{ - enum idmap_error_code err; - char *sid = NULL; - uint8_t *bin_sid = NULL; - size_t length; - - CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID); - - err = sss_idmap_unix_to_sid(ctx, id, &sid); - if (err != IDMAP_SUCCESS) { - goto done; - } - - err = sss_idmap_sid_to_bin_sid(ctx, sid, &bin_sid, &length); - if (err != IDMAP_SUCCESS) { - goto done; - } - - *_bin_sid = bin_sid; - *_length = length; - err = IDMAP_SUCCESS; - -done: - ctx->free_func(sid, ctx->alloc_pvt); - if (err != IDMAP_SUCCESS) { - ctx->free_func(bin_sid, ctx->alloc_pvt); - } - - return err; - -} - -enum idmap_error_code -sss_idmap_ctx_set_autorid(struct sss_idmap_ctx *ctx, bool use_autorid) -{ - CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID); - ctx->idmap_opts.autorid_mode = use_autorid; - return IDMAP_SUCCESS; -} - -enum idmap_error_code -sss_idmap_ctx_set_lower(struct sss_idmap_ctx *ctx, id_t lower) -{ - CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID); - ctx->idmap_opts.idmap_lower = lower; - return IDMAP_SUCCESS; -} - -enum idmap_error_code -sss_idmap_ctx_set_upper(struct sss_idmap_ctx *ctx, id_t upper) -{ - CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID); - ctx->idmap_opts.idmap_upper = upper; - return IDMAP_SUCCESS; -} - -enum idmap_error_code -sss_idmap_ctx_set_rangesize(struct sss_idmap_ctx *ctx, id_t rangesize) -{ - CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID); - ctx->idmap_opts.rangesize = rangesize; - return IDMAP_SUCCESS; -} - -enum idmap_error_code -sss_idmap_ctx_set_extra_slice_init(struct sss_idmap_ctx *ctx, - int extra_slice_init) -{ - CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID); - ctx->idmap_opts.extra_slice_init = extra_slice_init; - return IDMAP_SUCCESS; -} - -enum idmap_error_code -sss_idmap_ctx_get_autorid(struct sss_idmap_ctx *ctx, bool *_autorid) -{ - CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID); - *_autorid = ctx->idmap_opts.autorid_mode; - return IDMAP_SUCCESS; -} - -enum idmap_error_code -sss_idmap_ctx_get_lower(struct sss_idmap_ctx *ctx, id_t *_lower) -{ - CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID); - *_lower = ctx->idmap_opts.idmap_lower; - return IDMAP_SUCCESS; -} - -enum idmap_error_code -sss_idmap_ctx_get_upper(struct sss_idmap_ctx *ctx, id_t *_upper) -{ - CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID); - *_upper = ctx->idmap_opts.idmap_upper; - return IDMAP_SUCCESS; -} - -enum idmap_error_code -sss_idmap_ctx_get_rangesize(struct sss_idmap_ctx *ctx, id_t *_rangesize) -{ - CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID); - *_rangesize = ctx->idmap_opts.rangesize; - return IDMAP_SUCCESS; -} - -enum idmap_error_code -sss_idmap_domain_has_algorithmic_mapping(struct sss_idmap_ctx *ctx, - const char *dom_sid, - bool *has_algorithmic_mapping) -{ - struct idmap_domain_info *idmap_domain_info; - size_t len; - size_t dom_sid_len; - - if (dom_sid == NULL) { - return IDMAP_SID_INVALID; - } - - CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID); - - if (ctx->idmap_domain_info == NULL) { - return IDMAP_NO_DOMAIN; - } - - idmap_domain_info = ctx->idmap_domain_info; - - while (idmap_domain_info != NULL) { - if (idmap_domain_info->sid != NULL) { - len = strlen(idmap_domain_info->sid); - dom_sid_len = strlen(dom_sid); - if (((dom_sid_len > len && dom_sid[len] == '-') - || dom_sid_len == len) - && strncmp(dom_sid, idmap_domain_info->sid, len) == 0) { - - *has_algorithmic_mapping = !idmap_domain_info->external_mapping; - return IDMAP_SUCCESS; - - } - } - - idmap_domain_info = idmap_domain_info->next; - } - - return IDMAP_SID_UNKNOWN; -} - -enum idmap_error_code -sss_idmap_domain_by_name_has_algorithmic_mapping(struct sss_idmap_ctx *ctx, - const char *dom_name, - bool *has_algorithmic_mapping) -{ - struct idmap_domain_info *idmap_domain_info; - - if (dom_name == NULL) { - return IDMAP_ERROR; - } - - CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID); - - if (ctx->idmap_domain_info == NULL) { - return IDMAP_NO_DOMAIN; - } - - idmap_domain_info = ctx->idmap_domain_info; - - while (idmap_domain_info != NULL) { - if (idmap_domain_info->name != NULL - && strcmp(dom_name, idmap_domain_info->name) == 0) { - - *has_algorithmic_mapping = !idmap_domain_info->external_mapping; - return IDMAP_SUCCESS; - } - - idmap_domain_info = idmap_domain_info->next; - } - - return IDMAP_NAME_UNKNOWN; -} diff --git a/rust/idmap/src/sss_idmap.h b/rust/idmap/src/sss_idmap.h deleted file mode 100644 index a94c07f3bdf..00000000000 --- a/rust/idmap/src/sss_idmap.h +++ /dev/null @@ -1,1100 +0,0 @@ -/* - SSSD - - ID-mapping library - - Authors: - Sumit Bose - - Copyright (C) 2012 Red Hat - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef SSS_IDMAP_H_ -#define SSS_IDMAP_H_ - -#include -#include -#include -#include - -#define DOM_SID_PREFIX "S-1-5-21-" -#define DOM_SID_PREFIX_LEN (sizeof(DOM_SID_PREFIX) - 1) - -/** - * @defgroup sss_idmap Map Unix UIDs and GIDs to SIDs and back - * Libsss_idmap provides a mechanism to translate a SID to a UNIX UID or GID - * or the other way round. - * @{ - */ - -/** - * Error codes used by libsss_idmap - */ -enum idmap_error_code { - /** Success */ - IDMAP_SUCCESS = 0, - - /** Function is not yet implemented */ - IDMAP_NOT_IMPLEMENTED, - - /** General error */ - IDMAP_ERROR, - - /** Ran out of memory during processing */ - IDMAP_OUT_OF_MEMORY, - - /** No domain added */ - IDMAP_NO_DOMAIN, - - /** The provided idmap context is invalid */ - IDMAP_CONTEXT_INVALID, - - /** The provided SID is invalid */ - IDMAP_SID_INVALID, - - /** The provided SID was not found */ - IDMAP_SID_UNKNOWN, - - /** The provided UID or GID could not be mapped */ - IDMAP_NO_RANGE, - - /** The provided SID is a built-in one */ - IDMAP_BUILTIN_SID, - - /** No more free slices */ - IDMAP_OUT_OF_SLICES, - - /** New domain collides with existing one */ - IDMAP_COLLISION, - - /** External source should be consulted for idmapping */ - IDMAP_EXTERNAL, - - /** The provided name was not found */ - IDMAP_NAME_UNKNOWN, - - /** It is not possible to convert an id into the original value the id was - * derived from */ - IDMAP_NO_REVERSE, - - /** Error during UTF8 operation like normalization or casefolding */ - IDMAP_UTF8_ERROR, - - /** Sentinel to indicate the end of the error code list, not returned by - * any call */ - IDMAP_ERR_LAST -}; - -/** - * Typedef for memory allocation functions - */ -typedef void *(idmap_alloc_func)(size_t size, void *pvt); -typedef void (idmap_free_func)(void *ptr, void *pvt); - -/** - * Typedef for storing mappings of dynamically created domains - */ -typedef enum idmap_error_code (*idmap_store_cb)(const char *dom_name, - const char *dom_sid, - const char *range_id, - uint32_t min_id, - uint32_t max_id, - uint32_t first_rid, - void *pvt); - -/** - * Structure for id ranges - * FIXME: this struct might change when it is clear how ranges are handled on - * the server side - */ -struct sss_idmap_range { - uint32_t min; - uint32_t max; -}; - -/** - * Opaque type for SIDs - */ -struct sss_dom_sid; - -/** - * Opaque type for the idmap context - */ -struct sss_idmap_ctx; - -/** - * Placeholder for Samba's struct dom_sid. Consumers of libsss_idmap should - * include an appropriate Samba header file to define struct dom_sid. We use - * it here to avoid a hard dependency on Samba devel packages. - */ -struct dom_sid; - -/** - * @brief Initialize idmap context - * - * @param[in] alloc_func Function to allocate memory for the context, if - * NULL malloc() id used - * @param[in] alloc_pvt Private data for allocation routine - * @param[in] free_func Function to free the memory the context, if - * NULL free() id used - * @param[out] ctx idmap context - * - * @return - * - #IDMAP_OUT_OF_MEMORY: Insufficient memory to create the context - */ -enum idmap_error_code sss_idmap_init(idmap_alloc_func *alloc_func, - void *alloc_pvt, - idmap_free_func *free_func, - struct sss_idmap_ctx **ctx); - -/** - * @brief Set/unset autorid compatibility mode - * - * @param[in] ctx idmap context - * @param[in] use_autorid If true, autorid compatibility mode will be used - */ -enum idmap_error_code -sss_idmap_ctx_set_autorid(struct sss_idmap_ctx *ctx, bool use_autorid); - -/** - * @brief Set the lower bound of the range of POSIX IDs - * - * @param[in] ctx idmap context - * @param[in] lower lower bound of the range - */ -enum idmap_error_code -sss_idmap_ctx_set_lower(struct sss_idmap_ctx *ctx, id_t lower); - -/** - * @brief Set the upper bound of the range of POSIX IDs - * - * @param[in] ctx idmap context - * @param[in] upper upper bound of the range - */ -enum idmap_error_code -sss_idmap_ctx_set_upper(struct sss_idmap_ctx *ctx, id_t upper); - -/** - * @brief Set the range size of POSIX IDs available for single domain - * - * @param[in] ctx idmap context - * @param[in] rangesize range size of IDs - */ -enum idmap_error_code -sss_idmap_ctx_set_rangesize(struct sss_idmap_ctx *ctx, id_t rangesize); - -/** - * @brief Set the number of secondary slices available for domain - * - * @param[in] ctx idmap context - * @param[in] extra_slice_init number of secondary slices to be generated - * at startup - */ -enum idmap_error_code -sss_idmap_ctx_set_extra_slice_init(struct sss_idmap_ctx *ctx, - int extra_slice_init); - -/** - * @brief Check if autorid compatibility mode is set - * - * @param[in] ctx idmap context - * @param[out] _autorid true if autorid is used - */ -enum idmap_error_code -sss_idmap_ctx_get_autorid(struct sss_idmap_ctx *ctx, bool *_autorid); - -/** - * @brief Get the lower bound of the range of POSIX IDs - * - * @param[in] ctx idmap context - * @param[out] _lower returned lower bound - */ -enum idmap_error_code -sss_idmap_ctx_get_lower(struct sss_idmap_ctx *ctx, id_t *_lower); - -/** - * @brief Get the upper bound of the range of POSIX IDs - * - * @param[in] ctx idmap context - * @param[out] _upper returned upper bound - */ -enum idmap_error_code -sss_idmap_ctx_get_upper(struct sss_idmap_ctx *ctx, id_t *_upper); - -/** - * @brief Get the range size of POSIX IDs available for single domain - * - * @param[in] ctx idmap context - * @param[out] rangesize returned range size - */ -enum idmap_error_code -sss_idmap_ctx_get_rangesize(struct sss_idmap_ctx *ctx, id_t *rangesize); - -/** - * @brief Calculate new range of available POSIX IDs - * - * @param[in] ctx Idmap context - * @param[in] dom_sid Zero-terminated string representation of the domain - * SID (S-1-15-.....) - * @param[in,out] slice_num Slice number to be used. Set this pointer to NULL or - * the addressed value to -1 to calculate slice number - * automatically. The calculated value will be - * returned in this parameter. - * @param[out] range Structure containing upper and lower bound of the - * range of POSIX IDs - * - * @return - * - #IDMAP_OUT_OF_SLICES: Cannot calculate new range because all slices are - * used. - */ -enum idmap_error_code sss_idmap_calculate_range(struct sss_idmap_ctx *ctx, - const char *dom_sid, - id_t *slice_num, - struct sss_idmap_range *range); - -/** - * @brief Add a domain to the idmap context - * - * @param[in] ctx Idmap context - * @param[in] domain_name Zero-terminated string with the domain name - * @param[in] domain_sid Zero-terminated string representation of the domain - * SID (S-1-15-.....) - * @param[in] range TBD Some information about the id ranges of this - * domain - * - * @return - * - #IDMAP_OUT_OF_MEMORY: Insufficient memory to store the data in the idmap - * context - * - #IDMAP_SID_INVALID: Invalid SID provided - * - #IDMAP_NO_DOMAIN: No domain domain name given - * - #IDMAP_COLLISION: New domain collides with existing one - */ -enum idmap_error_code sss_idmap_add_domain(struct sss_idmap_ctx *ctx, - const char *domain_name, - const char *domain_sid, - struct sss_idmap_range *range); - -/** - * @brief Add a domain with the first mappable RID to the idmap context - * - * @param[in] ctx Idmap context - * @param[in] domain_name Zero-terminated string with the domain name - * @param[in] domain_sid Zero-terminated string representation of the domain - * SID (S-1-15-.....) - * @param[in] range TBD Some information about the id ranges of this - * domain - * @param[in] range_id optional unique identifier of a range, it is needed - * to allow updates at runtime - * @param[in] rid The RID that should be mapped to the first ID of the - * given range. - * @param[in] external_mapping If set to true the ID will not be mapped - * algorithmically, but the *_to_unix and *_unix_to_* - * calls will return IDMAP_EXTERNAL to instruct the - * caller to check external sources. For a single - * domain all ranges must be of the same type. It is - * not possible to mix algorithmic and external - * mapping. - * - * @return - * - #IDMAP_OUT_OF_MEMORY: Insufficient memory to store the data in the idmap - * context - * - #IDMAP_SID_INVALID: Invalid SID provided - * - #IDMAP_NO_DOMAIN: No domain domain name given - * - #IDMAP_COLLISION: New domain collides with existing one - */ -enum idmap_error_code sss_idmap_add_domain_ex(struct sss_idmap_ctx *ctx, - const char *domain_name, - const char *domain_sid, - struct sss_idmap_range *range, - const char *range_id, - uint32_t rid, - bool external_mapping); - -/** - * @brief Add a domain with the first mappable RID to the idmap context and - * generate automatically secondary slices - * - * @param[in] ctx Idmap context - * @param[in] domain_name Zero-terminated string with the domain name - * @param[in] domain_sid Zero-terminated string representation of the domain - * SID (S-1-15-.....) - * @param[in] range TBD Some information about the id ranges of this - * domain - * @param[in] range_id optional unique identifier of a range, it is needed - * to allow updates at runtime - * @param[in] rid The RID that should be mapped to the first ID of the - * given range. - * @param[in] external_mapping If set to true the ID will not be mapped - * algorithmically, but the *_to_unix and *_unix_to_* - * calls will return IDMAP_EXTERNAL to instruct the - * caller to check external sources. For a single - * domain all ranges must be of the same type. It is - * not possible to mix algorithmic and external - * mapping. - * @param[in] cb The callback for storing mapping of dynamically - * created domains. - * @param[in] pvt Private data for callback cb. - * - * @return - * - #IDMAP_OUT_OF_MEMORY: Insufficient memory to store the data in the idmap - * context - * - #IDMAP_SID_INVALID: Invalid SID provided - * - #IDMAP_NO_DOMAIN: No domain domain name given - * - #IDMAP_COLLISION: New domain collides with existing one - */ -enum idmap_error_code -sss_idmap_add_auto_domain_ex(struct sss_idmap_ctx *ctx, - const char *domain_name, - const char *domain_sid, - struct sss_idmap_range *range, - const char *range_id, - uint32_t rid, - bool external_mapping, - idmap_store_cb cb, - void *pvt); - -/** - * @brief Check if a new range would collide with any existing one - * - * @param[in] ctx Idmap context - * @param[in] n_name Zero-terminated string with the domain name the new - * range should belong to - * @param[in] n_sid Zero-terminated string representation of the domain - * SID (S-1-15-.....) the new range should belong to - * @param[in] n_range The new id range - * @param[in] n_range_id unique identifier of the new range, it is needed - * to allow updates at runtime, may be NULL - * @param[in] n_first_rid The RID that should be mapped to the first ID of the - * new range. - * @param[in] n_external_mapping Mapping type of the new range - * - * @return - * - #IDMAP_COLLISION: New range collides with existing one - */ -enum idmap_error_code sss_idmap_check_collision(struct sss_idmap_ctx *ctx, - char *n_name, char *n_sid, - struct sss_idmap_range *n_range, - uint32_t n_first_rid, - char *n_range_id, - bool n_external_mapping); - -/** - * @brief Check if two ranges would collide - * - * @param[in] o_name Zero-terminated string with the domain name the - * first range should belong to - * @param[in] o_sid Zero-terminated string representation of the domain - * SID (S-1-15-.....) the first range should belong to - * @param[in] o_range The first id range - * @param[in] o_range_id unique identifier of the first range, it is needed - * to allow updates at runtime, may be NULL - * @param[in] o_first_rid The RID that should be mapped to the first ID of the - * first range. - * @param[in] o_external_mapping Mapping type of the first range - * @param[in] n_name Zero-terminated string with the domain name the - * second range should belong to - * @param[in] n_sid Zero-terminated string representation of the domain - * SID (S-1-15-.....) the second range should belong to - * @param[in] n_range The second id range - * @param[in] n_range_id unique identifier of the second range, it is needed - * to allow updates at runtime, may be NULL - * @param[in] n_first_rid The RID that should be mapped to the first ID of the - * second range. - * @param[in] n_external_mapping Mapping type of the second range - * - * @return - * - #IDMAP_COLLISION: New range collides with existing one - */ -enum idmap_error_code sss_idmap_check_collision_ex(const char *o_name, - const char *o_sid, - struct sss_idmap_range *o_range, - uint32_t o_first_rid, - const char *o_range_id, - bool o_external_mapping, - const char *n_name, - const char *n_sid, - struct sss_idmap_range *n_range, - uint32_t n_first_rid, - const char *n_range_id, - bool n_external_mapping); - -/** - * @brief Translate SID to a unix UID or GID - * - * @param[in] ctx Idmap context - * @param[in] sid Zero-terminated string representation of the SID - * @param[out] id Returned unix UID or GID - * - * @return - * - #IDMAP_NO_DOMAIN: No domains are added to the idmap context - * - #IDMAP_SID_INVALID: Invalid SID provided - * - #IDMAP_SID_UNKNOWN: SID cannot be found in the domains added to the - * idmap context - * - #IDMAP_EXTERNAL: external source is authoritative for mapping - */ -enum idmap_error_code sss_idmap_sid_to_unix(struct sss_idmap_ctx *ctx, - const char *sid, - uint32_t *id); - -/** - * @brief Translate a SID structure to a unix UID or GID - * - * @param[in] ctx Idmap context - * @param[in] dom_sid SID structure - * @param[out] id Returned unix UID or GID - * - * @return - * - #IDMAP_NO_DOMAIN: No domains are added to the idmap context - * - #IDMAP_SID_INVALID: Invalid SID provided - * - #IDMAP_SID_UNKNOWN: SID cannot be found in the domains added to the - * idmap context - * - #IDMAP_EXTERNAL: external source is authoritative for mapping - */ -enum idmap_error_code sss_idmap_dom_sid_to_unix(struct sss_idmap_ctx *ctx, - struct sss_dom_sid *dom_sid, - uint32_t *id); - -/** - * @brief Translate a binary SID to a unix UID or GID - * - * @param[in] ctx Idmap context - * @param[in] bin_sid Array with the binary SID - * @param[in] length Size of the array containing the binary SID - * @param[out] id Returned unix UID or GID - * - * @return - * - #IDMAP_NO_DOMAIN: No domains are added to the idmap context - * - #IDMAP_SID_INVALID: Invalid SID provided - * - #IDMAP_SID_UNKNOWN: SID cannot be found in the domains added to the - * idmap context - * - #IDMAP_EXTERNAL: external source is authoritative for mapping - */ -enum idmap_error_code sss_idmap_bin_sid_to_unix(struct sss_idmap_ctx *ctx, - uint8_t *bin_sid, - size_t length, - uint32_t *id); - -/** - * @brief Translate a Samba dom_sid structure to a unix UID or GID - * - * @param[in] ctx Idmap context - * @param[in] smb_sid Samba dom_sid structure - * @param[out] id Returned unix UID or GID - * - * @return - * - #IDMAP_NO_DOMAIN: No domains are added to the idmap context - * - #IDMAP_SID_INVALID: Invalid SID provided - * - #IDMAP_SID_UNKNOWN: SID cannot be found in the domains added to the - * idmap context - * - #IDMAP_EXTERNAL: external source is authoritative for mapping - */ -enum idmap_error_code sss_idmap_smb_sid_to_unix(struct sss_idmap_ctx *ctx, - struct dom_sid *smb_sid, - uint32_t *id); - -/** - * @brief Check if a SID and a unix UID or GID belong to the same range - * - * @param[in] ctx Idmap context - * @param[in] sid Zero-terminated string representation of the SID - * @param[in] id Unix UID or GID - * - * @return - * - #IDMAP_NO_DOMAIN: No domains are added to the idmap context - * - #IDMAP_SID_INVALID: Invalid SID provided - * - #IDMAP_SID_UNKNOWN: SID cannot be found in the domains added to the - * idmap context - * - #IDMAP_NO_RANGE No matching ID range found - */ -enum idmap_error_code sss_idmap_check_sid_unix(struct sss_idmap_ctx *ctx, - const char *sid, - uint32_t id); - -/** - * @brief Check if a SID structure and a unix UID or GID belong to the same range - * - * @param[in] ctx Idmap context - * @param[in] dom_sid SID structure - * @param[in] id Unix UID or GID - * - * @return - * - #IDMAP_NO_DOMAIN: No domains are added to the idmap context - * - #IDMAP_SID_INVALID: Invalid SID provided - * - #IDMAP_SID_UNKNOWN: SID cannot be found in the domains added to the - * idmap context - * - #IDMAP_NO_RANGE No matching ID range found - */ -enum idmap_error_code sss_idmap_check_dom_sid_unix(struct sss_idmap_ctx *ctx, - struct sss_dom_sid *dom_sid, - uint32_t id); - -/** - * @brief Check if a binary SID and a unix UID or GID belong to the same range - * - * @param[in] ctx Idmap context - * @param[in] bin_sid Array with the binary SID - * @param[in] length Size of the array containing the binary SID - * @param[in] id Unix UID or GID - * - * @return - * - #IDMAP_NO_DOMAIN: No domains are added to the idmap context - * - #IDMAP_SID_INVALID: Invalid SID provided - * - #IDMAP_SID_UNKNOWN: SID cannot be found in the domains added to the - * idmap context - * - #IDMAP_NO_RANGE No matching ID range found - */ -enum idmap_error_code sss_idmap_check_bin_sid_unix(struct sss_idmap_ctx *ctx, - uint8_t *bin_sid, - size_t length, - uint32_t id); - -/** - * @brief Check if a Samba dom_sid structure and a unix UID or GID belong to - * the same range - * - * @param[in] ctx Idmap context - * @param[in] smb_sid Samba dom_sid structure - * @param[in] id Unix UID or GID - * - * @return - * - #IDMAP_NO_DOMAIN: No domains are added to the idmap context - * - #IDMAP_SID_INVALID: Invalid SID provided - * - #IDMAP_SID_UNKNOWN: SID cannot be found in the domains added to the - * idmap context - * - #IDMAP_NO_RANGE No matching ID range found - */ -enum idmap_error_code sss_idmap_check_smb_sid_unix(struct sss_idmap_ctx *ctx, - struct dom_sid *smb_sid, - uint32_t id); - -/** - * @brief Translate unix UID or GID to a SID - * - * @param[in] ctx Idmap context - * @param[in] id unix UID or GID - * @param[out] sid Zero-terminated string representation of the SID, must be - * freed if not needed anymore - * - * @return - * - #IDMAP_NO_DOMAIN: No domains are added to the idmap context - * - #IDMAP_NO_RANGE: The provided ID cannot be found in the domains added - * to the idmap context - * - #IDMAP_EXTERNAL: external source is authoritative for mapping - */ -enum idmap_error_code sss_idmap_unix_to_sid(struct sss_idmap_ctx *ctx, - uint32_t id, - char **sid); - -/** - * @brief Translate unix UID or GID to a SID structure - * - * @param[in] ctx Idmap context - * @param[in] id unix UID or GID - * @param[out] dom_sid SID structure, must be freed if not needed anymore - * - * @return - * - #IDMAP_NO_DOMAIN: No domains are added to the idmap context - * - #IDMAP_NO_RANGE: The provided ID cannot be found in the domains added - * to the idmap context - * - #IDMAP_EXTERNAL: external source is authoritative for mapping - */ -enum idmap_error_code sss_idmap_unix_to_dom_sid(struct sss_idmap_ctx *ctx, - uint32_t id, - struct sss_dom_sid **dom_sid); - -/** - * @brief Translate unix UID or GID to a binary SID - * - * @param[in] ctx Idmap context - * @param[in] id unix UID or GID - * @param[out] bin_sid Array with the binary SID, - * must be freed if not needed anymore - * @param[out] length size of the array containing the binary SID - * - * @return - * - #IDMAP_NO_DOMAIN: No domains are added to the idmap context - * - #IDMAP_NO_RANGE: The provided ID cannot be found in the domains added - * to the idmap context - * - #IDMAP_EXTERNAL: external source is authoritative for mapping - */ -enum idmap_error_code sss_idmap_unix_to_bin_sid(struct sss_idmap_ctx *ctx, - uint32_t id, - uint8_t **bin_sid, - size_t *length); - -/** - * @brief Free all the allocated memory of the idmap context - * - * @param[in] ctx Idmap context - * - * @return - * - #IDMAP_CONTEXT_INVALID: Provided context is invalid - */ -enum idmap_error_code sss_idmap_free(struct sss_idmap_ctx *ctx); - -/** - * @brief Free mapped SID. - * - * @param[in] ctx Idmap context - * @param[in] sid SID to be freed. - * - * @return - * - #IDMAP_CONTEXT_INVALID: Provided context is invalid - */ -enum idmap_error_code sss_idmap_free_sid(struct sss_idmap_ctx *ctx, - char *sid); - -/** - * @brief Free mapped domain SID. - * - * @param[in] ctx Idmap context - * @param[in] dom_sid Domain SID to be freed. - * - * @return - * - #IDMAP_CONTEXT_INVALID: Provided context is invalid - */ -enum idmap_error_code sss_idmap_free_dom_sid(struct sss_idmap_ctx *ctx, - struct sss_dom_sid *dom_sid); - -/** - * @brief Free mapped Samba SID. - * - * @param[in] ctx Idmap context - * @param[in] smb_sid Samba SID to be freed. - * - * @return - * - #IDMAP_CONTEXT_INVALID: Provided context is invalid - */ -enum idmap_error_code sss_idmap_free_smb_sid(struct sss_idmap_ctx *ctx, - struct dom_sid *smb_sid); - -/** - * @brief Free mapped binary SID. - * - * @param[in] ctx Idmap context - * @param[in] bin_sid Binary SID to be freed. - * - * @return - * - #IDMAP_CONTEXT_INVALID: Provided context is invalid - */ -enum idmap_error_code sss_idmap_free_bin_sid(struct sss_idmap_ctx *ctx, - uint8_t *bin_sid); - -/** - * @brief Translate error code to a string - * - * @param[in] err Idmap error code - * - * @return - * - Error description as a zero-terminated string - */ -const char *idmap_error_string(enum idmap_error_code err); - -/** - * @brief Check if given string can be used as domain SID - * - * @param[in] str String to check - * - * @return - * - true: String can be used as domain SID - * - false: String can not be used as domain SID - */ -bool is_domain_sid(const char *str); - -/** - * @brief Check if a domain is configured with algorithmic mapping - * - * @param[in] ctx Idmap context - * @param[in] dom_sid SID string, can be either a domain SID - * or an object SID - * @param[out] has_algorithmic_mapping Boolean value indicating if the given - * domain is configured for algorithmic - * mapping or not. - * - * @return - * - #IDMAP_SUCCESS: Domain for the given SID was found and - * has_algorithmic_mapping is set accordingly - * - #IDMAP_SID_INVALID: Provided SID is invalid - * - #IDMAP_CONTEXT_INVALID: Provided idmap context is invalid - * - #IDMAP_NO_DOMAIN: No domains are available in the idmap context - * - #IDMAP_SID_UNKNOWN: No domain with the given SID was found in the - * idmap context - */ -enum idmap_error_code -sss_idmap_domain_has_algorithmic_mapping(struct sss_idmap_ctx *ctx, - const char *dom_sid, - bool *has_algorithmic_mapping); - -/** - * @brief Check if a domain is configured with algorithmic mapping - * - * @param[in] ctx Idmap context - * @param[in] dom_name Name of the domain - * @param[out] has_algorithmic_mapping Boolean value indicating if the given - * domain is configured for algorithmic - * mapping or not. - * - * @return - * - #IDMAP_SUCCESS: Domain for the given name was found and - * has_algorithmic_mapping is set accordingly - * - #IDMAP_ERROR: Provided name is invalid - * - #IDMAP_CONTEXT_INVALID: Provided idmap context is invalid - * - #IDMAP_NO_DOMAIN: No domains are available in the idmap context - * - #IDMAP_NAME_UNKNOWN: No domain with the given name was found in the - * idmap context - */ -enum idmap_error_code -sss_idmap_domain_by_name_has_algorithmic_mapping(struct sss_idmap_ctx *ctx, - const char *dom_name, - bool *has_algorithmic_mapping); - -/** - * @brief Convert binary SID to SID structure - * - * @param[in] ctx Idmap context - * @param[in] bin_sid Array with the binary SID - * @param[in] length Size of the array containing the binary SID - * @param[out] dom_sid SID structure, - * must be freed if not needed anymore - * - * @return - * - #IDMAP_SID_INVALID: Given SID is invalid - * - #IDMAP_OUT_OF_MEMORY: Failed to allocate memory for the result - */ -enum idmap_error_code sss_idmap_bin_sid_to_dom_sid(struct sss_idmap_ctx *ctx, - const uint8_t *bin_sid, - size_t length, - struct sss_dom_sid **dom_sid); - -/** - * @brief Convert binary SID to SID string - * - * @param[in] ctx Idmap context - * @param[in] bin_sid Array with the binary SID - * @param[in] length Size of the array containing the binary SID - * @param[out] sid Zero-terminated string representation of the SID, - * must be freed if not needed anymore - * - * @return - * - #IDMAP_SID_INVALID: Given SID is invalid - * - #IDMAP_OUT_OF_MEMORY: Failed to allocate memory for the result - */ -enum idmap_error_code sss_idmap_bin_sid_to_sid(struct sss_idmap_ctx *ctx, - const uint8_t *bin_sid, - size_t length, - char **sid); - -/** - * @brief Convert SID structure to binary SID - * - * @param[in] ctx Idmap context - * @param[in] dom_sid SID structure - * @param[out] bin_sid Array with the binary SID, - * must be freed if not needed anymore - * @param[out] length Size of the array containing the binary SID - * - * @return - * - #IDMAP_SID_INVALID: Given SID is invalid - * - #IDMAP_OUT_OF_MEMORY: Failed to allocate memory for the result - */ -enum idmap_error_code sss_idmap_dom_sid_to_bin_sid(struct sss_idmap_ctx *ctx, - struct sss_dom_sid *dom_sid, - uint8_t **bin_sid, - size_t *length); - -/** - * @brief Convert SID string to binary SID - * - * @param[in] ctx Idmap context - * @param[in] sid Zero-terminated string representation of the SID - * @param[out] bin_sid Array with the binary SID, - * must be freed if not needed anymore - * @param[out] length Size of the array containing the binary SID - * - * @return - * - #IDMAP_SID_INVALID: Given SID is invalid - * - #IDMAP_OUT_OF_MEMORY: Failed to allocate memory for the result - */ -enum idmap_error_code sss_idmap_sid_to_bin_sid(struct sss_idmap_ctx *ctx, - const char *sid, - uint8_t **bin_sid, - size_t *length); - -/** - * @brief Convert SID structure to SID string - * - * @param[in] ctx Idmap context - * @param[in] dom_sid SID structure - * @param[out] sid Zero-terminated string representation of the SID, - * must be freed if not needed anymore - * - * @return - * - #IDMAP_SID_INVALID: Given SID is invalid - * - #IDMAP_OUT_OF_MEMORY: Failed to allocate memory for the result - */ -enum idmap_error_code sss_idmap_dom_sid_to_sid(struct sss_idmap_ctx *ctx, - struct sss_dom_sid *dom_sid, - char **sid); - -/** - * @brief Convert SID string to SID structure - * - * @param[in] ctx Idmap context - * @param[in] sid Zero-terminated string representation of the SID - * @param[out] dom_sid SID structure, - * must be freed if not needed anymore - * - * @return - * - #IDMAP_SID_INVALID: Given SID is invalid - * - #IDMAP_OUT_OF_MEMORY: Failed to allocate memory for the result - */ -enum idmap_error_code sss_idmap_sid_to_dom_sid(struct sss_idmap_ctx *ctx, - const char *sid, - struct sss_dom_sid **dom_sid); - -/** - * @brief Convert SID string to Samba dom_sid structure - * - * @param[in] ctx Idmap context - * @param[in] sid Zero-terminated string representation of the SID - * @param[out] smb_sid Samba dom_sid structure, - * must be freed if not needed anymore - * - * @return - * - #IDMAP_SID_INVALID: Given SID is invalid - * - #IDMAP_OUT_OF_MEMORY: Failed to allocate memory for the result - */ -enum idmap_error_code sss_idmap_sid_to_smb_sid(struct sss_idmap_ctx *ctx, - const char *sid, - struct dom_sid **smb_sid); - -/** - * @brief Convert Samba dom_sid structure to SID string - * - * @param[in] ctx Idmap context - * @param[in] smb_sid Samba dom_sid structure - * @param[out] sid Zero-terminated string representation of the SID, - * must be freed if not needed anymore - * - * @return - * - #IDMAP_SID_INVALID: Given SID is invalid - * - #IDMAP_OUT_OF_MEMORY: Failed to allocate memory for the result - */ -enum idmap_error_code sss_idmap_smb_sid_to_sid(struct sss_idmap_ctx *ctx, - struct dom_sid *smb_sid, - char **sid); - -/** - * @brief Convert SID structure to Samba dom_sid structure - * - * @param[in] ctx Idmap context - * @param[in] dom_sid SID structure - * @param[out] smb_sid Samba dom_sid structure, - * must be freed if not needed anymore - * - * @return - * - #IDMAP_SID_INVALID: Given SID is invalid - * - #IDMAP_OUT_OF_MEMORY: Failed to allocate memory for the result - */ -enum idmap_error_code sss_idmap_dom_sid_to_smb_sid(struct sss_idmap_ctx *ctx, - struct sss_dom_sid *dom_sid, - struct dom_sid **smb_sid); - -/** - * @brief Convert Samba dom_sid structure to SID structure - * - * @param[in] ctx Idmap context - * @param[in] smb_sid Samba dom_sid structure - * @param[out] dom_sid SID structure, - * must be freed if not needed anymore - * - * @return - * - #IDMAP_SID_INVALID: Given SID is invalid - * - #IDMAP_OUT_OF_MEMORY: Failed to allocate memory for the result - */ -enum idmap_error_code sss_idmap_smb_sid_to_dom_sid(struct sss_idmap_ctx *ctx, - struct dom_sid *smb_sid, - struct sss_dom_sid **dom_sid); - -/** - * @brief Convert binary SID to Samba dom_sid structure - * - * @param[in] ctx Idmap context - * @param[in] bin_sid Array with the binary SID - * @param[in] length Size of the array containing the binary SID - * @param[out] smb_sid Samba dom_sid structure, - * must be freed if not needed anymore - * - * @return - * - #IDMAP_SID_INVALID: Given SID is invalid - * - #IDMAP_OUT_OF_MEMORY: Failed to allocate memory for the result - */ -enum idmap_error_code sss_idmap_bin_sid_to_smb_sid(struct sss_idmap_ctx *ctx, - const uint8_t *bin_sid, - size_t length, - struct dom_sid **smb_sid); - -/** - * @brief Convert Samba dom_sid structure to binary SID - * - * @param[in] ctx Idmap context - * @param[in] smb_sid Samba dom_sid structure - * @param[out] bin_sid Array with the binary SID, - * must be freed if not needed anymore - * @param[out] length Size of the array containing the binary SID - * - * @return - * - #IDMAP_SID_INVALID: Given SID is invalid - * - #IDMAP_OUT_OF_MEMORY: Failed to allocate memory for the result - */ -enum idmap_error_code sss_idmap_smb_sid_to_bin_sid(struct sss_idmap_ctx *ctx, - struct dom_sid *smb_sid, - uint8_t **bin_sid, - size_t *length); - -/** - * Typedef for functions to calculate an offset for id-mapping and, if - * possible, for the reverse operation. - */ -typedef enum idmap_error_code (idmap_offset_func)(void *pvt, - uint32_t range_size, - const char *input, - long long *offset); - -typedef enum idmap_error_code (idmap_rev_offset_func)(struct sss_idmap_ctx *ctx, - void *pvt, - uint32_t offset, - char **out); - -/** - * @brief Add a generic domain to the idmap context - * - * @param[in] ctx Idmap context - * @param[in] domain_name Zero-terminated string with the domain name - * @param[in] domain_id Zero-terminated string representation of a unique - * identifier of the domain, e.g. if available a domain - * UUID or the URI of domain specific service - * @param[in] range Id ranges struct with smallest and largest id of the - * range - * @param[in] range_id A name for the id range, currently not used, might - * become important when we allow multiple ranges for a - * single domain - * @param[in] offset_func Function to calculate an offset in a given range - * from some input given as string, if NULL - * offset_murmurhash3 will be used. - * @param[in] rev_offset_func Function to calculate the original input from a - * given offset, i.e. the reverse of offset_func, may - * be NULL - * @param[in] offset_func_pvt Private data for offset_func and - * rev_offset_func, may be NULL - * @param[in] shift Currently not used, might become important when we - * allow multiple ranges for a single domain - * @param[in] external_mapping Indicates that for this domain the mapping - * should not be done by libsss_idmap, the related - * calls will return IDMAP_EXTERNAL in this case. - * Nevertheless it might be important to add the domain - * to the idmap context so that libsss_idmap will not - * use the related ranges for mapping. - * - * @return - * - #IDMAP_OUT_OF_MEMORY: Insufficient memory to store the data in the idmap - * context - * - #IDMAP_SID_INVALID: Invalid SID provided - * - #IDMAP_NO_DOMAIN: No domain domain name given - * - #IDMAP_COLLISION: New domain collides with existing one - */ -enum idmap_error_code sss_idmap_add_gen_domain_ex(struct sss_idmap_ctx *ctx, - const char *domain_name, - const char *domain_id, - struct sss_idmap_range *range, - const char *range_id, - idmap_offset_func *offset_func, - idmap_rev_offset_func *rev_offset_func, - void *offset_func_pvt, - uint32_t shift, - bool external_mapping); - -/** - * @brief Calculate offset from string containing only numbers - */ -enum idmap_error_code offset_identity(void *pvt, uint32_t range_size, - const char *input, long long *offset); - -/** - * @brief Reverse of offset_identity, return a string containing only numbers - * representing the given offset - */ -enum idmap_error_code rev_offset_identity(struct sss_idmap_ctx *ctx, void *pvt, - uint32_t id, char **_out); - -/** - * @brief Calculate offset from string with the help of murmurhash3 - */ -enum idmap_error_code offset_murmurhash3(void *pvt, uint32_t range_size, - const char *input, long long *offset); - -/** - * Structure for private data for offset_murmurhash3. If not given 0xdeadbeef - * will be used as seed. UTF8 strings will be normalized by default but not - * casefolded. - */ -struct offset_murmurhash3_data { - uint32_t seed; - bool normalize; - bool casefold; -}; - -/** - * @brief Translate some input to a unix UID or GID - * - * @param[in] ctx Idmap context - * @param[in] domain_id Zero-terminated string with the domain ID of a known - * domain - * @param[in] input Zero-terminated string which should be translated into - * an offset to calculate the unix UID or GID - * @param[out] id Returned unix UID or GID - * - * @return - * - #IDMAP_NO_DOMAIN: No domain with domain_id found in ctx - * - #IDMAP_EXTERNAL: external source is authoritative for mapping - */ -enum idmap_error_code sss_idmap_gen_to_unix(struct sss_idmap_ctx *ctx, - const char *domain_id, - const char *input, - uint32_t *_id); - -/** - * @brief Translate some input to a unix UID or GID - * - * @param[in] ctx Idmap context - * @param[in] id UNIX UID or GID - * an offset to calculate the unix UID or GID - * @param[out] out Original value the UID or GID was derived from - * - * @return - * - #IDMAP_NO_DOMAIN: No domain with domain_id found in ctx - * - #IDMAP_EXTERNAL: external source is authoritative for mapping - * - #IDMAP_NO_REVERSE: the id cannot be reverted back to the original - * source - */ -enum idmap_error_code sss_idmap_unix_to_gen(struct sss_idmap_ctx *ctx, - uint32_t id, - char **out); - -/** - * @} - */ -#endif /* SSS_IDMAP_H_ */ diff --git a/rust/idmap/src/sss_idmap_conv.c b/rust/idmap/src/sss_idmap_conv.c deleted file mode 100644 index bd3148d4e90..00000000000 --- a/rust/idmap/src/sss_idmap_conv.c +++ /dev/null @@ -1,570 +0,0 @@ -/* - SSSD - - ID-mapping library - conversion utilities - - Authors: - Sumit Bose - - Copyright (C) 2012 Red Hat - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include -#include -#include -#include - -#include "sss_idmap.h" -#include "sss_idmap_private.h" -//#include "util/util.h" -//#include "util/sss_endian.h" -#include "util.h" - -#define SID_ID_AUTHS 6 -#define SID_SUB_AUTHS 15 -struct sss_dom_sid { - uint8_t sid_rev_num; - int8_t num_auths; /* [range(0,15)] */ - uint8_t id_auth[SID_ID_AUTHS]; /* highest order byte has index 0 */ - uint32_t sub_auths[SID_SUB_AUTHS]; /* host byte-order */ -}; - -enum idmap_error_code sss_idmap_bin_sid_to_dom_sid(struct sss_idmap_ctx *ctx, - const uint8_t *bin_sid, - size_t length, - struct sss_dom_sid **_dom_sid) -{ - enum idmap_error_code err; - struct sss_dom_sid *dom_sid; - size_t i = 0; - size_t p = 0; - uint32_t val; - - CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID); - - if (length > sizeof(struct sss_dom_sid)) return IDMAP_SID_INVALID; - - dom_sid = ctx->alloc_func(sizeof(struct sss_dom_sid), ctx->alloc_pvt); - if (dom_sid == NULL) { - return IDMAP_OUT_OF_MEMORY; - } - memset(dom_sid, 0, sizeof(struct sss_dom_sid)); - - /* Safely copy in the SID revision number */ - dom_sid->sid_rev_num = (uint8_t) *(bin_sid + p); - p++; - - /* Safely copy in the number of sub auth values */ - dom_sid->num_auths = (uint8_t) *(bin_sid + p); - p++; - - /* Make sure we aren't being told to read more bin_sid - * than can fit in the structure - */ - if (dom_sid->num_auths > SID_SUB_AUTHS) { - err = IDMAP_SID_INVALID; - goto done; - } - - /* Safely copy in the id_auth values */ - for (i = 0; i < SID_ID_AUTHS; i++) { - dom_sid->id_auth[i] = (uint8_t) *(bin_sid + p); - p++; - } - - /* Safely copy in the sub_auths values */ - for (i = 0; i < dom_sid->num_auths; i++) { - /* SID sub auth values in Active Directory are stored little-endian, - * we store them in host order */ - SAFEALIGN_COPY_UINT32(&val, bin_sid + p, &p); - dom_sid->sub_auths[i] = le32toh(val); - } - - *_dom_sid = dom_sid; - err = IDMAP_SUCCESS; - -done: - if (err != IDMAP_SUCCESS) { - ctx->free_func(dom_sid, ctx->alloc_pvt); - } - return err; -} - -enum idmap_error_code sss_idmap_dom_sid_to_bin_sid(struct sss_idmap_ctx *ctx, - struct sss_dom_sid *dom_sid, - uint8_t **_bin_sid, - size_t *_length) -{ - enum idmap_error_code err; - uint8_t *bin_sid; - size_t length; - size_t i = 0; - size_t p = 0; - uint32_t val; - - CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID); - - if (dom_sid->num_auths > SID_SUB_AUTHS) { - return IDMAP_SID_INVALID; - } - - length = 2 + SID_ID_AUTHS + dom_sid->num_auths * 4; - - bin_sid = ctx->alloc_func(length, ctx->alloc_pvt); - if (bin_sid == NULL) { - return IDMAP_OUT_OF_MEMORY; - } - - bin_sid[p] = dom_sid->sid_rev_num; - p++; - - bin_sid[p] = dom_sid->num_auths; - p++; - - for (i = 0; i < SID_ID_AUTHS; i++) { - bin_sid[p] = dom_sid->id_auth[i]; - p++; - } - - for (i = 0; i < dom_sid->num_auths; i++) { - if (p + sizeof(uint32_t) > length) { - err = IDMAP_SID_INVALID; - goto done; - } - val = htole32(dom_sid->sub_auths[i]); - SAFEALIGN_COPY_UINT32(bin_sid + p, &val, &p); - } - - *_bin_sid = bin_sid; - *_length = length; - - err = IDMAP_SUCCESS; -done: - if (err != IDMAP_SUCCESS) { - ctx->free_func(bin_sid, ctx->alloc_pvt); - } - return err; -} - -enum idmap_error_code sss_idmap_dom_sid_to_sid(struct sss_idmap_ctx *ctx, - struct sss_dom_sid *dom_sid, - char **_sid) -{ - enum idmap_error_code err; - char *sid_buf; - size_t sid_buf_len; - char *p; - int nc; - int8_t i; - uint32_t id_auth_val = 0; - - if (dom_sid->num_auths > SID_SUB_AUTHS) { - return IDMAP_SID_INVALID; - } - - sid_buf_len = 25 + dom_sid->num_auths * 11; - sid_buf = ctx->alloc_func(sid_buf_len, ctx->alloc_pvt); - if (sid_buf == NULL) { - return IDMAP_OUT_OF_MEMORY; - } - memset(sid_buf, 0, sid_buf_len); - - /* Only 32bits are used for the string representation */ - id_auth_val = (dom_sid->id_auth[2] << 24) + - (dom_sid->id_auth[3] << 16) + - (dom_sid->id_auth[4] << 8) + - (dom_sid->id_auth[5]); - - nc = snprintf(sid_buf, sid_buf_len, "S-%u-%lu", dom_sid->sid_rev_num, - (unsigned long) id_auth_val); - if (nc < 0 || nc >= sid_buf_len) { - err = IDMAP_SID_INVALID; - goto done; - } - - - /* Loop through the sub-auths, if any, prepending a hyphen - * for each one. - */ - p = sid_buf; - for (i = 0; i < dom_sid->num_auths ; i++) { - p += nc; - sid_buf_len -= nc; - - nc = snprintf(p, sid_buf_len, "-%lu", - (unsigned long) dom_sid->sub_auths[i]); - if (nc < 0 || nc >= sid_buf_len) { - err = IDMAP_SID_INVALID; - goto done; - } - } - - *_sid = sid_buf; - err = IDMAP_SUCCESS; - -done: - if (err != IDMAP_SUCCESS) { - ctx->free_func(sid_buf, ctx->alloc_pvt); - } - - return err; -} - -enum idmap_error_code sss_idmap_sid_to_dom_sid(struct sss_idmap_ctx *ctx, - const char *sid, - struct sss_dom_sid **_dom_sid) -{ - enum idmap_error_code err; - unsigned long ul; - char *r; - char *end; - struct sss_dom_sid *dom_sid; - - CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID); - - if (sid == NULL || (sid[0] != 'S' && sid[0] != 's') || sid[1] != '-') { - return IDMAP_SID_INVALID; - } - - dom_sid = ctx->alloc_func(sizeof(struct sss_dom_sid), ctx->alloc_pvt); - if (dom_sid == NULL) { - return IDMAP_OUT_OF_MEMORY; - } - memset(dom_sid, 0, sizeof(struct sss_dom_sid)); - - - if (!isdigit(sid[2])) { - err = IDMAP_SID_INVALID; - goto done; - } - errno = 0; - ul = strtoul(sid + 2, &r, 10); - if (errno != 0 || r == NULL || *r != '-' || ul > UINT8_MAX) { - err = IDMAP_SID_INVALID; - goto done; - } - dom_sid->sid_rev_num = (uint8_t) ul; - r++; - - if (!isdigit(*r)) { - err = IDMAP_SID_INVALID; - goto done; - } - errno = 0; - ul = strtoul(r, &r, 10); - if (errno != 0 || r == NULL || ul > UINT32_MAX) { - err = IDMAP_SID_INVALID; - goto done; - } - - /* id_auth in the string should always be <2^32 in decimal */ - /* store values in the same order as the binary representation */ - dom_sid->id_auth[0] = 0; - dom_sid->id_auth[1] = 0; - dom_sid->id_auth[2] = (ul & 0xff000000) >> 24; - dom_sid->id_auth[3] = (ul & 0x00ff0000) >> 16; - dom_sid->id_auth[4] = (ul & 0x0000ff00) >> 8; - dom_sid->id_auth[5] = (ul & 0x000000ff); - - if (*r == '\0') { - /* no sub auths given */ - err = IDMAP_SUCCESS; - goto done; - } - - if (*r != '-') { - err = IDMAP_SID_INVALID; - goto done; - } - - do { - if (dom_sid->num_auths >= SID_SUB_AUTHS) { - err = IDMAP_SID_INVALID; - goto done; - } - - r++; - if (!isdigit(*r)) { - err = IDMAP_SID_INVALID; - goto done; - } - - errno = 0; - ul = strtoul(r, &end, 10); - if (errno != 0 || ul > UINT32_MAX || end == NULL || - (*end != '\0' && *end != '-')) { - err = IDMAP_SID_INVALID; - goto done; - } - - dom_sid->sub_auths[dom_sid->num_auths++] = ul; - - r = end; - } while (*r != '\0'); - - err = IDMAP_SUCCESS; - -done: - if (err != IDMAP_SUCCESS) { - ctx->free_func(dom_sid, ctx->alloc_pvt); - } else { - *_dom_sid = dom_sid; - } - - return err; -} - -enum idmap_error_code sss_idmap_sid_to_bin_sid(struct sss_idmap_ctx *ctx, - const char *sid, - uint8_t **_bin_sid, - size_t *_length) -{ - enum idmap_error_code err; - struct sss_dom_sid *dom_sid = NULL; - size_t length; - uint8_t *bin_sid = NULL; - - err = sss_idmap_sid_to_dom_sid(ctx, sid, &dom_sid); - if (err != IDMAP_SUCCESS) { - goto done; - } - - err = sss_idmap_dom_sid_to_bin_sid(ctx, dom_sid, &bin_sid, &length); - if (err != IDMAP_SUCCESS) { - goto done; - } - - *_length = length; - *_bin_sid = bin_sid; - err = IDMAP_SUCCESS; - -done: - ctx->free_func(dom_sid, ctx->alloc_pvt); - if (err != IDMAP_SUCCESS) { - ctx->free_func(bin_sid, ctx->alloc_pvt); - } - - return err; -} - -enum idmap_error_code sss_idmap_bin_sid_to_sid(struct sss_idmap_ctx *ctx, - const uint8_t *bin_sid, - size_t length, - char **_sid) -{ - enum idmap_error_code err; - struct sss_dom_sid *dom_sid = NULL; - char *sid = NULL; - - err = sss_idmap_bin_sid_to_dom_sid(ctx, bin_sid, length, &dom_sid); - if (err != IDMAP_SUCCESS) { - goto done; - } - - err = sss_idmap_dom_sid_to_sid(ctx, dom_sid, &sid); - if (err != IDMAP_SUCCESS) { - goto done; - } - - *_sid = sid; - err = IDMAP_SUCCESS; - -done: - ctx->free_func(dom_sid, ctx->alloc_pvt); - if (err != IDMAP_SUCCESS) { - ctx->free_func(sid, ctx->alloc_pvt); - } - - return err; -} - -enum idmap_error_code sss_idmap_sid_to_smb_sid(struct sss_idmap_ctx *ctx, - const char *sid, - struct dom_sid **_smb_sid) -{ - enum idmap_error_code err; - struct sss_dom_sid *dom_sid = NULL; - struct dom_sid *smb_sid = NULL; - - err = sss_idmap_sid_to_dom_sid(ctx, sid, &dom_sid); - if (err != IDMAP_SUCCESS) { - goto done; - } - - err = sss_idmap_dom_sid_to_smb_sid(ctx, dom_sid, &smb_sid); - if (err != IDMAP_SUCCESS) { - goto done; - } - - *_smb_sid = smb_sid; - err = IDMAP_SUCCESS; - -done: - ctx->free_func(dom_sid, ctx->alloc_pvt); - if (err != IDMAP_SUCCESS) { - ctx->free_func(smb_sid, ctx->alloc_pvt); - } - - return err; -} - -enum idmap_error_code sss_idmap_smb_sid_to_sid(struct sss_idmap_ctx *ctx, - struct dom_sid *smb_sid, - char **_sid) -{ - enum idmap_error_code err; - struct sss_dom_sid *dom_sid = NULL; - char *sid = NULL; - - err = sss_idmap_smb_sid_to_dom_sid(ctx, smb_sid, &dom_sid); - if (err != IDMAP_SUCCESS) { - goto done; - } - - err = sss_idmap_dom_sid_to_sid(ctx, dom_sid, &sid); - if (err != IDMAP_SUCCESS) { - goto done; - } - - *_sid = sid; - err = IDMAP_SUCCESS; - -done: - ctx->free_func(dom_sid, ctx->alloc_pvt); - if (err != IDMAP_SUCCESS) { - ctx->free_func(sid, ctx->alloc_pvt); - } - - return err; -} - -enum idmap_error_code sss_idmap_dom_sid_to_smb_sid(struct sss_idmap_ctx *ctx, - struct sss_dom_sid *dom_sid, - struct dom_sid **_smb_sid) -{ - struct dom_sid *smb_sid; - size_t c; - - smb_sid = ctx->alloc_func(sizeof(struct dom_sid), ctx->alloc_pvt); - if (smb_sid == NULL) { - return IDMAP_OUT_OF_MEMORY; - } - memset(smb_sid, 0, sizeof(struct dom_sid)); - - smb_sid->sid_rev_num = dom_sid->sid_rev_num; - smb_sid->num_auths = dom_sid->num_auths; - for (c = 0; c < SID_ID_AUTHS; c++) { - smb_sid->id_auth[c] = dom_sid->id_auth[c]; - } - for (c = 0; c < SID_SUB_AUTHS; c++) { - smb_sid->sub_auths[c] = dom_sid->sub_auths[c]; - } - - *_smb_sid = smb_sid; - - return IDMAP_SUCCESS; -} - -enum idmap_error_code sss_idmap_smb_sid_to_dom_sid(struct sss_idmap_ctx *ctx, - struct dom_sid *smb_sid, - struct sss_dom_sid **_dom_sid) -{ - struct sss_dom_sid *dom_sid; - size_t c; - - dom_sid = ctx->alloc_func(sizeof(struct sss_dom_sid), ctx->alloc_pvt); - if (dom_sid == NULL) { - return IDMAP_OUT_OF_MEMORY; - } - memset(dom_sid, 0, sizeof(struct sss_dom_sid)); - - dom_sid->sid_rev_num = smb_sid->sid_rev_num; - dom_sid->num_auths = smb_sid->num_auths; - for (c = 0; c < SID_ID_AUTHS; c++) { - dom_sid->id_auth[c] = smb_sid->id_auth[c]; - } - for (c = 0; c < SID_SUB_AUTHS; c++) { - dom_sid->sub_auths[c] = smb_sid->sub_auths[c]; - } - - *_dom_sid = dom_sid; - - return IDMAP_SUCCESS; -} - -enum idmap_error_code sss_idmap_bin_sid_to_smb_sid(struct sss_idmap_ctx *ctx, - const uint8_t *bin_sid, - size_t length, - struct dom_sid **_smb_sid) -{ - enum idmap_error_code err; - struct sss_dom_sid *dom_sid = NULL; - struct dom_sid *smb_sid = NULL; - - err = sss_idmap_bin_sid_to_dom_sid(ctx, bin_sid, length, &dom_sid); - if (err != IDMAP_SUCCESS) { - goto done; - } - - err = sss_idmap_dom_sid_to_smb_sid(ctx, dom_sid, &smb_sid); - if (err != IDMAP_SUCCESS) { - goto done; - } - - *_smb_sid = smb_sid; - err = IDMAP_SUCCESS; - -done: - ctx->free_func(dom_sid, ctx->alloc_pvt); - if (err != IDMAP_SUCCESS) { - ctx->free_func(smb_sid, ctx->alloc_pvt); - } - - return err; -} - -enum idmap_error_code sss_idmap_smb_sid_to_bin_sid(struct sss_idmap_ctx *ctx, - struct dom_sid *smb_sid, - uint8_t **_bin_sid, - size_t *_length) -{ - enum idmap_error_code err; - struct sss_dom_sid *dom_sid = NULL; - uint8_t *bin_sid = NULL; - size_t length; - - err = sss_idmap_smb_sid_to_dom_sid(ctx, smb_sid, &dom_sid); - if (err != IDMAP_SUCCESS) { - goto done; - } - - err = sss_idmap_dom_sid_to_bin_sid(ctx, dom_sid, &bin_sid, &length); - if (err != IDMAP_SUCCESS) { - goto done; - } - - *_bin_sid = bin_sid; - *_length = length; - err = IDMAP_SUCCESS; - -done: - ctx->free_func(dom_sid, ctx->alloc_pvt); - if (err != IDMAP_SUCCESS) { - ctx->free_func(bin_sid, ctx->alloc_pvt); - } - - return err; -} diff --git a/rust/idmap/src/sss_idmap_private.h b/rust/idmap/src/sss_idmap_private.h deleted file mode 100644 index 15300d11fc5..00000000000 --- a/rust/idmap/src/sss_idmap_private.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - SSSD - - ID-mapping library - private headers - - Authors: - Sumit Bose - - Copyright (C) 2012 Red Hat - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef SSS_IDMAP_PRIVATE_H_ -#define SSS_IDMAP_PRIVATE_H_ - -#define SSS_IDMAP_DEFAULT_LOWER 200000 -#define SSS_IDMAP_DEFAULT_UPPER 2000200000 -#define SSS_IDMAP_DEFAULT_RANGESIZE 200000 -#define SSS_IDMAP_DEFAULT_AUTORID false -#define SSS_IDMAP_DEFAULT_EXTRA_SLICE_INIT 10 - -#define CHECK_IDMAP_CTX(ctx, ret) do { \ - if (ctx == NULL || ctx->alloc_func == NULL || ctx->free_func == NULL) { \ - return ret; \ - } \ -} while(0) - -struct sss_idmap_opts { - /* true if autorid compatibility mode is used */ - bool autorid_mode; - - /* smallest available id (for all domains) */ - id_t idmap_lower; - - /* highest available id (for all domains) */ - id_t idmap_upper; - - /* number of available UIDs (for single domain) */ - id_t rangesize; - - /* maximal number of secondary slices */ - int extra_slice_init; -}; - -struct sss_idmap_ctx { - idmap_alloc_func *alloc_func; - void *alloc_pvt; - idmap_free_func *free_func; - struct sss_idmap_opts idmap_opts; - struct idmap_domain_info *idmap_domain_info; -}; - -/* This is a copy of the definition in the samba gen_ndr/security.h header - * file. We use it here to be able to offer conversions form struct dom_sid to - * string or binary representation since those are not made available by - * public samba libraries. - * - * If the definition ever changes on the samba side we have to adopt the - * change. But chances are very low that this will ever happen since e.g. this - * struct is also defined in public documentation from Microsoft. See e.g. - * section 2.4.2.3 of "[MS-DTYP]: Windows Data Types" - * http://msdn.microsoft.com/en-us/library/cc230364(v=prot.10) - */ - -struct dom_sid { - uint8_t sid_rev_num; - int8_t num_auths; - uint8_t id_auth[6]; - uint32_t sub_auths[15]; -}; - -#endif /* SSS_IDMAP_PRIVATE_H_ */ diff --git a/rust/idmap/src/util.h b/rust/idmap/src/util.h deleted file mode 100644 index 12d4cf9663e..00000000000 --- a/rust/idmap/src/util.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - Himmelblaud - - ID-mapping library utils - - Copyright (C) David Mulder 2024 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _UTILS_H -#define _UTILS_H - -#include -#include - -static inline void -safealign_memcpy(void *dest, const void *src, size_t n, size_t *counter) -{ - memcpy(dest, src, n); - if (counter) { - *counter += n; - } -} - -#define SAFEALIGN_COPY_UINT32(dest, src, pctr) \ - safealign_memcpy(dest, src, sizeof(uint32_t), pctr) - -#if defined(__GNUC__) && __GNUC__ >= 7 - #define SSS_ATTRIBUTE_FALLTHROUGH __attribute__ ((fallthrough)) -#else - #define SSS_ATTRIBUTE_FALLTHROUGH -#endif - -#endif /* _UTILS_H */ diff --git a/rust/nss/Cargo.toml b/rust/nss/Cargo.toml deleted file mode 100644 index 697015459cd..00000000000 --- a/rust/nss/Cargo.toml +++ /dev/null @@ -1,21 +0,0 @@ -[package] -name = "nss_himmelblau" -edition.workspace = true -license.workspace = true -homepage.workspace = true -version.workspace = true - -[lib] -name = "nss_himmelblau" -crate-type = [ "cdylib" ] -path = "src/lib.rs" - -[dependencies] -libc.workspace = true -libnss = "0.8.0" -ntstatus_gen.workspace = true -param = { workspace = true } -sock = { workspace = true } - -[build-dependencies] -version = { path = "../version" } diff --git a/rust/nss/build.rs b/rust/nss/build.rs deleted file mode 100644 index 6fcc6b9f08e..00000000000 --- a/rust/nss/build.rs +++ /dev/null @@ -1,18 +0,0 @@ -fn main() { - if let Some(vers) = version::samba_version_string() { - println!("cargo:rustc-env=CARGO_PKG_VERSION={}", vers); - } - println!( - "cargo:rustc-env=CARGO_PKG_VERSION_MAJOR={}", - version::SAMBA_VERSION_MAJOR - ); - println!( - "cargo:rustc-env=CARGO_PKG_VERSION_MINOR={}", - version::SAMBA_VERSION_MINOR - ); - println!( - "cargo:rustc-env=CARGO_PKG_VERSION_PATCH={}", - version::SAMBA_VERSION_RELEASE - ); - println!("cargo:rustc-env=LD_LIBRARY_PATH=../../bin/shared:../../bin/shared/private/"); -} diff --git a/rust/nss/src/lib.rs b/rust/nss/src/lib.rs deleted file mode 100644 index acd423fa83e..00000000000 --- a/rust/nss/src/lib.rs +++ /dev/null @@ -1,185 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - NSS module for the Himmelblau daemon - - Copyright (C) David Mulder 2024 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#[macro_use] -extern crate libnss; - -use libnss::group::{Group as NssGroup, GroupHooks}; -use libnss::interop::Response as NssResponse; -use libnss::passwd::{Passwd as NssPasswd, PasswdHooks}; -use param::LoadParm; -use sock::{stream_and_timeout, Group, Passwd, Request, Response}; - -struct HimmelblauPasswd; -libnss_passwd_hooks!(himmelblau, HimmelblauPasswd); - -impl PasswdHooks for HimmelblauPasswd { - fn get_all_entries() -> NssResponse> { - let lp = match LoadParm::new(None) { - Ok(lp) => lp, - Err(_) => return NssResponse::Unavail, - }; - let (mut stream, timeout) = match stream_and_timeout(&lp) { - Ok((stream, timeout)) => (stream, timeout), - Err(_) => return NssResponse::Unavail, - }; - - let req = Request::NssAccounts; - stream - .send(&req, timeout) - .map(|r| match r { - Response::NssAccounts(l) => { - l.into_iter().map(|passwd| passwd.into()).collect() - } - _ => vec![], - }) - .map(NssResponse::Success) - .unwrap_or_else(|_| NssResponse::Success(vec![])) - } - - fn get_entry_by_uid(uid: libc::uid_t) -> NssResponse { - let lp = match LoadParm::new(None) { - Ok(lp) => lp, - Err(_) => return NssResponse::Unavail, - }; - let (mut stream, timeout) = match stream_and_timeout(&lp) { - Ok((stream, timeout)) => (stream, timeout), - Err(_) => return NssResponse::Unavail, - }; - - let req = Request::NssAccountByUid(uid); - stream - .send(&req, timeout) - .map(|r| match r { - Response::NssAccount(passwd) => passwd - .map(nsspasswd_from_passwd) - .map(NssResponse::Success) - .unwrap_or_else(|| NssResponse::NotFound), - _ => NssResponse::NotFound, - }) - .unwrap_or_else(|_| NssResponse::NotFound) - } - - fn get_entry_by_name(name: String) -> NssResponse { - let lp = match LoadParm::new(None) { - Ok(lp) => lp, - Err(_) => return NssResponse::Unavail, - }; - let (mut stream, timeout) = match stream_and_timeout(&lp) { - Ok((stream, timeout)) => (stream, timeout), - Err(_) => return NssResponse::Unavail, - }; - - let req = Request::NssAccountByName(name); - stream - .send(&req, timeout) - .map(|r| match r { - Response::NssAccount(passwd) => passwd - .map(nsspasswd_from_passwd) - .map(NssResponse::Success) - .unwrap_or_else(|| NssResponse::NotFound), - _ => NssResponse::NotFound, - }) - .unwrap_or_else(|_| NssResponse::NotFound) - } -} - -struct HimmelblauGroup; -libnss_group_hooks!(himmelblau, HimmelblauGroup); - -impl GroupHooks for HimmelblauGroup { - fn get_all_entries() -> NssResponse> { - let lp = match LoadParm::new(None) { - Ok(lp) => lp, - Err(_) => return NssResponse::Unavail, - }; - let (mut stream, timeout) = match stream_and_timeout(&lp) { - Ok((stream, timeout)) => (stream, timeout), - Err(_) => return NssResponse::Unavail, - }; - - let req = Request::NssGroups; - stream - .send(&req, timeout) - .map(|r| match r { - Response::NssGroups(l) => { - l.into_iter().map(|group| group.into()).collect() - } - _ => vec![], - }) - .map(NssResponse::Success) - .unwrap_or_else(|_| NssResponse::Success(vec![])) - } - - fn get_entry_by_gid(gid: libc::gid_t) -> NssResponse { - let lp = match LoadParm::new(None) { - Ok(lp) => lp, - Err(_) => return NssResponse::Unavail, - }; - let (mut stream, timeout) = match stream_and_timeout(&lp) { - Ok((stream, timeout)) => (stream, timeout), - Err(_) => return NssResponse::Unavail, - }; - - let req = Request::NssGroupByGid(gid); - stream - .send(&req, timeout) - .map(|r| match r { - Response::NssGroup(group) => group - .map(nssgroup_from_group) - .map(NssResponse::Success) - .unwrap_or_else(|| NssResponse::NotFound), - _ => NssResponse::NotFound, - }) - .unwrap_or_else(|_| NssResponse::NotFound) - } - - fn get_entry_by_name(name: String) -> NssResponse { - let lp = match LoadParm::new(None) { - Ok(lp) => lp, - Err(_) => return NssResponse::Unavail, - }; - let (mut stream, timeout) = match stream_and_timeout(&lp) { - Ok((stream, timeout)) => (stream, timeout), - Err(_) => return NssResponse::Unavail, - }; - - let req = Request::NssGroupByName(name); - stream - .send(&req, timeout) - .map(|r| match r { - Response::NssGroup(group) => group - .map(nssgroup_from_group) - .map(NssResponse::Success) - .unwrap_or_else(|| NssResponse::NotFound), - _ => NssResponse::NotFound, - }) - .unwrap_or_else(|_| NssResponse::NotFound) - } -} - -fn nsspasswd_from_passwd(passwd: Passwd) -> NssPasswd { - passwd.into() -} - -fn nssgroup_from_group(group: Group) -> NssGroup { - group.into() -} diff --git a/rust/ntstatus_gen/Cargo.toml b/rust/ntstatus_gen/Cargo.toml deleted file mode 100644 index c36ee967dfe..00000000000 --- a/rust/ntstatus_gen/Cargo.toml +++ /dev/null @@ -1,6 +0,0 @@ -[package] -name = "ntstatus_gen" -edition.workspace = true -license.workspace = true -homepage.workspace = true -version.workspace = true diff --git a/rust/ntstatus_gen/src/lib.rs b/rust/ntstatus_gen/src/lib.rs deleted file mode 100644 index b112776f579..00000000000 --- a/rust/ntstatus_gen/src/lib.rs +++ /dev/null @@ -1,24 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Generated NTSTATUS Errors - - Copyright (C) David Mulder 2024 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#[path = "../../../bin/default/libcli/util/ntstatus_gen.rs"] -mod ntstatus_gen; -pub use ntstatus_gen::*; diff --git a/rust/pam/Cargo.toml b/rust/pam/Cargo.toml deleted file mode 100644 index 509468fd6e1..00000000000 --- a/rust/pam/Cargo.toml +++ /dev/null @@ -1,23 +0,0 @@ -[package] -name = "pam_himmelblau" -links = "pam" - -edition.workspace = true -license.workspace = true -homepage.workspace = true -version.workspace = true - -[lib] -name = "pam_himmelblau" -crate-type = [ "cdylib" ] -path = "src/lib.rs" - -[dependencies] -libc = { workspace = true } -dbg = { workspace = true } -sock.workspace = true -chelps.workspace = true -param.workspace = true - -[build-dependencies] -pkg-config = "0.3.30" diff --git a/rust/pam/build.rs b/rust/pam/build.rs deleted file mode 100644 index 11313da3e5c..00000000000 --- a/rust/pam/build.rs +++ /dev/null @@ -1,10 +0,0 @@ -fn main() { - println!("cargo:rerun-if-changed=build.rs"); - // ignore errors here since older versions of pam do not ship the pkg-config `pam.pc` file. - // Not setting anything here will fall back on just blindly linking with `-lpam`, - // which will work on environments with libpam.so, but no pkg-config file. - let _ = pkg_config::Config::new() - .atleast_version("1.3.0") - .probe("pam"); - println!("cargo:rustc-env=LD_LIBRARY_PATH=../../bin/shared:../../bin/shared/private/"); -} diff --git a/rust/pam/src/lib.rs b/rust/pam/src/lib.rs deleted file mode 100644 index 7a40284252b..00000000000 --- a/rust/pam/src/lib.rs +++ /dev/null @@ -1,43 +0,0 @@ -/* - MIT License - - Copyright (c) 2015 TOZNY - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*/ - -#![deny(warnings)] -#![warn(unused_extern_crates)] -#![deny(clippy::todo)] -#![deny(clippy::unimplemented)] -// In this file, we do want to panic on these faults. -// #![deny(clippy::unwrap_used)] -// #![deny(clippy::expect_used)] -#![deny(clippy::panic)] -#![deny(clippy::unreachable)] -#![deny(clippy::await_holding_lock)] -#![deny(clippy::needless_pass_by_value)] -#![deny(clippy::trivially_copy_pass_by_ref)] - -#[cfg(target_family = "unix")] -mod pam; - -// pub use needs to be here so it'll compile and export all the things -#[cfg(target_family = "unix")] -pub use crate::pam::*; diff --git a/rust/pam/src/pam/constants.rs b/rust/pam/src/pam/constants.rs deleted file mode 100644 index a626651be73..00000000000 --- a/rust/pam/src/pam/constants.rs +++ /dev/null @@ -1,118 +0,0 @@ -/* - MIT License - - Copyright (c) 2015 TOZNY - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*/ -use libc::{c_int, c_uint}; - -pub type PamFlag = c_uint; -pub type PamItemType = c_int; -pub type PamMessageStyle = c_int; -pub type AlwaysZero = c_int; - -// The Linux-PAM flags -// see /usr/include/security/_pam_types.h -pub const _PAM_SILENT: PamFlag = 0x8000; -pub const _PAM_DISALLOW_NULL_AUTHTOK: PamFlag = 0x0001; -pub const _PAM_ESTABLISH_CRED: PamFlag = 0x0002; -pub const _PAM_DELETE_CRED: PamFlag = 0x0004; -pub const _PAM_REINITIALIZE_CRED: PamFlag = 0x0008; -pub const _PAM_REFRESH_CRED: PamFlag = 0x0010; -pub const _PAM_CHANGE_EXPIRED_AUTHTOK: PamFlag = 0x0020; - -// The Linux-PAM item types -// see /usr/include/security/_pam_types.h -/// The service name -pub const PAM_SERVICE: PamItemType = 1; -/// The user name -pub const PAM_USER: PamItemType = 2; -/// The tty name -pub const PAM_TTY: PamItemType = 3; -/// The remote host name -pub const PAM_RHOST: PamItemType = 4; -/// The pam_conv structure -pub const PAM_CONV: PamItemType = 5; -/// The authentication token (password) -pub const PAM_AUTHTOK: PamItemType = 6; -/// The old authentication token -pub const PAM_OLDAUTHTOK: PamItemType = 7; -/// The remote user name -pub const PAM_RUSER: PamItemType = 8; -/// the prompt for getting a username -pub const PAM_USER_PROMPT: PamItemType = 9; -/* Linux-PAM :extensionsPamItemType = */ -/// app supplied function to override failure delays -pub const _PAM_FAIL_DELAY: PamItemType = 10; -/// X :display name -pub const _PAM_XDISPLAY: PamItemType = 11; -/// X :server authentication data -pub const _PAM_XAUTHDATA: PamItemType = 12; -/// The type for pam_get_authtok -pub const _PAM_AUTHTOK_TYPE: PamItemType = 13; - -// Message styles -pub const PAM_PROMPT_ECHO_OFF: PamMessageStyle = 1; -pub const PAM_PROMPT_ECHO_ON: PamMessageStyle = 2; -pub const PAM_ERROR_MSG: PamMessageStyle = 3; -pub const PAM_TEXT_INFO: PamMessageStyle = 4; -/// yes/no/maybe conditionals -pub const _PAM_RADIO_TYPE: PamMessageStyle = 5; -pub const _PAM_BINARY_PROMPT: PamMessageStyle = 7; - -// The Linux-PAM return values -// see /usr/include/security/_pam_types.h -#[allow(non_camel_case_types, dead_code)] -#[derive(Debug, PartialEq)] -#[repr(C)] -pub enum PamResultCode { - PAM_SUCCESS = 0, - PAM_OPEN_ERR = 1, - PAM_SYMBOL_ERR = 2, - PAM_SERVICE_ERR = 3, - PAM_SYSTEM_ERR = 4, - PAM_BUF_ERR = 5, - PAM_PERM_DENIED = 6, - PAM_AUTH_ERR = 7, - PAM_CRED_INSUFFICIENT = 8, - PAM_AUTHINFO_UNAVAIL = 9, - PAM_USER_UNKNOWN = 10, - PAM_MAXTRIES = 11, - PAM_NEW_AUTHTOK_REQD = 12, - PAM_ACCT_EXPIRED = 13, - PAM_SESSION_ERR = 14, - PAM_CRED_UNAVAIL = 15, - PAM_CRED_EXPIRED = 16, - PAM_CRED_ERR = 17, - PAM_NO_MODULE_DATA = 18, - PAM_CONV_ERR = 19, - PAM_AUTHTOK_ERR = 20, - PAM_AUTHTOK_RECOVERY_ERR = 21, - PAM_AUTHTOK_LOCK_BUSY = 22, - PAM_AUTHTOK_DISABLE_AGING = 23, - PAM_TRY_AGAIN = 24, - PAM_IGNORE = 25, - PAM_ABORT = 26, - PAM_AUTHTOK_EXPIRED = 27, - PAM_MODULE_UNKNOWN = 28, - PAM_BAD_ITEM = 29, - PAM_CONV_AGAIN = 30, - PAM_INCOMPLETE = 31, -} diff --git a/rust/pam/src/pam/conv.rs b/rust/pam/src/pam/conv.rs deleted file mode 100644 index 8fa8b46cedb..00000000000 --- a/rust/pam/src/pam/conv.rs +++ /dev/null @@ -1,112 +0,0 @@ -/* - MIT License - - Copyright (c) 2015 TOZNY - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*/ -use std::ffi::{CStr, CString}; -use std::ptr; - -use libc::{c_char, c_int}; - -use crate::pam::constants::{PamResultCode, *}; -use crate::pam::module::{PamItem, PamResult}; - -#[allow(missing_copy_implementations)] -pub enum AppDataPtr {} - -#[repr(C)] -struct PamMessage { - msg_style: PamMessageStyle, - msg: *const c_char, -} - -#[repr(C)] -struct PamResponse { - resp: *const c_char, - resp_retcode: AlwaysZero, -} - -/// `PamConv` acts as a channel for communicating with user. -/// -/// Communication is mediated by the pam client (the application that invoked -/// pam). Messages sent will be relayed to the user by the client, and response -/// will be relayed back. -#[repr(C)] -pub struct PamConv { - conv: extern "C" fn( - num_msg: c_int, - pam_message: &&PamMessage, - pam_response: &mut *const PamResponse, - appdata_ptr: *const AppDataPtr, - ) -> PamResultCode, - appdata_ptr: *const AppDataPtr, -} - -impl PamConv { - /// Sends a message to the pam client. - /// - /// This will typically result in the user seeing a message or a prompt. - /// There are several message styles available: - /// - /// - PAM_PROMPT_ECHO_OFF - /// - PAM_PROMPT_ECHO_ON - /// - PAM_ERROR_MSG - /// - PAM_TEXT_INFO - /// - PAM_RADIO_TYPE - /// - PAM_BINARY_PROMPT - /// - /// Note that the user experience will depend on how the client implements - /// these message styles - and not all applications implement all message - /// styles. - pub fn send( - &self, - style: PamMessageStyle, - msg: &str, - ) -> PamResult> { - let mut resp_ptr: *const PamResponse = ptr::null(); - let msg_cstr = CString::new(msg).unwrap(); - let msg = PamMessage { - msg_style: style, - msg: msg_cstr.as_ptr(), - }; - - let ret = (self.conv)(1, &&msg, &mut resp_ptr, self.appdata_ptr); - - if PamResultCode::PAM_SUCCESS == ret { - // PamResponse.resp is null for styles that don't return user input like PAM_TEXT_INFO - let response = unsafe { (*resp_ptr).resp }; - if response.is_null() { - Ok(None) - } else { - let bytes = unsafe { CStr::from_ptr(response).to_bytes() }; - Ok(String::from_utf8(bytes.to_vec()).ok()) - } - } else { - Err(ret) - } - } -} - -impl PamItem for PamConv { - fn item_type() -> PamItemType { - PAM_CONV - } -} diff --git a/rust/pam/src/pam/items.rs b/rust/pam/src/pam/items.rs deleted file mode 100644 index 14bcade14b8..00000000000 --- a/rust/pam/src/pam/items.rs +++ /dev/null @@ -1,101 +0,0 @@ -/* - MIT License - - Copyright (c) 2015 TOZNY - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*/ -use crate::pam::constants::{ - PamItemType, PAM_AUTHTOK, PAM_OLDAUTHTOK, PAM_RHOST, PAM_RUSER, - PAM_SERVICE, PAM_TTY, PAM_USER, PAM_USER_PROMPT, -}; -pub use crate::pam::conv::PamConv; -use crate::pam::module::PamItem; - -#[allow(dead_code)] -pub struct PamService {} - -impl PamItem for PamService { - fn item_type() -> PamItemType { - PAM_SERVICE - } -} - -#[allow(dead_code)] -pub struct PamUser {} - -impl PamItem for PamUser { - fn item_type() -> PamItemType { - PAM_USER - } -} - -#[allow(dead_code)] -pub struct PamUserPrompt {} - -impl PamItem for PamUserPrompt { - fn item_type() -> PamItemType { - PAM_USER_PROMPT - } -} - -#[allow(dead_code)] -pub struct PamTty {} - -impl PamItem for PamTty { - fn item_type() -> PamItemType { - PAM_TTY - } -} - -#[allow(dead_code)] -pub struct PamRUser {} - -impl PamItem for PamRUser { - fn item_type() -> PamItemType { - PAM_RUSER - } -} - -#[allow(dead_code)] -pub struct PamRHost {} - -impl PamItem for PamRHost { - fn item_type() -> PamItemType { - PAM_RHOST - } -} - -#[allow(dead_code)] -pub struct PamAuthTok {} - -impl PamItem for PamAuthTok { - fn item_type() -> PamItemType { - PAM_AUTHTOK - } -} - -#[allow(dead_code)] -pub struct PamOldAuthTok {} - -impl PamItem for PamOldAuthTok { - fn item_type() -> PamItemType { - PAM_OLDAUTHTOK - } -} diff --git a/rust/pam/src/pam/macros.rs b/rust/pam/src/pam/macros.rs deleted file mode 100644 index 6e3f6d90214..00000000000 --- a/rust/pam/src/pam/macros.rs +++ /dev/null @@ -1,140 +0,0 @@ -/* - MIT License - - Copyright (c) 2015 TOZNY - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*/ -/// Macro to generate the `extern "C"` entrypoint bindings needed by PAM -/// -/// You can call `pam_hooks!(SomeType);` for any type that implements `PamHooks` -/// -/// ## Examples: -/// -/// Here is full example of a PAM module that would authenticate and authorize everybody: -/// -/// ``` -/// #[macro_use] -/// extern crate pam; -/// -/// use pam::constants::{PamFlag, PamResultCode}; -/// use pam::module::{PamHandle, PamHooks}; -/// use std::ffi::CStr; -/// -/// # fn main() {} -/// struct MyPamModule; -/// pam_hooks!(MyPamModule); -/// -/// impl PamHooks for MyPamModule { -/// fn sm_authenticate(pamh: &PamHandle, args: Vec<&CStr>, flags: PamFlag) -> PamResultCode { -/// println!("Everybody is authenticated!"); -/// PamResultCode::PAM_SUCCESS -/// } -/// -/// fn acct_mgmt(pamh: &PamHandle, args: Vec<&CStr>, flags: PamFlag) -> PamResultCode { -/// println!("Everybody is authorized!"); -/// PamResultCode::PAM_SUCCESS -/// } -/// } -/// ``` -#[macro_export] -macro_rules! pam_hooks { - ($ident:ident) => { - pub use self::pam_hooks_scope::*; - mod pam_hooks_scope { - use std::ffi::CStr; - use std::os::raw::{c_char, c_int}; - - use $crate::pam::constants::{PamFlag, PamResultCode}; - use $crate::pam::module::{PamHandle, PamHooks}; - - fn extract_argv<'a>(argc: c_int, argv: *const *const c_char) -> Vec<&'a CStr> { - (0..argc) - .map(|o| unsafe { CStr::from_ptr(*argv.offset(o as isize) as *const c_char) }) - .collect() - } - - #[no_mangle] - pub extern "C" fn pam_sm_acct_mgmt( - pamh: &PamHandle, - flags: PamFlag, - argc: c_int, - argv: *const *const c_char, - ) -> PamResultCode { - let args = extract_argv(argc, argv); - super::$ident::acct_mgmt(pamh, args, flags) - } - - #[no_mangle] - pub extern "C" fn pam_sm_authenticate( - pamh: &PamHandle, - flags: PamFlag, - argc: c_int, - argv: *const *const c_char, - ) -> PamResultCode { - let args = extract_argv(argc, argv); - super::$ident::sm_authenticate(pamh, args, flags) - } - - #[no_mangle] - pub extern "C" fn pam_sm_chauthtok( - pamh: &PamHandle, - flags: PamFlag, - argc: c_int, - argv: *const *const c_char, - ) -> PamResultCode { - let args = extract_argv(argc, argv); - super::$ident::sm_chauthtok(pamh, args, flags) - } - - #[no_mangle] - pub extern "C" fn pam_sm_close_session( - pamh: &PamHandle, - flags: PamFlag, - argc: c_int, - argv: *const *const c_char, - ) -> PamResultCode { - let args = extract_argv(argc, argv); - super::$ident::sm_close_session(pamh, args, flags) - } - - #[no_mangle] - pub extern "C" fn pam_sm_open_session( - pamh: &PamHandle, - flags: PamFlag, - argc: c_int, - argv: *const *const c_char, - ) -> PamResultCode { - let args = extract_argv(argc, argv); - super::$ident::sm_open_session(pamh, args, flags) - } - - #[no_mangle] - pub extern "C" fn pam_sm_setcred( - pamh: &PamHandle, - flags: PamFlag, - argc: c_int, - argv: *const *const c_char, - ) -> PamResultCode { - let args = extract_argv(argc, argv); - super::$ident::sm_setcred(pamh, args, flags) - } - } - }; -} diff --git a/rust/pam/src/pam/mod.rs b/rust/pam/src/pam/mod.rs deleted file mode 100755 index 7447ee09a3a..00000000000 --- a/rust/pam/src/pam/mod.rs +++ /dev/null @@ -1,615 +0,0 @@ -/* - MIT License - - Copyright (c) 2015 TOZNY - Copyright (c) 2020 William Brown - Copyright (c) 2024 David Mulder - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*/ -//! Interface to the pluggable authentication module framework (PAM). -//! -//! The goal of this library is to provide a type-safe API that can be used to -//! interact with PAM. The library is incomplete - currently it supports -//! a subset of functions for use in a pam authentication module. A pam module -//! is a shared library that is invoked to authenticate a user, or to perform -//! other functions. -//! -//! For general information on writing pam modules, see -//! [The Linux-PAM Module Writers' Guide][module-guide] -//! -//! [module-guide]: http://www.linux-pam.org/Linux-PAM-html/Linux-PAM_MWG.html -//! -//! A typical authentication module will define an external function called -//! `pam_sm_authenticate()`, which will use functions in this library to -//! interrogate the program that requested authentication for more information, -//! and to render a result. For a working example that uses this library, see -//! [toznyauth-pam][]. -//! -//! [toznyauth-pam]: https://github.com/tozny/toznyauth-pam -//! -//! Note that constants that are normally read from pam header files are -//! hard-coded in the `constants` module. The values there are taken from -//! a Linux system. That means that it might take some work to get this library -//! to work on other platforms. - -pub mod constants; -pub mod conv; -pub mod items; -#[doc(hidden)] -pub mod macros; -pub mod module; - -use std::collections::BTreeSet; -use std::convert::TryFrom; -use std::ffi::CStr; - -use dbg::*; -use param::LoadParm; -use sock::{ - stream_and_timeout, PamAuthRequest, PamAuthResponse, Request, Response, -}; - -use crate::pam::constants::*; -use crate::pam::conv::PamConv; -use crate::pam::module::{PamHandle, PamHooks}; -use crate::pam_hooks; -use constants::PamResultCode; - -use std::thread; -use std::time::Duration; - -fn install_subscriber(lp: &LoadParm, debug: bool) { - debuglevel_set!(if debug { DBGLVL_DEBUG } else { DBGLVL_ERR }); - match lp.logfile() { - Ok(Some(logfile)) => { - debug_set_logfile(&logfile); - setup_logging(env!("CARGO_PKG_NAME"), DEBUG_FILE) - } - _ => setup_logging(env!("CARGO_PKG_NAME"), DEBUG_STDOUT), - } -} - -#[derive(Debug)] -struct Options { - debug: bool, - use_first_pass: bool, - ignore_unknown_user: bool, -} - -impl TryFrom<&Vec<&CStr>> for Options { - type Error = (); - - fn try_from(args: &Vec<&CStr>) -> Result { - let opts: Result, _> = - args.iter().map(|cs| cs.to_str()).collect(); - let gopts = match opts { - Ok(o) => o, - Err(e) => { - println!("Error in module args -> {:?}", e); - return Err(()); - } - }; - - Ok(Options { - debug: gopts.contains("debug"), - use_first_pass: gopts.contains("use_first_pass"), - ignore_unknown_user: gopts.contains("ignore_unknown_user"), - }) - } -} - -pub struct PamHimmelblau; - -pam_hooks!(PamHimmelblau); - -macro_rules! match_sm_auth_client_response { - ($expr:expr, $opts:ident, $conv:ident, $req:ident, $authtok:ident, $($pat:pat => $result:expr),*) => { - match $expr { - Ok(r) => match r { - $($pat => $result),* - Response::PamAuthStepResponse(PamAuthResponse::Success) => { - return PamResultCode::PAM_SUCCESS; - } - Response::PamAuthStepResponse(PamAuthResponse::Denied) => { - return PamResultCode::PAM_AUTH_ERR; - } - Response::PamAuthStepResponse(PamAuthResponse::Unknown) => { - if $opts.ignore_unknown_user { - return PamResultCode::PAM_IGNORE; - } else { - return PamResultCode::PAM_USER_UNKNOWN; - } - } - Response::PamAuthStepResponse(PamAuthResponse::SetupPin { - msg, - }) => { - match $conv.send(PAM_TEXT_INFO, &msg) { - Ok(_) => {} - Err(err) => { - if $opts.debug { - println!("Message prompt failed"); - } - return err; - } - } - - let mut pin; - let mut confirm; - loop { - pin = match $conv.send(PAM_PROMPT_ECHO_OFF, "New PIN: ") { - Ok(password) => match password { - Some(cred) => cred, - None => { - DBG_DEBUG!("no pin"); - return PamResultCode::PAM_CRED_INSUFFICIENT; - } - }, - Err(err) => { - DBG_DEBUG!("unable to get pin"); - return err; - } - }; - - confirm = match $conv.send(PAM_PROMPT_ECHO_OFF, "Confirm PIN: ") { - Ok(password) => match password { - Some(cred) => cred, - None => { - DBG_DEBUG!("no confirmation pin"); - return PamResultCode::PAM_CRED_INSUFFICIENT; - } - }, - Err(err) => { - DBG_DEBUG!("unable to get confirmation pin"); - return err; - } - }; - - if pin == confirm { - break; - } else { - match $conv.send(PAM_TEXT_INFO, "Inputs did not match. Try again.") { - Ok(_) => {} - Err(err) => { - if $opts.debug { - println!("Message prompt failed"); - } - return err; - } - } - } - } - - // Now setup the request for the next loop. - $req = Request::PamAuthenticateStep(PamAuthRequest::SetupPin { - pin, - }); - continue; - }, - Response::PamAuthStepResponse(PamAuthResponse::Pin) => { - let mut consume_authtok = None; - // Swap the authtok out with a None, so it can only be consumed once. - // If it's already been swapped, we are just swapping two null pointers - // here effectively. - std::mem::swap(&mut $authtok, &mut consume_authtok); - let cred = if let Some(cred) = consume_authtok { - cred - } else { - match $conv.send(PAM_PROMPT_ECHO_OFF, "PIN: ") { - Ok(password) => match password { - Some(cred) => cred, - None => { - DBG_DEBUG!("no pin"); - return PamResultCode::PAM_CRED_INSUFFICIENT; - } - }, - Err(err) => { - DBG_DEBUG!("unable to get pin"); - return err; - } - } - }; - - // Now setup the request for the next loop. - $req = Request::PamAuthenticateStep(PamAuthRequest::Pin { pin: cred }); - continue; - } - _ => { - // unexpected response. - DBG_ERR!("PAM_IGNORE, unexpected resolver response: {:?}", r); - return PamResultCode::PAM_IGNORE; - } - }, - Err(e) => { - DBG_ERR!("PAM_IGNORE: {:?}", e); - return PamResultCode::PAM_IGNORE; - } - } - } -} - -impl PamHooks for PamHimmelblau { - fn acct_mgmt( - pamh: &PamHandle, - args: Vec<&CStr>, - _flags: PamFlag, - ) -> PamResultCode { - let opts = match Options::try_from(&args) { - Ok(o) => o, - Err(_) => return PamResultCode::PAM_SERVICE_ERR, - }; - - let lp = match LoadParm::new(None) { - Ok(lp) => lp, - Err(_) => return PamResultCode::PAM_SERVICE_ERR, - }; - - install_subscriber(&lp, opts.debug); - - let tty = pamh.get_tty(); - let rhost = pamh.get_rhost(); - - DBG_DEBUG!("{:?} {:?} {:?} {:?} acct_mgmt", args, opts, tty, rhost); - - let account_id = match pamh.get_user(None) { - Ok(aid) => aid, - Err(e) => { - DBG_ERR!("get_user: {:?}", e); - return e; - } - }; - - let req = Request::PamAccountAllowed(account_id); - - let (mut stream, timeout) = match stream_and_timeout(&lp) { - Ok(res) => res, - Err(e) => { - DBG_ERR!("Error stream_and_timeout: {:?}", e); - return PamResultCode::PAM_SERVICE_ERR; - } - }; - - match stream.send(&req, timeout) { - Ok(r) => match r { - Response::PamStatus(Some(true)) => { - DBG_DEBUG!("PamResultCode::PAM_SUCCESS"); - PamResultCode::PAM_SUCCESS - } - Response::PamStatus(Some(false)) => { - DBG_DEBUG!("PamResultCode::PAM_AUTH_ERR"); - PamResultCode::PAM_AUTH_ERR - } - Response::PamStatus(None) => { - if opts.ignore_unknown_user { - DBG_DEBUG!("PamResultCode::PAM_IGNORE"); - PamResultCode::PAM_IGNORE - } else { - DBG_DEBUG!("PamResultCode::PAM_USER_UNKNOWN"); - PamResultCode::PAM_USER_UNKNOWN - } - } - _ => { - // unexpected response. - DBG_ERR!( - "PAM_IGNORE, unexpected resolver response: {:?}", - r - ); - PamResultCode::PAM_IGNORE - } - }, - Err(e) => { - DBG_ERR!("PamResultCode::PAM_IGNORE: {:?}", e); - PamResultCode::PAM_IGNORE - } - } - } - - fn sm_authenticate( - pamh: &PamHandle, - args: Vec<&CStr>, - _flags: PamFlag, - ) -> PamResultCode { - let opts = match Options::try_from(&args) { - Ok(o) => o, - Err(_) => return PamResultCode::PAM_SERVICE_ERR, - }; - - let lp = match LoadParm::new(None) { - Ok(lp) => lp, - Err(_) => return PamResultCode::PAM_SERVICE_ERR, - }; - - install_subscriber(&lp, opts.debug); - - let tty = pamh.get_tty(); - let rhost = pamh.get_rhost(); - - DBG_DEBUG!( - "{:?} {:?} {:?} {:?} sm_authenticate", - args, - opts, - tty, - rhost - ); - - let account_id = match pamh.get_user(None) { - Ok(aid) => aid, - Err(e) => { - DBG_ERR!("get_user: {:?}", e); - return e; - } - }; - - let (mut stream, timeout) = match stream_and_timeout(&lp) { - Ok(res) => res, - Err(e) => { - DBG_ERR!("Error stream_and_timeout: {:?}", e); - return PamResultCode::PAM_SERVICE_ERR; - } - }; - - // Later we may need to move this to a function and call it as a oneshot for auth methods - // that don't require any authtoks at all. For example, imagine a user authed and they - // needed to follow a URL to continue. In that case, they would fail here because they - // didn't enter an authtok that they didn't need! - let mut authtok = match pamh.get_authtok() { - Ok(Some(v)) => Some(v), - Ok(None) => { - if opts.use_first_pass { - DBG_DEBUG!("Don't have an authtok, returning PAM_AUTH_ERR"); - return PamResultCode::PAM_AUTH_ERR; - } - None - } - Err(e) => { - DBG_ERR!("get_authtok: {:?}", e); - return e; - } - }; - - let conv = match pamh.get_item::() { - Ok(conv) => conv, - Err(e) => { - DBG_ERR!("pam_conv: {:?}", e); - return e; - } - }; - - let mut req = Request::PamAuthenticateInit(account_id); - - loop { - match_sm_auth_client_response!(stream.send(&req, timeout), opts, conv, req, authtok, - Response::PamAuthStepResponse(PamAuthResponse::Password) => { - let mut consume_authtok = None; - // Swap the authtok out with a None, so it can only be consumed once. - // If it's already been swapped, we are just swapping two null pointers - // here effectively. - std::mem::swap(&mut authtok, &mut consume_authtok); - let cred = if let Some(cred) = consume_authtok { - cred - } else { - match conv.send(PAM_PROMPT_ECHO_OFF, "Password: ") { - Ok(password) => match password { - Some(cred) => cred, - None => { - DBG_DEBUG!("no password"); - return PamResultCode::PAM_CRED_INSUFFICIENT; - } - }, - Err(err) => { - DBG_DEBUG!("unable to get password"); - return err; - } - } - }; - - // Now setup the request for the next loop. - req = Request::PamAuthenticateStep(PamAuthRequest::Password { cred }); - continue; - }, - Response::PamAuthStepResponse(PamAuthResponse::MFACode { - msg, - }) => { - match conv.send(PAM_TEXT_INFO, &msg) { - Ok(_) => {} - Err(err) => { - if opts.debug { - println!("Message prompt failed"); - } - return err; - } - } - let cred = match conv.send(PAM_PROMPT_ECHO_OFF, "Code: ") { - Ok(password) => match password { - Some(cred) => cred, - None => { - DBG_DEBUG!("no mfa code"); - return PamResultCode::PAM_CRED_INSUFFICIENT; - } - }, - Err(err) => { - DBG_DEBUG!("unable to get mfa code"); - return err; - } - }; - - // Now setup the request for the next loop. - req = Request::PamAuthenticateStep(PamAuthRequest::MFACode { - cred, - }); - continue; - }, - Response::PamAuthStepResponse(PamAuthResponse::MFAPoll { - msg, - polling_interval, - }) => { - match conv.send(PAM_TEXT_INFO, &msg) { - Ok(_) => {} - Err(err) => { - if opts.debug { - println!("Message prompt failed"); - } - return err; - } - } - - // Necessary because of OpenSSH bug - // https://bugzilla.mindrot.org/show_bug.cgi?id=2876 - - // PAM_TEXT_INFO and PAM_ERROR_MSG conversation not - // honoured during PAM authentication - let _ = conv.send(PAM_PROMPT_ECHO_OFF, "Press enter to continue"); - - let mut poll_attempt = 0; - req = Request::PamAuthenticateStep( - PamAuthRequest::MFAPoll { poll_attempt } - ); - loop { - thread::sleep(Duration::from_secs(polling_interval.into())); - - match_sm_auth_client_response!( - stream.send(&req, timeout), opts, conv, req, authtok, - Response::PamAuthStepResponse( - PamAuthResponse::MFAPollWait, - ) => { - // Continue polling if the daemon says to wait - poll_attempt += 1; - req = Request::PamAuthenticateStep( - PamAuthRequest::MFAPoll { poll_attempt } - ); - continue; - } - ); - } - } - ); - } // while true, continue calling PamAuthenticateStep until we get a decision. - } - - fn sm_chauthtok( - _pamh: &PamHandle, - args: Vec<&CStr>, - _flags: PamFlag, - ) -> PamResultCode { - let opts = match Options::try_from(&args) { - Ok(o) => o, - Err(_) => return PamResultCode::PAM_SERVICE_ERR, - }; - - let lp = match LoadParm::new(None) { - Ok(lp) => lp, - Err(_) => return PamResultCode::PAM_SERVICE_ERR, - }; - - install_subscriber(&lp, opts.debug); - - DBG_DEBUG!("{:?} {:?} sm_chauthtok", args, opts); - - PamResultCode::PAM_IGNORE - } - - fn sm_close_session( - _pamh: &PamHandle, - args: Vec<&CStr>, - _flags: PamFlag, - ) -> PamResultCode { - let opts = match Options::try_from(&args) { - Ok(o) => o, - Err(_) => return PamResultCode::PAM_SERVICE_ERR, - }; - - let lp = match LoadParm::new(None) { - Ok(lp) => lp, - Err(_) => return PamResultCode::PAM_SERVICE_ERR, - }; - - install_subscriber(&lp, opts.debug); - - DBG_DEBUG!("{:?} {:?} sm_close_session", args, opts); - - PamResultCode::PAM_SUCCESS - } - - fn sm_open_session( - pamh: &PamHandle, - args: Vec<&CStr>, - _flags: PamFlag, - ) -> PamResultCode { - let opts = match Options::try_from(&args) { - Ok(o) => o, - Err(_) => return PamResultCode::PAM_SERVICE_ERR, - }; - - let lp = match LoadParm::new(None) { - Ok(lp) => lp, - Err(_) => return PamResultCode::PAM_SERVICE_ERR, - }; - - install_subscriber(&lp, opts.debug); - - DBG_DEBUG!("{:?} {:?} sm_open_session", args, opts); - - let account_id = match pamh.get_user(None) { - Ok(aid) => aid, - Err(e) => { - DBG_ERR!("get_user: {:?}", e); - return e; - } - }; - - let req = Request::PamAccountBeginSession(account_id); - - let (mut stream, timeout) = match stream_and_timeout(&lp) { - Ok(res) => res, - Err(e) => { - DBG_ERR!("Error stream_and_timeout: {:?}", e); - return PamResultCode::PAM_SERVICE_ERR; - } - }; - - match stream.send(&req, timeout) { - Ok(Response::Success) => PamResultCode::PAM_SUCCESS, - other => { - DBG_DEBUG!("PAM_IGNORE: {:?}", other); - PamResultCode::PAM_IGNORE - } - } - } - - fn sm_setcred( - _pamh: &PamHandle, - args: Vec<&CStr>, - _flags: PamFlag, - ) -> PamResultCode { - let opts = match Options::try_from(&args) { - Ok(o) => o, - Err(_) => return PamResultCode::PAM_SERVICE_ERR, - }; - - let lp = match LoadParm::new(None) { - Ok(lp) => lp, - Err(_) => return PamResultCode::PAM_SERVICE_ERR, - }; - - install_subscriber(&lp, opts.debug); - - DBG_DEBUG!("{:?} {:?} sm_setcred", args, opts); - - PamResultCode::PAM_SUCCESS - } -} diff --git a/rust/pam/src/pam/module.rs b/rust/pam/src/pam/module.rs deleted file mode 100755 index df2eade70fd..00000000000 --- a/rust/pam/src/pam/module.rs +++ /dev/null @@ -1,361 +0,0 @@ -/* - MIT License - - Copyright (c) 2015 TOZNY - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*/ -//! Functions for use in pam modules. - -use std::ffi::{CStr, CString}; -use std::{mem, ptr}; - -use libc::c_char; - -use crate::pam::constants::{ - PamFlag, PamItemType, PamResultCode, PAM_AUTHTOK, PAM_RHOST, PAM_TTY, -}; - -/// Opaque type, used as a pointer when making pam API calls. -/// -/// A module is invoked via an external function such as `pam_sm_authenticate`. -/// Such a call provides a pam handle pointer. The same pointer should be given -/// as an argument when making API calls. -#[allow(missing_copy_implementations)] -pub enum PamHandle {} - -#[allow(missing_copy_implementations)] -enum PamItemT {} - -#[allow(missing_copy_implementations)] -pub enum PamDataT {} - -#[link(name = "pam")] -extern "C" { - fn pam_get_data( - pamh: *const PamHandle, - module_data_name: *const c_char, - data: &mut *const PamDataT, - ) -> PamResultCode; - - fn pam_set_data( - pamh: *const PamHandle, - module_data_name: *const c_char, - data: *mut PamDataT, - cleanup: unsafe extern "C" fn( - pamh: *const PamHandle, - data: *mut PamDataT, - error_status: PamResultCode, - ), - ) -> PamResultCode; - - fn pam_get_item( - pamh: *const PamHandle, - item_type: PamItemType, - item: &mut *const PamItemT, - ) -> PamResultCode; - - fn pam_set_item( - pamh: *mut PamHandle, - item_type: PamItemType, - item: &PamItemT, - ) -> PamResultCode; - - fn pam_get_user( - pamh: *const PamHandle, - user: &*mut c_char, - prompt: *const c_char, - ) -> PamResultCode; -} - -/// # Safety -/// -/// We're doing what we can for this one, but it's FFI. -pub unsafe extern "C" fn cleanup( - _: *const PamHandle, - c_data: *mut PamDataT, - _: PamResultCode, -) { - let c_data = Box::from_raw(c_data); - let data: Box = mem::transmute(c_data); - mem::drop(data); -} - -pub type PamResult = Result; - -/// # Safety -/// -/// Type-level mapping for safely retrieving values with `get_item`. -/// -/// See `pam_get_item` in -/// -pub trait PamItem { - /// Maps a Rust type to a pam constant. - /// - /// For example, the type PamConv maps to the constant PAM_CONV. The pam - /// API contract specifies that when the API function `pam_get_item` is - /// called with the constant PAM_CONV, it will return a value of type - /// `PamConv`. - fn item_type() -> PamItemType; -} - -impl PamHandle { - /// # Safety - /// - /// Gets some value, identified by `key`, that has been set by the module - /// previously. - /// - /// See `pam_get_data` in - /// - pub unsafe fn get_data<'a, T>(&'a self, key: &str) -> PamResult<&'a T> { - let c_key = CString::new(key).unwrap(); - let mut ptr: *const PamDataT = ptr::null(); - let res = pam_get_data(self, c_key.as_ptr(), &mut ptr); - if PamResultCode::PAM_SUCCESS == res && !ptr.is_null() { - let typed_ptr: *const T = ptr as *const T; - let data: &T = &*typed_ptr; - Ok(data) - } else { - Err(res) - } - } - - /// Stores a value that can be retrieved later with `get_data`. The value lives - /// as long as the current pam cycle. - /// - /// See `pam_set_data` in - /// - pub fn set_data(&self, key: &str, data: Box) -> PamResult<()> { - let c_key = CString::new(key).unwrap(); - let res = unsafe { - let c_data: Box = mem::transmute(data); - let c_data = Box::into_raw(c_data); - pam_set_data(self, c_key.as_ptr(), c_data, cleanup::) - }; - if PamResultCode::PAM_SUCCESS == res { - Ok(()) - } else { - Err(res) - } - } - - /// Retrieves a value that has been set, possibly by the pam client. This is - /// particularly useful for getting a `PamConv` reference. - /// - /// See `pam_get_item` in - /// - pub fn get_item<'a, T: PamItem>(&self) -> PamResult<&'a T> { - let mut ptr: *const PamItemT = ptr::null(); - let (res, item) = unsafe { - let r = pam_get_item(self, T::item_type(), &mut ptr); - let typed_ptr: *const T = ptr as *const T; - let t: &T = &*typed_ptr; - (r, t) - }; - if PamResultCode::PAM_SUCCESS == res { - Ok(item) - } else { - Err(res) - } - } - - /// Sets a value in the pam context. The value can be retrieved using - /// `get_item`. - /// - /// Note that all items are strings, except `PAM_CONV` and `PAM_FAIL_DELAY`. - /// - /// See `pam_set_item` in - /// - pub fn set_item_str(&mut self, item: &str) -> PamResult<()> { - let c_item = CString::new(item).unwrap(); - - let res = unsafe { - pam_set_item( - self, - T::item_type(), - // unwrapping is okay here, as c_item will not be a NULL - // pointer - (c_item.as_ptr() as *const PamItemT).as_ref().unwrap(), - ) - }; - if PamResultCode::PAM_SUCCESS == res { - Ok(()) - } else { - Err(res) - } - } - - /// Retrieves the name of the user who is authenticating or logging in. - /// - /// This is really a specialization of `get_item`. - /// - /// See `pam_get_user` in - /// - pub fn get_user(&self, prompt: Option<&str>) -> PamResult { - let ptr: *mut c_char = ptr::null_mut(); - let res = match prompt { - Some(p) => { - let c_prompt = CString::new(p).unwrap(); - unsafe { pam_get_user(self, &ptr, c_prompt.as_ptr()) } - } - None => unsafe { pam_get_user(self, &ptr, ptr::null()) }, - }; - - if PamResultCode::PAM_SUCCESS == res && !ptr.is_null() { - let const_ptr = ptr as *const c_char; - let bytes = unsafe { CStr::from_ptr(const_ptr).to_bytes() }; - String::from_utf8(bytes.to_vec()) - .map_err(|_| PamResultCode::PAM_CONV_ERR) - } else { - Err(res) - } - } - - pub fn get_authtok(&self) -> PamResult> { - let mut ptr: *const PamItemT = ptr::null(); - let (res, item) = unsafe { - let r = pam_get_item(self, PAM_AUTHTOK, &mut ptr); - let t = if PamResultCode::PAM_SUCCESS == r && !ptr.is_null() { - let typed_ptr: *const c_char = ptr as *const c_char; - Some(CStr::from_ptr(typed_ptr).to_string_lossy().into_owned()) - } else { - None - }; - (r, t) - }; - if PamResultCode::PAM_SUCCESS == res { - Ok(item) - } else { - Err(res) - } - } - - pub fn get_tty(&self) -> PamResult> { - let mut ptr: *const PamItemT = ptr::null(); - let (res, item) = unsafe { - let r = pam_get_item(self, PAM_TTY, &mut ptr); - let t = if PamResultCode::PAM_SUCCESS == r && !ptr.is_null() { - let typed_ptr: *const c_char = ptr as *const c_char; - Some(CStr::from_ptr(typed_ptr).to_string_lossy().into_owned()) - } else { - None - }; - (r, t) - }; - if PamResultCode::PAM_SUCCESS == res { - Ok(item) - } else { - Err(res) - } - } - - pub fn get_rhost(&self) -> PamResult> { - let mut ptr: *const PamItemT = ptr::null(); - let (res, item) = unsafe { - let r = pam_get_item(self, PAM_RHOST, &mut ptr); - let t = if PamResultCode::PAM_SUCCESS == r && !ptr.is_null() { - let typed_ptr: *const c_char = ptr as *const c_char; - Some(CStr::from_ptr(typed_ptr).to_string_lossy().into_owned()) - } else { - None - }; - (r, t) - }; - if PamResultCode::PAM_SUCCESS == res { - Ok(item) - } else { - Err(res) - } - } -} - -/// Provides functions that are invoked by the entrypoints generated by the -/// [`pam_hooks!` macro](../macro.pam_hooks.html). -/// -/// All of hooks are ignored by PAM dispatch by default given the default return value of `PAM_IGNORE`. -/// Override any functions that you want to handle with your module. See `man pam(3)`. -#[allow(unused_variables)] -pub trait PamHooks { - /// This function performs the task of establishing whether the user is permitted to gain access at - /// this time. It should be understood that the user has previously been validated by an - /// authentication module. This function checks for other things. Such things might be: the time of - /// day or the date, the terminal line, remote hostname, etc. This function may also determine - /// things like the expiration on passwords, and respond that the user change it before continuing. - fn acct_mgmt( - pamh: &PamHandle, - args: Vec<&CStr>, - flags: PamFlag, - ) -> PamResultCode { - PamResultCode::PAM_IGNORE - } - - /// This function performs the task of authenticating the user. - fn sm_authenticate( - pamh: &PamHandle, - args: Vec<&CStr>, - flags: PamFlag, - ) -> PamResultCode { - PamResultCode::PAM_IGNORE - } - - /// This function is used to (re-)set the authentication token of the user. - /// - /// The PAM library calls this function twice in succession. The first time with - /// PAM_PRELIM_CHECK and then, if the module does not return PAM_TRY_AGAIN, subsequently with - /// PAM_UPDATE_AUTHTOK. It is only on the second call that the authorization token is - /// (possibly) changed. - fn sm_chauthtok( - pamh: &PamHandle, - args: Vec<&CStr>, - flags: PamFlag, - ) -> PamResultCode { - PamResultCode::PAM_IGNORE - } - - /// This function is called to terminate a session. - fn sm_close_session( - pamh: &PamHandle, - args: Vec<&CStr>, - flags: PamFlag, - ) -> PamResultCode { - PamResultCode::PAM_IGNORE - } - - /// This function is called to commence a session. - fn sm_open_session( - pamh: &PamHandle, - args: Vec<&CStr>, - flags: PamFlag, - ) -> PamResultCode { - PamResultCode::PAM_IGNORE - } - - /// This function performs the task of altering the credentials of the user with respect to the - /// corresponding authorization scheme. Generally, an authentication module may have access to more - /// information about a user than their authentication token. This function is used to make such - /// information available to the application. It should only be called after the user has been - /// authenticated but before a session has been established. - fn sm_setcred( - pamh: &PamHandle, - args: Vec<&CStr>, - flags: PamFlag, - ) -> PamResultCode { - PamResultCode::PAM_IGNORE - } -} diff --git a/rust/param/Cargo.toml b/rust/param/Cargo.toml deleted file mode 100644 index e90e500d7f5..00000000000 --- a/rust/param/Cargo.toml +++ /dev/null @@ -1,15 +0,0 @@ -[package] -name = "param" -edition.workspace = true -license.workspace = true -homepage.workspace = true -version.workspace = true - -[dependencies] -chelps = { workspace = true } -dbg.workspace = true -ntstatus_gen.workspace = true -paste = "1.0.15" - -[build-dependencies] -bindgen = "0.69.4" diff --git a/rust/param/build.rs b/rust/param/build.rs deleted file mode 100644 index 6d533e3b3db..00000000000 --- a/rust/param/build.rs +++ /dev/null @@ -1,53 +0,0 @@ -use std::env; -use std::path::PathBuf; - -fn main() { - let bindings = bindgen::Builder::default() - .blocklist_function("qgcvt") - .blocklist_function("qgcvt_r") - .blocklist_function("qfcvt") - .blocklist_function("qfcvt_r") - .blocklist_function("qecvt") - .blocklist_function("qecvt_r") - .blocklist_function("strtold") - .clang_arg("-Dbool=int") - .clang_arg("-Doffset_t=loff_t") - .clang_arg("-I../../bin/default") - .clang_arg("-I../../lib/talloc") - .generate_comments(false) - .clang_arg("-includestdint.h") - .header("../../lib/param/param.h") - .header("../../lib/param/loadparm.h") - .header("../../source3/param/loadparm.h") - .header("../../bin/default/lib/param/param_functions.h") - .parse_callbacks(Box::new(bindgen::CargoCallbacks::new())) - .generate() - .expect("Unable to generate bindings"); - println!("cargo:rerun-if-changed=../../lib/param/param.h"); - println!("cargo:rerun-if-changed=../../lib/param/loadparm.h"); - println!("cargo:rerun-if-changed=../../source3/param/loadparm.h"); - println!( - "cargo:rerun-if-changed=../../bin/default/lib/param/param_functions.h" - ); - - let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); - bindings - .write_to_file(out_path.join("bindings.rs")) - .expect("Couldn't write bindings!"); - - let mut src_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()); - src_dir.push("../../bin/default/source3"); - println!( - "cargo:rustc-link-search=native={}", - src_dir.to_str().unwrap() - ); - println!("cargo:rustc-link-lib=smbconf"); - - let mut src_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()); - src_dir.push("../../bin/default/lib/param"); - println!("cargo:rustc-link-lib=samba-hostconfig-private-samba"); - println!( - "cargo:rustc-link-search=native={}", - src_dir.to_str().unwrap() - ); -} diff --git a/rust/param/src/lib.rs b/rust/param/src/lib.rs deleted file mode 100644 index 38e27288119..00000000000 --- a/rust/param/src/lib.rs +++ /dev/null @@ -1,201 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Parameter loading functions - - Copyright (C) David Mulder 2024 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -use chelps::{string_free, wrap_c_char, wrap_string}; -use dbg::{DBG_ERR, DBG_INFO, DBG_WARNING}; -use ntstatus_gen::NT_STATUS_UNSUCCESSFUL; -use std::error::Error; -use std::ffi::c_void; -use std::ptr; -use std::sync::{Arc, Mutex}; - -mod ffi { - #![allow(non_upper_case_globals)] - #![allow(non_camel_case_types)] - #![allow(non_snake_case)] - #![allow(dead_code)] - #![allow(clippy::upper_case_acronyms)] - include!(concat!(env!("OUT_DIR"), "/bindings.rs")); -} - -pub struct LoadParm { - lp: Arc>, -} - -macro_rules! lpcfg_str { - ($var:ident) => { - paste::item! { - pub fn $var (&self) -> Result, Box> { - let lp = self.lp.lock()?; - let val = unsafe { ffi::[< lpcfg_ $var >] (*lp) } ; - unsafe { Ok(wrap_c_char(val)) } - } - } - }; -} - -macro_rules! lpcfg_i32 { - ($var:ident) => { - paste::item! { - pub fn $var (&self) -> Result> { - let lp = self.lp.lock()?; - unsafe { Ok(ffi::[< lpcfg_ $var >] (*lp)) } - } - } - }; -} - -macro_rules! lpcfg_bool { - ($var:ident) => { - paste::item! { - pub fn $var (&self) -> Result> { - let lp = self.lp.lock()?; - unsafe { Ok(ffi::[< lpcfg_ $var >] (*lp) != 0) } - } - } - }; -} - -impl LoadParm { - pub fn new(configfile: Option<&str>) -> Result> { - let lp = unsafe { - match configfile { - Some(configfile) => { - let configfile_cstr = wrap_string(configfile); - let lp = ffi::loadparm_init_global(0); - if ffi::lpcfg_load(lp, configfile_cstr) != 1 { - return Err(Box::new(NT_STATUS_UNSUCCESSFUL)); - } - string_free(configfile_cstr); - lp - } - None => ffi::loadparm_init_global(1), - } - }; - Ok(LoadParm { - lp: Arc::new(Mutex::new(lp)), - }) - } - - pub fn private_path( - &self, - name: &str, - ) -> Result, Box> { - let lp = self.lp.lock()?; - let path = unsafe { - let name_cstr = wrap_string(name); - let path = - ffi::lpcfg_private_path(*lp as *mut c_void, *lp, name_cstr); - string_free(name_cstr); - path - }; - unsafe { Ok(wrap_c_char(path)) } - } - - pub fn logfile(&self) -> Result, Box> { - let lp = self.lp.lock()?; - let logfile = unsafe { - let lp_sub = ffi::lpcfg_noop_substitution(); - ffi::lpcfg_logfile(*lp, lp_sub, *lp as *mut c_void) - }; - unsafe { Ok(wrap_c_char(logfile)) } - } - - pub fn idmap_range( - &self, - domain_name: &str, - ) -> Result<(u32, u32), Box> { - if let Ok(Some(backend)) = self.idmap_backend(domain_name) { - if backend != "upn" { - DBG_ERR!("Backend '{}' is not supported for Entra ID", backend); - return Err(Box::new(NT_STATUS_UNSUCCESSFUL)); - } - } else if domain_name != "*" { - DBG_WARNING!( - "No idmap backend configured for domain '{}'", - domain_name - ); - DBG_INFO!("Falling back to default idmap configuration"); - return self.idmap_range("*"); - } else { - DBG_WARNING!("No idmap backend configured"); - return Err(Box::new(NT_STATUS_UNSUCCESSFUL)); - } - let lp = self.lp.lock()?; - let parm_name = format!("idmap config {}", domain_name); - let parm_opt = "range"; - let range = unsafe { - let parm_name_cstr = wrap_string(&parm_name); - let parm_opt_cstr = wrap_string(parm_opt); - let parm_opt_value = ffi::lpcfg_parm_string( - *lp, - ptr::null_mut(), - parm_name_cstr, - parm_opt_cstr, - ); - string_free(parm_name_cstr); - string_free(parm_opt_cstr); - wrap_c_char(parm_opt_value) - } - .ok_or(Box::new(NT_STATUS_UNSUCCESSFUL))?; - let parts: Vec<&str> = range.split('-').collect(); - if parts.len() != 2 { - DBG_ERR!("Failed to parse the idmap range: {}", range); - return Err(Box::new(NT_STATUS_UNSUCCESSFUL)); - } - Ok((parts[0].parse::()?, parts[1].parse::()?)) - } - - pub fn idmap_backend( - &self, - domain_name: &str, - ) -> Result, Box> { - let lp = self.lp.lock()?; - let parm_name = format!("idmap config {}", domain_name); - let parm_opt = "backend"; - unsafe { - let parm_name_cstr = wrap_string(&parm_name); - let parm_opt_cstr = wrap_string(parm_opt); - let parm_opt_value = ffi::lpcfg_parm_string( - *lp, - ptr::null_mut(), - parm_name_cstr, - parm_opt_cstr, - ); - string_free(parm_name_cstr); - string_free(parm_opt_cstr); - Ok(wrap_c_char(parm_opt_value)) - } - } - - lpcfg_str!(realm); - lpcfg_str!(winbindd_socket_directory); - lpcfg_i32!(winbind_request_timeout); - lpcfg_bool!(himmelblaud_sfa_fallback); - lpcfg_bool!(himmelblaud_hello_enabled); - lpcfg_str!(cache_directory); - lpcfg_str!(template_homedir); - lpcfg_str!(template_shell); - lpcfg_str!(himmelblaud_hsm_pin_path); -} - -unsafe impl Send for LoadParm {} -unsafe impl Sync for LoadParm {} diff --git a/rust/rustfmt.toml b/rust/rustfmt.toml deleted file mode 100644 index fee2c90a695..00000000000 --- a/rust/rustfmt.toml +++ /dev/null @@ -1,2 +0,0 @@ -# Lightly enforce maximum 80 characters -max_width = 80 diff --git a/rust/sock/Cargo.toml b/rust/sock/Cargo.toml deleted file mode 100644 index be649bee9b4..00000000000 --- a/rust/sock/Cargo.toml +++ /dev/null @@ -1,16 +0,0 @@ -[package] -name = "sock" -edition.workspace = true -license.workspace = true -homepage.workspace = true -version.workspace = true - -[dependencies] -chelps.workspace = true -dbg.workspace = true -libc.workspace = true -libnss = "0.8.0" -ntstatus_gen.workspace = true -param.workspace = true -serde = { version = "1.0.204", features = ["derive"] } -serde_json = "1.0.120" diff --git a/rust/sock/src/lib.rs b/rust/sock/src/lib.rs deleted file mode 100644 index 9ccddde5027..00000000000 --- a/rust/sock/src/lib.rs +++ /dev/null @@ -1,141 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Unix socket communication for the Himmelblau daemon - - Copyright (C) David Mulder 2024 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -mod proto; -pub use proto::*; - -use dbg::DBG_ERR; -use ntstatus_gen::*; -use param::LoadParm; -use serde_json::{from_slice as json_from_slice, to_vec as json_to_vec}; -use std::error::Error; -use std::io::{Read, Write}; -use std::os::unix::net::UnixStream; -use std::path::{Path, PathBuf}; -use std::time::{Duration, SystemTime}; - -pub struct ClientStream { - stream: UnixStream, -} - -impl ClientStream { - pub fn new(path: &str) -> Result> { - Ok(ClientStream { - stream: UnixStream::connect(path) - .map_err(|e| { - DBG_ERR!("Unix socket stream setup error while connecting to {}: {:?}", - path, e - ); - e - })?, - }) - } - - pub fn send( - &mut self, - req: &Request, - timeout: u64, - ) -> Result> { - // Set the timeout - let timeout = Duration::from_secs(timeout); - self.stream.set_read_timeout(Some(timeout))?; - self.stream.set_write_timeout(Some(timeout))?; - - // Encode the request as bytes - let req_bytes = json_to_vec(req)?; - - // Send the request - self.stream.write_all(&req_bytes)?; - - // Now wait on the response - let start = SystemTime::now(); - let mut read_started = false; - let mut data = Vec::with_capacity(1024); - let mut counter = 0; - - loop { - let mut buffer = [0; 1024]; - let durr = - SystemTime::now().duration_since(start).map_err(Box::new)?; - if durr > timeout { - DBG_ERR!("Socket timeout"); - break; - } - match self.stream.read(&mut buffer) { - Ok(0) => { - if read_started { - break; - } else { - continue; - } - } - Ok(count) => { - data.extend_from_slice(&buffer); - counter += count; - if count == 1024 { - read_started = true; - continue; - } else { - break; - } - } - Err(e) => { - DBG_ERR!( - "Stream read failure from {:?}: {:?}", - &self.stream, - e - ); - return Err(Box::new(e)); - } - } - } - - data.truncate(counter); - - // Now decode the response - let resp: Response = json_from_slice(data.as_slice())?; - Ok(resp) - } -} - -pub fn stream_and_timeout( - lp: &LoadParm, -) -> Result<(ClientStream, u64), Box> { - // Get the socket path - let sock_dir_str = lp - .winbindd_socket_directory() - .map_err(|_| Box::new(NT_STATUS_NOT_FOUND))? - .ok_or(Box::new(NT_STATUS_NOT_FOUND))?; - let sock_dir = Path::new(&sock_dir_str); - let mut sock_path = PathBuf::from(sock_dir); - sock_path.push("hb_pipe"); - let sock_path = sock_path.to_str().ok_or(Box::new(NT_STATUS_NOT_FOUND))?; - - // Open the socket - let timeout: u64 = lp - .winbind_request_timeout() - .map_err(|_| Box::new(NT_STATUS_NOT_FOUND))? - .try_into() - .map_err(|_| Box::new(NT_STATUS_NOT_FOUND))?; - let stream = ClientStream::new(sock_path) - .map_err(|_| Box::new(NT_STATUS_PIPE_NOT_AVAILABLE))?; - Ok((stream, timeout)) -} diff --git a/rust/sock/src/proto.rs b/rust/sock/src/proto.rs deleted file mode 100644 index 728637ac807..00000000000 --- a/rust/sock/src/proto.rs +++ /dev/null @@ -1,116 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Unix socket communication for the Himmelblau daemon - - Copyright (C) David Mulder 2024 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -use libc::uid_t; -use libnss::group::Group as NssGroup; -use libnss::passwd::Passwd as NssPasswd; -use serde::{Deserialize, Serialize}; - -#[derive(Debug, Serialize, Deserialize)] -pub struct Passwd { - pub name: String, - pub passwd: String, - pub uid: u32, - pub gid: u32, - pub gecos: String, - pub dir: String, - pub shell: String, -} - -impl From for NssPasswd { - fn from(val: Passwd) -> Self { - NssPasswd { - name: val.name, - passwd: val.passwd, - uid: val.uid, - gid: val.gid, - gecos: val.gecos, - dir: val.dir, - shell: val.shell, - } - } -} - -#[derive(Debug, Serialize, Deserialize)] -pub struct Group { - pub name: String, - pub passwd: String, - pub gid: u32, - pub members: Vec, -} - -impl From for NssGroup { - fn from(val: Group) -> Self { - NssGroup { - name: val.name, - passwd: val.passwd, - gid: val.gid, - members: val.members, - } - } -} - -#[derive(Serialize, Deserialize)] -pub enum PamAuthRequest { - Password { cred: String }, - MFACode { cred: String }, - MFAPoll { poll_attempt: u32 }, - SetupPin { pin: String }, - Pin { pin: String }, -} - -#[derive(Serialize, Deserialize)] -pub enum Request { - NssAccounts, - NssAccountByUid(uid_t), - NssAccountByName(String), - NssGroups, - NssGroupByGid(uid_t), - NssGroupByName(String), - PamAuthenticateInit(String), - PamAuthenticateStep(PamAuthRequest), - PamAccountAllowed(String), - PamAccountBeginSession(String), -} - -#[derive(Debug, Serialize, Deserialize)] -pub enum PamAuthResponse { - Unknown, - Success, - Denied, - Password, - MFACode { msg: String }, - MFAPoll { msg: String, polling_interval: u32 }, - MFAPollWait, - SetupPin { msg: String }, - Pin, -} - -#[derive(Debug, Serialize, Deserialize)] -pub enum Response { - NssAccounts(Vec), - NssAccount(Option), - NssGroups(Vec), - NssGroup(Option), - PamStatus(Option), - PamAuthStepResponse(PamAuthResponse), - Success, - Error, -} diff --git a/rust/talloc/Cargo.toml b/rust/talloc/Cargo.toml deleted file mode 100644 index a21b3da9ad3..00000000000 --- a/rust/talloc/Cargo.toml +++ /dev/null @@ -1,13 +0,0 @@ -[package] -name = "talloc" -edition.workspace = true -license.workspace = true -homepage.workspace = true -version.workspace = true - -[build-dependencies] -bindgen = "0.69.4" -config.workspace = true - -[dependencies] -chelps.workspace = true diff --git a/rust/talloc/build.rs b/rust/talloc/build.rs deleted file mode 100644 index d14b0b045e9..00000000000 --- a/rust/talloc/build.rs +++ /dev/null @@ -1,38 +0,0 @@ -use std::env; -use std::path::PathBuf; - -fn main() { - let bindings = bindgen::Builder::default() - .blocklist_function("qgcvt") - .blocklist_function("qgcvt_r") - .blocklist_function("qfcvt") - .blocklist_function("qfcvt_r") - .blocklist_function("qecvt") - .blocklist_function("qecvt_r") - .blocklist_function("strtold") - .clang_arg("-Dbool=int") - .generate_comments(false) - .clang_arg("-I../../lib/talloc") - .header("../../lib/util/talloc_stack.h") - .parse_callbacks(Box::new(bindgen::CargoCallbacks::new())) - .generate() - .expect("Unable to generate bindings"); - println!("cargo:rerun-if-changed=../../lib/util/talloc_stack.h"); - - let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); - bindings - .write_to_file(out_path.join("bindings.rs")) - .expect("Couldn't write bindings!"); - - let mut src_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()); - src_dir.push("../../bin/default/lib/talloc"); - if config::USING_SYSTEM_TALLOC == 1 { - println!("cargo:rustc-link-lib=talloc"); - } else { - println!("cargo:rustc-link-lib=talloc-private-samba"); - } - println!( - "cargo:rustc-link-search=native={}", - src_dir.to_str().unwrap() - ); -} diff --git a/rust/talloc/src/lib.rs b/rust/talloc/src/lib.rs deleted file mode 100644 index c2eef6f93dd..00000000000 --- a/rust/talloc/src/lib.rs +++ /dev/null @@ -1,56 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Talloc stackframe functions - - Copyright (C) David Mulder 2024 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -pub mod ffi { - #![allow(non_upper_case_globals)] - #![allow(non_camel_case_types)] - #![allow(non_snake_case)] - #![allow(dead_code)] - #![allow(clippy::upper_case_acronyms)] - include!(concat!(env!("OUT_DIR"), "/bindings.rs")); -} - -#[macro_export] -macro_rules! talloc_stackframe { - () => {{ - let function = chelps::function!(); - let function_cstr = chelps::wrap_string(&function); - unsafe { - let ret = $crate::ffi::_talloc_stackframe(function_cstr); - chelps::string_free(function_cstr); - ret - } - }}; -} - -#[macro_export] -macro_rules! TALLOC_FREE { - ($ctx:ident) => {{ - if !$ctx.is_null() { - let function = chelps::function!(); - let function_cstr = chelps::wrap_string(&function); - unsafe { - $crate::ffi::_talloc_free($ctx, function_cstr); - chelps::string_free(function_cstr); - } - } - }}; -} diff --git a/rust/tdb/Cargo.toml b/rust/tdb/Cargo.toml deleted file mode 100644 index aad1c727d11..00000000000 --- a/rust/tdb/Cargo.toml +++ /dev/null @@ -1,16 +0,0 @@ -[package] -name = "tdb" -edition.workspace = true -license.workspace = true -homepage.workspace = true -version.workspace = true - -[dependencies] -chelps = { workspace = true } -dbg.workspace = true -libc.workspace = true -ntstatus_gen.workspace = true - -[build-dependencies] -bindgen = "0.69.4" -config.workspace = true diff --git a/rust/tdb/build.rs b/rust/tdb/build.rs deleted file mode 100644 index 57ee90aa8d4..00000000000 --- a/rust/tdb/build.rs +++ /dev/null @@ -1,35 +0,0 @@ -use std::env; -use std::path::PathBuf; - -fn main() { - let bindings = bindgen::Builder::default() - .blocklist_function("qgcvt") - .blocklist_function("qgcvt_r") - .blocklist_function("qfcvt") - .blocklist_function("qfcvt_r") - .blocklist_function("qecvt") - .blocklist_function("qecvt_r") - .blocklist_function("strtold") - .clang_arg("-includesys/stat.h") - .header("../../lib/tdb/include/tdb.h") - .parse_callbacks(Box::new(bindgen::CargoCallbacks::new())) - .generate() - .expect("Unable to generate bindings"); - - let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); - bindings - .write_to_file(out_path.join("bindings.rs")) - .expect("Couldn't write bindings!"); - - let mut src_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()); - src_dir.push("../../bin/default/lib/tdb"); - if config::USING_SYSTEM_TDB == 1 { - println!("cargo:rustc-link-lib=tdb"); - } else { - println!("cargo:rustc-link-lib=tdb-private-samba"); - } - println!( - "cargo:rustc-link-search=native={}", - src_dir.to_str().unwrap() - ); -} diff --git a/rust/tdb/src/lib.rs b/rust/tdb/src/lib.rs deleted file mode 100644 index cb9af44d8ed..00000000000 --- a/rust/tdb/src/lib.rs +++ /dev/null @@ -1,260 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - trivial database library FFI - - Copyright (C) David Mulder 2024 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -use chelps::wrap_string; -use dbg::DBG_ERR; -use libc::free; -use ntstatus_gen::NT_STATUS_UNSUCCESSFUL; -use std::error::Error; -use std::ffi::c_void; -use std::fmt; -use std::path::PathBuf; -use std::sync::{Arc, Mutex}; - -mod ffi { - #![allow(non_upper_case_globals)] - #![allow(non_camel_case_types)] - #![allow(non_snake_case)] - #![allow(dead_code)] - #![allow(clippy::upper_case_acronyms)] - include!(concat!(env!("OUT_DIR"), "/bindings.rs")); -} - -pub const TDB_SUCCESS: ffi::TDB_ERROR = ffi::TDB_ERROR_TDB_SUCCESS; -pub const TDB_ERR_CORRUPT: ffi::TDB_ERROR = ffi::TDB_ERROR_TDB_ERR_CORRUPT; -pub const TDB_ERR_IO: ffi::TDB_ERROR = ffi::TDB_ERROR_TDB_ERR_IO; -pub const TDB_ERR_LOCK: ffi::TDB_ERROR = ffi::TDB_ERROR_TDB_ERR_LOCK; -pub const TDB_ERR_OOM: ffi::TDB_ERROR = ffi::TDB_ERROR_TDB_ERR_OOM; -pub const TDB_ERR_EXISTS: ffi::TDB_ERROR = ffi::TDB_ERROR_TDB_ERR_EXISTS; -pub const TDB_ERR_NOLOCK: ffi::TDB_ERROR = ffi::TDB_ERROR_TDB_ERR_NOLOCK; -pub const TDB_ERR_LOCK_TIMEOUT: ffi::TDB_ERROR = - ffi::TDB_ERROR_TDB_ERR_LOCK_TIMEOUT; -pub const TDB_ERR_NOEXIST: ffi::TDB_ERROR = ffi::TDB_ERROR_TDB_ERR_NOEXIST; -pub const TDB_ERR_EINVAL: ffi::TDB_ERROR = ffi::TDB_ERROR_TDB_ERR_EINVAL; -pub const TDB_ERR_RDONLY: ffi::TDB_ERROR = ffi::TDB_ERROR_TDB_ERR_RDONLY; -pub const TDB_ERR_NESTING: ffi::TDB_ERROR = ffi::TDB_ERROR_TDB_ERR_NESTING; - -#[allow(non_camel_case_types)] -#[derive(PartialEq, Eq)] -pub struct TDB_ERROR(pub u32); - -impl TDB_ERROR { - fn description(&self) -> &str { - match self.0 { - ffi::TDB_ERROR_TDB_SUCCESS => "TDB_SUCCESS", - ffi::TDB_ERROR_TDB_ERR_CORRUPT => "TDB_ERR_CORRUPT", - ffi::TDB_ERROR_TDB_ERR_IO => "TDB_ERR_IO", - ffi::TDB_ERROR_TDB_ERR_LOCK => "TDB_ERR_LOCK", - ffi::TDB_ERROR_TDB_ERR_OOM => "TDB_ERR_OOM", - ffi::TDB_ERROR_TDB_ERR_EXISTS => "TDB_ERR_EXISTS", - ffi::TDB_ERROR_TDB_ERR_NOLOCK => "TDB_ERR_NOLOCK", - ffi::TDB_ERROR_TDB_ERR_LOCK_TIMEOUT => "TDB_ERR_LOCK_TIMEOUT", - ffi::TDB_ERROR_TDB_ERR_NOEXIST => "TDB_ERR_NOEXIST", - ffi::TDB_ERROR_TDB_ERR_EINVAL => "TDB_ERR_EINVAL", - ffi::TDB_ERROR_TDB_ERR_RDONLY => "TDB_ERR_RDONLY", - ffi::TDB_ERROR_TDB_ERR_NESTING => "TDB_ERR_NESTING", - _ => "Unknown TDB_ERROR error code", - } - } -} - -macro_rules! lock_check { - ($res:expr) => {{ - $res.map_err(|e| { - DBG_ERR!("Failed to obtain tdb lock: {:?}", e); - Box::new(TDB_ERROR(TDB_ERR_NOLOCK)) - })? - }}; -} - -impl fmt::Display for TDB_ERROR { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "TDB_ERROR({:#x}): {}", self.0, self.description()) - } -} - -impl fmt::Debug for TDB_ERROR { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "TDB_ERROR({:#x})", self.0) - } -} - -impl std::error::Error for TDB_ERROR {} - -#[derive(Clone)] -pub struct Tdb { - tdb: Arc>, -} - -impl Tdb { - pub fn open( - name: &str, - hash_size: Option, - tdb_flags: Option, - open_flags: Option, - mode: Option, - ) -> Result> { - let path = PathBuf::from(name); - let tdb = unsafe { - ffi::tdb_open( - wrap_string(name), - hash_size.unwrap_or(0), - tdb_flags.unwrap_or(ffi::TDB_DEFAULT as i32), - match open_flags { - Some(open_flags) => open_flags, - None => { - if path.exists() { - libc::O_RDWR - } else { - libc::O_RDWR | libc::O_CREAT - } - } - }, - mode.unwrap_or(0o600), - ) - }; - if tdb.is_null() { - return Err(Box::new(NT_STATUS_UNSUCCESSFUL)); - } - Ok(Tdb { - tdb: Arc::new(Mutex::new(tdb)), - }) - } - - pub fn transaction_start(&mut self) -> Result> { - let tdb = self.tdb.lock()?; - unsafe { Ok(ffi::tdb_transaction_start(*tdb) == 0) } - } - - pub fn transaction_commit(&mut self) -> Result> { - let tdb = self.tdb.lock()?; - unsafe { Ok(ffi::tdb_transaction_commit(*tdb) == 0) } - } - - pub fn transaction_cancel(&mut self) -> Result> { - let tdb = self.tdb.lock()?; - unsafe { Ok(ffi::tdb_transaction_cancel(*tdb) == 0) } - } - - pub fn exists(&self, key: &str) -> Result> { - let tdb = lock_check!(self.tdb.lock()); - let key = ffi::TDB_DATA { - dptr: wrap_string(key) as *mut u8, - dsize: key.len(), - }; - unsafe { Ok(ffi::tdb_exists(*tdb, key) == 1) } - } - - pub fn fetch(&self, key: &str) -> Result> { - let tdb = self.tdb.lock()?; - let key = ffi::TDB_DATA { - dptr: wrap_string(key) as *mut u8, - dsize: key.len(), - }; - let res = unsafe { ffi::tdb_fetch(*tdb, key) }; - if res.dptr.is_null() { - let err = unsafe { ffi::tdb_error(*tdb) }; - return Err(Box::new(TDB_ERROR(err))); - } - Ok(unsafe { - std::str::from_utf8_unchecked(std::slice::from_raw_parts( - res.dptr, res.dsize, - )) - } - .to_string()) - } - - pub fn delete(&mut self, key: &str) -> Result> { - let tdb = self.tdb.lock()?; - let key = ffi::TDB_DATA { - dptr: wrap_string(key) as *mut u8, - dsize: key.len(), - }; - unsafe { Ok(ffi::tdb_delete(*tdb, key) == 0) } - } - - pub fn store( - &mut self, - key: &str, - dbuf: &[u8], - flag: Option, - ) -> Result> { - let tdb = self.tdb.lock()?; - let flag = match flag { - Some(flag) => flag, - None => ffi::TDB_REPLACE, - }; - let key = ffi::TDB_DATA { - dptr: wrap_string(key) as *mut u8, - dsize: key.len(), - }; - let dbuf = ffi::TDB_DATA { - dptr: dbuf.as_ptr() as *mut u8, - dsize: dbuf.len(), - }; - unsafe { Ok(ffi::tdb_store(*tdb, key, dbuf, flag as i32) == 0) } - } - - pub fn keys(&self) -> Result, Box> { - let mut res = Vec::new(); - let tdb = self.tdb.lock()?; - let mut key = unsafe { ffi::tdb_firstkey(*tdb) }; - if key.dptr.is_null() { - return Ok(res); - } - let rkey = unsafe { - std::str::from_utf8_unchecked(std::slice::from_raw_parts( - key.dptr, key.dsize, - )) - } - .to_string(); - res.push(rkey); - - loop { - let next = unsafe { ffi::tdb_nextkey(*tdb, key) }; - unsafe { free(key.dptr as *mut c_void) }; - if next.dptr.is_null() { - break; - } else { - let rkey = unsafe { - std::str::from_utf8_unchecked(std::slice::from_raw_parts( - next.dptr, next.dsize, - )) - } - .to_string(); - res.push(rkey); - } - key = next; - } - - Ok(res) - } -} - -impl Drop for Tdb { - fn drop(&mut self) { - let tdb = self.tdb.lock().unwrap(); - unsafe { ffi::tdb_close(*tdb) }; - } -} - -unsafe impl Send for Tdb {} -unsafe impl Sync for Tdb {} diff --git a/rust/version/Cargo.toml b/rust/version/Cargo.toml deleted file mode 100644 index 046dbd074ed..00000000000 --- a/rust/version/Cargo.toml +++ /dev/null @@ -1,18 +0,0 @@ -[package] -name = "version" -edition.workspace = true -license.workspace = true -homepage.workspace = true -version.workspace = true - -[lib] -name = "version" -path = "src/lib.rs" - -[dependencies] -chelps.workspace = true -libc.workspace = true - -[build-dependencies] -cc = "1.0.97" -bindgen = "0.69.4" diff --git a/rust/version/build.rs b/rust/version/build.rs deleted file mode 100644 index b426fd6c222..00000000000 --- a/rust/version/build.rs +++ /dev/null @@ -1,29 +0,0 @@ -use std::env; -use std::path::{Path, PathBuf}; - -fn main() { - cc::Build::new() - .file("../../source3/lib/version.c") - .include(Path::new("../../bin/default")) - .include(Path::new("./include")) // for the empty includes.h - .warnings(false) - .compile("version"); - - let bindings = bindgen::Builder::default() - .blocklist_function("qgcvt") - .blocklist_function("qgcvt_r") - .blocklist_function("qfcvt") - .blocklist_function("qfcvt_r") - .blocklist_function("qecvt") - .blocklist_function("qecvt_r") - .blocklist_function("strtold") - .header("../../bin/default/version.h") - .parse_callbacks(Box::new(bindgen::CargoCallbacks::new())) - .generate() - .expect("Unable to generate bindings"); - - let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); - bindings - .write_to_file(out_path.join("bindings.rs")) - .expect("Couldn't write bindings!"); -} diff --git a/rust/version/include/includes.h b/rust/version/include/includes.h deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/rust/version/src/lib.rs b/rust/version/src/lib.rs deleted file mode 100644 index d71a4aae641..00000000000 --- a/rust/version/src/lib.rs +++ /dev/null @@ -1,40 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Samba Version functions - - Copyright (C) David Mulder 2024 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -use std::str; - -include!(concat!(env!("OUT_DIR"), "/bindings.rs")); - -pub fn samba_version_string() -> Option { - let null_trimmed_vers = - &SAMBA_VERSION_STRING[..SAMBA_VERSION_STRING.len() - 1]; - match str::from_utf8(null_trimmed_vers) { - Ok(vers) => Some(vers.to_string()), - Err(_) => None, - } -} - -pub fn samba_copyright_string() -> Option { - let null_trimmed_copy = - &SAMBA_COPYRIGHT_STRING[..SAMBA_COPYRIGHT_STRING.len() - 1]; - match str::from_utf8(null_trimmed_copy) { - Ok(copy) => Some(copy.to_string()), - Err(_) => None, - } -} diff --git a/rust/wscript_build b/rust/wscript_build index 5e08c299f18..1ecfee24830 100644 --- a/rust/wscript_build +++ b/rust/wscript_build @@ -2,21 +2,4 @@ bld.vendor_sources() -if conf.env.enable_himmelblau: - bld.SAMBA_RUST_BINARY('himmelblaud', 'himmelblaud', - ['param', - 'chelps', - 'dbg', - 'ntstatus_gen', - 'sock', - 'tdb', - 'version', - 'idmap']) - bld.SAMBA_RUST_LIBRARY('nss', 'libnss_himmelblau.so', ['sock', - 'ntstatus_gen', - 'param', - 'version']) - bld.SAMBA_RUST_LIBRARY('pam', 'libpam_himmelblau.so', ['sock', - 'chelps', - 'param', - 'version']) +# There are no Rust integrations at the moment. If there were, they would be built here. diff --git a/script/autobuild.py b/script/autobuild.py index 8acf6cdc854..feaafebe9e2 100755 --- a/script/autobuild.py +++ b/script/autobuild.py @@ -178,16 +178,11 @@ builddirs = { ctdb_configure_params = " --enable-developer ${PREFIX}" samba_configure_params = " ${ENABLE_COVERAGE} ${PREFIX} --with-profiling-data --with-prometheus-exporter" -# We cannot configure himmelblau on old systems missing openssl 3, with glibc -# older than version 2.32, or when cargo isn't available. -himmelblau_configure_params = '' rust_configure_param = '' glibc_vers = float('.'.join(get_libc_version().split('.')[:2])) cargo = shutil.which('cargo') if glibc_vers >= 2.32 and cargo != None: rust_configure_param = ' --enable-rust' -if ssl.OPENSSL_VERSION_INFO[0] >= 3 and rust_configure_param: - himmelblau_configure_params = rust_configure_param + ' --with-himmelblau' samba_libs_envvars = "PYTHONPATH=${PYTHON_PREFIX}:$PYTHONPATH" samba_libs_envvars += " PKG_CONFIG_PATH=$PKG_CONFIG_PATH:${PREFIX_DIR}/lib/pkgconfig" @@ -854,7 +849,7 @@ tasks = { "samba-o3": { "sequence": [ ("random-sleep", random_sleep(300, 900)), - ("configure", "ADDITIONAL_CFLAGS='" + samba_o3_cflags + "' ./configure.developer --abi-check-disable" + himmelblau_configure_params + samba_configure_params), + ("configure", "ADDITIONAL_CFLAGS='" + samba_o3_cflags + "' ./configure.developer --abi-check-disable" + samba_configure_params), ("make", "make -j"), ("test", make_test(cmd='make test', TESTS="--exclude=selftest/slow-none", include_envs=["none"])), ("quicktest", make_test(cmd='make quicktest', include_envs=["ad_dc", "ad_dc_smb1", "ad_dc_smb1_done"])), diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index d8ee4002fab..5a0cb261824 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -1014,13 +1014,6 @@ 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; - Globals.server_smb_encryption_over_quic = true; Globals.client_smb_encryption_over_quic = true; diff --git a/wscript b/wscript index 7ce8cb875a0..f27863737fa 100644 --- a/wscript +++ b/wscript @@ -156,10 +156,6 @@ def options(opt): dest='SAMBA_VERSION_VENDOR_SUFFIX', default=None) - opt.add_option('--with-himmelblau', default=False, - help=('Build with Azure Entra ID support.'), - action='store_true', dest='enable_himmelblau') - opt.samba_add_onoff_option('systemd-userdb', help=("Build winbind with support for systemd " "User/Group Record Lookup API via " @@ -503,14 +499,6 @@ def configure(conf): conf.env.debug = Options.options.debug conf.env.developer = Options.options.developer - conf.env.enable_himmelblau = Options.options.enable_himmelblau - if Options.options.enable_himmelblau: - if not conf.env.enable_rust: - conf.fatal('--with-himmelblau cannot be specified without ' - '--enable-rust') - if ssl.OPENSSL_VERSION_INFO[0] < 3: - conf.fatal('--with-himmelblau cannot be specified with ' - '%s' % ssl.OPENSSL_VERSION) # # FreeBSD is broken. It doesn't include 'extern char **environ' -- 2.47.3