20230614 unix account security - move account name deny to unixd (#1733)

This commit is contained in:
Firstyear 2023-06-15 13:24:53 +10:00 committed by GitHub
parent 76cee8cecb
commit a77a7aa2a4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 775 additions and 185 deletions

390
Cargo.lock generated
View file

@ -68,7 +68,7 @@ version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47"
dependencies = [ dependencies = [
"getrandom 0.2.9", "getrandom 0.2.10",
"once_cell", "once_cell",
"version_check", "version_check",
] ]
@ -86,13 +86,19 @@ dependencies = [
[[package]] [[package]]
name = "aho-corasick" name = "aho-corasick"
version = "1.0.1" version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67fc08ce920c31afb70f013dcce1bfc3a3195de6a228474e45e1f145b36f8d04" checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41"
dependencies = [ dependencies = [
"memchr", "memchr",
] ]
[[package]]
name = "allocator-api2"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4f263788a35611fba42eb41ff811c5d0360c58b97402570312a350736e2542e"
[[package]] [[package]]
name = "android-tzdata" name = "android-tzdata"
version = "0.1.1" version = "0.1.1"
@ -151,7 +157,7 @@ dependencies = [
"num-traits", "num-traits",
"rusticata-macros", "rusticata-macros",
"thiserror", "thiserror",
"time 0.3.21", "time 0.3.22",
] ]
[[package]] [[package]]
@ -566,9 +572,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]] [[package]]
name = "bitflags" name = "bitflags"
version = "2.3.1" version = "2.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6776fc96284a0bb647b615056fc496d1fe1644a7ab01829818a6d91cae888b84" checksum = "6dbe3c979c178231552ecba20214a8272df4e09f232a87aef4320cf06539aded"
[[package]] [[package]]
name = "blake3" name = "blake3"
@ -936,7 +942,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e859cd57d0710d9e06c381b550c06e76992472a8c6d527aecd2fc673dcc231fb" checksum = "e859cd57d0710d9e06c381b550c06e76992472a8c6d527aecd2fc673dcc231fb"
dependencies = [ dependencies = [
"percent-encoding", "percent-encoding",
"time 0.3.21", "time 0.3.22",
"version_check", "version_check",
] ]
@ -952,7 +958,7 @@ dependencies = [
"publicsuffix", "publicsuffix",
"serde", "serde",
"serde_json", "serde_json",
"time 0.3.21", "time 0.3.22",
"url", "url",
] ]
@ -1080,14 +1086,14 @@ dependencies = [
[[package]] [[package]]
name = "crossbeam-epoch" name = "crossbeam-epoch"
version = "0.9.14" version = "0.9.15"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695" checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7"
dependencies = [ dependencies = [
"autocfg", "autocfg",
"cfg-if 1.0.0", "cfg-if 1.0.0",
"crossbeam-utils", "crossbeam-utils",
"memoffset 0.8.0", "memoffset 0.9.0",
"scopeguard", "scopeguard",
] ]
@ -1103,9 +1109,9 @@ dependencies = [
[[package]] [[package]]
name = "crossbeam-utils" name = "crossbeam-utils"
version = "0.8.15" version = "0.8.16"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b" checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294"
dependencies = [ dependencies = [
"cfg-if 1.0.0", "cfg-if 1.0.0",
] ]
@ -1161,16 +1167,6 @@ dependencies = [
"memchr", "memchr",
] ]
[[package]]
name = "ctor"
version = "0.1.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096"
dependencies = [
"quote",
"syn 1.0.109",
]
[[package]] [[package]]
name = "ctr" name = "ctr"
version = "0.6.0" version = "0.6.0"
@ -1504,11 +1500,20 @@ checksum = "3364d69f691f3903b1a71605fa04f40a7c2d259f0f0512347e36d19a63debf1f"
dependencies = [ dependencies = [
"base64 0.21.2", "base64 0.21.2",
"byteorder", "byteorder",
"getrandom 0.2.9", "getrandom 0.2.10",
"openssl", "openssl",
"zeroize", "zeroize",
] ]
[[package]]
name = "file-id"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e13be71e6ca82e91bc0cb862bebaac0b2d1924a5a1d970c822b2f98b63fda8c3"
dependencies = [
"winapi-util",
]
[[package]] [[package]]
name = "filetime" name = "filetime"
version = "0.2.21" version = "0.2.21"
@ -1571,6 +1576,15 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "fsevent-sys"
version = "4.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "futures" name = "futures"
version = "0.3.28" version = "0.3.28"
@ -1718,9 +1732,9 @@ dependencies = [
[[package]] [[package]]
name = "getrandom" name = "getrandom"
version = "0.2.9" version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4" checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427"
dependencies = [ dependencies = [
"cfg-if 1.0.0", "cfg-if 1.0.0",
"js-sys", "js-sys",
@ -1973,12 +1987,22 @@ dependencies = [
] ]
[[package]] [[package]]
name = "hashlink" name = "hashbrown"
version = "0.8.2" version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0761a1b9491c4f2e3d66aa0f62d0fba0af9a0e2852e4d48ea506632a4b56e6aa" checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a"
dependencies = [ dependencies = [
"hashbrown 0.13.2", "ahash 0.8.3",
"allocator-api2",
]
[[package]]
name = "hashlink"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "312f66718a2d7789ffef4f4b7b213138ed9f1eb3aa1d0d82fc99f88fb3ffd26f"
dependencies = [
"hashbrown 0.14.0",
] ]
[[package]] [[package]]
@ -2154,9 +2178,9 @@ dependencies = [
[[package]] [[package]]
name = "iana-time-zone" name = "iana-time-zone"
version = "0.1.56" version = "0.1.57"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0722cd7114b7de04316e7ea5456a0bbb20e4adb46fd27a3697adb812cff0f37c" checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613"
dependencies = [ dependencies = [
"android_system_properties", "android_system_properties",
"core-foundation-sys", "core-foundation-sys",
@ -2262,6 +2286,26 @@ version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "64e9829a50b42bb782c1df523f78d332fe371b10c661e78b7a3c34b0198e9fac" checksum = "64e9829a50b42bb782c1df523f78d332fe371b10c661e78b7a3c34b0198e9fac"
[[package]]
name = "inotify"
version = "0.9.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff"
dependencies = [
"bitflags 1.3.2",
"inotify-sys",
"libc",
]
[[package]]
name = "inotify-sys"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "instant" name = "instant"
version = "0.1.12" version = "0.1.12"
@ -2314,9 +2358,9 @@ dependencies = [
[[package]] [[package]]
name = "js-sys" name = "js-sys"
version = "0.3.63" version = "0.3.64"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f37a4a5928311ac501dee68b3c7613a1037d0edb30c8e5427bd832d55d1b790" checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a"
dependencies = [ dependencies = [
"wasm-bindgen", "wasm-bindgen",
] ]
@ -2377,7 +2421,7 @@ dependencies = [
"reqwest", "reqwest",
"serde", "serde",
"serde_json", "serde_json",
"time 0.3.21", "time 0.3.22",
"tokio", "tokio",
"toml", "toml",
"tracing", "tracing",
@ -2421,7 +2465,7 @@ dependencies = [
"scim_proto", "scim_proto",
"serde", "serde",
"serde_json", "serde_json",
"time 0.3.21", "time 0.3.22",
"tracing", "tracing",
"url", "url",
"urlencoding", "urlencoding",
@ -2447,7 +2491,7 @@ dependencies = [
"serde", "serde",
"serde_json", "serde_json",
"shellexpand", "shellexpand",
"time 0.3.21", "time 0.3.22",
"tokio", "tokio",
"tracing", "tracing",
"tracing-subscriber", "tracing-subscriber",
@ -2464,6 +2508,7 @@ dependencies = [
"bytes", "bytes",
"clap", "clap",
"clap_complete", "clap_complete",
"csv",
"futures", "futures",
"kanidm_client", "kanidm_client",
"kanidm_lib_crypto", "kanidm_lib_crypto",
@ -2473,6 +2518,7 @@ dependencies = [
"libc", "libc",
"libsqlite3-sys", "libsqlite3-sys",
"lru 0.8.1", "lru 0.8.1",
"notify-debouncer-full",
"profiles", "profiles",
"r2d2", "r2d2",
"r2d2_sqlite", "r2d2_sqlite",
@ -2515,7 +2561,7 @@ dependencies = [
"tide", "tide",
"tide-compress", "tide-compress",
"tide-openssl", "tide-openssl",
"time 0.3.21", "time 0.3.22",
"tokio", "tokio",
"tokio-openssl", "tokio-openssl",
"tokio-util", "tokio-util",
@ -2567,7 +2613,7 @@ dependencies = [
"smolset", "smolset",
"sshkeys", "sshkeys",
"tide", "tide",
"time 0.3.21", "time 0.3.22",
"tokio", "tokio",
"tokio-util", "tokio-util",
"toml", "toml",
@ -2609,7 +2655,7 @@ dependencies = [
"serde_json", "serde_json",
"sketching", "sketching",
"testkit-macros", "testkit-macros",
"time 0.3.21", "time 0.3.22",
"tokio", "tokio",
"tracing", "tracing",
"url", "url",
@ -2629,7 +2675,7 @@ dependencies = [
"serde", "serde",
"serde-wasm-bindgen", "serde-wasm-bindgen",
"serde_json", "serde_json",
"time 0.3.21", "time 0.3.22",
"url", "url",
"uuid", "uuid",
"wasm-bindgen", "wasm-bindgen",
@ -2640,6 +2686,26 @@ dependencies = [
"yew-router", "yew-router",
] ]
[[package]]
name = "kqueue"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c8fc60ba15bf51257aa9807a48a61013db043fcf3a78cb0d916e8e396dcad98"
dependencies = [
"kqueue-sys",
"libc",
]
[[package]]
name = "kqueue-sys"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8367585489f01bc55dd27404dcf56b95e6da061a256a666ab23be9ba96a2e587"
dependencies = [
"bitflags 1.3.2",
"libc",
]
[[package]] [[package]]
name = "kv-log-macro" name = "kv-log-macro"
version = "1.0.7" version = "1.0.7"
@ -2672,9 +2738,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
[[package]] [[package]]
name = "lber" name = "lber"
version = "0.4.0" version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5d85f5e00e12cb50c70c3b1c1f0daff6546eb4c608b44d0a990e38a539e0446" checksum = "2df7f9fd9f64cf8f59e1a4a0753fe7d575a5b38d3d7ac5758dcee9357d83ef0a"
dependencies = [ dependencies = [
"bytes", "bytes",
"nom", "nom",
@ -2822,9 +2888,9 @@ checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519"
[[package]] [[package]]
name = "lock_api" name = "lock_api"
version = "0.4.9" version = "0.4.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16"
dependencies = [ dependencies = [
"autocfg", "autocfg",
"scopeguard", "scopeguard",
@ -2832,11 +2898,10 @@ dependencies = [
[[package]] [[package]]
name = "log" name = "log"
version = "0.4.17" version = "0.4.19"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4"
dependencies = [ dependencies = [
"cfg-if 1.0.0",
"serde", "serde",
"value-bag", "value-bag",
] ]
@ -2900,9 +2965,9 @@ dependencies = [
[[package]] [[package]]
name = "memoffset" name = "memoffset"
version = "0.8.0" version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1" checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c"
dependencies = [ dependencies = [
"autocfg", "autocfg",
] ]
@ -2930,14 +2995,14 @@ dependencies = [
[[package]] [[package]]
name = "mio" name = "mio"
version = "0.8.6" version = "0.8.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2"
dependencies = [ dependencies = [
"libc", "libc",
"log", "log",
"wasi 0.11.0+wasi-snapshot-preview1", "wasi 0.11.0+wasi-snapshot-preview1",
"windows-sys 0.45.0", "windows-sys 0.48.0",
] ]
[[package]] [[package]]
@ -2977,6 +3042,37 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "notify"
version = "6.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4d9ba6c734de18ca27c8cef5cd7058aa4ac9f63596131e4c7e41e579319032a2"
dependencies = [
"bitflags 1.3.2",
"crossbeam-channel",
"filetime",
"fsevent-sys",
"inotify",
"kqueue",
"libc",
"mio",
"walkdir",
"windows-sys 0.45.0",
]
[[package]]
name = "notify-debouncer-full"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4812c1eb49be776fb8df4961623bdc01ec9dfdc1abe8211ceb09150a2e64219"
dependencies = [
"crossbeam-channel",
"file-id",
"notify",
"parking_lot",
"walkdir",
]
[[package]] [[package]]
name = "nss_kanidm" name = "nss_kanidm"
version = "1.1.0-beta.13-dev" version = "1.1.0-beta.13-dev"
@ -3092,13 +3188,13 @@ dependencies = [
[[package]] [[package]]
name = "oauth2" name = "oauth2"
version = "4.4.0" version = "4.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50df55a3cc0374df91ef8da8741542d9e0b9e6581481ed1cffe84f64d2f5fc3d" checksum = "09a6e2a2b13a56ebeabba9142f911745be6456163fd6c3d361274ebcd891a80c"
dependencies = [ dependencies = [
"base64 0.13.1", "base64 0.13.1",
"chrono", "chrono",
"getrandom 0.2.9", "getrandom 0.2.10",
"http", "http",
"rand 0.8.5", "rand 0.8.5",
"serde", "serde",
@ -3120,9 +3216,9 @@ dependencies = [
[[package]] [[package]]
name = "once_cell" name = "once_cell"
version = "1.17.1" version = "1.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
[[package]] [[package]]
name = "oorandom" name = "oorandom"
@ -3216,9 +3312,9 @@ dependencies = [
[[package]] [[package]]
name = "os_str_bytes" name = "os_str_bytes"
version = "6.5.0" version = "6.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ceedf44fb00f2d1984b0bc98102627ce622e083e49a5bacdb3e514fa4238e267" checksum = "4d5d9eb14b174ee9aa2ef96dc2b94637a2d4b6e7cb873c7e171f0c20c6cf3eac"
[[package]] [[package]]
name = "overload" name = "overload"
@ -3253,15 +3349,15 @@ dependencies = [
[[package]] [[package]]
name = "parking_lot_core" name = "parking_lot_core"
version = "0.9.7" version = "0.9.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447"
dependencies = [ dependencies = [
"cfg-if 1.0.0", "cfg-if 1.0.0",
"libc", "libc",
"redox_syscall 0.2.16", "redox_syscall 0.3.5",
"smallvec", "smallvec",
"windows-sys 0.45.0", "windows-targets 0.48.0",
] ]
[[package]] [[package]]
@ -3660,7 +3756,7 @@ version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [ dependencies = [
"getrandom 0.2.9", "getrandom 0.2.10",
] ]
[[package]] [[package]]
@ -3718,7 +3814,7 @@ version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b"
dependencies = [ dependencies = [
"getrandom 0.2.9", "getrandom 0.2.10",
"redox_syscall 0.2.16", "redox_syscall 0.2.16",
"thiserror", "thiserror",
] ]
@ -3891,9 +3987,9 @@ dependencies = [
[[package]] [[package]]
name = "rustix" name = "rustix"
version = "0.37.19" version = "0.37.20"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acf8729d8542766f1b2cf77eb034d52f40d375bb8b615d0b147089946e16613d" checksum = "b96e891d04aa506a6d1f318d2771bcb1c7dfda84e126660ace067c9b474bb2c0"
dependencies = [ dependencies = [
"bitflags 1.3.2", "bitflags 1.3.2",
"errno", "errno",
@ -3952,7 +4048,7 @@ dependencies = [
"peg", "peg",
"serde", "serde",
"serde_json", "serde_json",
"time 0.3.21", "time 0.3.22",
"tracing", "tracing",
"tracing-subscriber", "tracing-subscriber",
"url", "url",
@ -4000,7 +4096,7 @@ version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b5ff8f655381fc80f470384da0a461b19b7bf18d685639ccf6df0abd3d2363d" checksum = "6b5ff8f655381fc80f470384da0a461b19b7bf18d685639ccf6df0abd3d2363d"
dependencies = [ dependencies = [
"bitflags 2.3.1", "bitflags 2.3.2",
"libc", "libc",
"once_cell", "once_cell",
"reference-counted-singleton", "reference-counted-singleton",
@ -4010,9 +4106,9 @@ dependencies = [
[[package]] [[package]]
name = "selinux-sys" name = "selinux-sys"
version = "0.6.4" version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f37ccfd0557caec11f117e6d6103aaa217d1aad80cfb6ee3d0e1af5b568a1d9" checksum = "f2b8dbf5dd0b21d466538786194081b2c4d61878e1427f7e52f99d5845432483"
dependencies = [ dependencies = [
"bindgen", "bindgen",
"cc", "cc",
@ -4412,11 +4508,70 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
[[package]] [[package]]
name = "sval" name = "sval"
version = "1.0.0-alpha.5" version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "45f6ee7c7b87caf59549e9fe45d6a69c75c8019e79e212a835c5da0e92f0ba08" checksum = "e2faba619276044eec7cd160d87b15d9191fb9b9f7198440343d2144f760cf08"
[[package]]
name = "sval_buffer"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a353d3cca10721384077c9643c3fafdd6ed2600e57933b8e45c0b580d97b25af"
dependencies = [
"sval",
"sval_ref",
]
[[package]]
name = "sval_dynamic"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee5fc7349e9f6cb2ab950046818f66ad3f2d7209ccc5dced93da19292a30273a"
dependencies = [
"sval",
]
[[package]]
name = "sval_fmt"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "098fb51d5d6007bd2c3f0a23b79aa953d7c46bf943086ce51424c3187c40f9b1"
dependencies = [
"itoa",
"ryu",
"sval",
]
[[package]]
name = "sval_json"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f01126a2783d767496f18f13af26ab2587881f6343368bb26dc62956a723d1c7"
dependencies = [
"itoa",
"ryu",
"sval",
]
[[package]]
name = "sval_ref"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5854d9eaa7bd31840a850322591c59c5b547eb29c9a6ecee1989d6ef963312ce"
dependencies = [
"sval",
]
[[package]]
name = "sval_serde"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8cdd25fc04c5e882787d62112591aa93efb5bdc2000b43164d29f08582bb85f7"
dependencies = [ dependencies = [
"serde", "serde",
"sval",
"sval_buffer",
"sval_fmt",
] ]
[[package]] [[package]]
@ -4455,15 +4610,16 @@ dependencies = [
[[package]] [[package]]
name = "tempfile" name = "tempfile"
version = "3.5.0" version = "3.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998" checksum = "31c0432476357e58790aaa47a8efb0c5138f137343f3b5f23bd36a27e3b0a6d6"
dependencies = [ dependencies = [
"autocfg",
"cfg-if 1.0.0", "cfg-if 1.0.0",
"fastrand", "fastrand",
"redox_syscall 0.3.5", "redox_syscall 0.3.5",
"rustix", "rustix",
"windows-sys 0.45.0", "windows-sys 0.48.0",
] ]
[[package]] [[package]]
@ -4620,9 +4776,9 @@ dependencies = [
[[package]] [[package]]
name = "time" name = "time"
version = "0.3.21" version = "0.3.22"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f3403384eaacbca9923fa06940178ac13e4edb725486d70e8e15881d0c836cc" checksum = "ea9e1b3cf1243ae005d9e74085d4d542f3125458f3a81af210d901dcd7411efd"
dependencies = [ dependencies = [
"itoa", "itoa",
"libc", "libc",
@ -4972,11 +5128,11 @@ dependencies = [
[[package]] [[package]]
name = "uuid" name = "uuid"
version = "1.3.3" version = "1.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "345444e32442451b267fc254ae85a209c64be56d2890e601a0c37ff0c3c5ecd2" checksum = "0fa2982af2eec27de306107c027578ff7f423d65f7250e40ce0fea8f45248b81"
dependencies = [ dependencies = [
"getrandom 0.2.9", "getrandom 0.2.10",
"serde", "serde",
] ]
@ -4988,16 +5144,38 @@ checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
[[package]] [[package]]
name = "value-bag" name = "value-bag"
version = "1.0.0-alpha.9" version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2209b78d1249f7e6f3293657c9779fe31ced465df091bbd433a1cf88e916ec55" checksum = "a4d330786735ea358f3bc09eea4caa098569c1c93f342d9aca0514915022fe7e"
dependencies = [
"value-bag-serde1",
"value-bag-sval2",
]
[[package]]
name = "value-bag-serde1"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4735c95b4cca1447b448e2e2e87e98d7e7498f4da27e355cf7af02204521001d"
dependencies = [ dependencies = [
"ctor",
"erased-serde", "erased-serde",
"serde", "serde",
"serde_fmt", "serde_fmt",
]
[[package]]
name = "value-bag-sval2"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "859cb4f0ce7da6a118b559ba74b0e63bf569bea867c20ba457a6b1c886a04e97"
dependencies = [
"sval", "sval",
"version_check", "sval_buffer",
"sval_dynamic",
"sval_fmt",
"sval_json",
"sval_ref",
"sval_serde",
] ]
[[package]] [[package]]
@ -5058,9 +5236,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]] [[package]]
name = "wasm-bindgen" name = "wasm-bindgen"
version = "0.2.86" version = "0.2.87"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5bba0e8cb82ba49ff4e229459ff22a191bbe9a1cb3a341610c9c33efc27ddf73" checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342"
dependencies = [ dependencies = [
"cfg-if 1.0.0", "cfg-if 1.0.0",
"serde", "serde",
@ -5070,9 +5248,9 @@ dependencies = [
[[package]] [[package]]
name = "wasm-bindgen-backend" name = "wasm-bindgen-backend"
version = "0.2.86" version = "0.2.87"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19b04bc93f9d6bdee709f6bd2118f57dd6679cf1176a1af464fca3ab0d66d8fb" checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd"
dependencies = [ dependencies = [
"bumpalo", "bumpalo",
"log", "log",
@ -5085,9 +5263,9 @@ dependencies = [
[[package]] [[package]]
name = "wasm-bindgen-futures" name = "wasm-bindgen-futures"
version = "0.4.36" version = "0.4.37"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d1985d03709c53167ce907ff394f5316aa22cb4e12761295c5dc57dacb6297e" checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03"
dependencies = [ dependencies = [
"cfg-if 1.0.0", "cfg-if 1.0.0",
"js-sys", "js-sys",
@ -5097,9 +5275,9 @@ dependencies = [
[[package]] [[package]]
name = "wasm-bindgen-macro" name = "wasm-bindgen-macro"
version = "0.2.86" version = "0.2.87"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14d6b024f1a526bb0234f52840389927257beb670610081360e5a03c5df9c258" checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d"
dependencies = [ dependencies = [
"quote", "quote",
"wasm-bindgen-macro-support", "wasm-bindgen-macro-support",
@ -5107,9 +5285,9 @@ dependencies = [
[[package]] [[package]]
name = "wasm-bindgen-macro-support" name = "wasm-bindgen-macro-support"
version = "0.2.86" version = "0.2.87"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e128beba882dd1eb6200e1dc92ae6c5dbaa4311aa7bb211ca035779e5efc39f8" checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -5120,15 +5298,15 @@ dependencies = [
[[package]] [[package]]
name = "wasm-bindgen-shared" name = "wasm-bindgen-shared"
version = "0.2.86" version = "0.2.87"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed9d5b4305409d1fc9482fee2d7f9bcbf24b3972bf59817ef757e23982242a93" checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1"
[[package]] [[package]]
name = "wasm-bindgen-test" name = "wasm-bindgen-test"
version = "0.3.36" version = "0.3.37"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c9e636f3a428ff62b3742ebc3c70e254dfe12b8c2b469d688ea59cdd4abcf502" checksum = "6e6e302a7ea94f83a6d09e78e7dc7d9ca7b186bc2829c24a22d0753efd680671"
dependencies = [ dependencies = [
"console_error_panic_hook", "console_error_panic_hook",
"js-sys", "js-sys",
@ -5140,9 +5318,9 @@ dependencies = [
[[package]] [[package]]
name = "wasm-bindgen-test-macro" name = "wasm-bindgen-test-macro"
version = "0.3.36" version = "0.3.37"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f18c1fad2f7c4958e7bcce014fa212f59a65d5e3721d0f77e6c0b27ede936ba3" checksum = "ecb993dd8c836930ed130e020e77d9b2e65dd0fbab1b67c790b0f5d80b11a575"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -5150,9 +5328,9 @@ dependencies = [
[[package]] [[package]]
name = "web-sys" name = "web-sys"
version = "0.3.63" version = "0.3.64"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3bdd9ef4e984da1187bf8110c5cf5b845fbc87a23602cdf912386a76fcd3a7c2" checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b"
dependencies = [ dependencies = [
"js-sys", "js-sys",
"wasm-bindgen", "wasm-bindgen",
@ -5531,7 +5709,7 @@ dependencies = [
"oid-registry", "oid-registry",
"rusticata-macros", "rusticata-macros",
"thiserror", "thiserror",
"time 0.3.21", "time 0.3.22",
] ]
[[package]] [[package]]
@ -5636,5 +5814,5 @@ dependencies = [
"lazy_static", "lazy_static",
"quick-error", "quick-error",
"regex", "regex",
"time 0.3.21", "time 0.3.22",
] ]

View file

@ -99,6 +99,7 @@ libnss = "^0.4.0"
libsqlite3-sys = "^0.25.0" libsqlite3-sys = "^0.25.0"
lru = "^0.8.0" lru = "^0.8.0"
mathru = "^0.13.0" mathru = "^0.13.0"
notify-debouncer-full = { version = "0.1" }
num_enum = "^0.5.11" num_enum = "^0.5.11"
oauth2_ext = { version = "^4.1.0", package = "oauth2", default-features = false } oauth2_ext = { version = "^4.1.0", package = "oauth2", default-features = false }
openssl-sys = "^0.9" openssl-sys = "^0.9"

View file

@ -56,6 +56,7 @@ use_etc_skel = false
uid_attr_map = "spn" uid_attr_map = "spn"
gid_attr_map = "spn" gid_attr_map = "spn"
selinux = true selinux = true
allow_local_account_override = ["account_name"]
``` ```
`pam_allowed_login_groups` defines a set of POSIX groups where membership of any of these groups `pam_allowed_login_groups` defines a set of POSIX groups where membership of any of these groups
@ -96,6 +97,12 @@ setting as no bearing on systems without SELinux, as these features will automat
if SELinux is not detected when the daemon starts. Note that `kanidm_unixd_tasks` must also be built if SELinux is not detected when the daemon starts. Note that `kanidm_unixd_tasks` must also be built
with the SELinux feature flag for this functionality. Defaults to true. with the SELinux feature flag for this functionality. Defaults to true.
`allow_local_account_override` allows kanidm to "override" the content of a user or group that is
defined locally. By default kanidm will detect when a user/group conflict with their entries from
`/etc/passwd` or `/etc/group` and will ignore the kanidm entry. However if you want kanidm to
override users or groups from the local system, you must list them in this field. Note that this can
have many unexpected consequences, so it is not recommended to enable this.
You can then check the communication status of the daemon: You can then check the communication status of the daemon:
```bash ```bash

View file

@ -8,3 +8,5 @@
# use_etc_skel = false # use_etc_skel = false
# uid_attr_map = "spn" # uid_attr_map = "spn"
# gid_attr_map = "spn" # gid_attr_map = "spn"
# allow_local_account_override = ["admin"]

View file

@ -42,17 +42,10 @@ lazy_static! {
}; };
pub static ref DISALLOWED_NAMES: HashSet<&'static str> = { pub static ref DISALLOWED_NAMES: HashSet<&'static str> = {
let mut m = HashSet::with_capacity(16); // Most of these were removed in favour of the unixd daemon filtering out
// local users instead.
let mut m = HashSet::with_capacity(2);
m.insert("root"); m.insert("root");
m.insert("nobody");
m.insert("nogroup");
m.insert("wheel");
m.insert("sshd");
m.insert("shadow");
m.insert("systemd");
m.insert("mail");
m.insert("man");
m.insert("administrator");
m.insert("dn=token"); m.insert("dn=token");
m m
}; };

View file

@ -43,6 +43,7 @@ path = "src/lib.rs"
[dependencies] [dependencies]
bytes.workspace = true bytes.workspace = true
clap = { workspace = true, features = ["derive", "env"] } clap = { workspace = true, features = ["derive", "env"] }
csv.workspace = true
futures.workspace = true futures.workspace = true
libc.workspace = true libc.workspace = true
libsqlite3-sys.workspace = true libsqlite3-sys.workspace = true
@ -51,7 +52,7 @@ kanidm_client.workspace = true
kanidm_proto.workspace = true kanidm_proto.workspace = true
kanidm_lib_crypto.workspace = true kanidm_lib_crypto.workspace = true
kanidm_lib_file_permissions.workspace = true kanidm_lib_file_permissions.workspace = true
notify-debouncer-full.workspace = true
r2d2.workspace = true r2d2.workspace = true
r2d2_sqlite.workspace = true r2d2_sqlite.workspace = true
rpassword.workspace = true rpassword.workspace = true
@ -62,7 +63,7 @@ serde_json.workspace = true
sketching.workspace = true sketching.workspace = true
toml.workspace = true toml.workspace = true
tokio = { workspace = true, features = ["rt", "macros", "sync", "time", "net", "io-util"] } tokio = { workspace = true, features = ["rt", "fs", "macros", "sync", "time", "net", "io-util"] }
tokio-util = { workspace = true, features = ["codec"] } tokio-util = { workspace = true, features = ["codec"] }
tracing.workspace = true tracing.workspace = true
reqwest = { workspace = true, default-features = false } reqwest = { workspace = true, default-features = false }

View file

@ -1,4 +1,4 @@
use std::collections::BTreeSet; use std::collections::{BTreeSet, HashSet};
use std::num::NonZeroUsize; use std::num::NonZeroUsize;
use std::ops::{Add, Sub}; use std::ops::{Add, Sub};
use std::path::Path; use std::path::Path;
@ -15,6 +15,8 @@ use crate::db::Db;
use crate::unix_config::{HomeAttr, UidAttr}; use crate::unix_config::{HomeAttr, UidAttr};
use crate::unix_proto::{HomeDirectoryInfo, NssGroup, NssUser}; use crate::unix_proto::{HomeDirectoryInfo, NssGroup, NssUser};
// use crate::unix_passwd::{EtcUser, EtcGroup};
const NXCACHE_SIZE: NonZeroUsize = unsafe { NonZeroUsize::new_unchecked(2048) }; const NXCACHE_SIZE: NonZeroUsize = unsafe { NonZeroUsize::new_unchecked(2048) };
#[derive(Debug, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@ -43,6 +45,8 @@ pub struct CacheLayer {
home_alias: Option<HomeAttr>, home_alias: Option<HomeAttr>,
uid_attr_map: UidAttr, uid_attr_map: UidAttr,
gid_attr_map: UidAttr, gid_attr_map: UidAttr,
allow_id_overrides: HashSet<Id>,
nxset: Mutex<HashSet<Id>>,
nxcache: Mutex<LruCache<Id, SystemTime>>, nxcache: Mutex<LruCache<Id, SystemTime>>,
} }
@ -72,6 +76,7 @@ impl CacheLayer {
home_alias: Option<HomeAttr>, home_alias: Option<HomeAttr>,
uid_attr_map: UidAttr, uid_attr_map: UidAttr,
gid_attr_map: UidAttr, gid_attr_map: UidAttr,
allow_id_overrides: Vec<String>,
) -> Result<Self, ()> { ) -> Result<Self, ()> {
let db = Db::new(path)?; let db = Db::new(path)?;
@ -83,7 +88,7 @@ impl CacheLayer {
} }
if pam_allow_groups.is_empty() { if pam_allow_groups.is_empty() {
eprintln!("Will not be able to authenticate users, pam_allow_groups config is not configured."); eprintln!("Will not be able to authorise user logins, pam_allow_groups config is not configured.");
} }
// We assume we are offline at start up, and we mark the next "online check" as // We assume we are offline at start up, and we mark the next "online check" as
@ -100,6 +105,11 @@ impl CacheLayer {
home_alias, home_alias,
uid_attr_map, uid_attr_map,
gid_attr_map, gid_attr_map,
allow_id_overrides: allow_id_overrides
.into_iter()
.map(|name| Id::Name(name))
.collect(),
nxset: Mutex::new(HashSet::new()),
nxcache: Mutex::new(LruCache::new(NXCACHE_SIZE)), nxcache: Mutex::new(LruCache::new(NXCACHE_SIZE)),
}) })
} }
@ -154,9 +164,31 @@ impl CacheLayer {
nxcache_txn.put(id.clone(), ex_time); nxcache_txn.put(id.clone(), ex_time);
} }
pub async fn check_nxcache(&self, id: &Id) -> bool { pub async fn check_nxcache(&self, id: &Id) -> Option<SystemTime> {
let nxcache_txn = self.nxcache.lock().await; let mut nxcache_txn = self.nxcache.lock().await;
nxcache_txn.contains(id) nxcache_txn.get(id).copied()
}
pub async fn reload_nxset(&self, iter: impl Iterator<Item = (String, u32)>) {
let mut nxset_txn = self.nxset.lock().await;
nxset_txn.clear();
for (name, gid) in iter {
let name = Id::Name(name);
let gid = Id::Gid(gid);
// Skip anything that the admin opted in to
if !(self.allow_id_overrides.contains(&gid) || self.allow_id_overrides.contains(&name))
{
debug!("Adding {:?}:{:?} to resolver exclusion set", name, gid);
nxset_txn.insert(name);
nxset_txn.insert(gid);
}
}
}
pub async fn check_nxset(&self, name: &str, idnumber: u32) -> bool {
let nxset_txn = self.nxset.lock().await;
nxset_txn.contains(&Id::Gid(idnumber)) || nxset_txn.contains(&Id::Name(name.to_string()))
} }
async fn get_cached_usertoken( async fn get_cached_usertoken(
@ -187,11 +219,10 @@ impl CacheLayer {
} }
None => { None => {
// it wasn't in the DB - lets see if it's in the nxcache. // it wasn't in the DB - lets see if it's in the nxcache.
let mut nxcache_txn = self.nxcache.lock().await; match self.check_nxcache(account_id).await {
match nxcache_txn.get(account_id) {
Some(ex_time) => { Some(ex_time) => {
let now = SystemTime::now(); let now = SystemTime::now();
if &now >= ex_time { if now >= ex_time {
// It's in the LRU, but we are past the expiry so // It's in the LRU, but we are past the expiry so
// lets attempt a refresh. // lets attempt a refresh.
Ok((true, None)) Ok((true, None))
@ -239,11 +270,10 @@ impl CacheLayer {
} }
None => { None => {
// it wasn't in the DB - lets see if it's in the nxcache. // it wasn't in the DB - lets see if it's in the nxcache.
let mut nxcache_txn = self.nxcache.lock().await; match self.check_nxcache(grp_id).await {
match nxcache_txn.get(grp_id) {
Some(ex_time) => { Some(ex_time) => {
let now = SystemTime::now(); let now = SystemTime::now();
if &now >= ex_time { if now >= ex_time {
// It's in the LRU, but we are past the expiry so // It's in the LRU, but we are past the expiry so
// lets attempt a refresh. // lets attempt a refresh.
Ok((true, None)) Ok((true, None))
@ -271,7 +301,7 @@ impl CacheLayer {
.map_err(|e| { .map_err(|e| {
error!("time conversion error - ex_time less than epoch? {:?}", e); error!("time conversion error - ex_time less than epoch? {:?}", e);
})?; })?;
// WIP #392
// Check if requested `shell` exists on the system, else use `default_shell` // Check if requested `shell` exists on the system, else use `default_shell`
let requested_shell_exists: bool = token let requested_shell_exists: bool = token
.shell .shell
@ -295,11 +325,20 @@ impl CacheLayer {
token.shell = Some(self.default_shell.clone()) token.shell = Some(self.default_shell.clone())
} }
// Filter out groups that are in the nxset
{
let nxset_txn = self.nxset.lock().await;
token.groups.retain(|g| {
!(nxset_txn.contains(&Id::Gid(g.gidnumber))
|| nxset_txn.contains(&Id::Name(g.name.clone())))
});
}
let dbtxn = self.db.write().await; let dbtxn = self.db.write().await;
// We need to add the groups first
token token
.groups .groups
.iter() .iter()
// We need to add the groups first
.try_for_each(|g| dbtxn.update_group(g, offset.as_secs())) .try_for_each(|g| dbtxn.update_group(g, offset.as_secs()))
.and_then(|_| .and_then(|_|
// So that when we add the account it can make the relationships. // So that when we add the account it can make the relationships.
@ -360,9 +399,15 @@ impl CacheLayer {
.await .await
{ {
Ok(mut n_tok) => { Ok(mut n_tok) => {
// We have the token! if self.check_nxset(&n_tok.name, n_tok.gidnumber).await {
self.set_cache_usertoken(&mut n_tok).await?; // Refuse to release the token, it's in the denied set.
Ok(Some(n_tok)) self.delete_cache_usertoken(&n_tok.uuid).await?;
Ok(None)
} else {
// We have the token!
self.set_cache_usertoken(&mut n_tok).await?;
Ok(Some(n_tok))
}
} }
Err(e) => { Err(e) => {
match e { match e {
@ -440,9 +485,15 @@ impl CacheLayer {
.await .await
{ {
Ok(n_tok) => { Ok(n_tok) => {
// We have the token! if self.check_nxset(&n_tok.name, n_tok.gidnumber).await {
self.set_cache_grouptoken(&n_tok).await?; // Refuse to release the token, it's in the denied set.
Ok(Some(n_tok)) self.delete_cache_grouptoken(&n_tok.uuid).await?;
Ok(None)
} else {
// We have the token!
self.set_cache_grouptoken(&n_tok).await?;
Ok(Some(n_tok))
}
} }
Err(e) => { Err(e) => {
match e { match e {
@ -763,10 +814,16 @@ impl CacheLayer {
.await .await
{ {
Ok(Some(mut n_tok)) => { Ok(Some(mut n_tok)) => {
debug!("online password check success."); if self.check_nxset(&n_tok.name, n_tok.gidnumber).await {
self.set_cache_usertoken(&mut n_tok).await?; // Refuse to release the token, it's in the denied set.
self.set_cache_userpassword(&n_tok.uuid, cred).await?; self.delete_cache_usertoken(&n_tok.uuid).await?;
Ok(Some(true)) Ok(None)
} else {
debug!("online password check success.");
self.set_cache_usertoken(&mut n_tok).await?;
self.set_cache_userpassword(&n_tok.uuid, cred).await?;
Ok(Some(true))
}
} }
Ok(None) => { Ok(None) => {
error!("incorrect password"); error!("incorrect password");

View file

@ -28,12 +28,15 @@ use kanidm_proto::constants::DEFAULT_CLIENT_CONFIG_PATH;
use kanidm_unix_common::cache::CacheLayer; use kanidm_unix_common::cache::CacheLayer;
use kanidm_unix_common::constants::DEFAULT_CONFIG_PATH; use kanidm_unix_common::constants::DEFAULT_CONFIG_PATH;
use kanidm_unix_common::unix_config::KanidmUnixdConfig; use kanidm_unix_common::unix_config::KanidmUnixdConfig;
use kanidm_unix_common::unix_passwd::{parse_etc_group, parse_etc_passwd};
use kanidm_unix_common::unix_proto::{ClientRequest, ClientResponse, TaskRequest, TaskResponse}; use kanidm_unix_common::unix_proto::{ClientRequest, ClientResponse, TaskRequest, TaskResponse};
use libc::umask; use libc::umask;
use sketching::tracing_forest::traits::*; use sketching::tracing_forest::traits::*;
use sketching::tracing_forest::util::*; use sketching::tracing_forest::util::*;
use sketching::tracing_forest::{self}; use sketching::tracing_forest::{self};
use tokio::fs::File;
use tokio::io::AsyncReadExt; // for read_to_end()
use tokio::net::{UnixListener, UnixStream}; use tokio::net::{UnixListener, UnixStream};
use tokio::sync::broadcast; use tokio::sync::broadcast;
use tokio::sync::mpsc::{channel, Receiver, Sender}; use tokio::sync::mpsc::{channel, Receiver, Sender};
@ -42,6 +45,8 @@ use tokio::time;
use tokio_util::codec::{Decoder, Encoder, Framed}; use tokio_util::codec::{Decoder, Encoder, Framed};
use users::{get_current_gid, get_current_uid, get_effective_gid, get_effective_uid}; use users::{get_current_gid, get_current_uid, get_effective_gid, get_effective_uid};
use notify_debouncer_full::{new_debouncer, notify::RecursiveMode, notify::Watcher};
//=== the codec //=== the codec
type AsyncTaskRequest = (TaskRequest, oneshot::Sender<()>); type AsyncTaskRequest = (TaskRequest, oneshot::Sender<()>);
@ -365,6 +370,29 @@ async fn handle_client(
Ok(()) Ok(())
} }
async fn process_etc_passwd_group(cachelayer: &CacheLayer) -> Result<(), Box<dyn Error>> {
let mut file = File::open("/etc/passwd").await?;
let mut contents = vec![];
file.read_to_end(&mut contents).await?;
let users = parse_etc_passwd(contents.as_slice()).map_err(|()| "Invalid passwd content")?;
let mut file = File::open("/etc/group").await?;
let mut contents = vec![];
file.read_to_end(&mut contents).await?;
let groups = parse_etc_group(contents.as_slice()).map_err(|()| "Invalid group content")?;
let id_iter = users
.iter()
.map(|user| (user.name.clone(), user.uid))
.chain(groups.iter().map(|group| (group.name.clone(), group.gid)));
cachelayer.reload_nxset(id_iter).await;
Ok(())
}
#[tokio::main(flavor = "current_thread")] #[tokio::main(flavor = "current_thread")]
async fn main() -> ExitCode { async fn main() -> ExitCode {
let cuid = get_current_uid(); let cuid = get_current_uid();
@ -544,7 +572,6 @@ async fn main() -> ExitCode {
rm_if_exist(cfg.task_sock_path.as_str()); rm_if_exist(cfg.task_sock_path.as_str());
// Check the db path will be okay. // Check the db path will be okay.
if !cfg.db_path.is_empty() { if !cfg.db_path.is_empty() {
let db_path = PathBuf::from(cfg.db_path.as_str()); let db_path = PathBuf::from(cfg.db_path.as_str());
@ -633,7 +660,6 @@ async fn main() -> ExitCode {
} }
}; };
let cl_inner = match CacheLayer::new( let cl_inner = match CacheLayer::new(
cfg.db_path.as_str(), // The sqlite db path cfg.db_path.as_str(), // The sqlite db path
cfg.cache_timeout, cfg.cache_timeout,
@ -645,6 +671,7 @@ async fn main() -> ExitCode {
cfg.home_alias, cfg.home_alias,
cfg.uid_attr_map, cfg.uid_attr_map,
cfg.gid_attr_map, cfg.gid_attr_map,
cfg.allow_local_account_override.clone(),
) )
.await .await
{ {
@ -669,6 +696,12 @@ async fn main() -> ExitCode {
// Undo umask changes. // Undo umask changes.
let _ = unsafe { umask(before) }; let _ = unsafe { umask(before) };
// Pre-process /etc/passwd and /etc/group for nxset
if let Err(_) = process_etc_passwd_group(&cachelayer).await {
error!("Failed to process system id providers");
return ExitCode::FAILURE
}
// Setup the tasks socket first. // Setup the tasks socket first.
let (task_channel_tx, mut task_channel_rx) = channel(16); let (task_channel_tx, mut task_channel_rx) = channel(16);
let task_channel_tx = Arc::new(task_channel_tx); let task_channel_tx = Arc::new(task_channel_tx);
@ -724,6 +757,48 @@ async fn main() -> ExitCode {
// TODO: Setup a task that handles pre-fetching here. // TODO: Setup a task that handles pre-fetching here.
let (inotify_tx, mut inotify_rx) = channel(4);
let _watcher =
match new_debouncer(Duration::from_secs(2), None, move |_event| {
let _ = inotify_tx.try_send(true);
})
.and_then(|mut debouncer| {
debouncer.watcher().watch(Path::new("/etc/passwd"), RecursiveMode::NonRecursive)
.map(|()| debouncer)
})
.and_then(|mut debouncer| debouncer.watcher().watch(Path::new("/etc/group"), RecursiveMode::NonRecursive)
.map(|()| debouncer)
)
{
Ok(watcher) => {
watcher
}
Err(e) => {
error!("Failed to setup inotify {:?}", e);
return ExitCode::FAILURE
}
};
let mut c_broadcast_rx = broadcast_tx.subscribe();
let inotify_cachelayer = cachelayer.clone();
let task_c = tokio::spawn(async move {
loop {
tokio::select! {
_ = c_broadcast_rx.recv() => {
break;
}
_ = inotify_rx.recv() => {
if let Err(_) = process_etc_passwd_group(&inotify_cachelayer).await {
error!("Failed to process system id providers");
}
}
}
}
});
// Set the umask while we open the path for most clients. // Set the umask while we open the path for most clients.
let before = unsafe { umask(0) }; let before = unsafe { umask(0) };
let listener = match UnixListener::bind(cfg.sock_path.as_str()) { let listener = match UnixListener::bind(cfg.sock_path.as_str()) {
@ -812,6 +887,7 @@ async fn main() -> ExitCode {
let _ = task_a.await; let _ = task_a.await;
let _ = task_b.await; let _ = task_b.await;
let _ = task_c.await;
ExitCode::SUCCESS ExitCode::SUCCESS
}) })

View file

@ -32,4 +32,6 @@ pub mod selinux_util;
#[cfg(target_family = "unix")] #[cfg(target_family = "unix")]
pub mod unix_config; pub mod unix_config;
#[cfg(target_family = "unix")] #[cfg(target_family = "unix")]
pub mod unix_passwd;
#[cfg(target_family = "unix")]
pub mod unix_proto; pub mod unix_proto;

View file

@ -25,7 +25,7 @@ use kanidm_unix_common::unix_proto::{ClientRequest, ClientResponse};
include!("./opt/ssh_authorizedkeys.rs"); include!("./opt/ssh_authorizedkeys.rs");
#[tokio::main] #[tokio::main(flavor = "current_thread")]
async fn main() -> ExitCode { async fn main() -> ExitCode {
let opt = SshAuthorizedOpt::parse(); let opt = SshAuthorizedOpt::parse();
if opt.debug { if opt.debug {

View file

@ -31,6 +31,8 @@ struct ConfigInt {
uid_attr_map: Option<String>, uid_attr_map: Option<String>,
gid_attr_map: Option<String>, gid_attr_map: Option<String>,
selinux: Option<bool>, selinux: Option<bool>,
#[serde(default)]
allow_local_account_override: Vec<String>,
} }
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
@ -90,6 +92,7 @@ pub struct KanidmUnixdConfig {
pub uid_attr_map: UidAttr, pub uid_attr_map: UidAttr,
pub gid_attr_map: UidAttr, pub gid_attr_map: UidAttr,
pub selinux: bool, pub selinux: bool,
pub allow_local_account_override: Vec<String>,
} }
impl Default for KanidmUnixdConfig { impl Default for KanidmUnixdConfig {
@ -122,7 +125,12 @@ impl Display for KanidmUnixdConfig {
writeln!(f, "uid_attr_map: {}", self.uid_attr_map)?; writeln!(f, "uid_attr_map: {}", self.uid_attr_map)?;
writeln!(f, "gid_attr_map: {}", self.gid_attr_map)?; writeln!(f, "gid_attr_map: {}", self.gid_attr_map)?;
writeln!(f, "selinux: {}", self.selinux) writeln!(f, "selinux: {}", self.selinux)?;
writeln!(
f,
"allow_local_account_override: {:#?}",
self.allow_local_account_override
)
} }
} }
@ -148,6 +156,7 @@ impl KanidmUnixdConfig {
uid_attr_map: DEFAULT_UID_ATTR_MAP, uid_attr_map: DEFAULT_UID_ATTR_MAP,
gid_attr_map: DEFAULT_GID_ATTR_MAP, gid_attr_map: DEFAULT_GID_ATTR_MAP,
selinux: DEFAULT_SELINUX, selinux: DEFAULT_SELINUX,
allow_local_account_override: Vec::default(),
} }
} }
@ -259,6 +268,7 @@ impl KanidmUnixdConfig {
true => selinux_util::supported(), true => selinux_util::supported(),
_ => false, _ => false,
}, },
allow_local_account_override: config.allow_local_account_override,
}) })
} }
} }

View file

@ -0,0 +1,110 @@
use serde::{
de::{self, Visitor},
Deserialize, Deserializer, Serialize,
};
use std::fmt;
#[derive(Serialize, Deserialize, Debug)]
pub struct EtcUser {
pub name: String,
pub password: String,
pub uid: u32,
pub gid: u32,
pub gecos: String,
pub homedir: String,
pub shell: String,
}
pub fn parse_etc_passwd(bytes: &[u8]) -> Result<Vec<EtcUser>, ()> {
use csv::ReaderBuilder;
let mut rdr = ReaderBuilder::new()
.has_headers(false)
.delimiter(b':')
.from_reader(bytes);
rdr.deserialize()
.map(|result| result.map_err(|_e| ()))
.collect::<Result<Vec<EtcUser>, ()>>()
}
fn members<'de, D>(deserializer: D) -> Result<Vec<String>, D::Error>
where
D: Deserializer<'de>,
{
struct InnerCsv;
impl<'de> Visitor<'de> for InnerCsv {
type Value = Vec<String>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("string")
}
fn visit_str<E>(self, value: &str) -> Result<Vec<String>, E>
where
E: de::Error,
{
Ok(value.split(',').map(|s| s.to_string()).collect())
}
}
deserializer.deserialize_str(InnerCsv)
}
#[derive(Serialize, Deserialize, Debug)]
pub struct EtcGroup {
pub name: String,
pub password: String,
pub gid: u32,
#[serde(deserialize_with = "members")]
pub members: Vec<String>,
}
pub fn parse_etc_group(bytes: &[u8]) -> Result<Vec<EtcGroup>, ()> {
use csv::ReaderBuilder;
let mut rdr = ReaderBuilder::new()
.has_headers(false)
.delimiter(b':')
.from_reader(bytes);
rdr.deserialize()
.map(|result| result.map_err(|_e| ()))
.collect::<Result<Vec<EtcGroup>, ()>>()
}
#[cfg(test)]
mod tests {
use super::*;
const EXAMPLE_PASSWD: &str = r#"root:x:0:0:root:/root:/bin/bash
systemd-timesync:x:498:498:systemd Time Synchronization:/:/usr/sbin/nologin
messagebus:x:484:484:User for D-Bus:/run/dbus:/usr/sbin/nologin
tftp:x:483:483:TFTP Account:/srv/tftpboot:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/var/lib/nobody:/bin/bash
"#;
const EXAMPLE_GROUP: &str = r#"root:x:0:
shadow:x:15:
trusted:x:42:
users:x:100:
systemd-journal:x:499:
systemd-timesync:x:498:
kmem:x:497:
lock:x:496:
tty:x:5:
wheel:x:481:admin,testuser
"#;
#[test]
fn test_parse_passwd() {
for record in parse_etc_passwd(EXAMPLE_PASSWD.as_bytes()).unwrap() {
println!("{:?}", record);
}
}
#[test]
fn test_parse_group() {
for record in parse_etc_group(EXAMPLE_GROUP.as_bytes()).unwrap() {
println!("{:?}", record);
}
}
}

View file

@ -110,6 +110,7 @@ async fn setup_test(fix_fn: Fixture) -> (CacheLayer, KanidmClient) {
DEFAULT_HOME_ALIAS, DEFAULT_HOME_ALIAS,
DEFAULT_UID_ATTR_MAP, DEFAULT_UID_ATTR_MAP,
DEFAULT_GID_ATTR_MAP, DEFAULT_GID_ATTR_MAP,
vec!["masked_group".to_string()],
) )
.await .await
.expect("Failed to build cache layer."); .expect("Failed to build cache layer.");
@ -171,6 +172,13 @@ async fn test_fixture(rsclient: KanidmClient) {
.idm_group_unix_extend("allowed_group", Some(20002)) .idm_group_unix_extend("allowed_group", Some(20002))
.await .await
.unwrap(); .unwrap();
// Setup a group that is masked by nxset, but allowed in overrides
rsclient.idm_group_create("masked_group").await.unwrap();
rsclient
.idm_group_unix_extend("masked_group", Some(20003))
.await
.unwrap();
} }
#[tokio::test] #[tokio::test]
@ -620,70 +628,215 @@ async fn test_cache_nxcache() {
assert!(cachelayer.test_connection().await); assert!(cachelayer.test_connection().await);
// Is it in the nxcache? // Is it in the nxcache?
assert!( assert!(cachelayer
!cachelayer .check_nxcache(&Id::Name("oracle".to_string()))
.check_nxcache(&Id::Name("root".to_string())) .await
.await .is_none());
); assert!(cachelayer.check_nxcache(&Id::Gid(2000)).await.is_none());
assert!(!cachelayer.check_nxcache(&Id::Gid(0)).await); assert!(cachelayer
assert!( .check_nxcache(&Id::Name("oracle_group".to_string()))
!cachelayer .await
.check_nxcache(&Id::Name("root_group".to_string())) .is_none());
.await assert!(cachelayer.check_nxcache(&Id::Gid(3000)).await.is_none());
);
assert!(!cachelayer.check_nxcache(&Id::Gid(1)).await);
// Look for the acc id + nss id // Look for the acc id + nss id
let ut = cachelayer let ut = cachelayer
.get_nssaccount_name("root") .get_nssaccount_name("oracle")
.await .await
.expect("Failed to get from cache"); .expect("Failed to get from cache");
assert!(ut.is_none()); assert!(ut.is_none());
let ut = cachelayer let ut = cachelayer
.get_nssaccount_gid(0) .get_nssaccount_gid(2000)
.await .await
.expect("Failed to get from cache"); .expect("Failed to get from cache");
assert!(ut.is_none()); assert!(ut.is_none());
let gt = cachelayer let gt = cachelayer
.get_nssgroup_name("root_group") .get_nssgroup_name("oracle_group")
.await .await
.expect("Failed to get from cache"); .expect("Failed to get from cache");
assert!(gt.is_none()); assert!(gt.is_none());
let gt = cachelayer let gt = cachelayer
.get_nssgroup_gid(1) .get_nssgroup_gid(3000)
.await .await
.expect("Failed to get from cache"); .expect("Failed to get from cache");
assert!(gt.is_none()); assert!(gt.is_none());
// Should all now be nxed // Should all now be nxed
assert!( assert!(cachelayer
cachelayer .check_nxcache(&Id::Name("oracle".to_string()))
.check_nxcache(&Id::Name("root".to_string())) .await
.await .is_some());
); assert!(cachelayer.check_nxcache(&Id::Gid(2000)).await.is_some());
assert!(cachelayer.check_nxcache(&Id::Gid(0)).await); assert!(cachelayer
assert!( .check_nxcache(&Id::Name("oracle_group".to_string()))
cachelayer .await
.check_nxcache(&Id::Name("root_group".to_string())) .is_some());
.await assert!(cachelayer.check_nxcache(&Id::Gid(3000)).await.is_some());
);
assert!(cachelayer.check_nxcache(&Id::Gid(1)).await);
// invalidate cache // invalidate cache
assert!(cachelayer.invalidate().await.is_ok()); assert!(cachelayer.invalidate().await.is_ok());
// Both should NOT be in nxcache now. // Both should NOT be in nxcache now.
assert!( assert!(cachelayer
!cachelayer .check_nxcache(&Id::Name("oracle".to_string()))
.check_nxcache(&Id::Name("root".to_string())) .await
.await .is_none());
); assert!(cachelayer.check_nxcache(&Id::Gid(2000)).await.is_none());
assert!(!cachelayer.check_nxcache(&Id::Gid(0)).await); assert!(cachelayer
assert!( .check_nxcache(&Id::Name("oracle_group".to_string()))
!cachelayer .await
.check_nxcache(&Id::Name("root_group".to_string())) .is_none());
.await assert!(cachelayer.check_nxcache(&Id::Gid(3000)).await.is_none());
); }
assert!(!cachelayer.check_nxcache(&Id::Gid(1)).await);
#[tokio::test]
async fn test_cache_nxset_account() {
let (cachelayer, _adminclient) = setup_test(fixture(test_fixture)).await;
// Important! This is what sets up that testaccount1 won't be resolved
// because it's in the "local" user set.
cachelayer
.reload_nxset(vec![("testaccount1".to_string(), 20000)].into_iter())
.await;
// Force offline. Show we have no account
cachelayer.mark_offline().await;
let ut = cachelayer
.get_nssaccount_name("testaccount1")
.await
.expect("Failed to get from cache");
assert!(ut.is_none());
// go online
cachelayer.attempt_online().await;
assert!(cachelayer.test_connection().await);
// get the account
let ut = cachelayer
.get_nssaccount_name("testaccount1")
.await
.expect("Failed to get from cache");
assert!(ut.is_none());
// go offline
cachelayer.mark_offline().await;
// still not present, was not cached.
let ut = cachelayer
.get_nssaccount_name("testaccount1")
.await
.expect("Failed to get from cache");
assert!(ut.is_none());
// Finally, check it's not in all accounts.
let us = cachelayer
.get_nssaccounts()
.await
.expect("failed to list all accounts");
assert!(us.is_empty());
}
#[tokio::test]
async fn test_cache_nxset_group() {
let (cachelayer, _adminclient) = setup_test(fixture(test_fixture)).await;
// Important! This is what sets up that testgroup1 won't be resolved
// because it's in the "local" group set.
cachelayer
.reload_nxset(vec![("testgroup1".to_string(), 20001)].into_iter())
.await;
// Force offline. Show we have no groups.
cachelayer.mark_offline().await;
let gt = cachelayer
.get_nssgroup_name("testgroup1")
.await
.expect("Failed to get from cache");
assert!(gt.is_none());
// go online. Get the group
cachelayer.attempt_online().await;
assert!(cachelayer.test_connection().await);
let gt = cachelayer
.get_nssgroup_name("testgroup1")
.await
.expect("Failed to get from cache");
assert!(gt.is_none());
// go offline. still works
cachelayer.mark_offline().await;
let gt = cachelayer
.get_nssgroup_name("testgroup1")
.await
.expect("Failed to get from cache");
assert!(gt.is_none());
// clear cache, go online
assert!(cachelayer.invalidate().await.is_ok());
cachelayer.attempt_online().await;
assert!(cachelayer.test_connection().await);
// get an account with the group
// DO NOT get the group yet.
let ut = cachelayer
.get_nssaccount_name("testaccount1")
.await
.expect("Failed to get from cache");
assert!(ut.is_some());
// go offline.
cachelayer.mark_offline().await;
// show we have the group despite no direct calls
let gt = cachelayer
.get_nssgroup_name("testgroup1")
.await
.expect("Failed to get from cache");
assert!(gt.is_none());
// Finally, check we only have the upg in the list
let gs = cachelayer
.get_nssgroups()
.await
.expect("failed to list all groups");
assert!(gs.len() == 1);
assert!(gs[0].name == "testaccount1@idm.example.com");
}
#[tokio::test]
async fn test_cache_nxset_allow_overrides() {
let (cachelayer, _adminclient) = setup_test(fixture(test_fixture)).await;
// Important! masked_group is set as an allowed override group even though
// it's been "inserted" to the nxset. This means it will still resolve!
cachelayer
.reload_nxset(vec![("masked_group".to_string(), 20003)].into_iter())
.await;
// Force offline. Show we have no groups.
cachelayer.mark_offline().await;
let gt = cachelayer
.get_nssgroup_name("masked_group")
.await
.expect("Failed to get from cache");
assert!(gt.is_none());
// go online. Get the group
cachelayer.attempt_online().await;
assert!(cachelayer.test_connection().await);
let gt = cachelayer
.get_nssgroup_name("masked_group")
.await
.expect("Failed to get from cache");
assert!(gt.is_some());
// go offline. still works
cachelayer.mark_offline().await;
let gt = cachelayer
.get_nssgroup_name("masked_group")
.await
.expect("Failed to get from cache");
assert!(gt.is_some());
} }