mirror of
https://github.com/kanidm/kanidm.git
synced 2025-05-20 16:03:55 +02:00
20231128 freeipa migration (#2338)
* Add more weak password formats for freeipa * Verification of freeipa migration from older ipa versions
This commit is contained in:
parent
bca2fbcf4e
commit
31b939fca3
150
Cargo.lock
generated
150
Cargo.lock
generated
|
@ -724,9 +724,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.4.8"
|
||||
version = "4.4.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2275f18819641850fa26c89acc84d465c1bf91ce57bc2748b28c420473352f64"
|
||||
checksum = "41fffed7514f420abec6d183b1d3acfd9099c79c3a10a06ade4f8203f1411272"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
|
@ -734,9 +734,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.4.8"
|
||||
version = "4.4.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07cdf1b148b25c1e1f7a42225e30a0d99a615cd4637eae7365548dd4529b95bc"
|
||||
checksum = "63361bae7eef3771745f02d8d892bec2fee5f6e34af316ba556e7f97a7069ff1"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
|
@ -1500,12 +1500,12 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
|||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
version = "0.3.7"
|
||||
version = "0.3.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f258a7194e7f7c2a7837a8913aeab7fd8c383457034fa20ce4dd3dcb813e8eb8"
|
||||
checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.48.0",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2067,7 +2067,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "409268480841ad008e81c17ca5a293393fbf9f2b6c2f85b8ab9de1f0c5176a16"
|
||||
dependencies = [
|
||||
"gix-hash",
|
||||
"hashbrown 0.14.2",
|
||||
"hashbrown 0.14.3",
|
||||
"parking_lot 0.12.1",
|
||||
]
|
||||
|
||||
|
@ -2564,9 +2564,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.14.2"
|
||||
version = "0.14.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156"
|
||||
checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
|
||||
dependencies = [
|
||||
"ahash 0.8.6",
|
||||
"allocator-api2",
|
||||
|
@ -2579,7 +2579,7 @@ version = "0.8.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7"
|
||||
dependencies = [
|
||||
"hashbrown 0.14.2",
|
||||
"hashbrown 0.14.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2855,7 +2855,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown 0.14.2",
|
||||
"hashbrown 0.14.3",
|
||||
"serde",
|
||||
]
|
||||
|
||||
|
@ -2955,9 +2955,9 @@ checksum = "bc0000e42512c92e31c2252315bda326620a4e034105e900c98ec492fa077b3e"
|
|||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.65"
|
||||
version = "0.3.66"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "54c0c35952f67de54bb584e9fd912b3023117cbafc0a77d8f3dee1fb5f572fe8"
|
||||
checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca"
|
||||
dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
@ -3179,7 +3179,7 @@ dependencies = [
|
|||
"compact_jwt 0.3.2",
|
||||
"csv",
|
||||
"futures",
|
||||
"hashbrown 0.14.2",
|
||||
"hashbrown 0.14.3",
|
||||
"kanidm-hsm-crypto",
|
||||
"kanidm_build_profiles",
|
||||
"kanidm_client",
|
||||
|
@ -3231,7 +3231,7 @@ dependencies = [
|
|||
"filetime",
|
||||
"futures",
|
||||
"futures-util",
|
||||
"hashbrown 0.14.2",
|
||||
"hashbrown 0.14.3",
|
||||
"http",
|
||||
"hyper",
|
||||
"kanidm_build_profiles",
|
||||
|
@ -3280,7 +3280,7 @@ dependencies = [
|
|||
"enum-iterator",
|
||||
"fernet",
|
||||
"futures",
|
||||
"hashbrown 0.14.2",
|
||||
"hashbrown 0.14.3",
|
||||
"hex",
|
||||
"idlset",
|
||||
"image 0.24.7",
|
||||
|
@ -3503,11 +3503,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ldap3_client"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a229cd5ee2a4e5a1a279b6216494aa2a5053a189c5ce37bb31f9156b63b63de"
|
||||
version = "0.4.2"
|
||||
dependencies = [
|
||||
"base64 0.13.1",
|
||||
"base64 0.21.5",
|
||||
"base64urlsafedata",
|
||||
"futures-util",
|
||||
"ldap3_proto",
|
||||
|
@ -3523,15 +3521,15 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ldap3_proto"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "93d073b5c98def43cec39ccd95e536b3b2448e36289222ecd64dfdf1389d1702"
|
||||
version = "0.4.2"
|
||||
dependencies = [
|
||||
"base64 0.21.5",
|
||||
"bytes",
|
||||
"lber",
|
||||
"nom",
|
||||
"peg",
|
||||
"serde",
|
||||
"thiserror",
|
||||
"tokio-util",
|
||||
"tracing",
|
||||
"uuid",
|
||||
|
@ -4259,7 +4257,7 @@ dependencies = [
|
|||
"csv",
|
||||
"dialoguer",
|
||||
"futures-util",
|
||||
"hashbrown 0.14.2",
|
||||
"hashbrown 0.14.3",
|
||||
"kanidm_build_profiles",
|
||||
"kanidm_client",
|
||||
"kanidm_proto",
|
||||
|
@ -4674,9 +4672,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068"
|
|||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.69"
|
||||
version = "1.0.70"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da"
|
||||
checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
@ -6358,9 +6356,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.88"
|
||||
version = "0.2.89"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7daec296f25a1bae309c0cd5c29c4b260e510e6d813c286b19eaadf409d40fce"
|
||||
checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"serde",
|
||||
|
@ -6370,9 +6368,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.88"
|
||||
version = "0.2.89"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e397f4664c0e4e428e8313a469aaa58310d302159845980fd23b0f22a847f217"
|
||||
checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"log",
|
||||
|
@ -6385,9 +6383,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-futures"
|
||||
version = "0.4.38"
|
||||
version = "0.4.39"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9afec9963e3d0994cac82455b2b3502b81a7f40f9a0d32181f7528d9f4b43e02"
|
||||
checksum = "ac36a15a220124ac510204aec1c3e5db8a22ab06fd6706d881dc6149f8ed9a12"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"js-sys",
|
||||
|
@ -6397,9 +6395,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.88"
|
||||
version = "0.2.89"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5961017b3b08ad5f3fe39f1e79877f8ee7c23c5e5fd5eb80de95abc41f1f16b2"
|
||||
checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
|
@ -6407,9 +6405,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.88"
|
||||
version = "0.2.89"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c5353b8dab669f5e10f5bd76df26a9360c748f054f862ff5f3f8aae0c7fb3907"
|
||||
checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -6420,15 +6418,15 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.88"
|
||||
version = "0.2.89"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0d046c5d029ba91a1ed14da14dca44b68bf2f124cfbaf741c54151fdb3e0750b"
|
||||
checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-test"
|
||||
version = "0.3.38"
|
||||
version = "0.3.39"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c6433b7c56db97397842c46b67e11873eda263170afeb3a2dc74a7cb370fee0d"
|
||||
checksum = "2cf9242c0d27999b831eae4767b2a146feb0b27d332d553e605864acd2afd403"
|
||||
dependencies = [
|
||||
"console_error_panic_hook",
|
||||
"js-sys",
|
||||
|
@ -6440,9 +6438,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-test-macro"
|
||||
version = "0.3.38"
|
||||
version = "0.3.39"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "493fcbab756bb764fa37e6bee8cec2dd709eb4273d06d0c282a5e74275ded735"
|
||||
checksum = "794645f5408c9a039fd09f4d113cdfb2e7eba5ff1956b07bcf701cf4b394fe89"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -6699,6 +6697,15 @@ 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.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.42.2"
|
||||
|
@ -6729,6 +6736,21 @@ dependencies = [
|
|||
"windows_x86_64_msvc 0.48.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm 0.52.0",
|
||||
"windows_aarch64_msvc 0.52.0",
|
||||
"windows_i686_gnu 0.52.0",
|
||||
"windows_i686_msvc 0.52.0",
|
||||
"windows_x86_64_gnu 0.52.0",
|
||||
"windows_x86_64_gnullvm 0.52.0",
|
||||
"windows_x86_64_msvc 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.41.0"
|
||||
|
@ -6747,6 +6769,12 @@ version = "0.48.5"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.41.0"
|
||||
|
@ -6765,6 +6793,12 @@ version = "0.48.5"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.41.0"
|
||||
|
@ -6783,6 +6817,12 @@ version = "0.48.5"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.41.0"
|
||||
|
@ -6801,6 +6841,12 @@ version = "0.48.5"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.41.0"
|
||||
|
@ -6819,6 +6865,12 @@ 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.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.41.0"
|
||||
|
@ -6837,6 +6889,12 @@ 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.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.41.0"
|
||||
|
@ -6855,6 +6913,12 @@ 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.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
|
||||
|
||||
[[package]]
|
||||
name = "winnow"
|
||||
version = "0.5.19"
|
||||
|
|
|
@ -148,8 +148,8 @@ js-sys = "^0.3.65"
|
|||
kanidmd_web_ui_shared = { path = "./server/web_ui/shared" }
|
||||
# REMOVE this
|
||||
lazy_static = "^1.4.0"
|
||||
ldap3_client = "^0.3.5"
|
||||
ldap3_proto = { version = "^0.3.5", features = ["serde"] }
|
||||
ldap3_client = "^0.4.2"
|
||||
ldap3_proto = { version = "^0.4.2", features = ["serde"] }
|
||||
|
||||
libc = "^0.2.150"
|
||||
libnss = "^0.4.0"
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#![deny(clippy::await_holding_lock)]
|
||||
#![deny(clippy::needless_pass_by_value)]
|
||||
#![deny(clippy::trivially_copy_pass_by_ref)]
|
||||
#![allow(clippy::unreachable)]
|
||||
#![deny(clippy::unreachable)]
|
||||
|
||||
use argon2::{Algorithm, Argon2, Params, PasswordHash, Version};
|
||||
use base64::engine::GeneralPurpose;
|
||||
|
@ -27,7 +27,7 @@ use openssl::error::ErrorStack as OpenSSLErrorStack;
|
|||
use openssl::hash::{self, MessageDigest};
|
||||
use openssl::nid::Nid;
|
||||
use openssl::pkcs5::pbkdf2_hmac;
|
||||
use openssl::sha::Sha512;
|
||||
use openssl::sha::{Sha1, Sha256, Sha512};
|
||||
|
||||
use kanidm_hsm_crypto::{HmacKey, Tpm};
|
||||
|
||||
|
@ -48,8 +48,10 @@ const PBKDF2_KEY_LEN: usize = 64;
|
|||
const PBKDF2_MIN_NIST_KEY_LEN: usize = 32;
|
||||
const PBKDF2_SHA1_MIN_KEY_LEN: usize = 19;
|
||||
|
||||
const DS_SSHA512_SALT_LEN: usize = 8;
|
||||
const DS_SSHA512_HASH_LEN: usize = 64;
|
||||
const DS_SHA_SALT_LEN: usize = 8;
|
||||
const DS_SHA1_HASH_LEN: usize = 20;
|
||||
const DS_SHA256_HASH_LEN: usize = 32;
|
||||
const DS_SHA512_HASH_LEN: usize = 64;
|
||||
|
||||
// Taken from the argon2 library and rfc 9106
|
||||
const ARGON2_VERSION: u32 = 19;
|
||||
|
@ -122,6 +124,11 @@ pub enum DbPasswordV1 {
|
|||
PBKDF2(usize, Vec<u8>, Vec<u8>),
|
||||
PBKDF2_SHA1(usize, Vec<u8>, Vec<u8>),
|
||||
PBKDF2_SHA512(usize, Vec<u8>, Vec<u8>),
|
||||
SHA1(Vec<u8>),
|
||||
SSHA1(Vec<u8>, Vec<u8>),
|
||||
SHA256(Vec<u8>),
|
||||
SSHA256(Vec<u8>, Vec<u8>),
|
||||
SHA512(Vec<u8>),
|
||||
SSHA512(Vec<u8>, Vec<u8>),
|
||||
NT_MD4(Vec<u8>),
|
||||
}
|
||||
|
@ -160,6 +167,23 @@ pub enum ReplPasswordV1 {
|
|||
salt: Base64UrlSafeData,
|
||||
hash: Base64UrlSafeData,
|
||||
},
|
||||
SHA1 {
|
||||
hash: Base64UrlSafeData,
|
||||
},
|
||||
SSHA1 {
|
||||
salt: Base64UrlSafeData,
|
||||
hash: Base64UrlSafeData,
|
||||
},
|
||||
SHA256 {
|
||||
hash: Base64UrlSafeData,
|
||||
},
|
||||
SSHA256 {
|
||||
salt: Base64UrlSafeData,
|
||||
hash: Base64UrlSafeData,
|
||||
},
|
||||
SHA512 {
|
||||
hash: Base64UrlSafeData,
|
||||
},
|
||||
SSHA512 {
|
||||
salt: Base64UrlSafeData,
|
||||
hash: Base64UrlSafeData,
|
||||
|
@ -177,6 +201,11 @@ impl fmt::Debug for DbPasswordV1 {
|
|||
DbPasswordV1::PBKDF2(_, _, _) => write!(f, "PBKDF2"),
|
||||
DbPasswordV1::PBKDF2_SHA1(_, _, _) => write!(f, "PBKDF2_SHA1"),
|
||||
DbPasswordV1::PBKDF2_SHA512(_, _, _) => write!(f, "PBKDF2_SHA512"),
|
||||
DbPasswordV1::SHA1(_) => write!(f, "SHA1"),
|
||||
DbPasswordV1::SSHA1(_, _) => write!(f, "SSHA1"),
|
||||
DbPasswordV1::SHA256(_) => write!(f, "SHA256"),
|
||||
DbPasswordV1::SSHA256(_, _) => write!(f, "SSHA256"),
|
||||
DbPasswordV1::SHA512(_) => write!(f, "SHA512"),
|
||||
DbPasswordV1::SSHA512(_, _) => write!(f, "SSHA512"),
|
||||
DbPasswordV1::NT_MD4(_) => write!(f, "NT_MD4"),
|
||||
}
|
||||
|
@ -386,6 +415,11 @@ enum Kdf {
|
|||
// cost, salt, hash
|
||||
PBKDF2_SHA512(usize, Vec<u8>, Vec<u8>),
|
||||
// salt hash
|
||||
SHA1(Vec<u8>),
|
||||
SSHA1(Vec<u8>, Vec<u8>),
|
||||
SHA256(Vec<u8>),
|
||||
SSHA256(Vec<u8>, Vec<u8>),
|
||||
SHA512(Vec<u8>),
|
||||
SSHA512(Vec<u8>, Vec<u8>),
|
||||
// hash
|
||||
NT_MD4(Vec<u8>),
|
||||
|
@ -430,6 +464,21 @@ impl TryFrom<DbPasswordV1> for Password {
|
|||
DbPasswordV1::PBKDF2_SHA512(c, s, h) => Ok(Password {
|
||||
material: Kdf::PBKDF2_SHA512(c, s, h),
|
||||
}),
|
||||
DbPasswordV1::SHA1(h) => Ok(Password {
|
||||
material: Kdf::SHA1(h),
|
||||
}),
|
||||
DbPasswordV1::SSHA1(s, h) => Ok(Password {
|
||||
material: Kdf::SSHA1(s, h),
|
||||
}),
|
||||
DbPasswordV1::SHA256(h) => Ok(Password {
|
||||
material: Kdf::SHA256(h),
|
||||
}),
|
||||
DbPasswordV1::SSHA256(s, h) => Ok(Password {
|
||||
material: Kdf::SSHA256(s, h),
|
||||
}),
|
||||
DbPasswordV1::SHA512(h) => Ok(Password {
|
||||
material: Kdf::SHA512(h),
|
||||
}),
|
||||
DbPasswordV1::SSHA512(s, h) => Ok(Password {
|
||||
material: Kdf::SSHA512(s, h),
|
||||
}),
|
||||
|
@ -488,6 +537,21 @@ impl TryFrom<&ReplPasswordV1> for Password {
|
|||
ReplPasswordV1::PBKDF2_SHA512 { cost, salt, hash } => Ok(Password {
|
||||
material: Kdf::PBKDF2_SHA512(*cost, salt.0.clone(), hash.0.clone()),
|
||||
}),
|
||||
ReplPasswordV1::SHA1 { hash } => Ok(Password {
|
||||
material: Kdf::SHA1(hash.0.clone()),
|
||||
}),
|
||||
ReplPasswordV1::SSHA1 { salt, hash } => Ok(Password {
|
||||
material: Kdf::SSHA1(salt.0.clone(), hash.0.clone()),
|
||||
}),
|
||||
ReplPasswordV1::SHA256 { hash } => Ok(Password {
|
||||
material: Kdf::SHA256(hash.0.clone()),
|
||||
}),
|
||||
ReplPasswordV1::SSHA256 { salt, hash } => Ok(Password {
|
||||
material: Kdf::SSHA256(salt.0.clone(), hash.0.clone()),
|
||||
}),
|
||||
ReplPasswordV1::SHA512 { hash } => Ok(Password {
|
||||
material: Kdf::SHA512(hash.0.clone()),
|
||||
}),
|
||||
ReplPasswordV1::SSHA512 { salt, hash } => Ok(Password {
|
||||
material: Kdf::SSHA512(salt.0.clone(), hash.0.clone()),
|
||||
}),
|
||||
|
@ -556,12 +620,14 @@ impl TryFrom<&str> for Password {
|
|||
let nt_md4 = match value.split_once(' ') {
|
||||
Some((_, v)) => v,
|
||||
None => {
|
||||
unreachable!();
|
||||
return Err(());
|
||||
}
|
||||
};
|
||||
|
||||
let h = base64::engine::general_purpose::STANDARD_NO_PAD
|
||||
// Great work.
|
||||
let h = base64::engine::general_purpose::URL_SAFE_NO_PAD
|
||||
.decode(nt_md4)
|
||||
.or_else(|_| base64::engine::general_purpose::URL_SAFE.decode(nt_md4))
|
||||
.map_err(|_| ())?;
|
||||
|
||||
return Ok(Password {
|
||||
|
@ -573,7 +639,7 @@ impl TryFrom<&str> for Password {
|
|||
let nt_md4 = match value.split_once(' ') {
|
||||
Some((_, v)) => v,
|
||||
None => {
|
||||
unreachable!();
|
||||
return Err(());
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -584,12 +650,71 @@ impl TryFrom<&str> for Password {
|
|||
}
|
||||
|
||||
// Test 389ds formats
|
||||
|
||||
if let Some(ds_ssha1) = value.strip_prefix("{SHA}") {
|
||||
let h = general_purpose::STANDARD.decode(ds_ssha1).map_err(|_| ())?;
|
||||
if h.len() != DS_SHA1_HASH_LEN {
|
||||
return Err(());
|
||||
}
|
||||
return Ok(Password {
|
||||
material: Kdf::SHA1(h.to_vec()),
|
||||
});
|
||||
}
|
||||
|
||||
if let Some(ds_ssha1) = value.strip_prefix("{SSHA}") {
|
||||
let sh = general_purpose::STANDARD.decode(ds_ssha1).map_err(|_| ())?;
|
||||
let (h, s) = sh.split_at(DS_SHA1_HASH_LEN);
|
||||
if s.len() != DS_SHA_SALT_LEN {
|
||||
return Err(());
|
||||
}
|
||||
return Ok(Password {
|
||||
material: Kdf::SSHA1(s.to_vec(), h.to_vec()),
|
||||
});
|
||||
}
|
||||
|
||||
if let Some(ds_ssha256) = value.strip_prefix("{SHA256}") {
|
||||
let h = general_purpose::STANDARD
|
||||
.decode(ds_ssha256)
|
||||
.map_err(|_| ())?;
|
||||
if h.len() != DS_SHA256_HASH_LEN {
|
||||
return Err(());
|
||||
}
|
||||
return Ok(Password {
|
||||
material: Kdf::SHA256(h.to_vec()),
|
||||
});
|
||||
}
|
||||
|
||||
if let Some(ds_ssha256) = value.strip_prefix("{SSHA256}") {
|
||||
let sh = general_purpose::STANDARD
|
||||
.decode(ds_ssha256)
|
||||
.map_err(|_| ())?;
|
||||
let (h, s) = sh.split_at(DS_SHA256_HASH_LEN);
|
||||
if s.len() != DS_SHA_SALT_LEN {
|
||||
return Err(());
|
||||
}
|
||||
return Ok(Password {
|
||||
material: Kdf::SSHA256(s.to_vec(), h.to_vec()),
|
||||
});
|
||||
}
|
||||
|
||||
if let Some(ds_ssha512) = value.strip_prefix("{SHA512}") {
|
||||
let h = general_purpose::STANDARD
|
||||
.decode(ds_ssha512)
|
||||
.map_err(|_| ())?;
|
||||
if h.len() != DS_SHA512_HASH_LEN {
|
||||
return Err(());
|
||||
}
|
||||
return Ok(Password {
|
||||
material: Kdf::SHA512(h.to_vec()),
|
||||
});
|
||||
}
|
||||
|
||||
if let Some(ds_ssha512) = value.strip_prefix("{SSHA512}") {
|
||||
let sh = general_purpose::STANDARD
|
||||
.decode(ds_ssha512)
|
||||
.map_err(|_| ())?;
|
||||
let (h, s) = sh.split_at(DS_SSHA512_HASH_LEN);
|
||||
if s.len() != DS_SSHA512_SALT_LEN {
|
||||
let (h, s) = sh.split_at(DS_SHA512_HASH_LEN);
|
||||
if s.len() != DS_SHA_SALT_LEN {
|
||||
return Err(());
|
||||
}
|
||||
return Ok(Password {
|
||||
|
@ -606,7 +731,7 @@ impl TryFrom<&str> for Password {
|
|||
let ol_pbkdf2 = match value.split_once('}') {
|
||||
Some((_, v)) => v,
|
||||
None => {
|
||||
unreachable!();
|
||||
return Err(());
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -663,7 +788,7 @@ impl TryFrom<&str> for Password {
|
|||
}
|
||||
|
||||
// Should be no way to get here!
|
||||
unreachable!();
|
||||
return Err(());
|
||||
} else {
|
||||
warn!("oldap pbkdf2 found but invalid number of elements?");
|
||||
}
|
||||
|
@ -1025,6 +1150,38 @@ impl Password {
|
|||
})
|
||||
.map_err(|e| e.into())
|
||||
}
|
||||
(Kdf::SHA1(key), _) => {
|
||||
let mut hasher = Sha1::new();
|
||||
hasher.update(cleartext.as_bytes());
|
||||
let r = hasher.finish();
|
||||
Ok(key == &(r.to_vec()))
|
||||
}
|
||||
(Kdf::SSHA1(salt, key), _) => {
|
||||
let mut hasher = Sha1::new();
|
||||
hasher.update(cleartext.as_bytes());
|
||||
hasher.update(salt);
|
||||
let r = hasher.finish();
|
||||
Ok(key == &(r.to_vec()))
|
||||
}
|
||||
(Kdf::SHA256(key), _) => {
|
||||
let mut hasher = Sha256::new();
|
||||
hasher.update(cleartext.as_bytes());
|
||||
let r = hasher.finish();
|
||||
Ok(key == &(r.to_vec()))
|
||||
}
|
||||
(Kdf::SSHA256(salt, key), _) => {
|
||||
let mut hasher = Sha256::new();
|
||||
hasher.update(cleartext.as_bytes());
|
||||
hasher.update(salt);
|
||||
let r = hasher.finish();
|
||||
Ok(key == &(r.to_vec()))
|
||||
}
|
||||
(Kdf::SHA512(key), _) => {
|
||||
let mut hasher = Sha512::new();
|
||||
hasher.update(cleartext.as_bytes());
|
||||
let r = hasher.finish();
|
||||
Ok(key == &(r.to_vec()))
|
||||
}
|
||||
(Kdf::SSHA512(salt, key), _) => {
|
||||
let mut hasher = Sha512::new();
|
||||
hasher.update(cleartext.as_bytes());
|
||||
|
@ -1099,6 +1256,11 @@ impl Password {
|
|||
Kdf::PBKDF2_SHA512(cost, salt, hash) => {
|
||||
DbPasswordV1::PBKDF2_SHA512(*cost, salt.clone(), hash.clone())
|
||||
}
|
||||
Kdf::SHA1(hash) => DbPasswordV1::SHA1(hash.clone()),
|
||||
Kdf::SSHA1(salt, hash) => DbPasswordV1::SSHA1(salt.clone(), hash.clone()),
|
||||
Kdf::SHA256(hash) => DbPasswordV1::SHA256(hash.clone()),
|
||||
Kdf::SSHA256(salt, hash) => DbPasswordV1::SSHA256(salt.clone(), hash.clone()),
|
||||
Kdf::SHA512(hash) => DbPasswordV1::SHA512(hash.clone()),
|
||||
Kdf::SSHA512(salt, hash) => DbPasswordV1::SSHA512(salt.clone(), hash.clone()),
|
||||
Kdf::NT_MD4(hash) => DbPasswordV1::NT_MD4(hash.clone()),
|
||||
}
|
||||
|
@ -1151,6 +1313,23 @@ impl Password {
|
|||
salt: salt.clone().into(),
|
||||
hash: hash.clone().into(),
|
||||
},
|
||||
Kdf::SHA1(hash) => ReplPasswordV1::SHA1 {
|
||||
hash: hash.clone().into(),
|
||||
},
|
||||
Kdf::SSHA1(salt, hash) => ReplPasswordV1::SSHA1 {
|
||||
salt: salt.clone().into(),
|
||||
hash: hash.clone().into(),
|
||||
},
|
||||
Kdf::SHA256(hash) => ReplPasswordV1::SHA256 {
|
||||
hash: hash.clone().into(),
|
||||
},
|
||||
Kdf::SSHA256(salt, hash) => ReplPasswordV1::SSHA256 {
|
||||
salt: salt.clone().into(),
|
||||
hash: hash.clone().into(),
|
||||
},
|
||||
Kdf::SHA512(hash) => ReplPasswordV1::SHA512 {
|
||||
hash: hash.clone().into(),
|
||||
},
|
||||
Kdf::SSHA512(salt, hash) => ReplPasswordV1::SSHA512 {
|
||||
salt: salt.clone().into(),
|
||||
hash: hash.clone().into(),
|
||||
|
@ -1187,6 +1366,11 @@ impl Password {
|
|||
Kdf::PBKDF2(_, _, _)
|
||||
| Kdf::PBKDF2_SHA512(_, _, _)
|
||||
| Kdf::PBKDF2_SHA1(_, _, _)
|
||||
| Kdf::SHA1(_)
|
||||
| Kdf::SSHA1(_, _)
|
||||
| Kdf::SHA256(_)
|
||||
| Kdf::SSHA256(_, _)
|
||||
| Kdf::SHA512(_)
|
||||
| Kdf::SSHA512(_, _)
|
||||
| Kdf::NT_MD4(_) => true,
|
||||
}
|
||||
|
@ -1243,6 +1427,56 @@ mod tests {
|
|||
assert!(r.verify(password).unwrap_or(false));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_password_from_ds_sha1() {
|
||||
let im_pw = "{SHA}W6ph5Mm5Pz8GgiULbPgzG37mj9g=";
|
||||
let password = "password";
|
||||
let r = Password::try_from(im_pw).expect("Failed to parse");
|
||||
// Known weak, require upgrade.
|
||||
assert!(r.requires_upgrade());
|
||||
assert!(r.verify(password).unwrap_or(false));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_password_from_ds_ssha1() {
|
||||
let im_pw = "{SSHA}EyzbBiP4u4zxOrLpKTORI/RX3HC6TCTJtnVOCQ==";
|
||||
let password = "password";
|
||||
let r = Password::try_from(im_pw).expect("Failed to parse");
|
||||
// Known weak, require upgrade.
|
||||
assert!(r.requires_upgrade());
|
||||
assert!(r.verify(password).unwrap_or(false));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_password_from_ds_sha256() {
|
||||
let im_pw = "{SHA256}XohImNooBHFR0OVvjcYpJ3NgPQ1qq73WKhHvch0VQtg=";
|
||||
let password = "password";
|
||||
let r = Password::try_from(im_pw).expect("Failed to parse");
|
||||
// Known weak, require upgrade.
|
||||
assert!(r.requires_upgrade());
|
||||
assert!(r.verify(password).unwrap_or(false));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_password_from_ds_ssha256() {
|
||||
let im_pw = "{SSHA256}luYWfFJOZgxySTsJXHgIaCYww4yMpu6yest69j/wO5n5OycuHFV/GQ==";
|
||||
let password = "password";
|
||||
let r = Password::try_from(im_pw).expect("Failed to parse");
|
||||
// Known weak, require upgrade.
|
||||
assert!(r.requires_upgrade());
|
||||
assert!(r.verify(password).unwrap_or(false));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_password_from_ds_sha512() {
|
||||
let im_pw = "{SHA512}sQnzu7wkTrgkQZF+0G1hi5AI3Qmzvv0bXgc5THBqi7mAsdd4Xll27ASbRt9fEyavWi6m0QP9B8lThf+rDKy8hg==";
|
||||
let password = "password";
|
||||
let r = Password::try_from(im_pw).expect("Failed to parse");
|
||||
// Known weak, require upgrade.
|
||||
assert!(r.requires_upgrade());
|
||||
assert!(r.verify(password).unwrap_or(false));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_password_from_ds_ssha512() {
|
||||
let im_pw = "{SSHA512}JwrSUHkI7FTAfHRVR6KoFlSN0E3dmaQWARjZ+/UsShYlENOqDtFVU77HJLLrY2MuSp0jve52+pwtdVl2QUAHukQ0XUf5LDtM";
|
||||
|
@ -1343,6 +1577,9 @@ mod tests {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
let im_pw = "ipaNTHash: pS43DjQLcUYhaNF_cd_Vhw==";
|
||||
Password::try_from(im_pw).expect("Failed to parse");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -114,6 +114,7 @@ pub const ATTR_MUST: &str = "must";
|
|||
pub const ATTR_NAME_HISTORY: &str = "name_history";
|
||||
pub const ATTR_NAME: &str = "name";
|
||||
pub const ATTR_NO_INDEX: &str = "no-index";
|
||||
pub const ATTR_NSACCOUNTLOCK: &str = "nsaccountlock";
|
||||
pub const ATTR_NSUNIQUEID: &str = "nsuniqueid";
|
||||
|
||||
pub const ATTR_OAUTH2_ALLOW_INSECURE_CLIENT_DISABLE_PKCE: &str =
|
||||
|
@ -183,7 +184,7 @@ pub const OAUTH2_SCOPE_READ: &str = "read";
|
|||
pub const OAUTH2_SCOPE_SUPPLEMENT: &str = "supplement";
|
||||
|
||||
pub const LDAP_ATTR_CN: &str = "cn";
|
||||
pub const LDAP_ATTR_DISPLAY_NAME: &str = "displayName";
|
||||
pub const LDAP_ATTR_DISPLAY_NAME: &str = "displayname";
|
||||
pub const LDAP_ATTR_EMAIL_ALTERNATIVE: &str = "emailalternative";
|
||||
pub const LDAP_ATTR_EMAIL_PRIMARY: &str = "emailprimary";
|
||||
pub const LDAP_ATTR_ENTRYDN: &str = "entrydn";
|
||||
|
@ -195,7 +196,7 @@ pub const LDAP_ATTR_MAIL_PRIMARY: &str = "mail;primary";
|
|||
pub const LDAP_ATTR_MAIL: &str = "mail";
|
||||
pub const LDAP_ATTR_MEMBER: &str = "member";
|
||||
pub const LDAP_ATTR_NAME: &str = "name";
|
||||
pub const LDAP_ATTR_OBJECTCLASS: &str = "objectClass";
|
||||
pub const LDAP_ATTR_OBJECTCLASS: &str = "objectclass";
|
||||
pub const LDAP_ATTR_OU: &str = "ou";
|
||||
pub const LDAP_ATTR_UID: &str = "uid";
|
||||
pub const LDAP_CLASS_GROUPOFNAMES: &str = "groupofnames";
|
||||
|
|
|
@ -9,8 +9,8 @@ pub use scim_proto::user::MultiValueAttr;
|
|||
use scim_proto::*;
|
||||
|
||||
use crate::constants::{
|
||||
ATTR_DESCRIPTION, ATTR_DISPLAYNAME, ATTR_GIDNUMBER, ATTR_LOGINSHELL, ATTR_MAIL, ATTR_MEMBER,
|
||||
ATTR_NAME, ATTR_SSH_PUBLICKEY,
|
||||
ATTR_ACCOUNT_EXPIRE, ATTR_ACCOUNT_VALID_FROM, ATTR_DESCRIPTION, ATTR_DISPLAYNAME,
|
||||
ATTR_GIDNUMBER, ATTR_LOGINSHELL, ATTR_MAIL, ATTR_MEMBER, ATTR_NAME, ATTR_SSH_PUBLICKEY,
|
||||
};
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, ToSchema)]
|
||||
|
@ -142,6 +142,8 @@ pub struct ScimSyncPerson {
|
|||
pub login_shell: Option<String>,
|
||||
pub mail: Vec<MultiValueAttr>,
|
||||
pub ssh_publickey: Vec<ScimSshPubKey>,
|
||||
pub account_valid_from: Option<String>,
|
||||
pub account_expire: Option<String>,
|
||||
}
|
||||
|
||||
// Need to allow this because clippy is broken and doesn't realise scimentry is out of crate
|
||||
|
@ -160,6 +162,8 @@ impl Into<ScimEntry> for ScimSyncPerson {
|
|||
login_shell,
|
||||
mail,
|
||||
ssh_publickey,
|
||||
account_valid_from,
|
||||
account_expire,
|
||||
} = self;
|
||||
|
||||
let schemas = if gidnumber.is_some() {
|
||||
|
@ -185,6 +189,8 @@ impl Into<ScimEntry> for ScimSyncPerson {
|
|||
set_option_string!(attrs, ATTR_LOGINSHELL, login_shell);
|
||||
set_multi_complex!(attrs, ATTR_MAIL, mail);
|
||||
set_multi_complex!(attrs, ATTR_SSH_PUBLICKEY, ssh_publickey); // with the underscore
|
||||
set_option_string!(attrs, ATTR_ACCOUNT_EXPIRE, account_expire);
|
||||
set_option_string!(attrs, ATTR_ACCOUNT_VALID_FROM, account_valid_from);
|
||||
|
||||
ScimEntry {
|
||||
schemas,
|
||||
|
|
|
@ -68,8 +68,8 @@ async fn client_process(
|
|||
return;
|
||||
};
|
||||
let (r, w) = tokio::io::split(tlsstream);
|
||||
let mut r = FramedRead::new(r, LdapCodec);
|
||||
let mut w = FramedWrite::new(w, LdapCodec);
|
||||
let mut r = FramedRead::new(r, LdapCodec::default());
|
||||
let mut w = FramedWrite::new(w, LdapCodec::default());
|
||||
|
||||
// This is a connected client session. we need to associate some state to the session
|
||||
let mut session = LdapSession::new();
|
||||
|
|
|
@ -115,6 +115,7 @@ pub enum Attribute {
|
|||
NameHistory,
|
||||
NoIndex,
|
||||
NsUniqueId,
|
||||
NsAccountLock,
|
||||
OAuth2AllowInsecureClientDisablePkce,
|
||||
OAuth2ConsentScopeMap,
|
||||
OAuth2JwtLegacyCryptoEnable,
|
||||
|
@ -295,6 +296,7 @@ impl TryFrom<String> for Attribute {
|
|||
ATTR_NAME_HISTORY => Attribute::NameHistory,
|
||||
ATTR_NO_INDEX => Attribute::NoIndex,
|
||||
ATTR_NSUNIQUEID => Attribute::NsUniqueId,
|
||||
ATTR_NSACCOUNTLOCK => Attribute::NsAccountLock,
|
||||
ATTR_OAUTH2_ALLOW_INSECURE_CLIENT_DISABLE_PKCE => {
|
||||
Attribute::OAuth2AllowInsecureClientDisablePkce
|
||||
}
|
||||
|
@ -452,6 +454,7 @@ impl From<Attribute> for &'static str {
|
|||
Attribute::NameHistory => ATTR_NAME_HISTORY,
|
||||
Attribute::NoIndex => ATTR_NO_INDEX,
|
||||
Attribute::NsUniqueId => ATTR_NSUNIQUEID,
|
||||
Attribute::NsAccountLock => ATTR_NSACCOUNTLOCK,
|
||||
Attribute::OAuth2AllowInsecureClientDisablePkce => {
|
||||
ATTR_OAUTH2_ALLOW_INSECURE_CLIENT_DISABLE_PKCE
|
||||
}
|
||||
|
|
|
@ -273,7 +273,7 @@ pub static ref SCHEMA_ATTR_NSUNIQUEID: SchemaAttribute = SchemaAttribute {
|
|||
pub static ref SCHEMA_ATTR_ACCOUNT_EXPIRE: SchemaAttribute = SchemaAttribute {
|
||||
uuid: UUID_SCHEMA_ATTR_ACCOUNT_EXPIRE,
|
||||
name: Attribute::AccountExpire.into(),
|
||||
description: "The datetime after which this accounnt no longer may authenticate.to_string().".to_string(),
|
||||
description: "The datetime after which this account no longer may authenticate.to_string().".to_string(),
|
||||
|
||||
sync_allowed: true,
|
||||
syntax: SyntaxType::DateTime,
|
||||
|
|
|
@ -1119,6 +1119,20 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
|
|||
}
|
||||
Ok(vs)
|
||||
}
|
||||
(
|
||||
SyntaxType::DateTime,
|
||||
false,
|
||||
ScimAttr::SingleSimple(ScimSimpleAttr::String(value)),
|
||||
) => {
|
||||
Value::new_datetime_s(value)
|
||||
.map(|v| vec![v])
|
||||
.ok_or_else(|| {
|
||||
error!("Invalid value attribute - must be scim simple string with rfc3339 formatted datetime");
|
||||
OperationError::InvalidAttribute(format!(
|
||||
"value must be scim simple string with rfc3339 formatted datetime - {scim_attr_name}"
|
||||
))
|
||||
})
|
||||
}
|
||||
(syn, mv, sa) => {
|
||||
error!(?syn, ?mv, ?sa, "Unsupported scim attribute conversion. This may be a syntax error in your import, or a missing feature in Kanidm.");
|
||||
Err(OperationError::InvalidAttribute(format!(
|
||||
|
@ -3287,7 +3301,9 @@ mod tests {
|
|||
"gidnumber": 12345,
|
||||
"loginshell": "/bin/sh",
|
||||
"name": "testuser",
|
||||
"password_import": "ipaNTHash: iEb36u6PsRetBr3YMLdYbA"
|
||||
"password_import": "ipaNTHash: iEb36u6PsRetBr3YMLdYbA",
|
||||
"account_valid_from": "2021-11-28T04:57:55Z",
|
||||
"account_expire": "2023-11-28T04:57:55Z"
|
||||
},
|
||||
{
|
||||
"schemas": [
|
||||
|
|
|
@ -235,7 +235,7 @@ impl SchemaAttribute {
|
|||
if r {
|
||||
Ok(())
|
||||
} else {
|
||||
trace!(
|
||||
error!(
|
||||
?a,
|
||||
?self,
|
||||
?v,
|
||||
|
@ -288,7 +288,7 @@ impl SchemaAttribute {
|
|||
if r {
|
||||
Ok(())
|
||||
} else {
|
||||
trace!(
|
||||
error!(
|
||||
?a,
|
||||
?self,
|
||||
?v,
|
||||
|
@ -311,10 +311,9 @@ impl SchemaAttribute {
|
|||
if valid && ava.validate(self) {
|
||||
Ok(())
|
||||
} else {
|
||||
admin_error!(
|
||||
error!(
|
||||
?a,
|
||||
"validate_ava - InvalidAttributeSyntax for {:?}",
|
||||
self.syntax
|
||||
"validate_ava - InvalidAttributeSyntax for {:?}", self.syntax
|
||||
);
|
||||
Err(SchemaError::InvalidAttributeSyntax(a.to_string()))
|
||||
}
|
||||
|
|
|
@ -1880,6 +1880,8 @@ impl Value {
|
|||
"value contains invalid whitespace chars forbidden by \"{}\"",
|
||||
*SINGLELINE_RE
|
||||
);
|
||||
// Trace only, could be an injection attack of some kind.
|
||||
trace!(?s, "Invalid whitespace");
|
||||
false
|
||||
}
|
||||
}
|
||||
|
@ -1888,6 +1890,8 @@ impl Value {
|
|||
// Look for and prevent certain types of string escapes and injections.
|
||||
if UNICODE_CONTROL_RE.is_match(s) {
|
||||
error!("value contains invalid unicode control character",);
|
||||
// Trace only, could be an injection attack of some kind.
|
||||
trace!(?s, "Invalid Uncode Control");
|
||||
false
|
||||
} else {
|
||||
true
|
||||
|
|
|
@ -361,7 +361,6 @@ async fn run_sync(
|
|||
// LdapFilter::Equality(LDAP_ATTR_OBJECTCLASS.into(), "domain".to_string()),
|
||||
LdapFilter::And(vec![
|
||||
LdapFilter::Equality(LDAP_ATTR_OBJECTCLASS.into(), "person".to_string()),
|
||||
LdapFilter::Equality(LDAP_ATTR_OBJECTCLASS.into(), "ipantuserattrs".to_string()),
|
||||
LdapFilter::Equality(LDAP_ATTR_OBJECTCLASS.into(), "posixaccount".to_string()),
|
||||
]),
|
||||
LdapFilter::And(vec![
|
||||
|
@ -382,6 +381,15 @@ async fn run_sync(
|
|||
LDAP_ATTR_CN.into(),
|
||||
"ipausers".to_string(),
|
||||
))),
|
||||
// Ignore editors/trust admins
|
||||
LdapFilter::Not(Box::new(LdapFilter::Equality(
|
||||
LDAP_ATTR_CN.into(),
|
||||
"editors".to_string(),
|
||||
))),
|
||||
LdapFilter::Not(Box::new(LdapFilter::Equality(
|
||||
LDAP_ATTR_CN.into(),
|
||||
"trust admins".to_string(),
|
||||
))),
|
||||
]),
|
||||
// Fetch TOTP's so we know when/if they change.
|
||||
LdapFilter::And(vec![
|
||||
|
@ -785,6 +793,7 @@ fn ipa_to_scim_entry(
|
|||
.attrs
|
||||
.get(LDAP_ATTR_OBJECTCLASS)
|
||||
.ok_or_else(|| {
|
||||
debug!(?sync_entry);
|
||||
error!("Invalid entry - no object class {}", dn);
|
||||
})?;
|
||||
|
||||
|
@ -823,14 +832,16 @@ fn ipa_to_scim_entry(
|
|||
error!("Missing required attribute {}", Attribute::Cn);
|
||||
})?;
|
||||
|
||||
// There are some installs that incorrectly assign this to a shared
|
||||
// group.
|
||||
let gidnumber = if let Some(number) = entry_config.map_gidnumber {
|
||||
Some(number)
|
||||
} else {
|
||||
entry
|
||||
.remove_ava_single(Attribute::GidNumber.as_ref())
|
||||
.map(|gid| {
|
||||
u32::from_str(&gid).map_err(|_| {
|
||||
error!("Invalid {}", Attribute::GidNumber);
|
||||
.remove_ava_single(Attribute::UidNumber.as_ref())
|
||||
.map(|uid| {
|
||||
u32::from_str(&uid).map_err(|_| {
|
||||
error!("Invalid {}", Attribute::UidNumber);
|
||||
})
|
||||
})
|
||||
.transpose()?
|
||||
|
@ -887,6 +898,23 @@ fn ipa_to_scim_entry(
|
|||
})
|
||||
.unwrap_or_default();
|
||||
|
||||
let account_disabled: bool = entry
|
||||
.remove_ava(Attribute::NsAccountLock.as_ref())
|
||||
.map(|set| {
|
||||
set.into_iter()
|
||||
.any(|value| value != "FALSE" && value != "false")
|
||||
})
|
||||
.unwrap_or_default();
|
||||
|
||||
// Account is not valid
|
||||
let account_expire = if account_disabled {
|
||||
Some(chrono::DateTime::UNIX_EPOCH.to_rfc3339())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let account_valid_from = None;
|
||||
|
||||
let login_shell = entry.remove_ava_single(Attribute::LoginShell.as_ref());
|
||||
let external_id = Some(entry.dn);
|
||||
|
||||
|
@ -902,6 +930,8 @@ fn ipa_to_scim_entry(
|
|||
login_shell,
|
||||
mail,
|
||||
ssh_publickey,
|
||||
account_expire,
|
||||
account_valid_from,
|
||||
}
|
||||
.into(),
|
||||
))
|
||||
|
|
|
@ -20,6 +20,7 @@ use chrono::Utc;
|
|||
use clap::Parser;
|
||||
use cron::Schedule;
|
||||
use kanidm_proto::constants::ATTR_OBJECTCLASS;
|
||||
use kanidmd_lib::prelude::Attribute;
|
||||
use std::fs::metadata;
|
||||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
|
@ -582,6 +583,22 @@ fn ldap_to_scim_entry(
|
|||
})
|
||||
.unwrap_or_default();
|
||||
|
||||
let account_disabled: bool = entry
|
||||
.remove_ava(Attribute::NsAccountLock.as_ref())
|
||||
.map(|set| {
|
||||
set.into_iter()
|
||||
.any(|value| value != "FALSE" && value != "false")
|
||||
})
|
||||
.unwrap_or_default();
|
||||
|
||||
// Account is not valid
|
||||
let account_expire = if account_disabled {
|
||||
Some(chrono::DateTime::UNIX_EPOCH.to_rfc3339())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let account_valid_from = None;
|
||||
|
||||
let login_shell = entry.remove_ava_single(&sync_config.person_attr_login_shell);
|
||||
let external_id = Some(entry.dn);
|
||||
|
||||
|
@ -597,6 +614,8 @@ fn ldap_to_scim_entry(
|
|||
login_shell,
|
||||
mail,
|
||||
ssh_publickey,
|
||||
account_expire,
|
||||
account_valid_from,
|
||||
}
|
||||
.into(),
|
||||
))
|
||||
|
|
|
@ -110,7 +110,7 @@ impl LdapClient {
|
|||
error!("Failed to initialise TLS -> {:?}", e);
|
||||
})?;
|
||||
|
||||
let mut framed = Framed::new(tlsstream, LdapCodec);
|
||||
let mut framed = Framed::new(tlsstream, LdapCodec::default());
|
||||
|
||||
framed.send(msg).await.map_err(|e| {
|
||||
error!("Unable to bind -> {:?}", e);
|
||||
|
|
Loading…
Reference in a new issue