diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4524173..bad8d24 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -77,7 +77,7 @@ jobs: strategy: matrix: os: [ubuntu-latest, windows-latest] - rust: [1.85, stable] + rust: [1.89, stable] runs-on: ${{ matrix.os }} steps: diff --git a/Cargo.lock b/Cargo.lock index a2b4210..23b773f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,19 +4,19 @@ version = 4 [[package]] name = "aead" -version = "0.6.0-rc.2" +version = "0.6.0-rc.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac8202ab55fcbf46ca829833f347a82a2a4ce0596f0304ac322c2d100030cd56" +checksum = "67a578e7d4edaef88aeb9cdd81556f4a62266ce26601317c006a79e8bc58b5af" dependencies = [ - "crypto-common 0.2.0-rc.4", + "crypto-common 0.2.0-rc.8", "inout", ] [[package]] name = "aes" -version = "0.9.0-rc.1" +version = "0.9.0-rc.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e713c57c2a2b19159e7be83b9194600d7e8eb3b7c2cd67e671adf47ce189a05" +checksum = "fd9e1c818b25efb32214df89b0ec22f01aa397aaeb718d1022bf0635a3bfd1a8" dependencies = [ "cfg-if", "cipher", @@ -25,9 +25,9 @@ dependencies = [ [[package]] name = "aes-gcm" -version = "0.11.0-rc.1" +version = "0.11.0-rc.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0686ba04dc80c816104c96cd7782b748f6ad58c5dd4ee619ff3258cf68e83d54" +checksum = "7f5c07f414d7dc0755870f84c7900425360288d24e0eae4836f9dee19a30fa5f" dependencies = [ "aead", "aes", @@ -48,9 +48,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.21" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" +checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" dependencies = [ "anstyle", "anstyle-parse", @@ -63,15 +63,15 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" [[package]] name = "anstyle-parse" -version = "0.2.7" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e" dependencies = [ "utf8parse", ] @@ -129,7 +129,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -146,9 +146,9 @@ checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "base16ct" -version = "0.3.0" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8b59d472eab27ade8d770dcb11da7201c11234bef9f82ce7aa517be028d462b" +checksum = "fd307490d624467aa6f74b0eabb77633d1f758a7b25f12bceb0b22e08d9726f6" [[package]] name = "base64" @@ -158,15 +158,15 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "base64ct" -version = "1.8.1" +version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e050f626429857a27ddccb31e0aca21356bfa709c04041aefddac081a8f068a" +checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" [[package]] name = "binrw" -version = "0.15.0" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81419ff39e6ed10a92a7f125290859776ced35d9a08a665ae40b23e7ca702f30" +checksum = "d53195f985e88ab94d1cc87e80049dd2929fd39e4a772c5ae96a7e5c4aad3642" dependencies = [ "array-init", "binrw_derive", @@ -175,15 +175,15 @@ dependencies = [ [[package]] name = "binrw_derive" -version = "0.15.0" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "376404e55ec40d0d6f8b4b7df3f87b87954bd987f0cf9a7207ea3b6ea5c9add4" +checksum = "5910da05ee556b789032c8ff5a61fb99239580aa3fd0bfaa8f4d094b2aee00ad" dependencies = [ "either", "owo-colors", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -194,9 +194,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.10.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" +checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" [[package]] name = "block-buffer" @@ -209,18 +209,27 @@ dependencies = [ [[package]] name = "block-buffer" -version = "0.11.0-rc.5" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9ef36a6fcdb072aa548f3da057640ec10859eb4e91ddf526ee648d50c76a949" +checksum = "96eb4cdd6cf1b31d671e9efe75c5d1ec614776856cefbe109ca373554a6d514f" +dependencies = [ + "hybrid-array", +] + +[[package]] +name = "block-buffer" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdd35008169921d80bc60d3d0ab416eecb028c4cd653352907921d95084790be" dependencies = [ "hybrid-array", ] [[package]] name = "block-padding" -version = "0.4.0-rc.4" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e59c1aab3e6c5e56afe1b7e8650be9b5a791cb997bdea449194ae62e4bf8c73" +checksum = "710f1dd022ef4e93f8a438b4ba958de7f64308434fa6a87104481645cc30068b" dependencies = [ "hybrid-array", ] @@ -236,15 +245,15 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.19.0" +version = "3.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" +checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" [[package]] name = "bytemuck" -version = "1.24.0" +version = "1.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fbdf580320f38b612e485521afda1ee26d10cc9884efaaa750d383e13e3c5f4" +checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec" [[package]] name = "byteorder" @@ -254,9 +263,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" [[package]] name = "cbc" @@ -269,9 +278,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.49" +version = "1.2.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90583009037521a116abf44494efecd645ba48b6622457080f080b85544e2215" +checksum = "43c5703da9466b66a946814e1adf53ea2c90f10063b86290cc9eb67ce3478a20" dependencies = [ "find-msvc-tools", "shlex", @@ -279,9 +288,9 @@ dependencies = [ [[package]] name = "ccm" -version = "0.6.0-pre.0" +version = "0.6.0-rc.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a49680966b1cae2a239dd94d11bac423894ee4e00dacea1c50e8673e26a9829f" +checksum = "d1ad0c3a709bfe243b5585554f3d697dc015d04ebad7598fd4d650bc2d7591a3" dependencies = [ "aead", "cipher", @@ -307,22 +316,33 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" +[[package]] +name = "chacha20" +version = "0.10.0-rc.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f895fb33c1ad22da4bc79d37c0bddff8aee2ba4575705345eb73b8ffbc386074" +dependencies = [ + "cfg-if", + "cpufeatures", + "rand_core 0.10.0-rc-3", +] + [[package]] name = "cipher" -version = "0.5.0-rc.1" +version = "0.5.0-rc.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e12a13eb01ded5d32ee9658d94f553a19e804204f2dc811df69ab4d9e0cb8c7" +checksum = "98d708bac5451350d56398433b19a7889022fa9187df1a769c0edbc3b2c03167" dependencies = [ - "block-buffer 0.11.0-rc.5", - "crypto-common 0.2.0-rc.4", + "block-buffer 0.11.0", + "crypto-common 0.2.0-rc.8", "inout", ] [[package]] name = "clap" -version = "4.5.53" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9e340e012a1bf4935f5282ed1436d1489548e8f72308207ea5df0e23d2d03f8" +checksum = "b193af5b67834b676abd72466a96c1024e6a6ad978a1f484bd90b85c94041351" dependencies = [ "clap_builder", "clap_derive", @@ -330,9 +350,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.53" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d76b5d13eaa18c901fd2f7fca939fefe3a0727a953561fefdf3b2922b8569d00" +checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" dependencies = [ "anstream", "anstyle", @@ -342,21 +362,21 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.49" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671" +checksum = "1110bd8a634a1ab8cb04345d8d878267d57c3cf1b38d91b71af6686408bbca6a" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] name = "clap_lex" -version = "0.7.6" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d" +checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" [[package]] name = "cmac" @@ -366,14 +386,20 @@ checksum = "e2fa99ca412f76b4656efeab943ef06f1ddd8036c31ca38f35188f173d0dc85e" dependencies = [ "cipher", "dbl", - "digest 0.11.0-rc.3", + "digest 0.11.0-rc.5", ] +[[package]] +name = "cmov" +version = "0.5.0-pre.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5417da527aa9bf6a1e10a781231effd1edd3ee82f27d5f8529ac9b279babce96" + [[package]] name = "colorchoice" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" +checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" [[package]] name = "combine" @@ -387,22 +413,21 @@ dependencies = [ [[package]] name = "console" -version = "0.16.1" +version = "0.16.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b430743a6eb14e9764d4260d4c0d8123087d504eeb9c48f2b2a5e810dd369df4" +checksum = "d64e8af5551369d19cf50138de61f1c42074ab970f74e99be916646777f8fc87" dependencies = [ "encode_unicode", "libc", - "once_cell", "unicode-width", "windows-sys 0.61.2", ] [[package]] name = "const-oid" -version = "0.10.1" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dabb6555f92fb9ee4140454eb5dcd14c7960e1225c6d1a6cc361f032947713e" +checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c" [[package]] name = "const_format" @@ -451,13 +476,15 @@ dependencies = [ [[package]] name = "crypto-bigint" -version = "0.7.0-rc.8" +version = "0.7.0-rc.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4113edbc9f68c0a64d5b911f803eb245d04bb812680fd56776411f69c670f3e0" +checksum = "37387ceb32048ff590f2cbd24d8b05fffe63c3f69a5cfa089d4f722ca4385a19" dependencies = [ + "ctutils", + "getrandom 0.4.0-rc.0", "hybrid-array", "num-traits", - "rand_core 0.9.3", + "rand_core 0.10.0-rc-3", "serdect", "subtle", "zeroize", @@ -475,12 +502,13 @@ dependencies = [ [[package]] name = "crypto-common" -version = "0.2.0-rc.4" +version = "0.2.0-rc.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a8235645834fbc6832939736ce2f2d08192652269e11010a6240f61b908a1c6" +checksum = "e6165b8029cdc3e765b74d3548f85999ee799d5124877ce45c2c85ca78e4d4aa" dependencies = [ + "getrandom 0.4.0-rc.0", "hybrid-array", - "rand_core 0.9.3", + "rand_core 0.10.0-rc-3", ] [[package]] @@ -495,45 +523,55 @@ dependencies = [ [[package]] name = "crypto-primes" -version = "0.7.0-pre.3" +version = "0.7.0-pre.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25f2523fbb68811c8710829417ad488086720a6349e337c38d12fa81e09e50bf" +checksum = "e79c98a281f9441200b24e3151407a629bfbe720399186e50516da939195e482" dependencies = [ "crypto-bigint", "libm", - "rand_core 0.9.3", + "rand_core 0.10.0-rc-3", ] [[package]] name = "ctr" -version = "0.10.0-rc.1" +version = "0.10.0-rc.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27e41d01c6f73b9330177f5cf782ae5b581b5f2c7840e298e0275ceee5001434" +checksum = "3d0ec605a95e78815a4c4b8040217d56d5a1ab37043851ee9e7e65b89afa00e3" dependencies = [ "cipher", ] [[package]] name = "ctrlc" -version = "3.5.1" +version = "3.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73736a89c4aff73035ba2ed2e565061954da00d4970fc9ac25dcc85a2a20d790" +checksum = "e0b1fab2ae45819af2d0731d60f2afe17227ebb1a1538a236da84c93e9a60162" dependencies = [ "dispatch2", "nix", "windows-sys 0.61.2", ] +[[package]] +name = "ctutils" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "758e5ed90be3c8abff7f9a6f37ab7f6d8c59c2210d448b81f3f508134aec84e4" +dependencies = [ + "cmov", + "subtle", +] + [[package]] name = "curve25519-dalek" -version = "5.0.0-pre.1" +version = "5.0.0-pre.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f9200d1d13637f15a6acb71e758f64624048d85b31a5fdbfd8eca1e2687d0b7" +checksum = "6ae8b2fe5e4995d7fd08a7604e794dc569a65ed19659f5939d529813ed816d38" dependencies = [ "cfg-if", "cpufeatures", "curve25519-dalek-derive", - "digest 0.11.0-rc.3", + "digest 0.11.0-rc.5", "fiat-crypto", "rustc_version", "subtle", @@ -548,7 +586,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -562,9 +600,9 @@ dependencies = [ [[package]] name = "der" -version = "0.8.0-rc.9" +version = "0.8.0-rc.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9d8dd2f26c86b27a2a8ea2767ec7f9df7a89516e4794e54ac01ee618dda3aa4" +checksum = "02c1d73e9668ea6b6a28172aa55f3ebec38507131ce179051c8033b5c6037653" dependencies = [ "const-oid", "pem-rfc7468", @@ -573,9 +611,9 @@ dependencies = [ [[package]] name = "deranged" -version = "0.5.5" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" dependencies = [ "powerfmt", ] @@ -601,23 +639,23 @@ dependencies = [ [[package]] name = "digest" -version = "0.11.0-rc.3" +version = "0.11.0-rc.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dac89f8a64533a9b0eaa73a68e424db0fb1fd6271c74cc0125336a05f090568d" +checksum = "ebf9423bafb058e4142194330c52273c343f8a5beb7176d052f0e73b17dd35b9" dependencies = [ - "block-buffer 0.11.0-rc.5", + "block-buffer 0.11.0", "const-oid", - "crypto-common 0.2.0-rc.4", + "crypto-common 0.2.0-rc.8", "subtle", ] [[package]] name = "dispatch2" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec" +checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "block2", "libc", "objc2", @@ -631,17 +669,17 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] name = "ecdsa" -version = "0.17.0-rc.7" +version = "0.17.0-rc.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4ab355ec063f7a110eb627471058093aba00eb7f4e70afbd15e696b79d1077b" +checksum = "569a1f3377df19ab839b2811061095ff7d9fb7ea3c0e500b7a4724343cf6ee3d" dependencies = [ "der", - "digest 0.11.0-rc.3", + "digest 0.11.0-rc.5", "elliptic-curve", "rfc6979", "signature", @@ -651,9 +689,9 @@ dependencies = [ [[package]] name = "ed25519" -version = "3.0.0-rc.1" +version = "3.0.0-rc.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ef49c0b20c0ad088893ad2a790a29c06a012b3f05bcfc66661fd22a94b32129" +checksum = "594435fe09e345ee388e4e8422072ff7dfeca8729389fbd997b3f5504c44cd47" dependencies = [ "pkcs8", "signature", @@ -661,13 +699,13 @@ dependencies = [ [[package]] name = "ed25519-dalek" -version = "3.0.0-pre.1" +version = "3.0.0-pre.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad207ed88a133091f83224265eac21109930db09bedcad05d5252f2af2de20a1" +checksum = "a4b9f613e0c236c699bf70d39f825594d9b03aadfd8dd856ea40685f782a4ef2" dependencies = [ "curve25519-dalek", "ed25519", - "rand_core 0.9.3", + "rand_core 0.10.0-rc-3", "sha2", "subtle", "zeroize", @@ -681,21 +719,22 @@ checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] name = "elliptic-curve" -version = "0.14.0-rc.15" +version = "0.14.0-rc.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e3be87c458d756141f3b6ee188828132743bf90c7d14843e2835d6443e5fb03" +checksum = "6bfae4ab886ff791e2119cc79402281e35408f22b6b7322acef371d01061054b" dependencies = [ "base16ct", "crypto-bigint", - "digest 0.11.0-rc.3", - "ff", - "group", + "digest 0.11.0-rc.5", + "getrandom 0.4.0-rc.0", "hkdf", "hybrid-array", "once_cell", "pem-rfc7468", "pkcs8", - "rand_core 0.9.3", + "rand_core 0.10.0-rc-3", + "rustcrypto-ff", + "rustcrypto-group", "sec1", "subtle", "zeroize", @@ -709,9 +748,9 @@ checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" [[package]] name = "env_filter" -version = "0.1.4" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bf3c259d255ca70051b30e2e95b5446cdb8949ac4cd22c0d7fd634d89f568e2" +checksum = "32e90c2accc4b07a8456ea0debdc2e7587bdd890680d71173a15d4ae604f6eef" dependencies = [ "log", "regex", @@ -719,9 +758,9 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.11.8" +version = "0.11.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f" +checksum = "0621c04f2196ac3f488dd583365b9c09be011a4ab8b9f37248ffcc8f6198b56a" dependencies = [ "anstream", "anstyle", @@ -732,13 +771,13 @@ dependencies = [ [[package]] name = "fastbloom" -version = "0.14.0" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18c1ddb9231d8554c2d6bdf4cfaabf0c59251658c68b6c95cd52dd0c513a912a" +checksum = "4e7f34442dbe69c60fe8eaf58a8cafff81a1f278816d8ab4db255b3bef4ac3c4" dependencies = [ "getrandom 0.3.4", "libm", - "rand 0.9.2", + "rand 0.9.4", "siphasher", ] @@ -748,7 +787,7 @@ version = "0.14.0-pre.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d42dd26f5790eda47c1a2158ea4120e32c35ddc9a7743c98a292accc01b54ef3" dependencies = [ - "rand_core 0.9.3", + "rand_core 0.9.5", "subtle", ] @@ -760,9 +799,9 @@ checksum = "64cd1e32ddd350061ae6edb1b082d7c54915b5c672c389143b9a63403a109f24" [[package]] name = "find-msvc-tools" -version = "0.1.5" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" [[package]] name = "form_urlencoded" @@ -775,9 +814,9 @@ dependencies = [ [[package]] name = "futures" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" dependencies = [ "futures-channel", "futures-core", @@ -790,9 +829,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" dependencies = [ "futures-core", "futures-sink", @@ -800,15 +839,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" [[package]] name = "futures-executor" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" dependencies = [ "futures-core", "futures-task", @@ -817,38 +856,38 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" +checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" [[package]] name = "futures-macro" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] name = "futures-sink" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" +checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" [[package]] name = "futures-task" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" [[package]] name = "futures-util" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" dependencies = [ "futures-channel", "futures-core", @@ -858,7 +897,6 @@ dependencies = [ "futures-task", "memchr", "pin-project-lite", - "pin-utils", "slab", ] @@ -874,9 +912,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" dependencies = [ "cfg-if", "js-sys", @@ -899,11 +937,24 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "getrandom" +version = "0.4.0-rc.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b99f0d993a2b9b97b9a201193aa8ad21305cde06a3be9a7e1f8f4201e5cc27e" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "rand_core 0.10.0-rc-3", + "wasip2", +] + [[package]] name = "ghash" -version = "0.6.0-rc.2" +version = "0.6.0-rc.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f88107cb02ed63adcc4282942e60c4d09d80208d33b360ce7c729ce6dae1739" +checksum = "333de57ed9494a40df4bbb866752b100819dde0d18f2264c48f5a08a85fe673d" dependencies = [ "polyval", ] @@ -915,7 +966,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ff6a0b2dd4b981b1ae9e3e6830ab146771f3660d31d57bafd9018805a91b0f1" dependencies = [ "ff", - "rand_core 0.9.3", + "rand_core 0.9.5", "subtle", ] @@ -933,20 +984,20 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "hkdf" -version = "0.13.0-rc.2" +version = "0.13.0-rc.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8ef30358b03ca095a5b910547f4f8d4b9f163e4057669c5233ef595b1ecf008" +checksum = "cfbb4225acf2b5cc4e12d384672cd6d1f0cb980ff5859ffcf144db25b593a24d" dependencies = [ "hmac", ] [[package]] name = "hmac" -version = "0.13.0-rc.2" +version = "0.13.0-rc.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3fd4dc94c318c1ede8a2a48341c250d6ddecd3ba793da2820301a9f92417ad9" +checksum = "f1c597ac7d6cc8143e30e83ef70915e7f883b18d8bec2e2b2bce47f5bbb06d57" dependencies = [ - "digest 0.11.0-rc.3", + "digest 0.11.0-rc.5", ] [[package]] @@ -990,9 +1041,9 @@ checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" [[package]] name = "hybrid-array" -version = "0.4.5" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f471e0a81b2f90ffc0cb2f951ae04da57de8baa46fa99112b062a5173a5088d0" +checksum = "3944cf8cf766b40e2a1a333ee5e9b563f854d5fa49d6a8ca2764e97c6eddb214" dependencies = [ "subtle", "typenum", @@ -1001,9 +1052,9 @@ dependencies = [ [[package]] name = "hyper" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ab2d4f250c3d7b1c9fcdff1cece94ea4e2dfbec68614f7b87cb205f24ca9d11" +checksum = "6299f016b246a94207e63da54dbe807655bf9e00044f73ded42c3ac5305fbcca" dependencies = [ "atomic-waker", "bytes", @@ -1014,7 +1065,6 @@ dependencies = [ "httparse", "itoa", "pin-project-lite", - "pin-utils", "smallvec", "tokio", "want", @@ -1022,16 +1072,15 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.27.7" +version = "0.27.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" +checksum = "c2b52f86d1d4bc0d6b4e6826d960b1b333217e07d36b882dca570a5e1c48895b" dependencies = [ "http", "hyper", "hyper-util", "rustls", "rustls-native-certs", - "rustls-pki-types", "tokio", "tokio-rustls", "tower-service", @@ -1039,14 +1088,13 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.19" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "727805d60e7938b76b826a6ef209eb70eaa1812794f9424d4a4e2d740662df5f" +checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" dependencies = [ "base64", "bytes", "futures-channel", - "futures-core", "futures-util", "http", "http-body", @@ -1063,12 +1111,13 @@ dependencies = [ [[package]] name = "icu_collections" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" +checksum = "2984d1cd16c883d7935b9e07e44071dca8d917fd52ecc02c04d5fa0b5a3f191c" dependencies = [ "displaydoc", "potential_utf", + "utf8_iter", "yoke", "zerofrom", "zerovec", @@ -1076,9 +1125,9 @@ dependencies = [ [[package]] name = "icu_locale_core" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" +checksum = "92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29" dependencies = [ "displaydoc", "litemap", @@ -1089,9 +1138,9 @@ dependencies = [ [[package]] name = "icu_normalizer" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" +checksum = "c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4" dependencies = [ "icu_collections", "icu_normalizer_data", @@ -1103,15 +1152,15 @@ dependencies = [ [[package]] name = "icu_normalizer_data" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" +checksum = "da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38" [[package]] name = "icu_properties" -version = "2.1.2" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec" +checksum = "bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de" dependencies = [ "icu_collections", "icu_locale_core", @@ -1123,15 +1172,15 @@ dependencies = [ [[package]] name = "icu_properties_data" -version = "2.1.2" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af" +checksum = "8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14" [[package]] name = "icu_provider" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" +checksum = "139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421" dependencies = [ "displaydoc", "icu_locale_core", @@ -1165,9 +1214,9 @@ dependencies = [ [[package]] name = "indicatif" -version = "0.18.3" +version = "0.18.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9375e112e4b463ec1b1c6c011953545c65a30164fbab5b581df32b3abf0dcb88" +checksum = "25470f23803092da7d239834776d653104d551bc4d7eacaf31e6837854b8e9eb" dependencies = [ "console", "portable-atomic", @@ -1178,9 +1227,9 @@ dependencies = [ [[package]] name = "inout" -version = "0.2.0-rc.6" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1603f76010ff924b616c8f44815a42eb10fb0b93d308b41deaa8da6d4251fd4b" +checksum = "4250ce6452e92010fdf7268ccc5d14faa80bb12fc741938534c58f16804e03c7" dependencies = [ "block-padding", "hybrid-array", @@ -1188,15 +1237,15 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.11.0" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" +checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" [[package]] name = "iri-string" -version = "0.7.9" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f867b9d1d896b67beb18518eda36fdb77a32ea590de864f1325b294a6d14397" +checksum = "25e659a4bb38e810ebc252e53b5814ff908a8c58c2a9ce2fae1bbec24cbf4e20" dependencies = [ "memchr", "serde", @@ -1210,15 +1259,15 @@ checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" [[package]] name = "itoa" -version = "1.0.15" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "jiff" -version = "0.2.16" +version = "0.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49cce2b81f2098e7e3efc35bc2e0a6b7abec9d34128283d7a26fa8f32a6dbb35" +checksum = "1a3546dc96b6d42c5f24902af9e2538e82e39ad350b0c766eb3fbf2d8f3d8359" dependencies = [ "jiff-static", "log", @@ -1229,13 +1278,13 @@ dependencies = [ [[package]] name = "jiff-static" -version = "0.2.16" +version = "0.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "980af8b43c3ad5d8d349ace167ec8170839f753a42d233ba19e08afe1850fa69" +checksum = "2a8c8b344124222efd714b73bb41f8b5120b27a7cc1c75593a6ff768d9d05aa4" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -1247,7 +1296,7 @@ dependencies = [ "cesu8", "cfg-if", "combine", - "jni-sys", + "jni-sys 0.3.1", "log", "thiserror 1.0.69", "walkdir", @@ -1256,16 +1305,40 @@ dependencies = [ [[package]] name = "jni-sys" -version = "0.3.0" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41a652e1f9b6e0275df1f15b32661cf0d4b78d4d87ddec5e0c3c20f097433258" +dependencies = [ + "jni-sys 0.4.1", +] + +[[package]] +name = "jni-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6377a88cb3910bee9b0fa88d4f42e1d2da8e79915598f65fb0c7ee14c878af2" +dependencies = [ + "jni-sys-macros", +] + +[[package]] +name = "jni-sys-macros" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" +checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" +dependencies = [ + "quote", + "syn 2.0.117", +] [[package]] name = "js-sys" -version = "0.3.83" +version = "0.3.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "464a3709c7f55f1f721e5389aa6ea4e3bc6aba669353300af094b29ffbdde1d8" +checksum = "2964e92d1d9dc3364cae4d718d93f227e3abb088e747d92e0395bfdedf1c12ca" dependencies = [ + "cfg-if", + "futures-util", "once_cell", "wasm-bindgen", ] @@ -1276,7 +1349,7 @@ version = "0.1.0-pre.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e97e1f9b50adafd503518a832b24241dca1d319bfc27e9e708bcf220b0b25419" dependencies = [ - "digest 0.11.0-rc.3", + "digest 0.11.0-rc.5", ] [[package]] @@ -1296,21 +1369,21 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.178" +version = "0.2.185" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091" +checksum = "52ff2c0fe9bc6cb6b14a0592c2ff4fa9ceb83eea9db979b0487cd054946a2b8f" [[package]] name = "libm" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" [[package]] name = "litemap" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" +checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" [[package]] name = "lock_api" @@ -1335,9 +1408,9 @@ checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" [[package]] name = "lz4_flex" -version = "0.11.5" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08ab2867e3eeeca90e844d1940eab391c9dc5228783db2ed999acbc0a9ed375a" +checksum = "373f5eceeeab7925e0c1098212f2fbc4d416adec9d35051a6ab251e824c1854a" [[package]] name = "matchers" @@ -1356,7 +1429,7 @@ checksum = "5cf92c10c7e361d6b99666ec1c6f9805b0bea2c3bd8c78dc6fe98ac5bd78db11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -1366,7 +1439,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9ec86664728010f574d67ef01aec964e6f1299241a3402857c1a8a390a62478" dependencies = [ "cfg-if", - "digest 0.11.0-rc.3", + "digest 0.11.0-rc.5", ] [[package]] @@ -1380,15 +1453,15 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.6" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" [[package]] name = "mio" -version = "1.1.1" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc" +checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1" dependencies = [ "libc", "wasi", @@ -1418,11 +1491,11 @@ dependencies = [ [[package]] name = "nix" -version = "0.30.1" +version = "0.31.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" +checksum = "5d6d0705320c1e6ba1d912b5e37cf18071b6c2e9b7fa8215a1e8a7651966f5d3" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "cfg-if", "cfg_aliases", "libc", @@ -1439,9 +1512,9 @@ dependencies = [ [[package]] name = "num-conv" -version = "0.1.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" +checksum = "c6673768db2d862beb9b39a78fdcb1a69439615d5794a1be50caa9bc92c81967" [[package]] name = "num-derive" @@ -1451,7 +1524,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -1465,9 +1538,9 @@ dependencies = [ [[package]] name = "objc2" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7c2599ce0ec54857b29ce62166b0ed9b4f6f1a70ccc9a71165b6154caca8c05" +checksum = "3a12a8ed07aefc768292f076dc3ac8c48f3781c8f2d5851dd3d98950e8c5a89f" dependencies = [ "objc2-encode", ] @@ -1489,9 +1562,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.21.3" +version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "once_cell_polyfill" @@ -1501,21 +1574,21 @@ checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" [[package]] name = "openssl-probe" -version = "0.1.6" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" +checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" [[package]] name = "owo-colors" -version = "4.2.3" +version = "4.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c6901729fa79e91a0913333229e9ca5dc725089d1c363b2f4b4760709dc4a52" +checksum = "d211803b9b6b570f68772237e415a029d5a50c65d382910b879fb19d3271f94d" [[package]] name = "p256" -version = "0.14.0-pre.11" +version = "0.14.0-rc.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81b374901df34ee468167a58e2a49e468cb059868479cafebeb804f6b855423d" +checksum = "4caab26e75ab3d0790a0f29df73f006308ada2e1fbbfcbab03e92346adc43dd9" dependencies = [ "ecdsa", "elliptic-curve", @@ -1526,9 +1599,9 @@ dependencies = [ [[package]] name = "p384" -version = "0.14.0-pre.11" +version = "0.14.0-rc.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "701032b3730df6b882496d6cee8221de0ce4bc11ddc64e6d89784aa5b8a6de30" +checksum = "30732b26c446549117425e4e905456494ff6c87da40216fd6c71ccc7c3976080" dependencies = [ "ecdsa", "elliptic-curve", @@ -1540,16 +1613,15 @@ dependencies = [ [[package]] name = "p521" -version = "0.14.0-pre.11" +version = "0.14.0-rc.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ba29c2906eb5c89a8c411c4f11243ee4e5517ee7d71d9a13fedc877a6057b1" +checksum = "3dd4780ae0e4fc6a0a722123508ee69e88d45f94bdff67ef25528f659dda9dbd" dependencies = [ "base16ct", "ecdsa", "elliptic-curve", "primefield", "primeorder", - "rand_core 0.9.3", "sha2", ] @@ -1573,7 +1645,7 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "windows-link 0.2.1", + "windows-link", ] [[package]] @@ -1588,16 +1660,16 @@ version = "0.13.0-rc.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca3fc18bb4460ac250ba6b75dfa7cf9d0b2273e3e623f660bd6ce2c3e902342e" dependencies = [ - "digest 0.11.0-rc.3", + "digest 0.11.0-rc.5", "hmac", "sha1", ] [[package]] name = "pem-rfc7468" -version = "1.0.0-rc.3" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8e58fab693c712c0d4e88f8eb3087b6521d060bcaf76aeb20cb192d809115ba" +checksum = "a6305423e0e7738146434843d1694d621cce767262b2a86910beab705e4493d9" dependencies = [ "base64ct", ] @@ -1610,19 +1682,19 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "picky" -version = "7.0.0-rc.20" +version = "7.0.0-rc.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cdc52be663aebd70d7006ae305c87eb32a2b836d6c2f26f7e384f845d80b621" +checksum = "e4d077505451145769907bee30661be7182a24c75e97f040ccaf5848fd5de928" dependencies = [ "base64", - "block-buffer 0.11.0-rc.5", + "block-buffer 0.11.0", "block-padding", "crypto-bigint", - "crypto-common 0.2.0-rc.4", + "crypto-common 0.2.0-rc.8", "crypto-primes", "curve25519-dalek", "der", - "digest 0.11.0-rc.3", + "digest 0.11.0-rc.5", "ecdsa", "ed25519", "ed25519-dalek", @@ -1637,7 +1709,6 @@ dependencies = [ "p256", "p384", "p521", - "pem-rfc7468", "picky-asn1", "picky-asn1-der", "picky-asn1-x509", @@ -1645,8 +1716,8 @@ dependencies = [ "pkcs8", "primefield", "primeorder", - "rand 0.9.2", - "rand_core 0.9.3", + "rand 0.10.0-rc.6", + "rand_core 0.10.0-rc-3", "rfc6979", "rsa", "sec1", @@ -1656,7 +1727,7 @@ dependencies = [ "sha3", "signature", "spki", - "thiserror 2.0.17", + "thiserror 2.0.18", "x25519-dalek", "zeroize", ] @@ -1676,9 +1747,9 @@ dependencies = [ [[package]] name = "picky-asn1-der" -version = "0.5.4" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b491eb61603cba1ad5c6be0269883538f8d74136c35e3641a840fb0fbcd41efc" +checksum = "09561f7aa88cd6fae98edaf7dca3d8520da5b86a92839f2109a928af12a55c41" dependencies = [ "picky-asn1", "serde", @@ -1687,9 +1758,9 @@ dependencies = [ [[package]] name = "picky-asn1-x509" -version = "0.15.2" +version = "0.15.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c97cd14d567a17755910fa8718277baf39d08682a980b1b1a4b4da7d0bc61a04" +checksum = "2cacf27a75aa1b95e8b1726569fcd693a19d3445aecbcd0d20120e7f82a3cb3b" dependencies = [ "base64", "crypto-bigint", @@ -1703,20 +1774,20 @@ dependencies = [ [[package]] name = "picky-krb" -version = "0.11.3" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14b13eb1a97b2293277b475f07d0c36c33579e2e71f852557015addcd95f8892" +checksum = "1647012bc081792da896ec538040c34aac79ce6b11cfdd68029b3baa06b0453f" dependencies = [ "aes", - "block-buffer 0.11.0-rc.5", + "block-buffer 0.11.0", "block-padding", "byteorder", "cbc", "cipher", "crypto-bigint", - "crypto-common 0.2.0-rc.4", + "crypto-common 0.2.0-rc.8", "des", - "digest 0.11.0-rc.3", + "digest 0.11.0-rc.5", "hmac", "inout", "oid", @@ -1724,18 +1795,18 @@ dependencies = [ "picky-asn1", "picky-asn1-der", "picky-asn1-x509", - "rand 0.9.2", + "rand 0.10.0-rc.6", "serde", "sha1", - "thiserror 2.0.17", + "thiserror 2.0.18", "uuid", ] [[package]] name = "pin-project-lite" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" [[package]] name = "pin-utils" @@ -1755,9 +1826,9 @@ dependencies = [ [[package]] name = "pkcs8" -version = "0.11.0-rc.7" +version = "0.11.0-rc.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93eac55f10aceed84769df670ea4a32d2ffad7399400d41ee1c13b1cd8e1b478" +checksum = "77089aec8290d0b7bb01b671b091095cf1937670725af4fd73d47249f03b12c0" dependencies = [ "der", "spki", @@ -1765,15 +1836,15 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.32" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" +checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" [[package]] name = "polyval" -version = "0.7.0-rc.2" +version = "0.7.0-rc.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ffd40cc99d0fbb02b4b3771346b811df94194bc103983efa0203c8893755085" +checksum = "1ad60831c19edda4b20878a676595c357e93a9b4e6dca2ba98d75b01066b317b" dependencies = [ "cfg-if", "cpufeatures", @@ -1782,24 +1853,24 @@ dependencies = [ [[package]] name = "portable-atomic" -version = "1.11.1" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" +checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" [[package]] name = "portable-atomic-util" -version = "0.2.4" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" +checksum = "091397be61a01d4be58e7841595bd4bfedb15f1cd54977d79b8271e94ed799a3" dependencies = [ "portable-atomic", ] [[package]] name = "potential_utf" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" +checksum = "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564" dependencies = [ "zerovec", ] @@ -1821,31 +1892,31 @@ dependencies = [ [[package]] name = "primefield" -version = "0.14.0-pre.6" +version = "0.14.0-rc.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7fcd4a163053332fd93f39b81c133e96a98567660981654579c90a99062fbf5" +checksum = "29b2bd4ddf14d08c2bc8d9cceaf362f28c146b0737d58c7fee6534b99e19a3ee" dependencies = [ "crypto-bigint", - "ff", - "rand_core 0.9.3", + "rand_core 0.10.0-rc-3", + "rustcrypto-ff", "subtle", "zeroize", ] [[package]] name = "primeorder" -version = "0.14.0-pre.9" +version = "0.14.0-rc.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c36e8766fcd270fa9c665b9dc364f570695f5a59240949441b077a397f15b74" +checksum = "4e56388fad6b8c7576e6987fd0c8c7f3bf94d73d74ae794edaac3e420f9cabfe" dependencies = [ "elliptic-curve", ] [[package]] name = "proc-macro2" -version = "1.0.103" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" dependencies = [ "unicode-ident", ] @@ -1864,7 +1935,7 @@ dependencies = [ "rustc-hash", "rustls", "socket2", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "tracing", "web-time", @@ -1872,22 +1943,22 @@ dependencies = [ [[package]] name = "quinn-proto" -version = "0.11.13" +version = "0.11.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31" +checksum = "434b42fec591c96ef50e21e886936e66d3cc3f737104fdb9b737c40ffb94c098" dependencies = [ "bytes", "fastbloom", "getrandom 0.3.4", "lru-slab", - "rand 0.9.2", + "rand 0.9.4", "ring", "rustc-hash", "rustls", "rustls-pki-types", "rustls-platform-verifier", "slab", - "thiserror 2.0.17", + "thiserror 2.0.18", "tinyvec", "tracing", "web-time", @@ -1909,9 +1980,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.42" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" dependencies = [ "proc-macro2", ] @@ -1935,12 +2006,23 @@ dependencies = [ [[package]] name = "rand" -version = "0.9.2" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" dependencies = [ "rand_chacha 0.9.0", - "rand_core 0.9.3", + "rand_core 0.9.5", +] + +[[package]] +name = "rand" +version = "0.10.0-rc.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bccc05ac8fad6ee391f3cc6725171817eed960345e2fb42ad229d486c1ca2d98" +dependencies = [ + "chacha20", + "getrandom 0.4.0-rc.0", + "rand_core 0.10.0-rc-3", ] [[package]] @@ -1960,7 +2042,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", - "rand_core 0.9.3", + "rand_core 0.9.5", ] [[package]] @@ -1969,32 +2051,38 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.16", + "getrandom 0.2.17", ] [[package]] name = "rand_core" -version = "0.9.3" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" dependencies = [ "getrandom 0.3.4", ] +[[package]] +name = "rand_core" +version = "0.10.0-rc-3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f66ee92bc15280519ef199a274fe0cafff4245d31bc39aaa31c011ad56cb1f05" + [[package]] name = "redox_syscall" version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", ] [[package]] name = "regex" -version = "1.12.2" +version = "1.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" dependencies = [ "aho-corasick", "memchr", @@ -2004,9 +2092,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" dependencies = [ "aho-corasick", "memchr", @@ -2015,15 +2103,15 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.8" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" [[package]] name = "reqwest" -version = "0.12.25" +version = "0.12.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6eff9328d40131d43bd911d42d79eb6a47312002a4daefc9e37f17e74a7701a" +checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" dependencies = [ "base64", "bytes", @@ -2061,9 +2149,9 @@ dependencies = [ [[package]] name = "rfc6979" -version = "0.5.0-rc.1" +version = "0.5.0-rc.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d369f9c4f79388704648e7bcb92749c0d6cf4397039293a9b747694fa4fb4bae" +checksum = "63b8e2323084c987a72875b2fd682b7307d5cf14d47e3875bb5e89948e8809d4" dependencies = [ "hmac", "subtle", @@ -2077,7 +2165,7 @@ checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", "cfg-if", - "getrandom 0.2.16", + "getrandom 0.2.17", "libc", "untrusted", "windows-sys 0.52.0", @@ -2085,29 +2173,27 @@ dependencies = [ [[package]] name = "rsa" -version = "0.10.0-rc.9" +version = "0.10.0-rc.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf8955ab399f6426998fde6b76ae27233cce950705e758a6c17afd2f6d0e5d52" +checksum = "c9a2b1eacbc34fbaf77f6f1db1385518446008d49b9f9f59dc9d1340fce4ca9e" dependencies = [ "const-oid", "crypto-bigint", "crypto-primes", - "digest 0.11.0-rc.3", + "digest 0.11.0-rc.5", "pkcs1", "pkcs8", - "rand_core 0.9.3", - "sha1", + "rand_core 0.10.0-rc-3", "signature", "spki", - "subtle", "zeroize", ] [[package]] name = "rustc-hash" -version = "2.1.1" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" +checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" [[package]] name = "rustc_version" @@ -2118,11 +2204,32 @@ dependencies = [ "semver", ] +[[package]] +name = "rustcrypto-ff" +version = "0.14.0-pre.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa9cd37111549306f79b09aa2618e15b1e8241b7178c286821e3dd71579db4db" +dependencies = [ + "rand_core 0.10.0-rc-3", + "subtle", +] + +[[package]] +name = "rustcrypto-group" +version = "0.14.0-pre.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e394cd734b5f97dfc3484fa42aad7acd912961c2bcd96c99aa05b3d6cab7cafd" +dependencies = [ + "rand_core 0.10.0-rc-3", + "rustcrypto-ff", + "subtle", +] + [[package]] name = "rustls" -version = "0.23.35" +version = "0.23.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "533f54bc6a7d4f647e46ad909549eda97bf5afc1585190ef692b4286b198bd8f" +checksum = "69f9466fb2c14ea04357e91413efb882e2a6d4a406e625449bc0a5d360d53a21" dependencies = [ "log", "once_cell", @@ -2135,9 +2242,9 @@ dependencies = [ [[package]] name = "rustls-native-certs" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9980d917ebb0c0536119ba501e90834767bffc3d60641457fd84a1f3fd337923" +checksum = "612460d5f7bea540c490b2b6395d8e34a953e52b491accd6c86c8164c5932a63" dependencies = [ "openssl-probe", "rustls-pki-types", @@ -2147,9 +2254,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.13.1" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "708c0f9d5f54ba0272468c1d306a52c495b31fa155e91bc25371e6df7996908c" +checksum = "be040f8b0a225e40375822a563fa9524378b9d63112f53e19ffff34df5d33fdd" dependencies = [ "web-time", "zeroize", @@ -2184,9 +2291,9 @@ checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" [[package]] name = "rustls-webpki" -version = "0.103.8" +version = "0.103.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ffdfa2f5286e2247234e03f680868ac2815974dc39e00ea15adc445d0aafe52" +checksum = "20a6af516fea4b20eccceaf166e8aa666ac996208e8a644ce3ef5aa783bc7cd4" dependencies = [ "ring", "rustls-pki-types", @@ -2201,9 +2308,9 @@ checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "ryu" -version = "1.0.20" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" +checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" [[package]] name = "same-file" @@ -2225,9 +2332,9 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.28" +version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1" +checksum = "91c1b7e4904c873ef0710c1f407dde2e6287de2bebc1bbbf7d430bb7cbffd939" dependencies = [ "windows-sys 0.61.2", ] @@ -2246,11 +2353,12 @@ checksum = "490dcfcbfef26be6800d11870ff2df8774fa6e86d047e3e8c8a76b25655e41ca" [[package]] name = "sec1" -version = "0.8.0-rc.10" +version = "0.8.0-rc.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dff52f6118bc9f0ac974a54a639d499ac26a6cad7a6e39bc0990c19625e793b" +checksum = "2568531a8ace88b848310caa98fb2115b151ef924d54aa523e659c21b9d32d71" dependencies = [ "base16ct", + "ctutils", "der", "hybrid-array", "subtle", @@ -2259,11 +2367,11 @@ dependencies = [ [[package]] name = "security-framework" -version = "3.5.1" +version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3297343eaf830f66ede390ea39da1d462b6b0c1b000f420d0a83f898bbbe6ef" +checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "core-foundation", "core-foundation-sys", "libc", @@ -2272,9 +2380,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.15.0" +version = "2.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0" +checksum = "6ce2691df843ecc5d231c0b14ece2acc3efb62c0a398c7e1d875f3983ce020e3" dependencies = [ "core-foundation-sys", "libc", @@ -2282,9 +2390,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.27" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" [[package]] name = "serde" @@ -2323,20 +2431,20 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] name = "serde_json" -version = "1.0.145" +version = "1.0.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" dependencies = [ "itoa", "memchr", - "ryu", "serde", "serde_core", + "zmij", ] [[package]] @@ -2353,9 +2461,9 @@ dependencies = [ [[package]] name = "serdect" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3ef0e35b322ddfaecbc60f34ab448e157e48531288ee49fafbb053696b8ffe2" +checksum = "9af4a3e75ebd5599b30d4de5768e00b5095d518a79fefc3ecbaf77e665d1ec06" dependencies = [ "base16ct", "serde", @@ -2363,11 +2471,12 @@ dependencies = [ [[package]] name = "serial_test" -version = "3.2.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b258109f244e1d6891bf1053a55d63a5cd4f8f4c30cf9a1280989f80e7a1fa9" +checksum = "911bd979bf1070a3f3aa7b691a3b3e9968f339ceeec89e08c280a8a22207a32f" dependencies = [ - "futures", + "futures-executor", + "futures-util", "log", "once_cell", "parking_lot", @@ -2377,35 +2486,35 @@ dependencies = [ [[package]] name = "serial_test_derive" -version = "3.2.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d69265a08751de7844521fd15003ae0a888e035773ba05695c5c759a6f89eef" +checksum = "0a7d91949b85b0d2fb687445e448b40d322b6b3e4af6b44a29b21d9a5f33e6d9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] name = "sha1" -version = "0.11.0-rc.2" +version = "0.11.0-rc.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5e046edf639aa2e7afb285589e5405de2ef7e61d4b0ac1e30256e3eab911af9" +checksum = "aa1ae819b9870cadc959a052363de870944a1646932d274a4e270f64bf79e5ef" dependencies = [ "cfg-if", "cpufeatures", - "digest 0.11.0-rc.3", + "digest 0.11.0-rc.5", ] [[package]] name = "sha2" -version = "0.11.0-rc.2" +version = "0.11.0-rc.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1e3878ab0f98e35b2df35fe53201d088299b41a6bb63e3e34dada2ac4abd924" +checksum = "19d43dc0354d88b791216bb5c1bfbb60c0814460cc653ae0ebd71f286d0bd927" dependencies = [ "cfg-if", "cpufeatures", - "digest 0.11.0-rc.3", + "digest 0.11.0-rc.5", ] [[package]] @@ -2414,7 +2523,7 @@ version = "0.11.0-rc.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2103ca0e6f4e9505eae906de5e5883e06fc3b2232fb5d6914890c7bbcb62f478" dependencies = [ - "digest 0.11.0-rc.3", + "digest 0.11.0-rc.5", "keccak", ] @@ -2435,25 +2544,25 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signature" -version = "3.0.0-rc.4" +version = "3.0.0-rc.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc280a6ff65c79fbd6622f64d7127f32b85563bca8c53cd2e9141d6744a9056d" +checksum = "597a96996ccff7dfa16f052bd995b4cecc72af22c35138738dc029f0ead6608d" dependencies = [ - "digest 0.11.0-rc.3", - "rand_core 0.9.3", + "digest 0.11.0-rc.5", + "rand_core 0.10.0-rc-3", ] [[package]] name = "siphasher" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" +checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e" [[package]] name = "slab" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "smallvec" @@ -2463,7 +2572,7 @@ checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] name = "smb" -version = "0.11.1" +version = "0.11.2" dependencies = [ "aead", "aes", @@ -2472,7 +2581,7 @@ dependencies = [ "byteorder", "ccm", "cmac", - "crypto-common 0.2.0-rc.4", + "crypto-common 0.2.0-rc.8", "futures", "futures-core", "futures-util", @@ -2481,6 +2590,7 @@ dependencies = [ "log", "lz4_flex", "maybe-async", + "md-5", "modular-bitfield", "pastey", "rand 0.8.5", @@ -2495,7 +2605,7 @@ dependencies = [ "sspi", "temp-env", "test-log", - "thiserror 2.0.17", + "thiserror 2.0.18", "time", "tokio", "tokio-stream", @@ -2505,7 +2615,7 @@ dependencies = [ [[package]] name = "smb-cli" -version = "0.11.1" +version = "0.11.2" dependencies = [ "clap", "ctrlc", @@ -2521,7 +2631,7 @@ dependencies = [ [[package]] name = "smb-dtyp" -version = "0.11.1" +version = "0.11.2" dependencies = [ "binrw", "modular-bitfield", @@ -2534,16 +2644,16 @@ dependencies = [ [[package]] name = "smb-dtyp-derive" -version = "0.11.1" +version = "0.11.2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] name = "smb-fscc" -version = "0.11.1" +version = "0.11.2" dependencies = [ "binrw", "const_format", @@ -2551,13 +2661,13 @@ dependencies = [ "pastey", "smb-dtyp", "smb-tests", - "thiserror 2.0.17", + "thiserror 2.0.18", "time", ] [[package]] name = "smb-msg" -version = "0.11.1" +version = "0.11.2" dependencies = [ "binrw", "const_format", @@ -2567,22 +2677,22 @@ dependencies = [ "smb-fscc", "smb-msg-derive", "smb-tests", - "thiserror 2.0.17", + "thiserror 2.0.18", "time", ] [[package]] name = "smb-msg-derive" -version = "0.11.1" +version = "0.11.2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] name = "smb-rpc" -version = "0.11.1" +version = "0.11.2" dependencies = [ "binrw", "maybe-async", @@ -2590,13 +2700,13 @@ dependencies = [ "pastey", "smb-dtyp", "smb-tests", - "thiserror 2.0.17", + "thiserror 2.0.18", "time", ] [[package]] name = "smb-tests" -version = "0.11.1" +version = "0.11.2" dependencies = [ "binrw", "hex", @@ -2604,7 +2714,7 @@ dependencies = [ [[package]] name = "smb-transport" -version = "0.11.1" +version = "0.11.2" dependencies = [ "binrw", "futures-core", @@ -2619,7 +2729,7 @@ dependencies = [ "smb-dtyp", "smb-msg", "smb-tests", - "thiserror 2.0.17", + "thiserror 2.0.18", "time", "tokio", "tokio-util", @@ -2627,12 +2737,12 @@ dependencies = [ [[package]] name = "socket2" -version = "0.6.1" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881" +checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" dependencies = [ "libc", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -2647,23 +2757,24 @@ dependencies = [ [[package]] name = "sspi" -version = "0.18.4" +version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70f8d436177e1f17d2efb8ec1b661068ad04fd282544dfd8369522168300a82e" +checksum = "0484adc2dd72428a01644ddb55fd87c5518ff2c7c663544fb6b1ee39a65d897a" dependencies = [ "async-dnssd", "async-recursion", - "bitflags 2.10.0", - "block-buffer 0.11.0-rc.5", + "bitflags 2.11.0", + "block-buffer 0.12.0", + "bytemuck", "byteorder", "cfg-if", "crypto-bigint", - "crypto-common 0.2.0-rc.4", + "crypto-common 0.2.0-rc.8", "crypto-mac", "crypto-primes", "curve25519-dalek", "der", - "digest 0.11.0-rc.3", + "digest 0.11.0-rc.5", "ed25519-dalek", "ff", "futures", @@ -2688,12 +2799,11 @@ dependencies = [ "pkcs8", "primefield", "primeorder", - "rand 0.9.2", + "rand 0.10.0-rc.6", "reqwest", "rsa", "rustls", "serde", - "serde_derive", "sha1", "sha2", "signature", @@ -2703,9 +2813,9 @@ dependencies = [ "tracing", "url", "uuid", + "widestring", "windows", "windows-registry", - "windows-sys 0.60.2", "zeroize", ] @@ -2746,9 +2856,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.111" +version = "2.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" dependencies = [ "proc-macro2", "quote", @@ -2772,7 +2882,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -2804,7 +2914,7 @@ checksum = "be35209fd0781c5401458ab66e4f98accf63553e8fae7425503e92fdd319783b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -2818,11 +2928,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.17" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" dependencies = [ - "thiserror-impl 2.0.17", + "thiserror-impl 2.0.18", ] [[package]] @@ -2833,18 +2943,18 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] name = "thiserror-impl" -version = "2.0.17" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -2858,29 +2968,30 @@ dependencies = [ [[package]] name = "time" -version = "0.3.44" +version = "0.3.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d" +checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" dependencies = [ "deranged", + "js-sys", "num-conv", "powerfmt", - "serde", + "serde_core", "time-core", "time-macros", ] [[package]] name = "time-core" -version = "0.1.6" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b" +checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" [[package]] name = "time-macros" -version = "0.2.24" +version = "0.2.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3" +checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" dependencies = [ "num-conv", "time-core", @@ -2888,9 +2999,9 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" +checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d" dependencies = [ "displaydoc", "zerovec", @@ -2898,9 +3009,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" +checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3" dependencies = [ "tinyvec_macros", ] @@ -2913,9 +3024,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.48.0" +version = "1.51.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" +checksum = "f66bf9585cda4b724d3e78ab34b73fb2bbaba9011b9bfdf69dc836382ea13b8c" dependencies = [ "bytes", "libc", @@ -2928,13 +3039,13 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" +checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -2949,9 +3060,9 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.17" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" +checksum = "32da49809aab5c3bc678af03902d4ccddea2a87d028d86392a4b1560c6906c70" dependencies = [ "futures-core", "pin-project-lite", @@ -2960,9 +3071,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.17" +version = "0.7.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2efa149fe76073d6e8fd97ef4f4eca7b67f599660115591483572e406e165594" +checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" dependencies = [ "bytes", "futures-core", @@ -2973,9 +3084,9 @@ dependencies = [ [[package]] name = "tower" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" +checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" dependencies = [ "futures-core", "futures-util", @@ -2992,7 +3103,7 @@ version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "bytes", "futures-util", "http", @@ -3018,9 +3129,9 @@ checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" -version = "0.1.43" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d15d90a0b5c19378952d479dc858407149d7bb45a14de0142f6c534b16fc647" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" dependencies = [ "log", "pin-project-lite", @@ -3036,14 +3147,14 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] name = "tracing-core" -version = "0.1.35" +version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a04e24fab5c89c6a36eb8558c9656f30d81de51dfa4d3b45f26b21d61fa0a6c" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" dependencies = [ "once_cell", "valuable", @@ -3062,9 +3173,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.22" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f30143827ddab0d256fd843b7a66d164e9f271cfa0dde49142c5ca0ca291f1e" +checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319" dependencies = [ "matchers", "nu-ansi-term", @@ -3091,9 +3202,9 @@ checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" [[package]] name = "unicode-ident" -version = "1.0.22" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" [[package]] name = "unicode-width" @@ -3115,11 +3226,11 @@ checksum = "81e544489bf3d8ef66c953931f56617f423cd4b5494be343d9b9d3dda037b9a3" [[package]] name = "universal-hash" -version = "0.6.0-rc.2" +version = "0.6.0-rc.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a55be643b40a21558f44806b53ee9319595bc7ca6896372e4e08e5d7d83c9cd6" +checksum = "0386f227888b17b65d3e38219a7d41185035471300855c285667811907bb1677" dependencies = [ - "crypto-common 0.2.0-rc.4", + "crypto-common 0.2.0-rc.8", "subtle", ] @@ -3131,9 +3242,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.7" +version = "2.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" +checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" dependencies = [ "form_urlencoded", "idna", @@ -3155,9 +3266,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.19.0" +version = "1.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2e054861b4bd027cd373e18e8d8d8e6548085000e41290d95ce0c373a654b4a" +checksum = "ee48d38b119b0cd71fe4141b30f5ba9c7c5d9f4e7a3a8b4a674e4b6ef789976f" dependencies = [ "getrandom 0.3.4", "js-sys", @@ -3204,18 +3315,18 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasip2" -version = "1.0.1+wasi-0.2.4" +version = "1.0.2+wasi-0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" +checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" dependencies = [ "wit-bindgen", ] [[package]] name = "wasm-bindgen" -version = "0.2.106" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d759f433fa64a2d763d1340820e46e111a7a5ab75f993d1852d70b03dbb80fd" +checksum = "0bf938a0bacb0469e83c1e148908bd7d5a6010354cf4fb73279b7447422e3a89" dependencies = [ "cfg-if", "once_cell", @@ -3226,22 +3337,19 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.56" +version = "0.4.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836d9622d604feee9e5de25ac10e3ea5f2d65b41eac0d9ce72eb5deae707ce7c" +checksum = "f371d383f2fb139252e0bfac3b81b265689bf45b6874af544ffa4c975ac1ebf8" dependencies = [ - "cfg-if", "js-sys", - "once_cell", "wasm-bindgen", - "web-sys", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.106" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48cb0d2638f8baedbc542ed444afc0644a29166f1595371af4fecf8ce1e7eeb3" +checksum = "eeff24f84126c0ec2db7a449f0c2ec963c6a49efe0698c4242929da037ca28ed" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3249,31 +3357,31 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.106" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cefb59d5cd5f92d9dcf80e4683949f15ca4b511f4ac0a6e14d4e1ac60c6ecd40" +checksum = "9d08065faf983b2b80a79fd87d8254c409281cf7de75fc4b773019824196c904" dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.106" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbc538057e648b67f72a982e708d485b2efa771e1ac05fec311f9f63e5800db4" +checksum = "5fd04d9e306f1907bd13c6361b5c6bfc7b3b3c095ed3f8a9246390f8dbdee129" dependencies = [ "unicode-ident", ] [[package]] name = "web-sys" -version = "0.3.83" +version = "0.3.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b32828d774c412041098d182a8b38b16ea816958e07cf40eec2bc080ae137ac" +checksum = "4f2dfbb17949fa2088e5d39408c48368947b86f7834484e87b73de55bc14d97d" dependencies = [ "js-sys", "wasm-bindgen", @@ -3291,9 +3399,9 @@ dependencies = [ [[package]] name = "webpki-root-certs" -version = "1.0.4" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee3e3b5f5e80bc89f30ce8d0343bf4e5f12341c51f3e26cbeecbc7c85443e85b" +checksum = "804f18a4ac2676ffb4e8b5b5fa9ae38af06df08162314f96a68d2a363e21a8ca" dependencies = [ "rustls-pki-types", ] @@ -3337,47 +3445,46 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows" -version = "0.61.3" +version = "0.62.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" +checksum = "527fadee13e0c05939a6a05d5bd6eec6cd2e3dbd648b9f8e447c6518133d8580" dependencies = [ "windows-collections", "windows-core", "windows-future", - "windows-link 0.1.3", "windows-numerics", ] [[package]] name = "windows-collections" -version = "0.2.0" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" +checksum = "23b2d95af1a8a14a3c7367e1ed4fc9c20e0a26e79551b1454d72583c97cc6610" dependencies = [ "windows-core", ] [[package]] name = "windows-core" -version = "0.61.2" +version = "0.62.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" dependencies = [ "windows-implement", "windows-interface", - "windows-link 0.1.3", + "windows-link", "windows-result", "windows-strings", ] [[package]] name = "windows-future" -version = "0.2.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" +checksum = "e1d6f90251fe18a279739e78025bd6ddc52a7e22f921070ccdc67dde84c605cb" dependencies = [ "windows-core", - "windows-link 0.1.3", + "windows-link", "windows-threading", ] @@ -3389,7 +3496,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] @@ -3400,15 +3507,9 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] -[[package]] -name = "windows-link" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" - [[package]] name = "windows-link" version = "0.2.1" @@ -3417,41 +3518,41 @@ checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] name = "windows-numerics" -version = "0.2.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" +checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26" dependencies = [ "windows-core", - "windows-link 0.1.3", + "windows-link", ] [[package]] name = "windows-registry" -version = "0.5.3" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a9ed28765efc97bbc954883f4e6796c33a06546ebafacbabee9696967499e" +checksum = "02752bf7fbdcce7f2a27a742f798510f3e5ad88dbe84871e5168e2120c3d5720" dependencies = [ - "windows-link 0.1.3", + "windows-link", "windows-result", "windows-strings", ] [[package]] name = "windows-result" -version = "0.3.4" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" dependencies = [ - "windows-link 0.1.3", + "windows-link", ] [[package]] name = "windows-strings" -version = "0.4.2" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" dependencies = [ - "windows-link 0.1.3", + "windows-link", ] [[package]] @@ -3487,7 +3588,7 @@ version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" dependencies = [ - "windows-link 0.2.1", + "windows-link", ] [[package]] @@ -3527,7 +3628,7 @@ version = "0.53.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" dependencies = [ - "windows-link 0.2.1", + "windows-link", "windows_aarch64_gnullvm 0.53.1", "windows_aarch64_msvc 0.53.1", "windows_i686_gnu 0.53.1", @@ -3540,11 +3641,11 @@ dependencies = [ [[package]] name = "windows-threading" -version = "0.1.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6" +checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37" dependencies = [ - "windows-link 0.1.3", + "windows-link", ] [[package]] @@ -3687,33 +3788,32 @@ checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" [[package]] name = "wit-bindgen" -version = "0.46.0" +version = "0.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" [[package]] name = "writeable" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" +checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" [[package]] name = "x25519-dalek" -version = "3.0.0-pre.1" +version = "3.0.0-pre.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a45998121837fd8c92655d2334aa8f3e5ef0645cdfda5b321b13760c548fd55" +checksum = "a5887899407ca8fb861126d509bb08465c14a9c60fad1f24c59ed59630a45586" dependencies = [ "curve25519-dalek", - "rand_core 0.9.3", - "serde", + "rand_core 0.10.0-rc-3", "zeroize", ] [[package]] name = "yoke" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" +checksum = "abe8c5fda708d9ca3df187cae8bfb9ceda00dd96231bed36e445a1a48e66f9ca" dependencies = [ "stable_deref_trait", "yoke-derive", @@ -3722,54 +3822,54 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" +checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", "synstructure", ] [[package]] name = "zerocopy" -version = "0.8.31" +version = "0.8.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd74ec98b9250adb3ca554bdde269adf631549f51d8a8f8f0a10b50f1cb298c3" +checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.31" +version = "0.8.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8a8d209fdf45cf5138cbb5a506f6b52522a25afccc534d1475dad8e31105c6a" +checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] name = "zerofrom" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +checksum = "69faa1f2a1ea75661980b013019ed6687ed0e83d069bc1114e2cc74c6c04c4df" dependencies = [ "zerofrom-derive", ] [[package]] name = "zerofrom-derive" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", "synstructure", ] @@ -3784,20 +3884,20 @@ dependencies = [ [[package]] name = "zeroize_derive" -version = "1.4.2" +version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] [[package]] name = "zerotrie" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" +checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf" dependencies = [ "displaydoc", "yoke", @@ -3806,9 +3906,9 @@ dependencies = [ [[package]] name = "zerovec" -version = "0.11.5" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" +checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239" dependencies = [ "yoke", "zerofrom", @@ -3817,11 +3917,17 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" +checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.117", ] + +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" diff --git a/Cargo.toml b/Cargo.toml index fa4537c..c6b2f65 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,7 @@ resolver = "2" [workspace.package] edition = "2024" -rust-version = "1.85.0" +rust-version = "1.89.0" license = "MIT" description = "A Pure Rust SMB Client implementation" homepage = "https://github.com/afiffon/smb-rs" @@ -13,21 +13,21 @@ authors = ["Aviv N "] keywords = ["smb", "network", "file-sharing", "windows"] categories = ["network-programming", "parsing", "filesystem"] readme = "README.md" -version = "0.11.1" +version = "0.11.2" [workspace.dependencies] # Crates in this workspace -smb = { path = "crates/smb", version = "=0.11.1", default-features = false } -smb-tests = { path = "crates/smb-tests", version = "=0.11.1" } -smb-msg = { path = "crates/smb-msg", version = "=0.11.1", default-features = false, features = [ +smb = { path = "crates/smb", version = "=0.11.2", default-features = false } +smb-tests = { path = "crates/smb-tests", version = "=0.11.2" } +smb-msg = { path = "crates/smb-msg", version = "=0.11.2", default-features = false, features = [ "client", ] } -smb-msg-derive = { path = "crates/smb-msg-derive", version = "=0.11.1" } -smb-dtyp = { path = "crates/smb-dtyp", version = "=0.11.1" } -smb-dtyp-derive = { path = "crates/smb-dtyp-derive", version = "=0.11.1" } -smb-rpc = { path = "crates/smb-rpc", version = "=0.11.1" } -smb-fscc = { path = "crates/smb-fscc", version = "=0.11.1" } -smb-transport = { path = "crates/smb-transport", version = "=0.11.1", default-features = false } +smb-msg-derive = { path = "crates/smb-msg-derive", version = "=0.11.2" } +smb-dtyp = { path = "crates/smb-dtyp", version = "=0.11.2" } +smb-dtyp-derive = { path = "crates/smb-dtyp-derive", version = "=0.11.2" } +smb-rpc = { path = "crates/smb-rpc", version = "=0.11.2" } +smb-fscc = { path = "crates/smb-fscc", version = "=0.11.2" } +smb-transport = { path = "crates/smb-transport", version = "=0.11.2", default-features = false } # Binary encoding/decoding binrw = "0.15.0" diff --git a/crates/smb-rpc/src/ndr64/align.rs b/crates/smb-rpc/src/ndr64/align.rs index 2e558d9..cc7ad79 100644 --- a/crates/smb-rpc/src/ndr64/align.rs +++ b/crates/smb-rpc/src/ndr64/align.rs @@ -7,7 +7,7 @@ pub const NDR64_ALIGNMENT: usize = 8; pub fn debug_assert_aligned(stream: &mut W) -> binrw::BinResult<()> { let pos = stream.stream_position()?; debug_assert!( - pos as usize % NDR64_ALIGNMENT == 0, + (pos as usize).is_multiple_of(NDR64_ALIGNMENT), "Writer is not aligned to NDR64" ); Ok(()) diff --git a/crates/smb/Cargo.toml b/crates/smb/Cargo.toml index fc7db99..cb055a8 100644 --- a/crates/smb/Cargo.toml +++ b/crates/smb/Cargo.toml @@ -42,12 +42,13 @@ url = "2.5.0" byteorder = { version = "1.5.0", optional = true } # APIs -sspi = { version = "0.18.0", features = ["ring"], default-features = false } +sspi = { version = "0.19.2", features = ["ring"], default-features = false } reqwest = { workspace = true, optional = true } # Crypto; RustCrypto provides support for RC versions only. hmac = "0.13.0-rc.2" sha2 = "0.11.0-rc.2" +md-5 = "0.11.0-rc.2" kbkdf = { version = "0.1.0-pre.0" } crypto-common = { version = "0.2.0-rc.4" } aes = "0.9.0-rc.1" diff --git a/crates/smb/src/compression.rs b/crates/smb/src/compression.rs index c5188c9..82f335c 100644 --- a/crates/smb/src/compression.rs +++ b/crates/smb/src/compression.rs @@ -156,12 +156,12 @@ impl CompressionMethod for ChainedCompression { "Decompressed size exceeds the expected size".to_string(), ))?; } - if let Some(original_size) = item.original_size { - if len_after - len_before != original_size as usize { - Err(CompressionError::ChainedCompressionFailed( - "Decompressed size does not match the item expected size".to_string(), - ))?; - } + if let Some(original_size) = item.original_size + && len_after - len_before != original_size as usize + { + Err(CompressionError::ChainedCompressionFailed( + "Decompressed size does not match the item expected size".to_string(), + ))?; } } diff --git a/crates/smb/src/connection.rs b/crates/smb/src/connection.rs index 08f3548..732d566 100644 --- a/crates/smb/src/connection.rs +++ b/crates/smb/src/connection.rs @@ -368,33 +368,52 @@ impl Connection { let has_signing = !signing_algorithms.is_empty(); let has_encryption = !encrypting_algorithms.is_empty(); - // Context list supported on SMB3.1.1+ + // Negotiate context list for SMB 3.1.1 (MS-SMB2 2.2.3.1). + // Contexts are ordered by ascending ContextType value as recommended by the spec. let ctx_list = if supported_dialects.contains(&Dialect::Smb0311) { let mut preauth_integrity_hash = [0u8; 32]; OsRng.fill_bytes(&mut preauth_integrity_hash); + + // 0x0001 - SMB2_PREAUTH_INTEGRITY_CAPABILITIES (mandatory for 3.1.1) let mut ctx_list = vec![ PreauthIntegrityCapabilities { hash_algorithms: vec![HashAlgorithm::Sha512], salt: preauth_integrity_hash.to_vec(), } .into(), - NetnameNegotiateContextId { - netname: client_netname.into(), - } - .into(), - EncryptionCapabilities { - ciphers: encrypting_algorithms, - } - .into(), + ]; + + // 0x0002 - SMB2_ENCRYPTION_CAPABILITIES + // MS-SMB2: CipherCount MUST be greater than zero, so only include this + // context when there are actual ciphers to offer. + if !encrypting_algorithms.is_empty() { + ctx_list.push( + EncryptionCapabilities { + ciphers: encrypting_algorithms, + } + .into(), + ); + } + + // 0x0003 - SMB2_COMPRESSION_CAPABILITIES + ctx_list.push( CompressionCapabilities { flags: CompressionCapsFlags::new() .with_chained(!compression_algorithms.is_empty()), compression_algorithms, } .into(), - SigningCapabilities { signing_algorithms }.into(), - ]; - // QUIC + ); + + // 0x0005 - SMB2_NETNAME_NEGOTIATE_CONTEXT_ID + ctx_list.push( + NetnameNegotiateContextId { + netname: client_netname.into(), + } + .into(), + ); + + // 0x0006 - SMB2_TRANSPORT_CAPABILITIES (QUIC only) #[cfg(feature = "quic")] if matches!(self.config.transport, TransportConfig::Quic(_)) { ctx_list.push(NegotiateContext { @@ -404,7 +423,8 @@ impl Connection { ), }); } - // TODO: Add to config + + // 0x0007 - SMB2_RDMA_TRANSFORM_CAPABILITIES if cfg!(feature = "rdma") { ctx_list.push(NegotiateContext { context_type: NegotiateContextType::RdmaTransformCapabilities, @@ -415,6 +435,12 @@ impl Connection { ), }); } + + // 0x0008 - SMB2_SIGNING_CAPABILITIES + if !signing_algorithms.is_empty() { + ctx_list.push(SigningCapabilities { signing_algorithms }.into()); + } + Some(ctx_list) } else { None @@ -657,24 +683,24 @@ impl ConnectionMessageHandler { #[maybe_async] async fn process_sequence_incoming(&self, msg: &IncomingMessage) -> crate::Result<()> { - if let Some(neg) = self.conn_info.get() { - if neg.negotiation.caps.large_mtu() { - let granted_credits = msg.message.header.credit_request; - let charged_credits = msg.message.header.credit_charge; - // Update the pool size - return how many EXTRA credits were granted. - // also, handle the case where the server granted less credits than charged. - if charged_credits > granted_credits { - self.credit_pool - .fetch_sub(charged_credits - granted_credits, Ordering::SeqCst); - } else { - self.credit_pool - .fetch_add(granted_credits - charged_credits, Ordering::SeqCst); - } - - // Return the credits to the pool. - self.curr_credits.add_permits(granted_credits as usize); - return Ok(()); + if let Some(neg) = self.conn_info.get() + && neg.negotiation.caps.large_mtu() + { + let granted_credits = msg.message.header.credit_request; + let charged_credits = msg.message.header.credit_charge; + // Update the pool size - return how many EXTRA credits were granted. + // also, handle the case where the server granted less credits than charged. + if charged_credits > granted_credits { + self.credit_pool + .fetch_sub(charged_credits - granted_credits, Ordering::SeqCst); + } else { + self.credit_pool + .fetch_add(granted_credits - charged_credits, Ordering::SeqCst); } + + // Return the credits to the pool. + self.curr_credits.add_permits(granted_credits as usize); + return Ok(()); } // Default case: return a single credit to the pool. @@ -788,10 +814,10 @@ impl MessageHandler for ConnectionMessageHandler { let msg = self.worker.get().unwrap().receive(&options).await?; // Command matching (if needed). - if let Some(cmd) = options.cmd { - if msg.message.header.command != cmd { - return Err(Error::UnexpectedMessageCommand(msg.message.header.command)); - } + if let Some(cmd) = options.cmd + && msg.message.header.command != cmd + { + return Err(Error::UnexpectedMessageCommand(msg.message.header.command)); } // Direction matching. diff --git a/crates/smb/src/connection/config.rs b/crates/smb/src/connection/config.rs index febd7cc..3577097 100644 --- a/crates/smb/src/connection/config.rs +++ b/crates/smb/src/connection/config.rs @@ -166,29 +166,30 @@ impl ConnectionConfig { /// Validates common configuration settings. pub fn validate(&self) -> crate::Result<()> { // Make sure dialects min <= max. - if let (Some(min), Some(max)) = (self.min_dialect, self.max_dialect) { - if min > max { - return Err(crate::Error::InvalidConfiguration( - "Minimum dialect is greater than maximum dialect".to_string(), - )); - } + if let (Some(min), Some(max)) = (self.min_dialect, self.max_dialect) + && min > max + { + return Err(crate::Error::InvalidConfiguration( + "Minimum dialect is greater than maximum dialect".to_string(), + )); } // Make sure transport is supported by the dialects. #[cfg(feature = "quic")] - if let Some(min) = self.min_dialect { - if min < Dialect::Smb0311 && matches!(self.transport, TransportConfig::Quic(_)) { - return Err(crate::Error::InvalidConfiguration( - "SMB over QUIC is not supported by the selected dialect".to_string(), - )); - } + if let Some(min) = self.min_dialect + && min < Dialect::Smb0311 + && matches!(self.transport, TransportConfig::Quic(_)) + { + return Err(crate::Error::InvalidConfiguration( + "SMB over QUIC is not supported by the selected dialect".to_string(), + )); } - if let Some(default_transaction_size) = self.default_transaction_size { - if default_transaction_size == 0 { - return Err(crate::Error::InvalidConfiguration( - "Default transaction size cannot be zero".to_string(), - )); - } + if let Some(default_transaction_size) = self.default_transaction_size + && default_transaction_size == 0 + { + return Err(crate::Error::InvalidConfiguration( + "Default transaction size cannot be zero".to_string(), + )); } Ok(()) } diff --git a/crates/smb/src/connection/preauth_hash.rs b/crates/smb/src/connection/preauth_hash.rs index 4050eed..4b82234 100644 --- a/crates/smb/src/connection/preauth_hash.rs +++ b/crates/smb/src/connection/preauth_hash.rs @@ -17,6 +17,10 @@ pub enum PreauthHashState { } impl PreauthHashState { + pub fn is_in_progress(&self) -> bool { + matches!(self, PreauthHashState::InProgress(_)) + } + pub fn begin() -> PreauthHashState { PreauthHashState::InProgress([0; 64]) } diff --git a/crates/smb/src/connection/worker/parallel/threading_backend.rs b/crates/smb/src/connection/worker/parallel/threading_backend.rs index 39fdc27..32a8cd4 100644 --- a/crates/smb/src/connection/worker/parallel/threading_backend.rs +++ b/crates/smb/src/connection/worker/parallel/threading_backend.rs @@ -30,10 +30,10 @@ impl ThreadingBackend { while !self.is_cancelled() { let next = rtransport.receive(); // Handle polling fail - if let Err(TransportError::IoError(ref e)) = next { - if e.kind() == std::io::ErrorKind::WouldBlock { - continue; - } + if let Err(TransportError::IoError(ref e)) = next + && e.kind() == std::io::ErrorKind::WouldBlock + { + continue; } match self.worker.incoming_data_callback(next) { Ok(_) => {} diff --git a/crates/smb/src/dialects.rs b/crates/smb/src/dialects.rs index 3e25595..f0af1b3 100644 --- a/crates/smb/src/dialects.rs +++ b/crates/smb/src/dialects.rs @@ -196,12 +196,12 @@ impl DialectMethods for Smb311 { // Make sure preauth integrity capability is SHA-512, if it exists in response: let ctx_integrity = response.get_ctx_preauth_integrity_capabilities(); - if let Some(algo) = ctx_integrity.and_then(|ctx| ctx.hash_algorithms.first()) { - if !preauth_hash::SUPPORTED_ALGOS.contains(algo) { - return Err(Error::NegotiationError( - "Unsupported preauth integrity algorithm received".into(), - )); - } + if let Some(algo) = ctx_integrity.and_then(|ctx| ctx.hash_algorithms.first()) + && !preauth_hash::SUPPORTED_ALGOS.contains(algo) + { + return Err(Error::NegotiationError( + "Unsupported preauth integrity algorithm received".into(), + )); } // And verify that the encryption algorithm is supported. diff --git a/crates/smb/src/resource.rs b/crates/smb/src/resource.rs index 29aaa88..7a1f36e 100644 --- a/crates/smb/src/resource.rs +++ b/crates/smb/src/resource.rs @@ -927,10 +927,10 @@ impl Drop for ResourceHandle { let handler = self.handler.clone(); log::debug!("Spawning task to close file with ID: {file_id:?}"); tokio::task::spawn(async move { - if file_id != FileId::EMPTY { - if let Err(e) = Self::send_close(file_id, &handler).await { - log::error!("Error closing file: {e}"); - } + if file_id != FileId::EMPTY + && let Err(e) = Self::send_close(file_id, &handler).await + { + log::error!("Error closing file: {e}"); } }); } diff --git a/crates/smb/src/session.rs b/crates/smb/src/session.rs index 598953e..86b3bab 100644 --- a/crates/smb/src/session.rs +++ b/crates/smb/src/session.rs @@ -29,6 +29,7 @@ mod channel; mod encryptor_decryptor; mod setup; mod signer; +mod spnego; #[cfg(feature = "kerberos")] mod sspi_network_client; mod state; diff --git a/crates/smb/src/session/authenticator.rs b/crates/smb/src/session/authenticator.rs index 1958d03..84bd7a1 100644 --- a/crates/smb/src/session/authenticator.rs +++ b/crates/smb/src/session/authenticator.rs @@ -1,24 +1,71 @@ use std::sync::Arc; use crate::Error; -use crate::connection::AuthMethodsConfig; use crate::connection::connection_info::ConnectionInfo; use maybe_async::*; +use sspi::Username; use sspi::{ - AcquireCredentialsHandleResult, AuthIdentity, BufferType, ClientRequestFlags, CredentialUse, - DataRepresentation, InitializeSecurityContextResult, Negotiate, SecurityBuffer, Sspi, - ntlm::NtlmConfig, + AcquireCredentialsHandleResult, AuthIdentity, AuthIdentityBuffers, BufferType, + ClientRequestFlags, CredentialUse, DataRepresentation, InitializeSecurityContextResult, + SecurityBuffer, Sspi, SspiImpl, + ntlm::{Ntlm, NtlmConfig}, }; -use sspi::{CredentialsBuffers, NegotiateConfig, SspiImpl, Username}; +fn rc4_crypt(key: &[u8], data: &[u8]) -> Vec { + let mut s: Vec = (0..=255).collect(); + let mut j: usize = 0; + for i in 0..256 { + j = (j + s[i] as usize + key[i % key.len()] as usize) & 0xff; + s.swap(i, j); + } + let mut i: usize = 0; + j = 0; + data.iter() + .map(|&b| { + i = (i + 1) & 0xff; + j = (j + s[i] as usize) & 0xff; + s.swap(i, j); + b ^ s[(s[i] as usize + s[j] as usize) & 0xff] + }) + .collect() +} + +/// Extract the NegotiateFlags field from a raw NTLM AUTHENTICATE_MESSAGE (Type-3). +/// +/// Layout per [MS-NLMP] 2.2.1.3: +/// Signature(8) + MessageType(4) + LmChallengeResponseFields(8) + +/// NtChallengeResponseFields(8) + DomainNameFields(8) + UserNameFields(8) + +/// WorkstationFields(8) + EncryptedRandomSessionKeyFields(8) = 60 bytes +/// followed by 4 bytes of NegotiateFlags (little-endian). +fn extract_ntlm_type3_negotiate_flags(ntlm_msg: &[u8]) -> Option { + if ntlm_msg.len() < 64 { + return None; + } + if &ntlm_msg[..8] != b"NTLMSSP\0" { + return None; + } + if u32::from_le_bytes(ntlm_msg[8..12].try_into().ok()?) != 3 { + return None; + } + Some(u32::from_le_bytes(ntlm_msg[60..64].try_into().ok()?)) +} + +/// SMB session authenticator using NTLM SSP directly. +/// +/// Previous versions used sspi-rs's `Negotiate` SSP, which wraps NTLM in +/// an additional GSS-API / NegoEx framing layer that Windows 10's SMB server +/// rejects with `STATUS_INVALID_PARAMETER`. By driving the `Ntlm` SSP +/// directly we get clean NTLM tokens that our `spnego` module wraps in the +/// standard SPNEGO envelope expected by SMB2. #[derive(Debug)] pub struct Authenticator { server_hostname: String, user_name: Username, - ssp: Negotiate, - cred_handle: AcquireCredentialsHandleResult>, + ssp: Ntlm, + cred_handle: AcquireCredentialsHandleResult>, current_state: Option, + first_token_sent: bool, } impl Authenticator { @@ -26,31 +73,45 @@ impl Authenticator { identity: AuthIdentity, conn_info: &Arc, ) -> crate::Result { - let client_computer_name = conn_info - .config - .client_name - .as_ref() - .unwrap_or(&String::from("smb-rs")) - .clone(); - let mut negotiate_ssp = Negotiate::new_client(NegotiateConfig::new( - Box::new(NtlmConfig::default()), - Some(Self::get_available_ssp_pkgs(&conn_info.config.auth_methods)), - client_computer_name, - ))?; + // This authenticator drives the NTLM SSP directly (see module docs). + // It does not implement Kerberos — the previous `Negotiate` SSP path + // that used to cover Kerberos produced NegoEx framing Windows SMB + // servers reject, so it was removed. To avoid silently downgrading a + // user who explicitly asked for Kerberos, fail fast here when the + // connection config requests it. + let auth_methods = &conn_info.config.auth_methods; + if auth_methods.kerberos && !auth_methods.ntlm { + return Err(Error::UnsupportedAuthenticationMechanism( + "Kerberos-only authentication is not supported by this build; \ + enable NTLM (auth_methods.ntlm = true) or use a build with \ + Kerberos support" + .into(), + )); + } + if auth_methods.kerberos { + log::warn!( + "AuthMethodsConfig.kerberos = true but this build only \ + implements NTLM; falling back to NTLM. Set kerberos = false \ + to silence this warning." + ); + } + + let mut ntlm_ssp = Ntlm::with_config(NtlmConfig::default()); let user_name = identity.username.clone(); - let cred_handle = negotiate_ssp + let cred_handle = ntlm_ssp .acquire_credentials_handle() .with_credential_use(CredentialUse::Outbound) - .with_auth_data(&sspi::Credentials::AuthIdentity(identity.clone())) - .execute(&mut negotiate_ssp)?; + .with_auth_data(&identity) + .execute(&mut ntlm_ssp)?; Ok(Authenticator { server_hostname: conn_info.server_name.clone(), - ssp: negotiate_ssp, + ssp: ntlm_ssp, cred_handle, current_state: None, user_name, + first_token_sent: false, }) } @@ -66,21 +127,116 @@ impl Authenticator { } pub fn session_key(&self) -> crate::Result<[u8; 16]> { - // Use the first 16 bytes of the session key. let key_info = self.ssp.query_context_session_key()?; - let k = &key_info.session_key.as_ref()[..16]; - Ok(k.try_into().unwrap()) + let full = key_info.session_key.as_ref(); + // A well-formed NTLMv2 session always has a 16-byte ExportedSessionKey. + // Validate the length instead of `.try_into().unwrap()` so a malformed + // upstream response degrades gracefully rather than panicking. + if full.len() < 16 { + return Err(Error::InvalidState(format!( + "NTLM session key too short: {} bytes (expected ≥ 16)", + full.len() + ))); + } + let mut out = [0u8; 16]; + out.copy_from_slice(&full[..16]); + Ok(out) } - fn make_sspi_target_name(server_fqdn: &str) -> String { - format!("cifs/{server_fqdn}") + /// Compute the SPNEGO mechListMIC manually. + /// + /// Implements the MIC computation described in [MS-SPNG] §3.1.5.1 + + /// [MS-NLMP] §3.4.4.1: + /// + /// ```text + /// 1. Derive ClientSigningKey and ClientSealingKey from ExportedSessionKey. + /// 2. Digest = HMAC-MD5(ClientSigningKey, seq_num_le || mechTypeList). + /// 3. If NTLMSSP_NEGOTIATE_KEY_EXCH was negotiated: + /// Checksum = RC4(ClientSealingKey, Digest[0:8]) + /// Otherwise: + /// Checksum = Digest[0:8] (NTLMv2 + ESS without key exchange). + /// 4. MIC = version(1u32_le) || Checksum || seq_num_le. + /// ``` + /// + /// `ntlm_negotiate_flags` MUST be the NegotiateFlags value actually sent on + /// the wire in the AUTHENTICATE_MESSAGE (Type-3); otherwise server-side + /// verification will fail. + pub fn compute_mech_list_mic( + &mut self, + mech_list: &[u8], + ntlm_negotiate_flags: u32, + ) -> crate::Result> { + use hmac::{Hmac, KeyInit, Mac}; + use md5::Md5; + + /// [MS-NLMP] 2.2.2.5 : NTLMSSP_NEGOTIATE_KEY_EXCH + const NTLMSSP_NEGOTIATE_KEY_EXCH: u32 = 0x4000_0000; + + let session_key = self.session_key()?; + + // Derive ClientSigningKey = MD5(ExportedSessionKey || CLIENT_SIGN_MAGIC) + let client_sign_magic = b"session key to client-to-server signing key magic constant\x00"; + let signing_key: [u8; 16] = { + let mut hasher = ::new(); + md5::Digest::update(&mut hasher, session_key); + md5::Digest::update(&mut hasher, client_sign_magic.as_slice()); + md5::Digest::finalize(hasher).into() + }; + + // Derive ClientSealingKey = MD5(ExportedSessionKey || CLIENT_SEAL_MAGIC) + let client_seal_magic = b"session key to client-to-server sealing key magic constant\x00"; + let sealing_key: [u8; 16] = { + let mut hasher = ::new(); + md5::Digest::update(&mut hasher, session_key); + md5::Digest::update(&mut hasher, client_seal_magic.as_slice()); + md5::Digest::finalize(hasher).into() + }; + + if cfg!(feature = "__debug-dump-keys") { + log::debug!( + "MIC keys: signing={:02x?}, sealing={:02x?}", + signing_key, + sealing_key + ); + } + + // Digest = HMAC-MD5(ClientSigningKey, seq_num(0) || mechTypeList) + let seq_num: u32 = 0; + let mut mac = + Hmac::::new_from_slice(&signing_key).expect("HMAC-MD5 key length is valid"); + mac.update(&seq_num.to_le_bytes()); + mac.update(mech_list); + let digest: [u8; 16] = mac.finalize().into_bytes().into(); + + // Checksum = RC4(ClientSealingKey, Digest[0:8]) iff KEY_EXCH was negotiated; + // otherwise the checksum is just digest[0..8]. + let key_exch_enabled = ntlm_negotiate_flags & NTLMSSP_NEGOTIATE_KEY_EXCH != 0; + let checksum: Vec = if key_exch_enabled { + rc4_crypt(&sealing_key, &digest[..8]) + } else { + digest[..8].to_vec() + }; + + // MIC = version(1) || checksum || seq_num + let mut mic = Vec::with_capacity(16); + mic.extend_from_slice(&1u32.to_le_bytes()); // version + mic.extend_from_slice(&checksum); // 8 bytes + mic.extend_from_slice(&seq_num.to_le_bytes()); // seq_num + assert_eq!(mic.len(), 16); + + log::trace!( + "mechListMIC: key_exch={}, mic={:02x?}", + key_exch_enabled, + &mic + ); + + Ok(mic) } fn get_context_requirements() -> ClientRequestFlags { - ClientRequestFlags::DELEGATE - | ClientRequestFlags::MUTUAL_AUTH - | ClientRequestFlags::INTEGRITY - | ClientRequestFlags::FRAGMENT_TO_FIT + ClientRequestFlags::INTEGRITY + | ClientRequestFlags::REPLAY_DETECT + | ClientRequestFlags::SEQUENCE_DETECT | ClientRequestFlags::USE_SESSION_KEY } @@ -100,8 +256,14 @@ impl Authenticator { )); } + // Ntlm SSP only accepts raw NTLM tokens, so unwrap the SPNEGO envelope first. + let sspi_input = if gss_token.is_empty() { + gss_token.to_owned() + } else { + super::spnego::unwrap_response(gss_token)? + }; + let mut output_buffer = vec![SecurityBuffer::new(Vec::new(), BufferType::Token)]; - let target_name = Self::make_sspi_target_name(&self.server_hostname); let mut builder = self .ssp .initialize_security_context() @@ -110,84 +272,67 @@ impl Authenticator { .with_target_data_representation(Self::SSPI_REQ_DATA_REPRESENTATION) .with_output(&mut output_buffer); - if cfg!(feature = "kerberos") { - builder = builder.with_target_name(&target_name) - } + let target_name = format!("cifs/{}", self.server_hostname); + builder = builder.with_target_name(&target_name); let mut input_buffers = vec![]; - input_buffers.push(SecurityBuffer::new(gss_token.to_owned(), BufferType::Token)); + input_buffers.push(SecurityBuffer::new(sspi_input, BufferType::Token)); builder = builder.with_input(&mut input_buffers); let result = { let mut generator = self.ssp.initialize_security_context_impl(&mut builder)?; - // Kerberos requires a network client to be set up. - // We avoid compiling with the network client if kerberos is not enabled, - // so be sure to avoid using it in that case. - // while default, sync network client is supported in sspi, - // an implementation of the async one had to be added in this module. - #[cfg(feature = "kerberos")] - { - use super::sspi_network_client::ReqwestNetworkClient; - #[cfg(feature = "async")] - { - Self::_resolve_with_async_client( - &mut generator, - &mut ReqwestNetworkClient::new(), - ) - .await? - } - #[cfg(not(feature = "async"))] - { - generator.resolve_with_client(&ReqwestNetworkClient {})? - } - } - #[cfg(not(feature = "kerberos"))] - { - generator.resolve_to_result()? - } + generator.resolve_to_result()? }; self.current_state = Some(result); - let output_buffer = output_buffer + let raw_token = output_buffer .pop() .ok_or_else(|| Error::InvalidState("SSPI output buffer is empty.".to_string()))? .buffer; - Ok(output_buffer) - } - - /// This method, despite being very similar to [`sspi::generator::Generator::resolve_with_async_client`], - /// adds the `Send` bound to the network client, which is required for our async code. - /// - /// See [] for more details. - #[cfg(all(feature = "kerberos", feature = "async"))] - async fn _resolve_with_async_client( - generator: &mut sspi::generator::GeneratorInitSecurityContext<'_>, // Generator returned from `sspi-rs`. - network_client: &mut super::sspi_network_client::ReqwestNetworkClient, // Your custom network client. - ) -> sspi::Result { - let mut state = generator.start(); - - use sspi::generator::GeneratorState::*; - loop { - match state { - Suspended(ref request) => { - state = generator.resume(network_client.send(request).await); - } - Completed(client_state) => { - return client_state; - } - } - } - } + log::trace!( + "NTLM SSP output: {} bytes, starts_with_ntlmssp={}", + raw_token.len(), + super::spnego::is_raw_ntlm(&raw_token) + ); - fn get_available_ssp_pkgs(config: &AuthMethodsConfig) -> String { - let krb_pku2u_config = if cfg!(feature = "kerberos") && config.kerberos { - "kerberos,!pku2u" + // Ntlm SSP emits raw NTLM tokens; we wrap them into SPNEGO manually. + if !self.first_token_sent { + self.first_token_sent = true; + let wrapped = super::spnego::wrap_init(&raw_token); + log::trace!( + "SPNEGO: NTLM Type-1 ({} bytes) -> NegTokenInit ({} bytes)", + raw_token.len(), + wrapped.len() + ); + Ok(wrapped) + } else if self.is_authenticated()? { + // NTLM exchange is complete; include a mechListMIC in the Type-3 + // NegTokenResp. The MIC algorithm depends on the NegotiateFlags + // actually sent on the wire in Type-3 (notably the KEY_EXCH bit), + // so we parse the real flags from raw_token instead of assuming. + let ntlm_flags = extract_ntlm_type3_negotiate_flags(&raw_token).ok_or_else(|| { + Error::InvalidState("Failed to parse NegotiateFlags from NTLM Type-3".into()) + })?; + log::trace!("NTLM Type-3 NegotiateFlags: 0x{:08x}", ntlm_flags); + let mic = + self.compute_mech_list_mic(super::spnego::MECH_TYPE_LIST_BYTES, ntlm_flags)?; + let wrapped = super::spnego::wrap_response_with_mic(&raw_token, &mic); + log::trace!( + "SPNEGO: NTLM Type-3 ({} bytes) + MIC -> NegTokenResp ({} bytes)", + raw_token.len(), + wrapped.len() + ); + Ok(wrapped) } else { - "!kerberos,!pku2u" - }; - let ntlm_config = if config.ntlm { "ntlm" } else { "!ntlm" }; - format!("{ntlm_config},{krb_pku2u_config}") + let wrapped = super::spnego::wrap_response(&raw_token); + log::trace!( + "SPNEGO: NTLM Type-3 ({} bytes) -> NegTokenResp ({} bytes)", + raw_token.len(), + wrapped.len() + ); + Ok(wrapped) + } } } diff --git a/crates/smb/src/session/setup.rs b/crates/smb/src/session/setup.rs index f34ce1b..cdc1b1b 100644 --- a/crates/smb/src/session/setup.rs +++ b/crates/smb/src/session/setup.rs @@ -117,41 +117,108 @@ where /// /// This function loops until the authentication is complete, requesting GSS tokens /// and passing them to the server. + /// + /// Preauth hash policy (MS-SMB2 §3.2.5.3 / §3.2.4.2.3): + /// - Each outgoing request is chained into the hash. + /// - Each intermediate response (MORE_PROCESSING_REQUIRED) is chained. + /// - The final SUCCESS response is NOT included. + /// - `make_channel()` (key derivation) runs once the authentication is + /// complete and the preauth hash is finalized. async fn _setup_loop(&mut self) -> crate::Result<()> { - // While there's a response to process, do so. - while !self.authenticator.is_authenticated()? { + let mut server_needs_more = true; + const MAX_ROUNDS: usize = 8; + let mut round = 0; + + while server_needs_more { + round += 1; + if round > MAX_ROUNDS { + return Err(Error::InvalidState( + "Too many session setup rounds".to_string(), + )); + } + let next_buf = match self.last_setup_response.as_ref() { Some(response) => self.authenticator.next(&response.buffer).await?, None => self.authenticator.next(&[]).await?, }; let is_auth_done = self.authenticator.is_authenticated()?; - // If keys are exchanged, set them up, to enable validation of next response! let request = self.send_setup_request(next_buf).await?; - if is_auth_done { + + // MS-SMB2 §3.2.5.3 : the signing key is derived from SessionKey and the + // preauth hash covering every message up to and including the final + // client request, and excludes the final SUCCESS response. + // + // If NTLM is done on this round (i.e. we just sent Type-3+MIC) the server + // will answer with a signed SUCCESS. The transformer verifies signatures + // against the session's channel, so the channel (signing keys) MUST be + // derived BEFORE we try to receive that response - otherwise the + // transformer rejects the message with "Message is required to be signed, + // but no channel is set up!". + // + // We can do this safely here because the preauth hash already reflects + // every message up to the just-sent Type-3 request, which is exactly the + // input MS-SMB2 mandates. `self.result` exists only after the first round + // has learned the session_id from Type-2, so gating on it keeps round 1 + // untouched. + let channel_already_built = match self.result.as_ref() { + Some(s) => s.read().await?.channel.is_some(), + None => false, + }; + if is_auth_done && self.result.is_some() && !channel_already_built { self.preauth_hash = self.preauth_hash.take().unwrap().finish().into(); self.make_channel().await?; } let response = self.receive_setup_response(request.msg_id).await?; + let response_status = response.message.header.status().ok(); let message_form = response.form; let session_id = response.message.header.session_id; let session_setup_response = response.message.content.to_sessionsetup()?; - // First iteration: construct a session state object. - // TODO: currently, there's a bug which prevents authentication on first attempt - // to complete successfully: since we need the session ID to construct the session state, - // which is required for channel construction and signature validation, - // the first request must arrive here, and then be validated. if self.result.is_none() { log::trace!("Creating session state with id {session_id}."); self.set_session(T::init_session(self, session_id).await?) .await?; } + server_needs_more = response_status == Some(Status::MoreProcessingRequired); + if is_auth_done { - // Important: If we did NOT make sure the message's signature is valid, - // we should do it now, as long as the session is not anonymous or guest. + if server_needs_more { + // Server returned MORE_PROCESSING_REQUIRED even though NTLM + // authentication is already complete on our side. This + // typically means the SPNEGO `mechListMIC` we embedded in + // Type-3 was missing or incorrect, so the server is asking + // for another round our state machine cannot produce. + // + // Per MS-SMB2 §3.2.5.3, accepting this response as "final" + // would leave the client using a session the server has + // not actually acknowledged as complete. Rather than + // silently continuing with a half-negotiated session, fail + // fast so the caller can diagnose and fix the underlying + // mechListMIC or SPNEGO flow. + return Err(Error::InvalidState(format!( + "NTLM auth completed locally but server still returned \ + STATUS_MORE_PROCESSING_REQUIRED; refusing to finalize \ + a session the server has not accepted \ + (likely a bad Type-3 mechListMIC). round={round}" + ))); + } + + // preauth_hash has already been finalized right after + // send_setup_request, and make_channel() was invoked before + // receive; this block only performs final validation. + if self.preauth_hash.as_ref().unwrap().is_in_progress() { + // Defensive fallback: if the early-finalize branch above did + // not fire (e.g. on a legacy code path), finalize here. + self.preauth_hash = self.preauth_hash.take().unwrap().finish().into(); + self.make_channel().await?; + } + + // `server_needs_more == true` already returned above, so we + // know the server accepted this as the final response. Only + // the guest / null-session / signed-message checks remain. if !session_setup_response .session_flags .is_guest_or_null_session() @@ -162,11 +229,12 @@ where )); } } else { + // Intermediate response: chain into preauth hash and continue. self.next_preauth_hash(&response.raw); } self.flags = Some(session_setup_response.session_flags); - self.last_setup_response = Some(session_setup_response) + self.last_setup_response = Some(session_setup_response); } self.flags.ok_or(Error::InvalidState( @@ -202,8 +270,12 @@ where async fn receive_setup_response(&mut self, for_msg_id: u64) -> crate::Result { let is_auth_done = self.authenticator.is_authenticated()?; - let expected_status = if is_auth_done { - &[Status::Success] + // After the NTLM exchange completes, some servers send an additional + // STATUS_MORE_PROCESSING_REQUIRED with a final SPNEGO accept token + // (e.g. mechListMIC verification) before STATUS_SUCCESS. Accept both + // statuses so the session setup can proceed. + let expected_status: &[Status] = if is_auth_done { + &[Status::Success, Status::MoreProcessingRequired] } else { &[Status::MoreProcessingRequired] }; @@ -221,7 +293,11 @@ where .await? .channel .is_some(); - let skip_security_validation = !is_auth_done && !channel_set_up; + // Skip security validation when the channel (signing keys) is not + // yet available. This covers both the initial rounds (auth not done) + // AND extra SPNEGO rounds after NTLM completes but before + // make_channel() derives the session key. + let skip_security_validation = !channel_set_up; if let Some(handler) = &self.handler { log::trace!( "setup loop: receiving with channel handler; skip_security_validation={skip_security_validation}" @@ -230,7 +306,6 @@ where .recvo_internal(roptions, skip_security_validation) .await } else { - assert!(skip_security_validation); log::trace!("setup loop: receiving with upstream handler"); self.upstream.handler.recvo(roptions).await } @@ -261,10 +336,20 @@ where T::on_session_key_exchanged(self).await?; log::trace!("Session keys are set."); + let session_key = self.session_key()?; + let preauth_hash_val = self.preauth_hash_value(); + if cfg!(feature = "__debug-dump-keys") { + log::debug!( + "make_channel: session_key={:02x?}, preauth_hash(first 16)={:02x?}", + session_key, + preauth_hash_val.as_ref().map(|h| &h[..16]) + ); + } + let channel_info = ChannelInfo::new( self.new_channel_id, - &self.session_key()?, - &self.preauth_hash_value(), + &session_key, + &preauth_hash_val, self.conn_info, )?; @@ -290,8 +375,20 @@ where } fn next_preauth_hash(&mut self, data: &IoVec) -> &PreauthHashState { - if let Some(ref mut hash) = self.preauth_hash { + if let Some(ref mut hash) = self.preauth_hash + && hash.is_in_progress() + { + log::trace!( + "preauth hash: chaining {} bytes ({} segments)", + data.total_size(), + data.len() + ); *hash = hash.clone().next(data); + if cfg!(feature = "__debug-dump-keys") + && let &mut PreauthHashState::InProgress(ref h) = hash + { + log::debug!("preauth hash (updated): {:02x?}", &h[..16]); + } } self.preauth_hash.as_ref().unwrap() } diff --git a/crates/smb/src/session/spnego.rs b/crates/smb/src/session/spnego.rs new file mode 100644 index 0000000..26d0847 --- /dev/null +++ b/crates/smb/src/session/spnego.rs @@ -0,0 +1,480 @@ +//! Minimal SPNEGO (RFC 4178) wrapper for SMB2 Session Setup. +//! +//! sspi-rs's `Negotiate` SSP produces raw NTLM tokens when Kerberos is +//! unavailable. SMB2 Session Setup, however, requires the security blob +//! to be a GSSAPI / SPNEGO token (MS-SMB2 §3.2.4.2.3). +//! +//! This module provides lightweight DER helpers to: +//! * Wrap an NTLM Type-1 in a SPNEGO `NegTokenInit`. +//! * Wrap an NTLM Type-3 in a SPNEGO `NegTokenResp`. +//! * Unwrap a server's SPNEGO `NegTokenResp` to extract the inner +//! NTLM Type-2 challenge. +//! +//! Only the minimum ASN.1/DER subset required by NTLM-over-SPNEGO is +//! implemented. Full ASN.1 parsing is deliberately avoided. + +use crate::Error; + +// ── OID constants (DER-encoded, including tag + length) ────────────── + +/// SPNEGO mechanism OID 1.3.6.1.5.5.2 +const SPNEGO_OID: &[u8] = &[0x06, 0x06, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x02]; + +/// NTLMSSP mechanism OID 1.3.6.1.4.1.311.2.2.10 +const NTLMSSP_OID: &[u8] = &[ + 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x02, 0x02, 0x0a, +]; + +/// NTLM signature at byte offset 0 of every NTLM message. +const NTLMSSP_SIGNATURE: &[u8] = b"NTLMSSP\0"; + +// ── DER helpers ────────────────────────────────────────────────────── + +fn der_encode_length(len: usize) -> Vec { + if len < 0x80 { + vec![len as u8] + } else if len < 0x100 { + vec![0x81, len as u8] + } else if len < 0x10000 { + vec![0x82, (len >> 8) as u8, len as u8] + } else if len < 0x100_0000 { + vec![0x83, (len >> 16) as u8, (len >> 8) as u8, len as u8] + } else { + // `der_read_length` rejects any length field wider than 3 bytes, so we + // must match that ceiling here instead of silently truncating the high + // byte into an on-the-wire TLV with the wrong declared size. NTLM + // Type-1/3 tokens are orders of magnitude below this limit, so this is + // an invariant, not a runtime concern. + panic!("DER: value length {len} exceeds the supported 24-bit encoding ceiling") + } +} + +/// Build a DER TLV (tag-length-value). +fn der_tlv(tag: u8, payload: &[u8]) -> Vec { + let mut out = Vec::with_capacity(1 + 4 + payload.len()); + out.push(tag); + out.extend(der_encode_length(payload.len())); + out.extend(payload); + out +} + +/// Read the length field of a DER TLV. +/// Returns `(value_length, bytes_consumed_for_length_field)`. +fn der_read_length(data: &[u8]) -> crate::Result<(usize, usize)> { + if data.is_empty() { + return Err(Error::InvalidMessage("DER: empty length field".into())); + } + let first = data[0]; + if first < 0x80 { + Ok((first as usize, 1)) + } else { + let num_bytes = (first & 0x7f) as usize; + if num_bytes == 0 || num_bytes > 3 || data.len() < 1 + num_bytes { + return Err(Error::InvalidMessage( + "DER: unsupported length encoding".into(), + )); + } + let mut val: usize = 0; + for i in 0..num_bytes { + val = (val << 8) | data[1 + i] as usize; + } + Ok((val, 1 + num_bytes)) + } +} + +/// Skip a DER tag byte + length field, returning the total header size +/// and the value length. +/// +/// Also validates that the declared value is actually present in `data`, +/// so callers can trust `val_len` without further clamping. A truncated +/// TLV is rejected up front instead of being silently clipped. +fn der_skip_header(data: &[u8]) -> crate::Result<(usize, usize)> { + if data.is_empty() { + return Err(Error::InvalidMessage("DER: unexpected end of data".into())); + } + let (val_len, len_bytes) = der_read_length(&data[1..])?; + let header_len = 1 + len_bytes; + let total = header_len + .checked_add(val_len) + .ok_or_else(|| Error::InvalidMessage("DER: length overflow".into()))?; + if data.len() < total { + return Err(Error::InvalidMessage(format!( + "DER: truncated value (declared {val_len} bytes, have {} after header)", + data.len().saturating_sub(header_len) + ))); + } + Ok((header_len, val_len)) +} + +// ── Public API ─────────────────────────────────────────────────────── + +/// Returns `true` if `token` looks like a raw NTLM message (starts with +/// `NTLMSSP\0`). When `false`, the token is presumably already SPNEGO. +pub fn is_raw_ntlm(token: &[u8]) -> bool { + token.len() >= NTLMSSP_SIGNATURE.len() && token.starts_with(NTLMSSP_SIGNATURE) +} + +/// Wrap an NTLM Type-1 (NEGOTIATE_MESSAGE) in a SPNEGO `NegTokenInit`. +/// +/// ```text +/// APPLICATION[0] { +/// OID 1.3.6.1.5.5.2 -- SPNEGO +/// [0] { -- NegotiationToken (CHOICE → NegTokenInit) +/// SEQUENCE { -- NegTokenInit +/// [0] SEQUENCE OF { OID NTLMSSP } -- mechTypes +/// [2] OCTET STRING { } -- mechToken +/// } +/// } +/// } +/// ``` +pub fn wrap_init(ntlm_token: &[u8]) -> Vec { + let mech_token = der_tlv(0x04, ntlm_token); // OCTET STRING + let mech_token_ctx = der_tlv(0xa2, &mech_token); // [2] + + let mech_types_seq = der_tlv(0x30, NTLMSSP_OID); // SEQUENCE OF { OID } + let mech_types_ctx = der_tlv(0xa0, &mech_types_seq); // [0] + + let mut init_body = Vec::with_capacity(mech_types_ctx.len() + mech_token_ctx.len()); + init_body.extend(&mech_types_ctx); + init_body.extend(&mech_token_ctx); + let neg_token_init = der_tlv(0x30, &init_body); // SEQUENCE + + let negotiation_token = der_tlv(0xa0, &neg_token_init); // [0] CHOICE + + let mut app_body = Vec::with_capacity(SPNEGO_OID.len() + negotiation_token.len()); + app_body.extend(SPNEGO_OID); + app_body.extend(&negotiation_token); + der_tlv(0x60, &app_body) // APPLICATION[0] +} + +/// Wrap an NTLM Type-3 (AUTHENTICATE_MESSAGE) in a SPNEGO `NegTokenResp`. +/// +/// ```text +/// [1] { -- NegotiationToken (CHOICE → NegTokenResp) +/// SEQUENCE { +/// [2] OCTET STRING { } -- responseToken +/// } +/// } +/// ``` +pub fn wrap_response(ntlm_token: &[u8]) -> Vec { + let response_token = der_tlv(0x04, ntlm_token); // OCTET STRING + let response_token_ctx = der_tlv(0xa2, &response_token); // [2] + let neg_token_resp = der_tlv(0x30, &response_token_ctx); // SEQUENCE + der_tlv(0xa1, &neg_token_resp) // [1] CHOICE +} + +/// Wrap an NTLM Type-3 (AUTHENTICATE_MESSAGE) in a SPNEGO `NegTokenResp` +/// with a mechListMIC. +/// +/// Per MS-SPNG §3.1.5.1, when the negotiated mechanism's security context +/// is complete, the initiator MUST include the mechListMIC. +/// +/// ```text +/// [1] { +/// SEQUENCE { +/// [2] OCTET STRING { } -- responseToken +/// [3] OCTET STRING { } -- mechListMIC +/// } +/// } +/// ``` +pub fn wrap_response_with_mic(ntlm_token: &[u8], mic: &[u8]) -> Vec { + let response_token = der_tlv(0x04, ntlm_token); // OCTET STRING + let response_token_ctx = der_tlv(0xa2, &response_token); // [2] + let mic_octet = der_tlv(0x04, mic); // OCTET STRING + let mic_ctx = der_tlv(0xa3, &mic_octet); // [3] mechListMIC + let mut seq = response_token_ctx; + seq.extend(mic_ctx); + let neg_token_resp = der_tlv(0x30, &seq); // SEQUENCE + der_tlv(0xa1, &neg_token_resp) // [1] CHOICE +} + +/// The DER-encoded mechTypeList from the NegTokenInit (only NTLMSSP OID). +/// +/// Per MS-SPNG §3.1.5.1, the mechListMIC is computed over the `mechTypes` +/// field of the initial NegTokenInit. This is the raw `MechTypeList` +/// (SEQUENCE OF MechType) WITHOUT the context tag [0]. +/// +/// ```text +/// SEQUENCE { +/// OID 1.3.6.1.4.1.311.2.2.10 -- NTLMSSP +/// } +/// ``` +pub const MECH_TYPE_LIST_BYTES: &[u8] = &[ + 0x30, 0x0C, // SEQUENCE of 12 bytes + 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x02, 0x02, 0x0A, +]; + +/// Same as MECH_TYPE_LIST_BYTES but with the context [0] tag wrapper. +/// Some implementations compute the MIC over the tagged field. +#[allow(dead_code)] +pub const MECH_TYPE_LIST_BYTES_TAGGED: &[u8] = &[ + 0xa0, 0x0E, // [0] context tag, length 14 + 0x30, 0x0C, // SEQUENCE of 12 bytes + 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x02, 0x02, 0x0A, +]; + +/// Build a minimal SPNEGO NegTokenResp with negState = accept-completed (0). +/// +/// Used as the final client acknowledgment when the server sends +/// STATUS_MORE_PROCESSING_REQUIRED with a mechListMIC after the NTLM +/// exchange is complete. Per RFC 4178 §5, when the preferred mechanism +/// is the common mechanism and optimistic token was used, the response +/// need not include a mechListMIC. +/// +/// Kept for symmetry with [`make_accept_complete_with_mic`] and for +/// servers that might require an empty accept-complete acknowledgment. +#[allow(dead_code)] +pub fn make_accept_complete() -> Vec { + let neg_state = der_tlv(0x0a, &[0x00]); // ENUMERATED: accept-completed + let neg_state_ctx = der_tlv(0xa0, &neg_state); // [0] + let neg_token_resp = der_tlv(0x30, &neg_state_ctx); // SEQUENCE + der_tlv(0xa1, &neg_token_resp) // [1] CHOICE +} + +/// Build a SPNEGO NegTokenResp with negState = accept-completed (0) and +/// a mechListMIC computed by the caller. +/// +/// Used as the final client acknowledgment when the server sends +/// STATUS_MORE_PROCESSING_REQUIRED with its own mechListMIC. +#[allow(dead_code)] +pub fn make_accept_complete_with_mic(mic: &[u8]) -> Vec { + let neg_state = der_tlv(0x0a, &[0x00]); // ENUMERATED: accept-completed + let neg_state_ctx = der_tlv(0xa0, &neg_state); // [0] + let mic_octet = der_tlv(0x04, mic); // OCTET STRING + let mic_ctx = der_tlv(0xa3, &mic_octet); // [3] mechListMIC + let mut seq = neg_state_ctx; + seq.extend(mic_ctx); + let neg_token_resp = der_tlv(0x30, &seq); // SEQUENCE + der_tlv(0xa1, &neg_token_resp) // [1] CHOICE +} + +/// Extract the mechToken from a SPNEGO `NegTokenInit` (APPLICATION[0]). +/// +/// This is used to strip sspi-rs's own SPNEGO wrapper so we can re-wrap +/// with a clean, minimal NegTokenInit containing only the NTLMSSP OID. +/// +/// Returns the raw mechanism token (NTLM Type-1), or an error if the +/// structure cannot be parsed. +/// +/// Kept for symmetry with [`wrap_init`] — only `unwrap_response` is +/// currently exercised on the NTLM path, but this helper is useful for +/// callers that need to strip an outer SPNEGO layer from an incoming +/// initial token (e.g. when proxying or re-wrapping). +#[allow(dead_code)] +pub fn unwrap_init(gss_token: &[u8]) -> crate::Result> { + if gss_token.is_empty() || gss_token[0] != 0x60 { + return Err(Error::InvalidMessage(format!( + "SPNEGO: expected APPLICATION[0] (0x60), got 0x{:02x}", + gss_token.first().copied().unwrap_or(0) + ))); + } + + // Skip APPLICATION[0] header. + let (app_hdr, _) = der_skip_header(gss_token)?; + let inner = &gss_token[app_hdr..]; + + // Skip the SPNEGO OID (should be 06 06 2b 06 01 05 05 02). + if inner.len() < SPNEGO_OID.len() || &inner[..SPNEGO_OID.len()] != SPNEGO_OID { + return Err(Error::InvalidMessage( + "SPNEGO: missing SPNEGO OID in NegTokenInit".into(), + )); + } + let after_oid = &inner[SPNEGO_OID.len()..]; + + // Skip [0] NegotiationToken wrapper. + if after_oid.is_empty() || after_oid[0] != 0xa0 { + return Err(Error::InvalidMessage( + "SPNEGO: expected [0] in NegTokenInit".into(), + )); + } + let (ctx0_hdr, _) = der_skip_header(after_oid)?; + let neg_token = &after_oid[ctx0_hdr..]; + + // Skip SEQUENCE (NegTokenInit body). + if neg_token.is_empty() || neg_token[0] != 0x30 { + return Err(Error::InvalidMessage( + "SPNEGO: expected SEQUENCE in NegTokenInit".into(), + )); + } + let (seq_hdr, seq_len) = der_skip_header(neg_token)?; + let seq_body = &neg_token[seq_hdr..seq_hdr + seq_len]; + let mut pos = 0; + + while pos < seq_len { + let tag = seq_body[pos]; + let (elem_hdr, elem_len) = der_skip_header(&seq_body[pos..])?; + + if tag == 0xa2 { + // [2] mechToken — extract the OCTET STRING inside. + let elem_body = &seq_body[pos + elem_hdr..pos + elem_hdr + elem_len]; + if elem_body.is_empty() || elem_body[0] != 0x04 { + return Err(Error::InvalidMessage( + "SPNEGO: expected OCTET STRING inside mechToken".into(), + )); + } + let (octet_hdr, octet_len) = der_skip_header(elem_body)?; + return Ok(elem_body[octet_hdr..octet_hdr + octet_len].to_vec()); + } + + pos += elem_hdr + elem_len; + } + + Err(Error::InvalidMessage( + "SPNEGO: mechToken ([2]) not found in NegTokenInit".into(), + )) +} + +/// Extract the inner NTLM token from a server's SPNEGO `NegTokenResp`. +/// +/// The server sends: +/// ```text +/// [1] { -- NegTokenResp +/// SEQUENCE { +/// [0] ENUMERATED { … } -- negState (optional) +/// [1] OID { … } -- supportedMech (optional) +/// [2] OCTET STRING { } -- responseToken +/// [3] OCTET STRING { … } -- mechListMIC (optional) +/// } +/// } +/// ``` +/// +/// If the token is already raw NTLM, it is returned unchanged. +pub fn unwrap_response(gss_token: &[u8]) -> crate::Result> { + // Fast path: already raw NTLM. + if is_raw_ntlm(gss_token) { + return Ok(gss_token.to_vec()); + } + + // Expect outer tag [1] (NegTokenResp). + if gss_token.is_empty() || gss_token[0] != 0xa1 { + return Err(Error::InvalidMessage(format!( + "SPNEGO: expected NegTokenResp (0xa1), got 0x{:02x}", + gss_token.first().copied().unwrap_or(0) + ))); + } + + let (hdr_size, _) = der_skip_header(gss_token)?; + let inner = &gss_token[hdr_size..]; + + // Inner must be SEQUENCE. + if inner.is_empty() || inner[0] != 0x30 { + return Err(Error::InvalidMessage( + "SPNEGO: expected SEQUENCE inside NegTokenResp".into(), + )); + } + + let (seq_hdr, seq_len) = der_skip_header(inner)?; + let seq_body = &inner[seq_hdr..seq_hdr + seq_len]; + let mut pos = 0; + + while pos < seq_len { + let tag = seq_body[pos]; + let (elem_hdr, elem_len) = der_skip_header(&seq_body[pos..])?; + + if tag == 0xa2 { + // [2] responseToken — should contain OCTET STRING. + let elem_body = &seq_body[pos + elem_hdr..pos + elem_hdr + elem_len]; + if elem_body.is_empty() || elem_body[0] != 0x04 { + return Err(Error::InvalidMessage( + "SPNEGO: expected OCTET STRING inside responseToken".into(), + )); + } + let (octet_hdr, octet_len) = der_skip_header(elem_body)?; + return Ok(elem_body[octet_hdr..octet_hdr + octet_len].to_vec()); + } + + pos += elem_hdr + elem_len; + } + + Err(Error::InvalidMessage( + "SPNEGO: responseToken ([2]) not found in NegTokenResp".into(), + )) +} + +// ── Unit tests ─────────────────────────────────────────────────────── + +#[cfg(test)] +mod tests { + use super::*; + + /// Minimal NTLM Type-1 stub (just the signature + message type). + const FAKE_TYPE1: &[u8] = b"NTLMSSP\x00\x01\x00\x00\x00"; + + #[test] + fn is_raw_ntlm_detects_signature() { + assert!(is_raw_ntlm(FAKE_TYPE1)); + assert!(!is_raw_ntlm(&[0xa1, 0x03, 0x30, 0x01, 0x00])); + assert!(!is_raw_ntlm(&[])); + } + + #[test] + fn wrap_init_produces_valid_der() { + let wrapped = wrap_init(FAKE_TYPE1); + // APPLICATION[0] tag + assert_eq!(wrapped[0], 0x60); + // Contains SPNEGO OID + assert!(wrapped.windows(SPNEGO_OID.len()).any(|w| w == SPNEGO_OID)); + // Contains NTLMSSP OID + assert!(wrapped.windows(NTLMSSP_OID.len()).any(|w| w == NTLMSSP_OID)); + // Contains the original NTLM token + assert!(wrapped.windows(FAKE_TYPE1.len()).any(|w| w == FAKE_TYPE1)); + } + + #[test] + fn wrap_response_produces_valid_der() { + let wrapped = wrap_response(FAKE_TYPE1); + assert_eq!(wrapped[0], 0xa1); + assert!(wrapped.windows(FAKE_TYPE1.len()).any(|w| w == FAKE_TYPE1)); + } + + #[test] + fn unwrap_response_roundtrips() { + let inner_token = b"NTLMSSP\x00\x02\x00\x00\x00CHALLENGE_DATA_HERE"; + + // Manually build a NegTokenResp with [2] responseToken. + let octet = der_tlv(0x04, inner_token); + let ctx2 = der_tlv(0xa2, &octet); + // Also add a dummy [0] negState before the responseToken. + let neg_state = der_tlv(0xa0, &[0x0a, 0x01, 0x01]); // ENUMERATED accept-incomplete + let mut seq_body = Vec::new(); + seq_body.extend(&neg_state); + seq_body.extend(&ctx2); + let seq = der_tlv(0x30, &seq_body); + let neg_token_resp = der_tlv(0xa1, &seq); + + let extracted = unwrap_response(&neg_token_resp).unwrap(); + assert_eq!(&extracted, inner_token); + } + + #[test] + fn unwrap_response_passes_raw_ntlm_through() { + let raw = b"NTLMSSP\x00\x02\x00\x00\x00"; + let extracted = unwrap_response(raw).unwrap(); + assert_eq!(&extracted, raw); + } + + #[test] + fn der_encode_length_covers_each_branch() { + // Short form (1 byte). + assert_eq!(der_encode_length(0x00), vec![0x00]); + assert_eq!(der_encode_length(0x7F), vec![0x7F]); + // Long form, 1 length byte. + assert_eq!(der_encode_length(0x80), vec![0x81, 0x80]); + assert_eq!(der_encode_length(0xFF), vec![0x81, 0xFF]); + // Long form, 2 length bytes. + assert_eq!(der_encode_length(0x0100), vec![0x82, 0x01, 0x00]); + assert_eq!(der_encode_length(0xFFFF), vec![0x82, 0xFF, 0xFF]); + // Long form, 3 length bytes. + assert_eq!(der_encode_length(0x01_0000), vec![0x83, 0x01, 0x00, 0x00]); + assert_eq!(der_encode_length(0xFF_FFFF), vec![0x83, 0xFF, 0xFF, 0xFF]); + } + + /// The decoder rejects any length field wider than 3 bytes, so the + /// encoder must refuse to emit one instead of silently truncating the + /// high byte into a malformed TLV. + #[test] + #[should_panic(expected = "exceeds the supported 24-bit encoding ceiling")] + fn der_encode_length_rejects_over_24_bits() { + let _ = der_encode_length(0x0100_0000); + } +} diff --git a/crates/smb/src/session/sspi_network_client.rs b/crates/smb/src/session/sspi_network_client.rs index 8059dd5..b5031c2 100644 --- a/crates/smb/src/session/sspi_network_client.rs +++ b/crates/smb/src/session/sspi_network_client.rs @@ -182,7 +182,12 @@ mod client_impl { } } +// This blocking variant is kept upstream for API symmetry but is not +// constructed by any caller in the current crate (the `Ntlm` SSP path +// used by `Authenticator` never instantiates a network client). Silence +// the stricter nightly clippy warnings instead of deleting upstream code. #[cfg(not(feature = "async"))] +#[allow(dead_code)] mod client_impl { use super::*; use byteorder::{BigEndian, ReadBytesExt}; @@ -299,4 +304,5 @@ mod client_impl { } } +#[allow(unused_imports)] pub use client_impl::*;