diff --git a/.envrc b/.envrc index 172993c4..bad73b75 100644 --- a/.envrc +++ b/.envrc @@ -2,8 +2,6 @@ dotenv_if_exists -if [ -f /etc/os-release ] && grep -q '^ID=nixos' /etc/os-release; then - use flake ".#${DIRENV_DEVSHELL:-default}" -fi +# use flake ".#${DIRENV_DEVSHELL:-default}" PATH_add bin diff --git a/.forgejo/workflows/prek-checks.yml b/.forgejo/workflows/prek-checks.yml index ac330ca2..18f573bb 100644 --- a/.forgejo/workflows/prek-checks.yml +++ b/.forgejo/workflows/prek-checks.yml @@ -18,7 +18,7 @@ jobs: persist-credentials: false - name: Install uv - uses: https://github.com/astral-sh/setup-uv@v5 + uses: https://github.com/astral-sh/setup-uv@v6 with: enable-cache: true ignore-nothing-to-cache: true diff --git a/Cargo.lock b/Cargo.lock index 2b044a1f..5d7192b6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -126,7 +126,7 @@ checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] @@ -183,7 +183,7 @@ dependencies = [ "rustc-hash 2.1.1", "serde", "serde_derive", - "syn 2.0.104", + "syn", ] [[package]] @@ -198,45 +198,6 @@ dependencies = [ "winnow", ] -[[package]] -name = "asn1-rs" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f6fd5ddaf0351dff5b8da21b2fb4ff8e08ddd02857f0bf69c47639106c0fff0" -dependencies = [ - "asn1-rs-derive", - "asn1-rs-impl", - "displaydoc", - "nom", - "num-traits", - "rusticata-macros", - "thiserror 1.0.69", - "time", -] - -[[package]] -name = "asn1-rs-derive" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "726535892e8eae7e70657b4c8ea93d26b8553afb1ce617caee529ef96d7dee6c" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", - "synstructure 0.12.6", -] - -[[package]] -name = "asn1-rs-impl" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2777730b2039ac0f95f093556e61b6d26cebed5393ca6f152717777cec3a42ed" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "assign" version = "1.1.1" @@ -289,7 +250,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] @@ -300,7 +261,7 @@ checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] @@ -472,11 +433,11 @@ dependencies = [ "hyper", "hyper-util", "pin-project-lite", - "rustls 0.23.29", - "rustls-pemfile 2.2.0", + "rustls", + "rustls-pemfile", "rustls-pki-types", "tokio", - "tokio-rustls 0.26.2", + "tokio-rustls", "tower-service", ] @@ -491,9 +452,9 @@ dependencies = [ "http", "http-body-util", "pin-project", - "rustls 0.23.29", + "rustls", "tokio", - "tokio-rustls 0.26.2", + "tokio-rustls", "tokio-util", "tower-layer", "tower-service", @@ -560,7 +521,7 @@ dependencies = [ "regex", "rustc-hash 1.1.0", "shlex", - "syn 2.0.104", + "syn", "which", ] @@ -579,7 +540,7 @@ dependencies = [ "regex", "rustc-hash 2.1.1", "shlex", - "syn 2.0.104", + "syn", ] [[package]] @@ -833,7 +794,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] @@ -1011,7 +972,7 @@ dependencies = [ "rand 0.8.5", "regex", "reqwest", - "ring 0.17.14", + "ring", "ruma", "sanitize-filename", "serde", @@ -1058,7 +1019,7 @@ dependencies = [ "itertools 0.14.0", "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] @@ -1083,7 +1044,7 @@ dependencies = [ "hyper-util", "log", "ruma", - "rustls 0.23.29", + "rustls", "sd-notify", "sentry", "sentry-tower", @@ -1113,7 +1074,6 @@ dependencies = [ "image", "ipaddress", "itertools 0.14.0", - "ldap3", "log", "loole", "lru-cache", @@ -1223,16 +1183,6 @@ dependencies = [ "crossterm", ] -[[package]] -name = "core-foundation" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "core-foundation" version = "0.10.1" @@ -1306,7 +1256,7 @@ dependencies = [ "proc-macro2", "quote", "strict", - "syn 2.0.104", + "syn", ] [[package]] @@ -1416,7 +1366,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a2785755761f3ddc1492979ce1e48d2c00d09311c39e4466429188f3dd6501" dependencies = [ "quote", - "syn 2.0.104", + "syn", ] [[package]] @@ -1443,7 +1393,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] @@ -1484,20 +1434,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "der-parser" -version = "8.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbd676fbbab537128ef0278adb5576cf363cff6aa22a7b24effe97347cfab61e" -dependencies = [ - "asn1-rs", - "displaydoc", - "nom", - "num-bigint", - "num-traits", - "rusticata-macros", -] - [[package]] name = "deranged" version = "0.4.0" @@ -1525,7 +1461,7 @@ dependencies = [ "convert_case", "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] @@ -1547,7 +1483,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] @@ -1608,7 +1544,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] @@ -1628,7 +1564,7 @@ checksum = "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] @@ -1798,7 +1734,6 @@ checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" dependencies = [ "futures-channel", "futures-core", - "futures-executor", "futures-io", "futures-sink", "futures-task", @@ -1846,7 +1781,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] @@ -2095,7 +2030,7 @@ dependencies = [ "ipnet", "once_cell", "rand 0.9.2", - "ring 0.17.14", + "ring", "serde", "thiserror 2.0.12", "tinyvec", @@ -2187,7 +2122,7 @@ dependencies = [ "markup5ever", "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] @@ -2281,11 +2216,11 @@ dependencies = [ "http", "hyper", "hyper-util", - "rustls 0.23.29", - "rustls-native-certs 0.8.1", + "rustls", + "rustls-native-certs", "rustls-pki-types", "tokio", - "tokio-rustls 0.26.2", + "tokio-rustls", "tower-service", "webpki-roots 1.0.2", ] @@ -2509,7 +2444,7 @@ checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] @@ -2678,7 +2613,7 @@ dependencies = [ "proc-macro2", "quote", "regex", - "syn 2.0.104", + "syn", ] [[package]] @@ -2693,43 +2628,6 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" -[[package]] -name = "lber" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2df7f9fd9f64cf8f59e1a4a0753fe7d575a5b38d3d7ac5758dcee9357d83ef0a" -dependencies = [ - "bytes", - "nom", -] - -[[package]] -name = "ldap3" -version = "0.11.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "166199a8207874a275144c8a94ff6eed5fcbf5c52303e4d9b4d53a0c7ac76554" -dependencies = [ - "async-trait", - "bytes", - "futures", - "futures-util", - "lazy_static", - "lber", - "log", - "nom", - "percent-encoding", - "ring 0.16.20", - "rustls 0.21.12", - "rustls-native-certs 0.6.3", - "thiserror 1.0.69", - "tokio", - "tokio-rustls 0.24.1", - "tokio-stream", - "tokio-util", - "url", - "x509-parser", -] - [[package]] name = "lebe" version = "0.5.2" @@ -2968,7 +2866,7 @@ checksum = "a9882ef5c56df184b8ffc107fc6c61e33ee3a654b021961d790a78571bb9d67a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] @@ -3134,7 +3032,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] @@ -3196,15 +3094,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "oid-registry" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bedf36ffb6ba96c2eb7144ef6270557b52e54b20c0a8e1eb2ff99a6c6959bff" -dependencies = [ - "asn1-rs", -] - [[package]] name = "once_cell" version = "1.21.3" @@ -3395,7 +3284,7 @@ dependencies = [ "proc-macro2", "proc-macro2-diagnostics", "quote", - "syn 2.0.104", + "syn", ] [[package]] @@ -3469,7 +3358,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] @@ -3569,7 +3458,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff24dfcda44452b9816fff4cd4227e1bb73ff5a2f1bc1105aa92fb8565ce44d2" dependencies = [ "proc-macro2", - "syn 2.0.104", + "syn", ] [[package]] @@ -3598,7 +3487,7 @@ checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", "version_check", "yansi", ] @@ -3619,7 +3508,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52717f9a02b6965224f95ca2a81e2e0c5c43baacd28ca057577988930b6c3d5b" dependencies = [ "quote", - "syn 2.0.104", + "syn", ] [[package]] @@ -3642,7 +3531,7 @@ dependencies = [ "itertools 0.14.0", "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] @@ -3708,7 +3597,7 @@ dependencies = [ "quinn-proto", "quinn-udp", "rustc-hash 2.1.1", - "rustls 0.23.29", + "rustls", "socket2", "thiserror 2.0.12", "tokio", @@ -3726,9 +3615,9 @@ dependencies = [ "getrandom 0.3.3", "lru-slab", "rand 0.9.2", - "ring 0.17.14", + "ring", "rustc-hash 2.1.1", - "rustls 0.23.29", + "rustls", "rustls-pki-types", "slab", "thiserror 2.0.12", @@ -3987,16 +3876,16 @@ dependencies = [ "percent-encoding", "pin-project-lite", "quinn", - "rustls 0.23.29", - "rustls-native-certs 0.8.1", - "rustls-pemfile 2.2.0", + "rustls", + "rustls-native-certs", + "rustls-pemfile", "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", "sync_wrapper", "tokio", - "tokio-rustls 0.26.2", + "tokio-rustls", "tokio-socks", "tokio-util", "tower 0.5.2", @@ -4020,21 +3909,6 @@ version = "0.8.52" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c6a884d2998352bb4daf0183589aec883f16a6da1f4dde84d8e2e9a5409a1ce" -[[package]] -name = "ring" -version = "0.16.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" -dependencies = [ - "cc", - "libc", - "once_cell", - "spin", - "untrusted 0.7.1", - "web-sys", - "winapi", -] - [[package]] name = "ring" version = "0.17.14" @@ -4045,7 +3919,7 @@ dependencies = [ "cfg-if", "getrandom 0.2.16", "libc", - "untrusted 0.9.0", + "untrusted", "windows-sys 0.52.0", ] @@ -4219,7 +4093,7 @@ dependencies = [ "quote", "ruma-identifiers-validation", "serde", - "syn 2.0.104", + "syn", "toml", ] @@ -4304,15 +4178,6 @@ dependencies = [ "semver", ] -[[package]] -name = "rusticata-macros" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "faf0c4a6ece9950b9abdb62b1cfcf2a68b3b67a10ba445b3bb85be2a293d0632" -dependencies = [ - "nom", -] - [[package]] name = "rustix" version = "0.38.44" @@ -4339,18 +4204,6 @@ dependencies = [ "windows-sys 0.60.2", ] -[[package]] -name = "rustls" -version = "0.21.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" -dependencies = [ - "log", - "ring 0.17.14", - "rustls-webpki 0.101.7", - "sct", -] - [[package]] name = "rustls" version = "0.23.29" @@ -4360,25 +4213,13 @@ dependencies = [ "aws-lc-rs", "log", "once_cell", - "ring 0.17.14", + "ring", "rustls-pki-types", - "rustls-webpki 0.103.4", + "rustls-webpki", "subtle", "zeroize", ] -[[package]] -name = "rustls-native-certs" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" -dependencies = [ - "openssl-probe", - "rustls-pemfile 1.0.4", - "schannel", - "security-framework 2.11.1", -] - [[package]] name = "rustls-native-certs" version = "0.8.1" @@ -4388,16 +4229,7 @@ dependencies = [ "openssl-probe", "rustls-pki-types", "schannel", - "security-framework 3.2.0", -] - -[[package]] -name = "rustls-pemfile" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" -dependencies = [ - "base64 0.21.7", + "security-framework", ] [[package]] @@ -4419,16 +4251,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "rustls-webpki" -version = "0.101.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" -dependencies = [ - "ring 0.17.14", - "untrusted 0.9.0", -] - [[package]] name = "rustls-webpki" version = "0.103.4" @@ -4436,9 +4258,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0a17884ae0c1b773f1ccd2bd4a8c72f16da897310a98b0e84bf349ad5ead92fc" dependencies = [ "aws-lc-rs", - "ring 0.17.14", + "ring", "rustls-pki-types", - "untrusted 0.9.0", + "untrusted", ] [[package]] @@ -4497,16 +4319,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" -[[package]] -name = "sct" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" -dependencies = [ - "ring 0.17.14", - "untrusted 0.9.0", -] - [[package]] name = "sd-notify" version = "0.4.5" @@ -4516,19 +4328,6 @@ dependencies = [ "libc", ] -[[package]] -name = "security-framework" -version = "2.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" -dependencies = [ - "bitflags 2.9.1", - "core-foundation 0.9.4", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - [[package]] name = "security-framework" version = "3.2.0" @@ -4536,7 +4335,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "271720403f46ca04f7ba6f55d438f8bd878d6b8ca0a1046e8228c4145bcbb316" dependencies = [ "bitflags 2.9.1", - "core-foundation 0.10.1", + "core-foundation", "core-foundation-sys", "libc", "security-framework-sys", @@ -4566,7 +4365,7 @@ checksum = "255914a8e53822abd946e2ce8baa41d4cded6b8e938913b7f7b9da5b7ab44335" dependencies = [ "httpdate", "reqwest", - "rustls 0.23.29", + "rustls", "sentry-backtrace", "sentry-contexts", "sentry-core", @@ -4710,7 +4509,7 @@ checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] @@ -4924,12 +4723,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "spin" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" - [[package]] name = "spki" version = "0.7.3" @@ -4998,17 +4791,6 @@ version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - [[package]] name = "syn" version = "2.0.104" @@ -5029,18 +4811,6 @@ dependencies = [ "futures-core", ] -[[package]] -name = "synstructure" -version = "0.12.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", - "unicode-xid", -] - [[package]] name = "synstructure" version = "0.13.2" @@ -5049,7 +4819,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] @@ -5140,7 +4910,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] @@ -5151,7 +4921,7 @@ checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] @@ -5318,7 +5088,7 @@ checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] @@ -5333,23 +5103,13 @@ dependencies = [ "tokio-stream", ] -[[package]] -name = "tokio-rustls" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" -dependencies = [ - "rustls 0.21.12", - "tokio", -] - [[package]] name = "tokio-rustls" version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" dependencies = [ - "rustls 0.23.29", + "rustls", "tokio", ] @@ -5547,7 +5307,7 @@ source = "git+https://forgejo.ellis.link/continuwuation/tracing?rev=1e64095a8051 dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] @@ -5701,24 +5461,12 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a1a07cc7db3810833284e8d372ccdc6da29741639ecc70c9ec107df0fa6154c" -[[package]] -name = "unicode-xid" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" - [[package]] name = "unsafe-libyaml" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" -[[package]] -name = "untrusted" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" - [[package]] name = "untrusted" version = "0.9.0" @@ -5734,7 +5482,7 @@ dependencies = [ "base64 0.22.1", "log", "once_cell", - "rustls 0.23.29", + "rustls", "rustls-pki-types", "url", "webpki-roots 0.26.11", @@ -5869,7 +5617,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn 2.0.104", + "syn", "wasm-bindgen-shared", ] @@ -5904,7 +5652,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -6084,7 +5832,7 @@ checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] @@ -6095,7 +5843,7 @@ checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] @@ -6416,23 +6164,6 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" -[[package]] -name = "x509-parser" -version = "0.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7069fba5b66b9193bd2c5d3d4ff12b839118f6bcbef5328efafafb5395cf63da" -dependencies = [ - "asn1-rs", - "data-encoding", - "der-parser", - "lazy_static", - "nom", - "oid-registry", - "rusticata-macros", - "thiserror 1.0.69", - "time", -] - [[package]] name = "xml5ever" version = "0.18.1" @@ -6490,8 +6221,8 @@ checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", - "synstructure 0.13.2", + "syn", + "synstructure", ] [[package]] @@ -6511,7 +6242,7 @@ checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] @@ -6531,8 +6262,8 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", - "synstructure 0.13.2", + "syn", + "synstructure", ] [[package]] @@ -6571,7 +6302,7 @@ checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.104", + "syn", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 84fb9b21..fcc548f6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -546,11 +546,6 @@ features = ["std"] [workspace.dependencies.maplit] version = "1.0.2" -[workspace.dependencies.ldap3] -version = "0.11.5" -default-features = false -features = ["sync", "tls-rustls"] - # # Patches # @@ -872,7 +867,7 @@ unused-qualifications = "warn" #unused-results = "warn" # TODO ## some sadness -mismatched_lifetime_syntaxes = "allow" # TODO! +elided_named_lifetimes = "allow" # TODO! let_underscore_drop = "allow" missing_docs = "allow" # cfgs cannot be limited to expected cfgs or their de facto non-transitive/opt-in use-case e.g. @@ -1011,6 +1006,3 @@ literal_string_with_formatting_args = { level = "allow", priority = 1 } needless_raw_string_hashes = "allow" - -# TODO: Enable this lint & fix all instances -collapsible_if = "allow" diff --git a/conduwuit-example.toml b/conduwuit-example.toml index f0e510b4..541050b1 100644 --- a/conduwuit-example.toml +++ b/conduwuit-example.toml @@ -1696,10 +1696,6 @@ # #config_reload_signal = true -# This item is undocumented. Please contribute documentation for it. -# -#ldap = false - [global.tls] # Path to a valid TLS certificate file. @@ -1778,91 +1774,3 @@ # is 33.55MB. Setting it to 0 disables blurhashing. # #blurhash_max_raw_size = 33554432 - -[global.ldap] - -# Whether to enable LDAP login. -# -# example: "true" -# -#enable = false - -# Whether to force LDAP authentication or authorize classical password -# login. -# -# example: "true" -# -#ldap_only = false - -# URI of the LDAP server. -# -# example: "ldap://ldap.example.com:389" -# -#uri = "" - -# Root of the searches. -# -# example: "ou=users,dc=example,dc=org" -# -#base_dn = "" - -# Bind DN if anonymous search is not enabled. -# -# You can use the variable `{username}` that will be replaced by the -# entered username. In such case, the password used to bind will be the -# one provided for the login and not the one given by -# `bind_password_file`. Beware: automatically granting admin rights will -# not work if you use this direct bind instead of a LDAP search. -# -# example: "cn=ldap-reader,dc=example,dc=org" or -# "cn={username},ou=users,dc=example,dc=org" -# -#bind_dn = "" - -# Path to a file on the system that contains the password for the -# `bind_dn`. -# -# The server must be able to access the file, and it must not be empty. -# -#bind_password_file = "" - -# Search filter to limit user searches. -# -# You can use the variable `{username}` that will be replaced by the -# entered username for more complex filters. -# -# example: "(&(objectClass=person)(memberOf=matrix))" -# -#filter = "(objectClass=*)" - -# Attribute to use to uniquely identify the user. -# -# example: "uid" or "cn" -# -#uid_attribute = "uid" - -# Attribute containing the display name of the user. -# -# example: "givenName" or "sn" -# -#name_attribute = "givenName" - -# Root of the searches for admin users. -# -# Defaults to `base_dn` if empty. -# -# example: "ou=admins,dc=example,dc=org" -# -#admin_base_dn = "" - -# The LDAP search filter to find administrative users for continuwuity. -# -# If left blank, administrative state must be configured manually for each -# user. -# -# You can use the variable `{username}` that will be replaced by the -# entered username for more complex filters. -# -# example: "(objectClass=conduwuitAdmin)" or "(uid={username})" -# -#admin_filter = "" diff --git a/flake.lock b/flake.lock index 4c2bf9fb..51a04c6c 100644 --- a/flake.lock +++ b/flake.lock @@ -153,11 +153,11 @@ "rust-analyzer-src": "rust-analyzer-src" }, "locked": { - "lastModified": 1755585599, - "narHash": "sha256-tl/0cnsqB/Yt7DbaGMel2RLa7QG5elA8lkaOXli6VdY=", + "lastModified": 1751525020, + "narHash": "sha256-oDO6lCYS5Bf4jUITChj9XV7k3TP38DE0Ckz5n5ORCME=", "owner": "nix-community", "repo": "fenix", - "rev": "6ed03ef4c8ec36d193c18e06b9ecddde78fb7e42", + "rev": "a1a5f92f47787e7df9f30e5e5ac13e679215aa1e", "type": "github" }, "original": { @@ -516,16 +516,16 @@ "rocksdb": { "flake": false, "locked": { - "lastModified": 1753385396, - "narHash": "sha256-/Hvy1yTH/0D5aa7bc+/uqFugCQq4InTdwlRw88vA5IY=", - "ref": "10.4.fb", - "rev": "28d4b7276c16ed3e28af1bd96162d6442ce25923", - "revCount": 13318, + "lastModified": 1741308171, + "narHash": "sha256-YdBvdQ75UJg5ffwNjxizpviCVwVDJnBkM8ZtGIduMgY=", + "ref": "v9.11.1", + "rev": "3ce04794bcfbbb0d2e6f81ae35fc4acf688b6986", + "revCount": 13177, "type": "git", "url": "https://forgejo.ellis.link/continuwuation/rocksdb" }, "original": { - "ref": "10.4.fb", + "ref": "v9.11.1", "type": "git", "url": "https://forgejo.ellis.link/continuwuation/rocksdb" } @@ -546,11 +546,11 @@ "rust-analyzer-src": { "flake": false, "locked": { - "lastModified": 1755504847, - "narHash": "sha256-VX0B9hwhJypCGqncVVLC+SmeMVd/GAYbJZ0MiiUn2Pk=", + "lastModified": 1751433876, + "narHash": "sha256-IsdwOcvLLDDlkFNwhdD5BZy20okIQL01+UQ7Kxbqh8s=", "owner": "rust-lang", "repo": "rust-analyzer", - "rev": "a905e3b21b144d77e1b304e49f3264f6f8d4db75", + "rev": "11d45c881389dae90b0da5a94cde52c79d0fc7ef", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index d6beb84e..564cd479 100644 --- a/flake.nix +++ b/flake.nix @@ -17,7 +17,7 @@ nix-filter.url = "github:numtide/nix-filter?ref=main"; nixpkgs.url = "github:NixOS/nixpkgs?ref=nixpkgs-unstable"; rocksdb = { - url = "git+https://forgejo.ellis.link/continuwuation/rocksdb?ref=10.4.fb"; + url = "git+https://forgejo.ellis.link/continuwuation/rocksdb?ref=v9.11.1"; flake = false; }; }; @@ -31,17 +31,13 @@ inherit system; }; - fnx = inputs.fenix.packages.${system}; # The Rust toolchain to use - toolchain = fnx.combine [ - (fnx.fromToolchainFile { - file = ./rust-toolchain.toml; + toolchain = inputs.fenix.packages.${system}.fromToolchainFile { + file = ./rust-toolchain.toml; - # See also `rust-toolchain.toml` - sha256 = "sha256-+9FmLhAOezBZCOziO0Qct1NOrfpjNsXxc/8I0c7BdKE="; - }) - fnx.complete.rustfmt - ]; + # See also `rust-toolchain.toml` + sha256 = "sha256-KUm16pHj+cRedf8vxs/Hd2YWxpOrWZ7UOrwhILdSJBU="; + }; mkScope = pkgs: @@ -66,7 +62,7 @@ }).overrideAttrs (old: { src = inputs.rocksdb; - version = "v10.4.fb"; + version = "v9.11.1"; cmakeFlags = pkgs.lib.subtractLists [ # No real reason to have snappy or zlib, no one uses this diff --git a/renovate.json b/renovate.json index deb428af..b48fc6dc 100644 --- a/renovate.json +++ b/renovate.json @@ -13,8 +13,8 @@ "enabled": true }, "labels": [ - "Dependencies", - "Dependencies/Renovate" + "dependencies", + "github_actions" ], "ignoreDeps": [ "tikv-jemallocator", diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 63e9d9ce..bdb608aa 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -9,16 +9,13 @@ # If you're having trouble making the relevant changes, bug a maintainer. [toolchain] +channel = "1.87.0" profile = "minimal" -channel = "1.89.0" components = [ # For rust-analyzer "rust-src", "rust-analyzer", # For CI and editors + "rustfmt", "clippy", - # you have to install rustfmt nightly yourself (if you're not on NixOS) - # - # The rust-toolchain.toml file doesn't provide any syntax for specifying components from different toolchains - # "rustfmt" ] diff --git a/src/admin/user/commands.rs b/src/admin/user/commands.rs index 56864a32..86206c2b 100644 --- a/src/admin/user/commands.rs +++ b/src/admin/user/commands.rs @@ -68,8 +68,7 @@ pub(super) async fn create_user(&self, username: String, password: Option return Err!("Couldn't reset the password for user {user_id}: {e}"), | Ok(()) => { diff --git a/src/api/Cargo.toml b/src/api/Cargo.toml index 9b4ea460..15ada812 100644 --- a/src/api/Cargo.toml +++ b/src/api/Cargo.toml @@ -49,9 +49,6 @@ jemalloc_stats = [ "conduwuit-core/jemalloc_stats", "conduwuit-service/jemalloc_stats", ] -ldap = [ - "conduwuit-service/ldap" -] release_max_log_level = [ "conduwuit-core/release_max_log_level", "conduwuit-service/release_max_log_level", diff --git a/src/api/client/account.rs b/src/api/client/account.rs index 67268c9f..0cea7bd9 100644 --- a/src/api/client/account.rs +++ b/src/api/client/account.rs @@ -373,7 +373,7 @@ pub(crate) async fn register_route( let password = if is_guest { None } else { body.password.as_deref() }; // Create user - services.users.create(&user_id, password, None).await?; + services.users.create(&user_id, password)?; // Default to pretty displayname let mut displayname = user_id.localpart().to_owned(); @@ -659,8 +659,7 @@ pub(crate) async fn change_password_route( services .users - .set_password(sender_user, Some(&body.new_password)) - .await?; + .set_password(sender_user, Some(&body.new_password))?; if body.logout_devices { // Logout all devices except the current one diff --git a/src/api/client/profile.rs b/src/api/client/profile.rs index eaa66e70..1882495c 100644 --- a/src/api/client/profile.rs +++ b/src/api/client/profile.rs @@ -90,7 +90,7 @@ pub(crate) async fn get_displayname_route( .await { if !services.users.exists(&body.user_id).await { - services.users.create(&body.user_id, None, None).await?; + services.users.create(&body.user_id, None)?; } services @@ -189,7 +189,7 @@ pub(crate) async fn get_avatar_url_route( .await { if !services.users.exists(&body.user_id).await { - services.users.create(&body.user_id, None, None).await?; + services.users.create(&body.user_id, None)?; } services @@ -248,7 +248,7 @@ pub(crate) async fn get_profile_route( .await { if !services.users.exists(&body.user_id).await { - services.users.create(&body.user_id, None, None).await?; + services.users.create(&body.user_id, None)?; } services diff --git a/src/api/client/session.rs b/src/api/client/session.rs index da7bed2c..fe07e41d 100644 --- a/src/api/client/session.rs +++ b/src/api/client/session.rs @@ -3,14 +3,13 @@ use std::time::Duration; use axum::extract::State; use axum_client_ip::InsecureClientIp; use conduwuit::{ - Err, Error, Result, debug, err, info, - utils::{self, ReadyExt, hash}, + Err, Error, Result, debug, err, info, utils, + utils::{ReadyExt, hash}, }; -use conduwuit_core::{debug_error, debug_warn}; -use conduwuit_service::{Services, uiaa::SESSION_ID_LENGTH}; +use conduwuit_service::uiaa::SESSION_ID_LENGTH; use futures::StreamExt; use ruma::{ - OwnedUserId, UserId, + UserId, api::client::{ session::{ get_login_token, @@ -50,154 +49,6 @@ pub(crate) async fn get_login_types_route( ])) } -/// Authenticates the given user by its ID and its password. -/// -/// Returns the user ID if successful, and an error otherwise. -#[tracing::instrument(skip_all, fields(%user_id), name = "password")] -pub(crate) async fn password_login( - services: &Services, - user_id: &UserId, - lowercased_user_id: &UserId, - password: &str, -) -> Result { - // Restrict login to accounts only of type 'password', including untyped - // legacy accounts which are equivalent to 'password'. - if services - .users - .origin(user_id) - .await - .is_ok_and(|origin| origin != "password") - { - return Err!(Request(Forbidden("Account does not permit password login."))); - } - - let (hash, user_id) = match services.users.password_hash(user_id).await { - | Ok(hash) => (hash, user_id), - | Err(_) => services - .users - .password_hash(lowercased_user_id) - .await - .map(|hash| (hash, lowercased_user_id)) - .map_err(|_| err!(Request(Forbidden("Wrong username or password."))))?, - }; - - if hash.is_empty() { - return Err!(Request(UserDeactivated("The user has been deactivated"))); - } - - hash::verify_password(password, &hash) - .inspect_err(|e| debug_error!("{e}")) - .map_err(|_| err!(Request(Forbidden("Wrong username or password."))))?; - - Ok(user_id.to_owned()) -} - -/// Authenticates the given user through the configured LDAP server. -/// -/// Creates the user if the user is found in the LDAP and do not already have an -/// account. -#[tracing::instrument(skip_all, fields(%user_id), name = "ldap")] -pub(super) async fn ldap_login( - services: &Services, - user_id: &UserId, - lowercased_user_id: &UserId, - password: &str, -) -> Result { - let (user_dn, is_ldap_admin) = match services.config.ldap.bind_dn.as_ref() { - | Some(bind_dn) if bind_dn.contains("{username}") => - (bind_dn.replace("{username}", lowercased_user_id.localpart()), false), - | _ => { - debug!("Searching user in LDAP"); - - let dns = services.users.search_ldap(user_id).await?; - if dns.len() >= 2 { - return Err!(Ldap("LDAP search returned two or more results")); - } - - let Some((user_dn, is_admin)) = dns.first() else { - return password_login(services, user_id, lowercased_user_id, password).await; - }; - - (user_dn.clone(), *is_admin) - }, - }; - - let user_id = services - .users - .auth_ldap(&user_dn, password) - .await - .map(|()| lowercased_user_id.to_owned())?; - - // LDAP users are automatically created on first login attempt. This is a very - // common feature that can be seen on many services using a LDAP provider for - // their users (synapse, Nextcloud, Jellyfin, ...). - // - // LDAP users are crated with a dummy password but non empty because an empty - // password is reserved for deactivated accounts. The conduwuit password field - // will never be read to login a LDAP user so it's not an issue. - if !services.users.exists(lowercased_user_id).await { - services - .users - .create(lowercased_user_id, Some("*"), Some("ldap")) - .await?; - } - - let is_conduwuit_admin = services.admin.user_is_admin(lowercased_user_id).await; - - if is_ldap_admin && !is_conduwuit_admin { - services.admin.make_user_admin(lowercased_user_id).await?; - } else if !is_ldap_admin && is_conduwuit_admin { - services.admin.revoke_admin(lowercased_user_id).await?; - } - - Ok(user_id) -} - -pub(crate) async fn handle_login( - services: &Services, - body: &Ruma, - identifier: Option<&uiaa::UserIdentifier>, - password: &str, - user: Option<&String>, -) -> Result { - debug!("Got password login type"); - let user_id = - if let Some(uiaa::UserIdentifier::UserIdOrLocalpart(user_id)) = identifier { - UserId::parse_with_server_name(user_id, &services.config.server_name) - } else if let Some(user) = user { - UserId::parse_with_server_name(user, &services.config.server_name) - } else { - return Err!(Request(Unknown( - debug_warn!(?body.login_info, "Valid identifier or username was not provided (invalid or unsupported login type?)") - ))); - } - .map_err(|e| err!(Request(InvalidUsername(warn!("Username is invalid: {e}")))))?; - - let lowercased_user_id = UserId::parse_with_server_name( - user_id.localpart().to_lowercase(), - &services.config.server_name, - )?; - - if !services.globals.user_is_local(&user_id) - || !services.globals.user_is_local(&lowercased_user_id) - { - return Err!(Request(Unknown("User ID does not belong to this homeserver"))); - } - - if cfg!(feature = "ldap") && services.config.ldap.enable { - match Box::pin(ldap_login(services, &user_id, &lowercased_user_id, password)).await { - | Ok(user_id) => Ok(user_id), - | Err(err) if services.config.ldap.ldap_only => Err(err), - | Err(err) => { - debug_warn!("{err}"); - password_login(services, &user_id, &lowercased_user_id, password).await - }, - } - } else { - password_login(services, &user_id, &lowercased_user_id, password).await - } -} - /// # `POST /_matrix/client/v3/login` /// /// Authenticates the user and returns an access token it can use in subsequent @@ -229,7 +80,70 @@ pub(crate) async fn login_route( password, user, .. - }) => handle_login(&services, &body, identifier.as_ref(), password, user.as_ref()).await?, + }) => { + debug!("Got password login type"); + let user_id = + if let Some(uiaa::UserIdentifier::UserIdOrLocalpart(user_id)) = identifier { + UserId::parse_with_server_name(user_id, &services.config.server_name) + } else if let Some(user) = user { + UserId::parse_with_server_name(user, &services.config.server_name) + } else { + return Err!(Request(Unknown( + debug_warn!(?body.login_info, "Valid identifier or username was not provided (invalid or unsupported login type?)") + ))); + } + .map_err(|e| err!(Request(InvalidUsername(warn!("Username is invalid: {e}")))))?; + + let lowercased_user_id = UserId::parse_with_server_name( + user_id.localpart().to_lowercase(), + &services.config.server_name, + )?; + + if !services.globals.user_is_local(&user_id) + || !services.globals.user_is_local(&lowercased_user_id) + { + return Err!(Request(Unknown("User ID does not belong to this homeserver"))); + } + + // first try the username as-is + let hash = services + .users + .password_hash(&user_id) + .await + .inspect_err(|e| debug!("{e}")); + + match hash { + | Ok(hash) => { + if hash.is_empty() { + return Err!(Request(UserDeactivated("The user has been deactivated"))); + } + + hash::verify_password(password, &hash) + .inspect_err(|e| debug!("{e}")) + .map_err(|_| err!(Request(Forbidden("Wrong username or password."))))?; + + user_id + }, + | Err(_e) => { + let hash_lowercased_user_id = services + .users + .password_hash(&lowercased_user_id) + .await + .inspect_err(|e| debug!("{e}")) + .map_err(|_| err!(Request(Forbidden("Wrong username or password."))))?; + + if hash_lowercased_user_id.is_empty() { + return Err!(Request(UserDeactivated("The user has been deactivated"))); + } + + hash::verify_password(password, &hash_lowercased_user_id) + .inspect_err(|e| debug!("{e}")) + .map_err(|_| err!(Request(Forbidden("Wrong username or password."))))?; + + lowercased_user_id + }, + } + }, | login::v3::LoginInfo::Token(login::v3::Token { token }) => { debug!("Got token login type"); if !services.server.config.login_via_existing_session { diff --git a/src/api/client/sync/v4.rs b/src/api/client/sync/v4.rs index a16e4526..14cd50d8 100644 --- a/src/api/client/sync/v4.rs +++ b/src/api/client/sync/v4.rs @@ -45,7 +45,6 @@ use crate::{ type TodoRooms = BTreeMap, usize, u64)>; const SINGLE_CONNECTION_SYNC: &str = "single_connection_sync"; -#[allow(clippy::cognitive_complexity)] /// POST `/_matrix/client/unstable/org.matrix.msc3575/sync` /// /// Sliding Sync endpoint (future endpoint: `/_matrix/client/v4/sync`) diff --git a/src/api/client/unstable.rs b/src/api/client/unstable.rs index f8703ff3..08f70975 100644 --- a/src/api/client/unstable.rs +++ b/src/api/client/unstable.rs @@ -292,7 +292,7 @@ pub(crate) async fn get_timezone_key_route( .await { if !services.users.exists(&body.user_id).await { - services.users.create(&body.user_id, None, None).await?; + services.users.create(&body.user_id, None)?; } services @@ -352,7 +352,7 @@ pub(crate) async fn get_profile_key_route( .await { if !services.users.exists(&body.user_id).await { - services.users.create(&body.user_id, None, None).await?; + services.users.create(&body.user_id, None)?; } services diff --git a/src/core/config/mod.rs b/src/core/config/mod.rs index e8518ed4..aa021be7 100644 --- a/src/core/config/mod.rs +++ b/src/core/config/mod.rs @@ -1,4 +1,3 @@ -#![allow(clippy::doc_link_with_quotes)] pub mod check; pub mod manager; pub mod proxy; @@ -1948,10 +1947,6 @@ pub struct Config { pub allow_invalid_tls_certificates_yes_i_know_what_the_fuck_i_am_doing_with_this_and_i_know_this_is_insecure: bool, - // external structure; separate section - #[serde(default)] - pub ldap: LdapConfig, - // external structure; separate section #[serde(default)] pub blurhashing: BlurhashConfig, @@ -2046,114 +2041,6 @@ pub struct BlurhashConfig { pub blurhash_max_raw_size: u64, } -#[derive(Clone, Debug, Default, Deserialize)] -#[config_example_generator(filename = "conduwuit-example.toml", section = "global.ldap")] -pub struct LdapConfig { - /// Whether to enable LDAP login. - /// - /// example: "true" - #[serde(default)] - pub enable: bool, - - /// Whether to force LDAP authentication or authorize classical password - /// login. - /// - /// example: "true" - #[serde(default)] - pub ldap_only: bool, - - /// URI of the LDAP server. - /// - /// example: "ldap://ldap.example.com:389" - /// - /// default: "" - #[serde(default)] - pub uri: Option, - - /// Root of the searches. - /// - /// example: "ou=users,dc=example,dc=org" - /// - /// default: "" - #[serde(default)] - pub base_dn: String, - - /// Bind DN if anonymous search is not enabled. - /// - /// You can use the variable `{username}` that will be replaced by the - /// entered username. In such case, the password used to bind will be the - /// one provided for the login and not the one given by - /// `bind_password_file`. Beware: automatically granting admin rights will - /// not work if you use this direct bind instead of a LDAP search. - /// - /// example: "cn=ldap-reader,dc=example,dc=org" or - /// "cn={username},ou=users,dc=example,dc=org" - /// - /// default: "" - #[serde(default)] - pub bind_dn: Option, - - /// Path to a file on the system that contains the password for the - /// `bind_dn`. - /// - /// The server must be able to access the file, and it must not be empty. - /// - /// default: "" - #[serde(default)] - pub bind_password_file: Option, - - /// Search filter to limit user searches. - /// - /// You can use the variable `{username}` that will be replaced by the - /// entered username for more complex filters. - /// - /// example: "(&(objectClass=person)(memberOf=matrix))" - /// - /// default: "(objectClass=*)" - #[serde(default = "default_ldap_search_filter")] - pub filter: String, - - /// Attribute to use to uniquely identify the user. - /// - /// example: "uid" or "cn" - /// - /// default: "uid" - #[serde(default = "default_ldap_uid_attribute")] - pub uid_attribute: String, - - /// Attribute containing the display name of the user. - /// - /// example: "givenName" or "sn" - /// - /// default: "givenName" - #[serde(default = "default_ldap_name_attribute")] - pub name_attribute: String, - - /// Root of the searches for admin users. - /// - /// Defaults to `base_dn` if empty. - /// - /// example: "ou=admins,dc=example,dc=org" - /// - /// default: "" - #[serde(default)] - pub admin_base_dn: String, - - /// The LDAP search filter to find administrative users for continuwuity. - /// - /// If left blank, administrative state must be configured manually for each - /// user. - /// - /// You can use the variable `{username}` that will be replaced by the - /// entered username for more complex filters. - /// - /// example: "(objectClass=conduwuitAdmin)" or "(uid={username})" - /// - /// default: "" - #[serde(default)] - pub admin_filter: String, -} - #[derive(Deserialize, Clone, Debug)] #[serde(transparent)] struct ListeningPort { @@ -2543,9 +2430,3 @@ pub(super) fn default_blurhash_x_component() -> u32 { 4 } pub(super) fn default_blurhash_y_component() -> u32 { 3 } // end recommended & blurhashing defaults - -fn default_ldap_search_filter() -> String { "(objectClass=*)".to_owned() } - -fn default_ldap_uid_attribute() -> String { String::from("uid") } - -fn default_ldap_name_attribute() -> String { String::from("givenName") } diff --git a/src/core/debug.rs b/src/core/debug.rs index c728278d..21a5ada4 100644 --- a/src/core/debug.rs +++ b/src/core/debug.rs @@ -100,7 +100,7 @@ pub fn trap() { #[must_use] pub fn panic_str(p: &Box) -> &'static str { - (**p).downcast_ref::<&str>().copied().unwrap_or_default() + p.downcast_ref::<&str>().copied().unwrap_or_default() } #[inline(always)] diff --git a/src/core/error/mod.rs b/src/core/error/mod.rs index 541af793..e46edf09 100644 --- a/src/core/error/mod.rs +++ b/src/core/error/mod.rs @@ -110,8 +110,6 @@ pub enum Error { InconsistentRoomState(&'static str, ruma::OwnedRoomId), #[error(transparent)] IntoHttp(#[from] ruma::api::error::IntoHttpError), - #[error("{0}")] - Ldap(Cow<'static, str>), #[error(transparent)] Mxc(#[from] ruma::MxcUriError), #[error(transparent)] diff --git a/src/database/maps.rs b/src/database/maps.rs index da97ef45..214dbf34 100644 --- a/src/database/maps.rs +++ b/src/database/maps.rs @@ -374,10 +374,6 @@ pub(super) static MAPS: &[Descriptor] = &[ name: "userid_masterkeyid", ..descriptor::RANDOM_SMALL }, - Descriptor { - name: "userid_origin", - ..descriptor::RANDOM - }, Descriptor { name: "userid_password", ..descriptor::RANDOM diff --git a/src/main/Cargo.toml b/src/main/Cargo.toml index eafa1e48..8aaa3cc6 100644 --- a/src/main/Cargo.toml +++ b/src/main/Cargo.toml @@ -56,7 +56,6 @@ standard = [ "jemalloc", "jemalloc_conf", "journald", - "ldap", "media_thumbnail", "systemd", "url_preview", @@ -115,9 +114,6 @@ jemalloc_stats = [ jemalloc_conf = [ "conduwuit-core/jemalloc_conf", ] -ldap = [ - "conduwuit-api/ldap", -] media_thumbnail = [ "conduwuit-service/media_thumbnail", ] diff --git a/src/router/serve/unix.rs b/src/router/serve/unix.rs index 9bb3dd6e..2af17274 100644 --- a/src/router/serve/unix.rs +++ b/src/router/serve/unix.rs @@ -30,7 +30,7 @@ use tower::{Service, ServiceExt}; type MakeService = IntoMakeServiceWithConnectInfo; -const NULL_ADDR: net::SocketAddr = net::SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 0); +const NULL_ADDR: net::SocketAddr = net::SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 0); const FINI_POLL_INTERVAL: Duration = Duration::from_millis(750); #[tracing::instrument(skip_all, level = "debug")] diff --git a/src/service/Cargo.toml b/src/service/Cargo.toml index 6e538f40..fdebd1d7 100644 --- a/src/service/Cargo.toml +++ b/src/service/Cargo.toml @@ -53,9 +53,6 @@ jemalloc_stats = [ "conduwuit-core/jemalloc_stats", "conduwuit-database/jemalloc_stats", ] -ldap = [ - "dep:ldap3" -] media_thumbnail = [ "dep:image", ] @@ -92,8 +89,6 @@ image.workspace = true image.optional = true ipaddress.workspace = true itertools.workspace = true -ldap3.workspace = true -ldap3.optional = true log.workspace = true loole.workspace = true lru-cache.workspace = true diff --git a/src/service/admin/create.rs b/src/service/admin/create.rs index 755673fe..157b4d65 100644 --- a/src/service/admin/create.rs +++ b/src/service/admin/create.rs @@ -38,7 +38,7 @@ pub async fn create_admin_room(services: &Services) -> Result { // Create a user for the server let server_user = services.globals.server_user.as_ref(); - services.users.create(server_user, None, None).await?; + services.users.create(server_user, None)?; let create_content = { use RoomVersionId::*; diff --git a/src/service/appservice/mod.rs b/src/service/appservice/mod.rs index adbf3b6e..ebd798f6 100644 --- a/src/service/appservice/mod.rs +++ b/src/service/appservice/mod.rs @@ -109,10 +109,7 @@ impl Service { )?; if !self.services.users.exists(&appservice_user_id).await { - self.services - .users - .create(&appservice_user_id, None, None) - .await?; + self.services.users.create(&appservice_user_id, None)?; } else if self .services .users @@ -123,8 +120,7 @@ impl Service { // Reactivate the appservice user if it was accidentally deactivated self.services .users - .set_password(&appservice_user_id, None) - .await?; + .set_password(&appservice_user_id, None)?; } self.registration_info diff --git a/src/service/emergency/mod.rs b/src/service/emergency/mod.rs index f8ecbb3e..3a61f710 100644 --- a/src/service/emergency/mod.rs +++ b/src/service/emergency/mod.rs @@ -41,11 +41,6 @@ impl crate::Service for Service { return Ok(()); } - if self.services.config.ldap.enable { - warn!("emergency password feature not available with LDAP enabled."); - return Ok(()); - } - self.set_emergency_access().await.inspect_err(|e| { error!("Could not set the configured emergency password for the server user: {e}"); }) @@ -62,8 +57,7 @@ impl Service { self.services .users - .set_password(server_user, self.services.config.emergency_password.as_deref()) - .await?; + .set_password(server_user, self.services.config.emergency_password.as_deref())?; let (ruleset, pwd_set) = match self.services.config.emergency_password { | Some(_) => (Ruleset::server_default(server_user), true), diff --git a/src/service/rooms/state_cache/update.rs b/src/service/rooms/state_cache/update.rs index 86c1afe7..32c67947 100644 --- a/src/service/rooms/state_cache/update.rs +++ b/src/service/rooms/state_cache/update.rs @@ -49,7 +49,7 @@ pub async fn update_membership( #[allow(clippy::collapsible_if)] if !self.services.globals.user_is_local(user_id) { if !self.services.users.exists(user_id).await { - self.services.users.create(user_id, None, None).await?; + self.services.users.create(user_id, None)?; } } diff --git a/src/service/users/mod.rs b/src/service/users/mod.rs index fff1661c..eb54660e 100644 --- a/src/service/users/mod.rs +++ b/src/service/users/mod.rs @@ -1,19 +1,11 @@ -#[cfg(feature = "ldap")] -use std::collections::HashMap; use std::{collections::BTreeMap, mem, sync::Arc}; -#[cfg(feature = "ldap")] -use conduwuit::result::LogErr; use conduwuit::{ - Err, Error, Result, Server, at, debug_warn, err, is_equal_to, trace, + Err, Error, Result, Server, at, debug_warn, err, trace, utils::{self, ReadyExt, stream::TryIgnore, string::Unquoted}, }; -#[cfg(feature = "ldap")] -use conduwuit_core::{debug, error}; use database::{Deserialized, Ignore, Interfix, Json, Map}; use futures::{Stream, StreamExt, TryFutureExt}; -#[cfg(feature = "ldap")] -use ldap3::{LdapConnAsync, Scope, SearchEntry}; use ruma::{ DeviceId, KeyId, MilliSecondsSinceUnixEpoch, OneTimeKeyAlgorithm, OneTimeKeyId, OneTimeKeyName, OwnedDeviceId, OwnedKeyId, OwnedMxcUri, OwnedUserId, RoomId, UInt, UserId, @@ -71,7 +63,6 @@ struct Data { userid_displayname: Arc, userid_lastonetimekeyupdate: Arc, userid_masterkeyid: Arc, - userid_origin: Arc, userid_password: Arc, userid_suspension: Arc, userid_selfsigningkeyid: Arc, @@ -109,7 +100,6 @@ impl crate::Service for Service { userid_displayname: args.db["userid_displayname"].clone(), userid_lastonetimekeyupdate: args.db["userid_lastonetimekeyupdate"].clone(), userid_masterkeyid: args.db["userid_masterkeyid"].clone(), - userid_origin: args.db["userid_origin"].clone(), userid_password: args.db["userid_password"].clone(), userid_suspension: args.db["userid_suspension"].clone(), userid_selfsigningkeyid: args.db["userid_selfsigningkeyid"].clone(), @@ -146,21 +136,9 @@ impl Service { } /// Create a new user account on this homeserver. - /// - /// User origin is by default "password" (meaning that it will login using - /// its user_id/password). Users with other origins (currently only "ldap" - /// is available) have special login processes. #[inline] - pub async fn create( - &self, - user_id: &UserId, - password: Option<&str>, - origin: Option<&str>, - ) -> Result<()> { - self.db - .userid_origin - .insert(user_id, origin.unwrap_or("password")); - self.set_password(user_id, password).await + pub fn create(&self, user_id: &UserId, password: Option<&str>) -> Result<()> { + self.set_password(user_id, password) } /// Deactivate account @@ -174,7 +152,7 @@ impl Service { // result in an empty string, so the user will not be able to log in again. // Systems like changing the password without logging in should check if the // account is deactivated. - self.set_password(user_id, None).await?; + self.set_password(user_id, None)?; // TODO: Unhook 3PID Ok(()) @@ -275,34 +253,13 @@ impl Service { .ready_filter_map(|(u, p): (&UserId, &[u8])| (!p.is_empty()).then_some(u)) } - /// Returns the origin of the user (password/LDAP/...). - pub async fn origin(&self, user_id: &UserId) -> Result { - self.db.userid_origin.get(user_id).await.deserialized() - } - /// Returns the password hash for the given user. pub async fn password_hash(&self, user_id: &UserId) -> Result { self.db.userid_password.get(user_id).await.deserialized() } /// Hash and set the user's password to the Argon2 hash - pub async fn set_password(&self, user_id: &UserId, password: Option<&str>) -> Result<()> { - // Cannot change the password of a LDAP user. There are two special cases : - // - a `None` password can be used to deactivate a LDAP user - // - a "*" password is used as the default password of an active LDAP user - if cfg!(feature = "ldap") - && password.is_some_and(|pwd| pwd != "*") - && self - .db - .userid_origin - .get(user_id) - .await - .deserialized::() - .is_ok_and(is_equal_to!("ldap")) - { - return Err!(Request(InvalidParam("Cannot change password of a LDAP user"))); - } - + pub fn set_password(&self, user_id: &UserId, password: Option<&str>) -> Result<()> { password .map(utils::hash::password) .transpose() @@ -1175,154 +1132,6 @@ impl Service { self.db.useridprofilekey_value.del(key); } } - - #[cfg(not(feature = "ldap"))] - pub async fn search_ldap(&self, _user_id: &UserId) -> Result> { - Err!(FeatureDisabled("ldap")) - } - - #[cfg(feature = "ldap")] - pub async fn search_ldap(&self, user_id: &UserId) -> Result> { - let localpart = user_id.localpart().to_owned(); - let lowercased_localpart = localpart.to_lowercase(); - - let config = &self.services.server.config.ldap; - let uri = config - .uri - .as_ref() - .ok_or_else(|| err!(Ldap(error!("LDAP URI is not configured."))))?; - - debug!(?uri, "LDAP creating connection..."); - let (conn, mut ldap) = LdapConnAsync::new(uri.as_str()) - .await - .map_err(|e| err!(Ldap(error!(?user_id, "LDAP connection setup error: {e}"))))?; - - let driver = self.services.server.runtime().spawn(async move { - match conn.drive().await { - | Err(e) => error!("LDAP connection error: {e}"), - | Ok(()) => debug!("LDAP connection completed."), - } - }); - - match (&config.bind_dn, &config.bind_password_file) { - | (Some(bind_dn), Some(bind_password_file)) => { - let bind_pw = String::from_utf8(std::fs::read(bind_password_file)?)?; - ldap.simple_bind(bind_dn, bind_pw.trim()) - .await - .and_then(ldap3::LdapResult::success) - .map_err(|e| err!(Ldap(error!("LDAP bind error: {e}"))))?; - }, - | (..) => {}, - } - - let attr = [&config.uid_attribute, &config.name_attribute]; - - let user_filter = &config.filter.replace("{username}", &lowercased_localpart); - - let (entries, _result) = ldap - .search(&config.base_dn, Scope::Subtree, user_filter, &attr) - .await - .and_then(ldap3::SearchResult::success) - .inspect(|(entries, result)| trace!(?entries, ?result, "LDAP Search")) - .map_err(|e| err!(Ldap(error!(?attr, ?user_filter, "LDAP search error: {e}"))))?; - - let mut dns: HashMap = entries - .into_iter() - .filter_map(|entry| { - let search_entry = SearchEntry::construct(entry); - debug!(?search_entry, "LDAP search entry"); - search_entry - .attrs - .get(&config.uid_attribute) - .into_iter() - .chain(search_entry.attrs.get(&config.name_attribute)) - .any(|ids| ids.contains(&localpart) || ids.contains(&lowercased_localpart)) - .then_some((search_entry.dn, false)) - }) - .collect(); - - if !config.admin_filter.is_empty() { - let admin_base_dn = if config.admin_base_dn.is_empty() { - &config.base_dn - } else { - &config.admin_base_dn - }; - - let admin_filter = &config - .admin_filter - .replace("{username}", &lowercased_localpart); - - let (admin_entries, _result) = ldap - .search(admin_base_dn, Scope::Subtree, admin_filter, &attr) - .await - .and_then(ldap3::SearchResult::success) - .inspect(|(entries, result)| trace!(?entries, ?result, "LDAP Admin Search")) - .map_err(|e| { - err!(Ldap(error!(?attr, ?admin_filter, "Ldap admin search error: {e}"))) - })?; - - dns.extend(admin_entries.into_iter().filter_map(|entry| { - let search_entry = SearchEntry::construct(entry); - debug!(?search_entry, "LDAP search entry"); - search_entry - .attrs - .get(&config.uid_attribute) - .into_iter() - .chain(search_entry.attrs.get(&config.name_attribute)) - .any(|ids| ids.contains(&localpart) || ids.contains(&lowercased_localpart)) - .then_some((search_entry.dn, true)) - })); - } - - ldap.unbind() - .await - .map_err(|e| err!(Ldap(error!("LDAP unbind error: {e}"))))?; - - driver.await.log_err().ok(); - - Ok(dns.drain().collect()) - } - - #[cfg(not(feature = "ldap"))] - pub async fn auth_ldap(&self, _user_dn: &str, _password: &str) -> Result { - Err!(FeatureDisabled("ldap")) - } - - #[cfg(feature = "ldap")] - pub async fn auth_ldap(&self, user_dn: &str, password: &str) -> Result { - let config = &self.services.server.config.ldap; - let uri = config - .uri - .as_ref() - .ok_or_else(|| err!(Ldap(error!("LDAP URI is not configured."))))?; - - debug!(?uri, "LDAP creating connection..."); - let (conn, mut ldap) = LdapConnAsync::new(uri.as_str()) - .await - .map_err(|e| err!(Ldap(error!(?user_dn, "LDAP connection setup error: {e}"))))?; - - let driver = self.services.server.runtime().spawn(async move { - match conn.drive().await { - | Err(e) => error!("LDAP connection error: {e}"), - | Ok(()) => debug!("LDAP connection completed."), - } - }); - - ldap.simple_bind(user_dn, password) - .await - .and_then(ldap3::LdapResult::success) - .map_err(|e| { - err!(Request(Forbidden(debug_error!("LDAP authentication error: {e}")))) - })?; - - ldap.unbind() - .await - .map_err(|e| err!(Ldap(error!("LDAP unbind error: {e}"))))?; - - driver.await.log_err().ok(); - - Ok(()) - } } pub fn parse_master_key(