From 8ab5f434500a876ee6c72c15a06e316b857d6db2 Mon Sep 17 00:00:00 2001 From: Chase Douglas Date: Thu, 14 May 2026 13:50:23 -0700 Subject: [PATCH] deps: upgrade the reqwest stack to 0.13 The reqwest 0.13 rustls feature selects the aws-lc provider. Use rustls-no-provider instead, add rustls 0.23 with the ring provider, and install that provider at process startup. This keeps Vaultwarden on the existing ring crypto provider while giving reqwest, OpenDAL and lettre a process-wide rustls provider. Disable openidconnect default features and provide a small AsyncHttpClient wrapper around Vaultwarden's shared reqwest client builder. This preserves custom DNS, request blocking, timeouts and the no-redirect OIDC behavior without openidconnect enabling its own reqwest stack. Upgrade yubico_ng to 0.15.0 and OpenDAL to 0.56.0. OpenDAL 0.56 also moves S3 signing to reqsign 3, so switch the optional S3 dependencies from reqsign/anyhow to reqsign-core and reqsign-aws-v4 and adapt the AWS SDK credential bridge to the new ProvideCredential API. Adjust the local OpenDAL call sites for the 0.56 API: use the FS_SCHEME constant for filesystem checks and replace deprecated remove_all() with delete_with(...).recursive(true) for Send file cleanup. --- Cargo.lock | 480 ++++++++++++------------------------ Cargo.toml | 15 +- src/api/core/sends.rs | 2 +- src/config.rs | 37 ++- src/db/models/attachment.rs | 2 +- src/db/models/send.rs | 2 +- src/main.rs | 9 + src/sso_client.rs | 41 ++- 8 files changed, 239 insertions(+), 349 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ac84b501..9a44e0b2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,17 +8,6 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" -[[package]] -name = "aes" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" -dependencies = [ - "cfg-if", - "cipher", - "cpufeatures 0.2.17", -] - [[package]] name = "ahash" version = "0.8.12" @@ -670,17 +659,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "backon" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cffb0e931875b666fc4fcb20fee52e9bbd1ef836fd9e9e04ec21555f9f85f7ef" -dependencies = [ - "fastrand", - "gloo-timers", - "tokio", -] - [[package]] name = "base16ct" version = "0.2.0" @@ -778,15 +756,6 @@ dependencies = [ "hybrid-array", ] -[[package]] -name = "block-padding" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93" -dependencies = [ - "generic-array", -] - [[package]] name = "blocking" version = "1.6.2" @@ -892,15 +861,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ade8366b8bd5ba243f0a58f036cc0ca8a2f069cff1a2351ef1cac6b083e16fc0" -[[package]] -name = "cbc" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6" -dependencies = [ - "cipher", -] - [[package]] name = "cc" version = "1.2.61" @@ -919,12 +879,6 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" -[[package]] -name = "cfg_aliases" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" - [[package]] name = "chacha20" version = "0.10.0" @@ -960,16 +914,6 @@ dependencies = [ "phf 0.12.1", ] -[[package]] -name = "cipher" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" -dependencies = [ - "crypto-common 0.1.6", - "inout", -] - [[package]] name = "cmov" version = "0.5.3" @@ -2357,15 +2301,6 @@ dependencies = [ "digest 0.11.2", ] -[[package]] -name = "home" -version = "0.5.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc627f471c528ff0c4a49e1d5e60450c8f6461dd6d10ba9dcd3a61d3dff7728d" -dependencies = [ - "windows-sys 0.61.2", -] - [[package]] name = "hostname" version = "0.4.2" @@ -2516,11 +2451,9 @@ dependencies = [ "hyper 1.9.0", "hyper-util", "rustls 0.23.40", - "rustls-native-certs", "tokio", "tokio-rustls 0.26.4", "tower-service", - "webpki-roots", ] [[package]] @@ -2716,16 +2649,6 @@ version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8fae54786f62fb2918dcfae3d568594e50eb9b5c25bf04371af6fe7516452fb" -[[package]] -name = "inout" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" -dependencies = [ - "block-padding", - "generic-array", -] - [[package]] name = "ipconfig" version = "0.3.4" @@ -2798,10 +2721,12 @@ checksum = "f00b5dbd620d61dfdcb6007c9c1f6054ebd75319f163d886a9055cec1155073d" dependencies = [ "jiff-static", "jiff-tzdb-platform", + "js-sys", "log", "portable-atomic", "portable-atomic-util", "serde_core", + "wasm-bindgen", "windows-sys 0.61.2", ] @@ -2913,21 +2838,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "jsonwebtoken" -version = "9.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a87cc7a48537badeae96744432de36f4be2b4a34a05a5ef32e9dd8a1c169dde" -dependencies = [ - "base64 0.22.1", - "js-sys", - "pem", - "ring", - "serde", - "serde_json", - "simple_asn1", -] - [[package]] name = "jsonwebtoken" version = "10.3.0" @@ -3098,12 +3008,6 @@ dependencies = [ "tracing-subscriber", ] -[[package]] -name = "lru-slab" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" - [[package]] name = "macros" version = "0.1.0" @@ -3131,6 +3035,15 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "mea" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6747f54621d156e1b47eb6b25f39a941b9fc347f98f67d25d8881ff99e8ed832" +dependencies = [ + "slab", +] + [[package]] name = "memchr" version = "2.8.0" @@ -3408,7 +3321,6 @@ dependencies = [ "getrandom 0.2.17", "http 1.4.0", "rand 0.8.6", - "reqwest", "serde", "serde_json", "serde_path_to_error", @@ -3438,31 +3350,76 @@ dependencies = [ [[package]] name = "opendal" -version = "0.55.0" +version = "0.56.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97b31d3d8e99a85d83b73ec26647f5607b80578ed9375810b6e44ffa3590a236" +dependencies = [ + "opendal-core", + "opendal-service-fs", + "opendal-service-s3", +] + +[[package]] +name = "opendal-core" +version = "0.56.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d075ab8a203a6ab4bc1bce0a4b9fe486a72bf8b939037f4b78d95386384bc80a" +checksum = "1849dd2687e173e776d3af5fce1ba3ae47b9dd37a09d1c4deba850ef45fe00ca" dependencies = [ "anyhow", - "backon", "base64 0.22.1", "bytes", - "crc32c", "futures", - "getrandom 0.2.17", "http 1.4.0", "http-body 1.0.1", "jiff", "log", "md-5", + "mea", "percent-encoding", "quick-xml 0.38.4", - "reqsign", + "reqsign-core", "reqwest", "serde", "serde_json", "tokio", "url", "uuid", + "web-time", +] + +[[package]] +name = "opendal-service-fs" +version = "0.56.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf0be0417abeeb0053376d816b90fceb9ca98f20dfb54ebf1f2a282729f83663" +dependencies = [ + "bytes", + "log", + "opendal-core", + "serde", + "tokio", + "xattr", +] + +[[package]] +name = "opendal-service-s3" +version = "0.56.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dadddeb9bb50b0d30927dd914c298c4ddca47e4c1cfa7674d311f0cf9b051c8" +dependencies = [ + "base64 0.22.1", + "bytes", + "crc32c", + "http 1.4.0", + "log", + "md-5", + "opendal-core", + "quick-xml 0.38.4", + "reqsign-aws-v4", + "reqsign-core", + "reqsign-file-read-tokio", + "serde", + "url", ] [[package]] @@ -3651,16 +3608,6 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c5a797f0e07bdf071d15742978fc3128ec6c22891c31a3a931513263904c982a" -[[package]] -name = "pbkdf2" -version = "0.12.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" -dependencies = [ - "digest 0.10.7", - "hmac 0.12.1", -] - [[package]] name = "pear" version = "0.2.9" @@ -3852,21 +3799,6 @@ dependencies = [ "spki", ] -[[package]] -name = "pkcs5" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e847e2c91a18bfa887dd028ec33f2fe6f25db77db3619024764914affe8b69a6" -dependencies = [ - "aes", - "cbc", - "der", - "pbkdf2", - "scrypt", - "sha2 0.10.9", - "spki", -] - [[package]] name = "pkcs8" version = "0.10.2" @@ -3874,8 +3806,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" dependencies = [ "der", - "pkcs5", - "rand_core 0.6.4", "spki", ] @@ -4040,9 +3970,9 @@ checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" [[package]] name = "quick-xml" -version = "0.37.5" +version = "0.38.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "331e97a1af0bf59823e6eadffe373d7b27f485be8748f71471c662c1f269b7fb" +checksum = "b66c2058c55a409d601666cffe35f04333cf1013010882cec174a7467cd4e21c" dependencies = [ "memchr", "serde", @@ -4050,69 +3980,14 @@ dependencies = [ [[package]] name = "quick-xml" -version = "0.38.4" +version = "0.39.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b66c2058c55a409d601666cffe35f04333cf1013010882cec174a7467cd4e21c" +checksum = "cdcc8dd4e2f670d309a5f0e83fe36dfdc05af317008fea29144da1a2ac858e5e" dependencies = [ "memchr", "serde", ] -[[package]] -name = "quinn" -version = "0.11.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" -dependencies = [ - "bytes", - "cfg_aliases", - "pin-project-lite", - "quinn-proto", - "quinn-udp", - "rustc-hash", - "rustls 0.23.40", - "socket2 0.6.3", - "thiserror 2.0.18", - "tokio", - "tracing", - "web-time", -] - -[[package]] -name = "quinn-proto" -version = "0.11.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "434b42fec591c96ef50e21e886936e66d3cc3f737104fdb9b737c40ffb94c098" -dependencies = [ - "bytes", - "getrandom 0.3.4", - "lru-slab", - "rand 0.9.4", - "ring", - "rustc-hash", - "rustls 0.23.40", - "rustls-pki-types", - "slab", - "thiserror 2.0.18", - "tinyvec", - "tracing", - "web-time", -] - -[[package]] -name = "quinn-udp" -version = "0.5.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" -dependencies = [ - "cfg_aliases", - "libc", - "once_cell", - "socket2 0.6.3", - "tracing", - "windows-sys 0.60.2", -] - [[package]] name = "quote" version = "1.0.45" @@ -4312,43 +4187,64 @@ dependencies = [ ] [[package]] -name = "reqsign" -version = "0.16.5" +name = "reqsign-aws-v4" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43451dbf3590a7590684c25fb8d12ecdcc90ed3ac123433e500447c7d77ed701" +checksum = "44eaca382e94505a49f1a4849658d153aebf79d9c1a58e5dd3b10361511e9f43" dependencies = [ "anyhow", - "async-trait", - "base64 0.22.1", - "chrono", + "bytes", "form_urlencoded", - "getrandom 0.2.17", - "hex", - "hmac 0.12.1", - "home", "http 1.4.0", - "jsonwebtoken 9.3.1", "log", - "once_cell", "percent-encoding", - "quick-xml 0.37.5", - "rand 0.8.6", - "reqwest", - "rsa", + "quick-xml 0.39.4", + "reqsign-core", "rust-ini", "serde", "serde_json", + "serde_urlencoded", + "sha1", +] + +[[package]] +name = "reqsign-core" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b10302cf0a7d7e7352ba211fc92c3c5bebf1286153e49cc5aa87348078a8e102" +dependencies = [ + "anyhow", + "base64 0.22.1", + "bytes", + "form_urlencoded", + "futures", + "hex", + "hmac 0.12.1", + "http 1.4.0", + "jiff", + "log", + "percent-encoding", "sha1", "sha2 0.10.9", + "windows-sys 0.61.2", +] + +[[package]] +name = "reqsign-file-read-tokio" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d89295b3d17abea31851cc8de55d843d89c52132c864963c38d41920613dc5" +dependencies = [ + "anyhow", + "reqsign-core", "tokio", - "toml 0.8.23", ] [[package]] name = "reqwest" -version = "0.12.28" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" +checksum = "62e0021ea2c22aed41653bc7e1419abb2c97e038ff2c33d0e1309e49a97deec0" dependencies = [ "base64 0.22.1", "bytes", @@ -4370,10 +4266,9 @@ dependencies = [ "mime", "percent-encoding", "pin-project-lite", - "quinn", "rustls 0.23.40", - "rustls-native-certs", "rustls-pki-types", + "rustls-platform-verifier", "serde", "serde_json", "serde_urlencoded", @@ -4389,7 +4284,6 @@ dependencies = [ "wasm-bindgen-futures", "wasm-streams", "web-sys", - "webpki-roots", ] [[package]] @@ -4560,7 +4454,6 @@ dependencies = [ "pkcs1", "pkcs8", "rand_core 0.6.4", - "sha2 0.10.9", "signature", "spki", "subtle", @@ -4597,12 +4490,6 @@ dependencies = [ "ordered-multimap", ] -[[package]] -name = "rustc-hash" -version = "2.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" - [[package]] name = "rustc_version" version = "0.4.1" @@ -4688,10 +4575,36 @@ version = "1.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "30a7197ae7eb376e574fe940d068c30fe0462554a3ddbe4eca7838e049c937a9" dependencies = [ - "web-time", "zeroize", ] +[[package]] +name = "rustls-platform-verifier" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d1e2536ce4f35f4846aa13bff16bd0ff40157cdb14cc056c7b14ba41233ba0" +dependencies = [ + "core-foundation 0.10.1", + "core-foundation-sys", + "jni", + "log", + "once_cell", + "rustls 0.23.40", + "rustls-native-certs", + "rustls-platform-verifier-android", + "rustls-webpki 0.103.13", + "security-framework", + "security-framework-sys", + "webpki-root-certs", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustls-platform-verifier-android" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" + [[package]] name = "rustls-webpki" version = "0.101.7" @@ -4725,15 +4638,6 @@ version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" -[[package]] -name = "salsa20" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97a22f5af31f73a954c10289c93e8a50cc23d971e80ee446f1f6f7137a088213" -dependencies = [ - "cipher", -] - [[package]] name = "same-file" version = "1.0.6" @@ -4797,17 +4701,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" -[[package]] -name = "scrypt" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0516a385866c09368f0b5bcd1caff3366aace790fcd46e2bb032697bb172fd1f" -dependencies = [ - "pbkdf2", - "salsa20", - "sha2 0.10.9", -] - [[package]] name = "sct" version = "0.7.1" @@ -5869,7 +5762,6 @@ checksum = "7ba6f5989077681266825251a52748b8c1d8a4ad098cc37e440103d0ea717fc0" name = "vaultwarden" version = "1.0.0" dependencies = [ - "anyhow", "argon2", "aws-config", "aws-credential-types", @@ -5899,7 +5791,7 @@ dependencies = [ "html5gum", "http 1.4.0", "job_scheduler_ng", - "jsonwebtoken 10.3.0", + "jsonwebtoken", "lettre", "libsqlite3-sys", "log", @@ -5916,13 +5808,15 @@ dependencies = [ "pico-args", "rand 0.10.1", "regex", - "reqsign", + "reqsign-aws-v4", + "reqsign-core", "reqwest", "ring", "rmpv", "rocket", "rocket_ws", "rpassword", + "rustls 0.23.40", "semver", "serde", "serde_json", @@ -6083,9 +5977,9 @@ dependencies = [ [[package]] name = "wasm-streams" -version = "0.4.2" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65" +checksum = "9d1ec4f6517c9e11ae630e200b2b65d193279042e28edd4a2cda233e46670bbb" dependencies = [ "futures-util", "js-sys", @@ -6195,10 +6089,10 @@ dependencies = [ ] [[package]] -name = "webpki-roots" +name = "webpki-root-certs" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52f5ee44c96cf55f1b349600768e3ece3a8f26010c05265ab73f945bb1a2eb9d" +checksum = "f31141ce3fc3e300ae89b78c0dd67f9708061d1d2eda54b8209346fd6be9a92c" dependencies = [ "rustls-pki-types", ] @@ -6346,15 +6240,6 @@ dependencies = [ "windows-targets 0.52.6", ] -[[package]] -name = "windows-sys" -version = "0.60.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" -dependencies = [ - "windows-targets 0.53.5", -] - [[package]] name = "windows-sys" version = "0.61.2" @@ -6388,30 +6273,13 @@ dependencies = [ "windows_aarch64_gnullvm 0.52.6", "windows_aarch64_msvc 0.52.6", "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm 0.52.6", + "windows_i686_gnullvm", "windows_i686_msvc 0.52.6", "windows_x86_64_gnu 0.52.6", "windows_x86_64_gnullvm 0.52.6", "windows_x86_64_msvc 0.52.6", ] -[[package]] -name = "windows-targets" -version = "0.53.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" -dependencies = [ - "windows-link", - "windows_aarch64_gnullvm 0.53.1", - "windows_aarch64_msvc 0.53.1", - "windows_i686_gnu 0.53.1", - "windows_i686_gnullvm 0.53.1", - "windows_i686_msvc 0.53.1", - "windows_x86_64_gnu 0.53.1", - "windows_x86_64_gnullvm 0.53.1", - "windows_x86_64_msvc 0.53.1", -] - [[package]] name = "windows_aarch64_gnullvm" version = "0.48.5" @@ -6424,12 +6292,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" - [[package]] name = "windows_aarch64_msvc" version = "0.48.5" @@ -6442,12 +6304,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" -[[package]] -name = "windows_aarch64_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" - [[package]] name = "windows_i686_gnu" version = "0.48.5" @@ -6460,24 +6316,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" -[[package]] -name = "windows_i686_gnu" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" - [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" -[[package]] -name = "windows_i686_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" - [[package]] name = "windows_i686_msvc" version = "0.48.5" @@ -6490,12 +6334,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" -[[package]] -name = "windows_i686_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" - [[package]] name = "windows_x86_64_gnu" version = "0.48.5" @@ -6508,12 +6346,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" -[[package]] -name = "windows_x86_64_gnu" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" - [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" @@ -6526,12 +6358,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" - [[package]] name = "windows_x86_64_msvc" version = "0.48.5" @@ -6544,12 +6370,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" -[[package]] -name = "windows_x86_64_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" - [[package]] name = "winnow" version = "0.6.26" @@ -6691,6 +6511,16 @@ dependencies = [ "time", ] +[[package]] +name = "xattr" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32e45ad4206f6d2479085147f02bc2ef834ac85886624a23575ae137c8aa8156" +dependencies = [ + "libc", + "rustix", +] + [[package]] name = "xml" version = "1.2.1" @@ -6737,9 +6567,9 @@ dependencies = [ [[package]] name = "yubico_ng" -version = "0.14.1" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "929981f5b46b8fb8ee54b144de6b55c3a94fbe26635ee25b0e126e184250867c" +checksum = "228e2862e3c66f3224102d9a00d9d3646b271a05cc6c4819fea195fa8b5c00e0" dependencies = [ "base64 0.22.1", "form_urlencoded", diff --git a/Cargo.toml b/Cargo.toml index e7fd5ade..271d102d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,7 +39,7 @@ vendored_openssl = ["openssl/vendored"] # Enable MiMalloc memory allocator to replace the default malloc # This can improve performance for Alpine builds enable_mimalloc = ["dep:mimalloc"] -s3 = ["opendal/services-s3", "dep:aws-config", "dep:aws-credential-types", "dep:aws-smithy-runtime-api", "dep:anyhow", "dep:http", "dep:reqsign"] +s3 = ["opendal/services-s3", "dep:aws-config", "dep:aws-credential-types", "dep:aws-smithy-runtime-api", "dep:http", "dep:reqsign-aws-v4", "dep:reqsign-core"] # OIDC specific features oidc-accept-rfc3339-timestamps = ["openidconnect/accept-rfc3339-timestamps"] @@ -102,6 +102,7 @@ libsqlite3-sys = { version = "0.37.0", optional = true } # Crypto-related libraries rand = "0.10.1" ring = "0.17.14" +rustls = { version = "0.23.40", features = ["ring", "std"], default-features = false } subtle = "2.6.1" # UUID generation @@ -125,7 +126,7 @@ jsonwebtoken = { version = "10.3.0", features = ["use_pem", "rust_crypto"], defa totp-lite = "2.0.1" # Yubico Library -yubico = { package = "yubico_ng", version = "0.14.1", features = ["online-tokio"], default-features = false } +yubico = { package = "yubico_ng", version = "0.15.0", features = ["online-tokio"], default-features = false } # WebAuthn libraries # danger-allow-state-serialisation is needed to save the state in the db @@ -146,7 +147,7 @@ email_address = "0.2.9" handlebars = { version = "6.4.0", features = ["dir_source"] } # HTTP client (Used for favicons, version check, DUO and HIBP API) -reqwest = { version = "0.12.28", features = ["rustls-tls", "rustls-tls-native-roots", "stream", "json", "deflate", "gzip", "brotli", "zstd", "socks", "cookies", "charset", "http2", "system-proxy"], default-features = false} +reqwest = { version = "0.13.3", features = ["rustls-no-provider", "stream", "json", "form", "deflate", "gzip", "brotli", "zstd", "socks", "cookies", "charset", "http2", "system-proxy"], default-features = false} hickory-resolver = "0.26.1" # Favicon extraction libraries @@ -174,7 +175,7 @@ pastey = "0.2.2" governor = "0.10.4" # OIDC for SSO -openidconnect = { version = "4.0.1", features = ["reqwest", "rustls-tls"] } +openidconnect = { version = "4.0.1", default-features = false } moka = { version = "0.12.15", features = ["future"] } # Check client versions for specific features. @@ -196,15 +197,15 @@ rpassword = "7.5.1" grass_compiler = { version = "0.13.4", default-features = false } # File are accessed through Apache OpenDAL -opendal = { version = "0.55.0", features = ["services-fs"], default-features = false } +opendal = { version = "0.56.0", features = ["services-fs"], default-features = false } # For retrieving AWS credentials, including temporary SSO credentials -anyhow = { version = "1.0.102", optional = true } aws-config = { version = "1.8.16", features = ["behavior-version-latest", "rt-tokio", "credentials-process", "sso"], default-features = false, optional = true } aws-credential-types = { version = "1.2.14", optional = true } aws-smithy-runtime-api = { version = "1.12.0", optional = true } http = { version = "1.4.0", optional = true } -reqsign = { version = "0.16.5", optional = true } +reqsign-aws-v4 = { version = "3.0.0", optional = true } +reqsign-core = { version = "3.0.0", optional = true } # Strip debuginfo from the release builds # The debug symbols are to provide better panic traces diff --git a/src/api/core/sends.rs b/src/api/core/sends.rs index 22abb396..5612d0b6 100644 --- a/src/api/core/sends.rs +++ b/src/api/core/sends.rs @@ -568,7 +568,7 @@ async fn post_access_file( async fn download_url(host: &Host, send_id: &SendId, file_id: &SendFileId) -> Result { let operator = CONFIG.opendal_operator_for_path_type(&PathType::Sends)?; - if operator.info().scheme() == <&'static str>::from(opendal::Scheme::Fs) { + if operator.info().scheme() == opendal::services::FS_SCHEME { let token_claims = crate::auth::generate_send_claims(send_id, file_id); let token = crate::auth::encode_jwt(&token_claims); diff --git a/src/config.rs b/src/config.rs index ae995f69..9a1d26c7 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1395,17 +1395,22 @@ fn opendal_operator_for_path(path: &str) -> Result { fn opendal_s3_operator_for_path(path: &str) -> Result { use crate::http_client::aws::AwsReqwestConnector; use aws_config::{default_provider::credentials::DefaultCredentialsChain, provider_config::ProviderConfig}; + use reqsign_aws_v4::Credential; + use reqsign_core::{Context, ProvideCredential, ProvideCredentialChain}; // This is a custom AWS credential loader that uses the official AWS Rust // SDK config crate to load credentials. This ensures maximum compatibility // with AWS credential configurations. For example, OpenDAL doesn't support // AWS SSO temporary credentials yet. - struct OpenDALS3CredentialLoader {} + #[derive(Debug)] + struct OpenDALS3CredentialProvider; - #[async_trait] - impl reqsign::AwsCredentialLoad for OpenDALS3CredentialLoader { - async fn load_credential(&self, _client: reqwest::Client) -> anyhow::Result> { + impl ProvideCredential for OpenDALS3CredentialProvider { + type Credential = Credential; + + async fn provide_credential(&self, _ctx: &Context) -> reqsign_core::Result> { use aws_credential_types::provider::ProvideCredentials as _; + use reqsign_core::time::Timestamp; use tokio::sync::OnceCell; static DEFAULT_CREDENTIAL_CHAIN: OnceCell = OnceCell::const_new(); @@ -1423,25 +1428,37 @@ fn opendal_s3_operator_for_path(path: &str) -> Result }) .await; - let creds = chain.provide_credentials().await?; + let creds = chain.provide_credentials().await.map_err(|e| { + reqsign_core::Error::unexpected("failed to load AWS credentials via AWS SDK").with_source(e) + })?; + + let expires_in = if let Some(expiration) = creds.expiry() { + let duration = expiration.duration_since(std::time::UNIX_EPOCH).map_err(|e| { + reqsign_core::Error::unexpected("AWS credential expiration is before the Unix epoch").with_source(e) + })?; + let seconds = i64::try_from(duration.as_secs()).map_err(|e| { + reqsign_core::Error::unexpected("AWS credential expiration is too large").with_source(e) + })?; + Some(Timestamp::from_second(seconds)?) + } else { + None + }; - Ok(Some(reqsign::AwsCredential { + Ok(Some(Credential { access_key_id: creds.access_key_id().to_string(), secret_access_key: creds.secret_access_key().to_string(), session_token: creds.session_token().map(|s| s.to_string()), - expires_in: creds.expiry().map(|expiration| expiration.into()), + expires_in, })) } } - const OPEN_DAL_S3_CREDENTIAL_LOADER: OpenDALS3CredentialLoader = OpenDALS3CredentialLoader {}; - let url = Url::parse(path).map_err(|e| format!("Invalid path S3 URL path {path:?}: {e}"))?; let bucket = url.host_str().ok_or_else(|| format!("Missing Bucket name in data folder S3 URL {path:?}"))?; let builder = opendal::services::S3::default() - .customized_credential_load(Box::new(OPEN_DAL_S3_CREDENTIAL_LOADER)) + .credential_provider_chain(ProvideCredentialChain::new().push(OpenDALS3CredentialProvider)) .enable_virtual_host_style() .bucket(bucket) .root(url.path()) diff --git a/src/db/models/attachment.rs b/src/db/models/attachment.rs index 7611b927..437bb586 100644 --- a/src/db/models/attachment.rs +++ b/src/db/models/attachment.rs @@ -46,7 +46,7 @@ impl Attachment { pub async fn get_url(&self, host: &str) -> Result { let operator = CONFIG.opendal_operator_for_path_type(&PathType::Attachments)?; - if operator.info().scheme() == <&'static str>::from(opendal::Scheme::Fs) { + if operator.info().scheme() == opendal::services::FS_SCHEME { let token = encode_jwt(&generate_file_download_claims(self.cipher_uuid.clone(), self.id.clone())); Ok(format!("{host}/attachments/{}/{}?token={token}", self.cipher_uuid, self.id)) } else { diff --git a/src/db/models/send.rs b/src/db/models/send.rs index 84802c54..5b6611fa 100644 --- a/src/db/models/send.rs +++ b/src/db/models/send.rs @@ -237,7 +237,7 @@ impl Send { if self.atype == SendType::File as i32 { let operator = CONFIG.opendal_operator_for_path_type(&PathType::Sends)?; - operator.remove_all(&self.uuid).await.ok(); + operator.delete_with(&self.uuid).recursive(true).await.ok(); } db_run! { conn: { diff --git a/src/main.rs b/src/main.rs index 60c5a593..5f5cc50a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -70,6 +70,7 @@ pub use util::is_running_in_container; #[rocket::main] async fn main() -> Result<(), Error> { + install_rustls_crypto_provider(); parse_args(); launch_info(); @@ -202,6 +203,14 @@ fn parse_args() { } } +fn install_rustls_crypto_provider() { + if rustls::crypto::CryptoProvider::get_default().is_none() { + rustls::crypto::ring::default_provider() + .install_default() + .expect("failed to install rustls ring crypto provider"); + } +} + fn launch_info() { println!( "\ diff --git a/src/sso_client.rs b/src/sso_client.rs index abff6bcb..68e171c6 100644 --- a/src/sso_client.rs +++ b/src/sso_client.rs @@ -1,12 +1,13 @@ -use std::{borrow::Cow, sync::LazyLock, time::Duration}; +use std::{borrow::Cow, future::Future, pin::Pin, sync::LazyLock, time::Duration}; -use openidconnect::{core::*, reqwest, *}; +use openidconnect::{core::*, *}; use regex::Regex; use url::Url; use crate::{ api::{ApiResult, EmptyResult}, db::models::SsoAuth, + http_client::get_reqwest_client_builder, sso::{OIDCCode, OIDCCodeChallenge, OIDCCodeVerifier, OIDCState}, CONFIG, }; @@ -46,10 +47,42 @@ pub type RefreshTokenResponse = (Option, String, Option); #[derive(Clone)] pub struct Client { - pub http_client: reqwest::Client, + pub http_client: OidcHttpClient, pub core_client: CustomClient, } +#[derive(Clone)] +pub struct OidcHttpClient { + client: reqwest::Client, +} + +impl OidcHttpClient { + fn new() -> Result { + get_reqwest_client_builder().redirect(reqwest::redirect::Policy::none()).build().map(|client| Self { + client, + }) + } +} + +impl<'c> AsyncHttpClient<'c> for OidcHttpClient { + type Error = HttpClientError; + type Future = Pin> + Send + Sync + 'c>>; + + fn call(&'c self, request: HttpRequest) -> Self::Future { + Box::pin(async move { + let response = self.client.execute(request.try_into().map_err(Box::new)?).await.map_err(Box::new)?; + + let mut builder = http::Response::builder().status(response.status()).version(response.version()); + + for (name, value) in response.headers() { + builder = builder.header(name, value); + } + + builder.body(response.bytes().await.map_err(Box::new)?.to_vec()).map_err(HttpClientError::Http) + }) + } +} + impl Client { // Call the OpenId discovery endpoint to retrieve configuration async fn _get_client() -> ApiResult { @@ -58,7 +91,7 @@ impl Client { let issuer_url = CONFIG.sso_issuer_url()?; - let http_client = match reqwest::ClientBuilder::new().redirect(reqwest::redirect::Policy::none()).build() { + let http_client = match OidcHttpClient::new() { Err(err) => err!(format!("Failed to build http client: {err}")), Ok(client) => client, };