From 23cb0534165c2603fbb5595a740a59b8cbfd7eef Mon Sep 17 00:00:00 2001 From: Diego Date: Wed, 27 May 2026 18:47:28 -0300 Subject: [PATCH] chore: Upgrade quinn 0.11, rustls 0.23, hickory-resolver 0.26 --- Cargo.lock | 450 +++++++++++++------------- Cargo.toml | 14 +- src/crypto/tls/certificate.rs | 65 +++- src/crypto/tls/mod.rs | 25 +- src/crypto/tls/verifier.rs | 88 +++-- src/error.rs | 2 +- src/lib.rs | 9 +- src/transport/quic/listener.rs | 70 ++-- src/transport/quic/mod.rs | 25 +- src/transport/quic/substream.rs | 26 +- src/transport/tcp/connection.rs | 32 +- src/transport/tcp/mod.rs | 8 +- src/transport/websocket/connection.rs | 10 +- 13 files changed, 489 insertions(+), 335 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 977ed5470..96007477c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -299,6 +299,17 @@ dependencies = [ "cpufeatures 0.2.17", ] +[[package]] +name = "chacha20" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.0", + "rand_core 0.10.1", +] + [[package]] name = "chacha20poly1305" version = "0.10.1" @@ -306,7 +317,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35" dependencies = [ "aead", - "chacha20", + "chacha20 0.9.1", "cipher", "poly1305", "zeroize", @@ -557,7 +568,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ab67060fc6b8ef687992d439ca0fa36e7ed17e9a0b16b25b601e8757df720de" dependencies = [ "data-encoding", - "syn 1.0.109", + "syn 2.0.117", ] [[package]] @@ -907,7 +918,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f2f12607f92c69b12ed746fabf9ca4f5c482cba46679c1a75b874ed7c26adb" dependencies = [ "futures-io", - "rustls 0.23.38", + "rustls", "rustls-pki-types", ] @@ -1086,6 +1097,30 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e712f64ec3850b98572bffac52e2c6f282b29fe6c5fa6d42334b30be438d95c1" +[[package]] +name = "hickory-net" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2295ed2f9c31e471e1428a8f88a3f0e1f4b27c15049592138d1eebe9c35b183" +dependencies = [ + "async-trait", + "cfg-if", + "data-encoding", + "futures-channel", + "futures-io", + "futures-util", + "hickory-proto 0.26.1", + "idna", + "ipnet", + "jni", + "rand 0.10.1", + "thiserror 2.0.18", + "tinyvec", + "tokio", + "tracing", + "url", +] + [[package]] name = "hickory-proto" version = "0.25.2" @@ -1103,7 +1138,7 @@ dependencies = [ "ipnet", "once_cell", "rand 0.9.4", - "ring 0.17.14", + "ring", "socket2 0.5.10", "thiserror 2.0.18", "tinyvec", @@ -1112,6 +1147,26 @@ dependencies = [ "url", ] +[[package]] +name = "hickory-proto" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bab31817bfb44672a252e97fe81cd0c18d1b2cf892108922f6818820df8c643" +dependencies = [ + "data-encoding", + "idna", + "ipnet", + "jni", + "once_cell", + "prefix-trie", + "rand 0.10.1", + "ring", + "thiserror 2.0.18", + "tinyvec", + "tracing", + "url", +] + [[package]] name = "hickory-resolver" version = "0.25.2" @@ -1120,7 +1175,7 @@ checksum = "dc62a9a99b0bfb44d2ab95a7208ac952d31060efc16241c87eaf36406fecf87a" dependencies = [ "cfg-if", "futures-util", - "hickory-proto", + "hickory-proto 0.25.2", "ipconfig", "moka", "once_cell", @@ -1133,6 +1188,32 @@ dependencies = [ "tracing", ] +[[package]] +name = "hickory-resolver" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0d58d28879ceecde6607729660c2667a081ccdc082e082675042793960f178c" +dependencies = [ + "cfg-if", + "futures-util", + "hickory-net", + "hickory-proto 0.26.1", + "ipconfig", + "ipnet", + "jni", + "moka", + "ndk-context", + "once_cell", + "parking_lot", + "rand 0.10.1", + "resolv-conf", + "smallvec", + "system-configuration", + "thiserror 2.0.18", + "tokio", + "tracing", +] + [[package]] name = "hkdf" version = "0.12.4" @@ -1448,6 +1529,9 @@ name = "ipnet" version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" +dependencies = [ + "serde", +] [[package]] name = "is" @@ -1477,6 +1561,55 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" +[[package]] +name = "jni" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5efd9a482cf3a427f00d6b35f14332adc7902ce91efb778580e180ff90fa3498" +dependencies = [ + "cfg-if", + "combine", + "jni-macros", + "jni-sys", + "log", + "simd_cesu8", + "thiserror 2.0.18", + "walkdir", + "windows-link", +] + +[[package]] +name = "jni-macros" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a00109accc170f0bdb141fed3e393c565b6f5e072365c3bd58f5b062591560a3" +dependencies = [ + "proc-macro2", + "quote", + "rustc_version", + "simd_cesu8", + "syn 2.0.117", +] + +[[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 = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" +dependencies = [ + "quote", + "syn 2.0.117", +] + [[package]] name = "js-sys" version = "0.3.95" @@ -1594,7 +1727,7 @@ checksum = "0b770c1c8476736ca98c578cba4b505104ff8e842c2876b528925f9766379f9a" dependencies = [ "async-trait", "futures", - "hickory-resolver", + "hickory-resolver 0.25.2", "libp2p-core", "libp2p-identity", "parking_lot", @@ -1675,7 +1808,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c66872d0f1ffcded2788683f76931be1c52e27f343edb93bc6d0bcd8887be443" dependencies = [ "futures", - "hickory-proto", + "hickory-proto 0.25.2", "if-watch", "libp2p-core", "libp2p-identity", @@ -1756,10 +1889,10 @@ dependencies = [ "libp2p-core", "libp2p-identity", "libp2p-tls", - "quinn 0.11.9", + "quinn", "rand 0.8.6", - "ring 0.17.14", - "rustls 0.23.38", + "ring", + "rustls", "socket2 0.5.10", "thiserror 2.0.18", "tokio", @@ -1826,8 +1959,8 @@ dependencies = [ "libp2p-core", "libp2p-identity", "rcgen 0.13.2", - "ring 0.17.14", - "rustls 0.23.38", + "ring", + "rustls", "rustls-webpki", "thiserror 2.0.18", "x509-parser 0.17.0", @@ -1911,7 +2044,7 @@ dependencies = [ "futures-timer", "futures_ringbuf", "hex-literal", - "hickory-resolver", + "hickory-resolver 0.26.1", "indexmap", "ip_network", "libc", @@ -1926,11 +2059,11 @@ dependencies = [ "prost 0.13.5", "prost-build", "quickcheck", - "quinn 0.9.4", + "quinn", "rand 0.8.6", "rcgen 0.14.7", - "ring 0.17.14", - "rustls 0.20.9", + "ring", + "rustls", "serde", "serde_json", "serde_millis", @@ -2163,6 +2296,12 @@ dependencies = [ "unsigned-varint 0.7.2", ] +[[package]] +name = "ndk-context" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" + [[package]] name = "netlink-packet-core" version = "0.8.1" @@ -2577,6 +2716,17 @@ dependencies = [ "termtree", ] +[[package]] +name = "prefix-trie" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cf6e3177f0684016a5c209b00882e15f8bdd3f3bb48f0491df10cd102d0c6e7" +dependencies = [ + "either", + "ipnet", + "num-traits", +] + [[package]] name = "prettyplease" version = "0.2.37" @@ -2735,24 +2885,6 @@ dependencies = [ "rand 0.10.1", ] -[[package]] -name = "quinn" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e8b432585672228923edbbf64b8b12c14e1112f62e88737655b4a083dbcd78e" -dependencies = [ - "bytes", - "pin-project-lite", - "quinn-proto 0.9.6", - "quinn-udp 0.3.2", - "rustc-hash 1.1.0", - "rustls 0.20.9", - "thiserror 1.0.69", - "tokio", - "tracing", - "webpki", -] - [[package]] name = "quinn" version = "0.11.9" @@ -2763,10 +2895,10 @@ dependencies = [ "cfg_aliases", "futures-io", "pin-project-lite", - "quinn-proto 0.11.14", - "quinn-udp 0.5.14", - "rustc-hash 2.1.2", - "rustls 0.23.38", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls", "socket2 0.6.3", "thiserror 2.0.18", "tokio", @@ -2774,24 +2906,6 @@ dependencies = [ "web-time", ] -[[package]] -name = "quinn-proto" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94b0b33c13a79f669c85defaf4c275dc86a0c0372807d0ca3d78e0bb87274863" -dependencies = [ - "bytes", - "rand 0.8.6", - "ring 0.16.20", - "rustc-hash 1.1.0", - "rustls 0.20.9", - "slab", - "thiserror 1.0.69", - "tinyvec", - "tracing", - "webpki", -] - [[package]] name = "quinn-proto" version = "0.11.14" @@ -2802,9 +2916,9 @@ dependencies = [ "getrandom 0.3.4", "lru-slab", "rand 0.9.4", - "ring 0.17.14", - "rustc-hash 2.1.2", - "rustls 0.23.38", + "ring", + "rustc-hash", + "rustls", "rustls-pki-types", "slab", "thiserror 2.0.18", @@ -2813,19 +2927,6 @@ dependencies = [ "web-time", ] -[[package]] -name = "quinn-udp" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "641538578b21f5e5c8ea733b736895576d0fe329bb883b937db6f4d163dbaaf4" -dependencies = [ - "libc", - "quinn-proto 0.9.6", - "socket2 0.4.10", - "tracing", - "windows-sys 0.42.0", -] - [[package]] name = "quinn-udp" version = "0.5.14" @@ -2888,6 +2989,7 @@ version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207" dependencies = [ + "chacha20 0.10.0", "getrandom 0.4.2", "rand_core 0.10.1", ] @@ -2943,7 +3045,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75e669e5202259b5314d1ea5397316ad400819437857b90861765f24c4cf80a2" dependencies = [ "pem", - "ring 0.17.14", + "ring", "rustls-pki-types", "time", "yasna", @@ -2956,7 +3058,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "10b99e0098aa4082912d4c649628623db6aba77335e4f4569ff5083a6448b32e" dependencies = [ "pem", - "ring 0.17.14", + "ring", "rustls-pki-types", "time", "x509-parser 0.18.1", @@ -3007,21 +3109,6 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e061d1b48cb8d38042de4ae0a7a6401009d6143dc80d2e2d6f31f0bdd6470c7" -[[package]] -name = "ring" -version = "0.16.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" -dependencies = [ - "cc", - "libc", - "once_cell", - "spin", - "untrusted 0.7.1", - "web-sys", - "winapi", -] - [[package]] name = "ring" version = "0.17.14" @@ -3032,7 +3119,7 @@ dependencies = [ "cfg-if", "getrandom 0.2.17", "libc", - "untrusted 0.9.0", + "untrusted", "windows-sys 0.52.0", ] @@ -3063,12 +3150,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - [[package]] name = "rustc-hash" version = "2.1.2" @@ -3106,25 +3187,15 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "rustls" -version = "0.20.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b80e3dec595989ea8510028f30c408a4630db12c9cbb8de34203b89d6577e99" -dependencies = [ - "ring 0.16.20", - "sct", - "webpki", -] - [[package]] name = "rustls" version = "0.23.38" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69f9466fb2c14ea04357e91413efb882e2a6d4a406e625449bc0a5d360d53a21" dependencies = [ + "log", "once_cell", - "ring 0.17.14", + "ring", "rustls-pki-types", "rustls-webpki", "subtle", @@ -3159,9 +3230,9 @@ version = "0.103.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8279bb85272c9f10811ae6a6c547ff594d6a7f3c6c6b02ee9726d1d0dcfcdd06" dependencies = [ - "ring 0.17.14", + "ring", "rustls-pki-types", - "untrusted 0.9.0", + "untrusted", ] [[package]] @@ -3181,6 +3252,15 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "schannel" version = "0.1.29" @@ -3196,16 +3276,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" -[[package]] -name = "sct" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" -dependencies = [ - "ring 0.17.14", - "untrusted 0.9.0", -] - [[package]] name = "sctp-proto" version = "0.9.0" @@ -3216,7 +3286,7 @@ dependencies = [ "crc", "log", "rand 0.9.4", - "rustc-hash 2.1.2", + "rustc-hash", "slab", "thiserror 2.0.18", ] @@ -3369,6 +3439,22 @@ dependencies = [ "rand_core 0.6.4", ] +[[package]] +name = "simd_cesu8" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94f90157bb87cddf702797c5dadfa0be7d266cdf49e22da2fcaa32eff75b2c33" +dependencies = [ + "rustc_version", + "simdutf8", +] + +[[package]] +name = "simdutf8" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" + [[package]] name = "simple-dns" version = "0.11.2" @@ -3401,22 +3487,12 @@ dependencies = [ "chacha20poly1305", "curve25519-dalek", "rand_core 0.6.4", - "ring 0.17.14", + "ring", "rustc_version", "sha2 0.10.9", "subtle", ] -[[package]] -name = "socket2" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" -dependencies = [ - "libc", - "winapi", -] - [[package]] name = "socket2" version = "0.5.10" @@ -3452,12 +3528,6 @@ dependencies = [ "sha1", ] -[[package]] -name = "spin" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" - [[package]] name = "spki" version = "0.7.3" @@ -3752,7 +3822,7 @@ version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" dependencies = [ - "rustls 0.23.38", + "rustls", "tokio", ] @@ -3775,7 +3845,7 @@ checksum = "489a59b6730eda1b0171fcfda8b121f4bee2b35cba8645ca35c5f7ba3eb736c1" dependencies = [ "futures-util", "log", - "rustls 0.23.38", + "rustls", "rustls-native-certs", "rustls-pki-types", "tokio", @@ -3913,7 +3983,7 @@ dependencies = [ "httparse", "log", "rand 0.9.4", - "rustls 0.23.38", + "rustls", "rustls-pki-types", "sha1", "thiserror 2.0.18", @@ -3983,12 +4053,6 @@ dependencies = [ "tokio-util", ] -[[package]] -name = "untrusted" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" - [[package]] name = "untrusted" version = "0.9.0" @@ -4048,6 +4112,16 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + [[package]] name = "want" version = "0.3.1" @@ -4160,16 +4234,6 @@ dependencies = [ "semver", ] -[[package]] -name = "web-sys" -version = "0.3.95" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f2dfbb17949fa2088e5d39408c48368947b86f7834484e87b73de55bc14d97d" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - [[package]] name = "web-time" version = "1.1.0" @@ -4186,8 +4250,8 @@ version = "0.22.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed63aea5ce73d0ff405984102c42de94fc55a6b75765d621c65262469b3c9b53" dependencies = [ - "ring 0.17.14", - "untrusted 0.9.0", + "ring", + "untrusted", ] [[package]] @@ -4230,6 +4294,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys 0.61.2", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" @@ -4348,21 +4421,6 @@ dependencies = [ "windows-link", ] -[[package]] -name = "windows-sys" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" -dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", -] - [[package]] name = "windows-sys" version = "0.52.0" @@ -4432,12 +4490,6 @@ dependencies = [ "windows-link", ] -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" - [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" @@ -4450,12 +4502,6 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" - [[package]] name = "windows_aarch64_msvc" version = "0.52.6" @@ -4468,12 +4514,6 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" -[[package]] -name = "windows_i686_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" - [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -4498,12 +4538,6 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" -[[package]] -name = "windows_i686_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" - [[package]] name = "windows_i686_msvc" version = "0.52.6" @@ -4516,12 +4550,6 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" - [[package]] name = "windows_x86_64_gnu" version = "0.52.6" @@ -4534,12 +4562,6 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" - [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" @@ -4552,12 +4574,6 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" - [[package]] name = "windows_x86_64_msvc" version = "0.52.6" @@ -4720,7 +4736,7 @@ dependencies = [ "lazy_static", "nom 7.1.3", "oid-registry", - "ring 0.17.14", + "ring", "rusticata-macros", "thiserror 2.0.18", "time", diff --git a/Cargo.toml b/Cargo.toml index 5ee256cb0..6b33ed41b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -56,7 +56,7 @@ tokio = { version = "1.45.0", features = [ "parking_lot", ] } tracing = { version = "0.1.40", features = ["log"] } -hickory-resolver = "0.25.2" +hickory-resolver = "0.26" uint = "0.10.0" unsigned-varint = { version = "0.8.0", features = ["codec"] } url = "2.5.4" @@ -74,15 +74,17 @@ tokio-tungstenite = { version = "0.27.0", features = [ # End of websocket related dependencies. # Quic related dependencies. Quic is an experimental feature flag. The dependencies must be updated. -quinn = { version = "0.9.3", default-features = false, features = [ - "tls-rustls", +quinn = { version = "0.11.9", default-features = false, features = [ "runtime-tokio", + "rustls-ring", ], optional = true } -rustls = { version = "0.20.7", default-features = false, features = [ - "dangerous_configuration", +rustls = { version = "0.23.38", default-features = false, features = [ + "ring", + "std", + "logging", ], optional = true } ring = { version = "0.17.14", optional = true } -webpki = { version = "0.22.4", optional = true } +webpki = { version = "0.22.4", default-features = false, features = ["std"], optional = true } rcgen = { version = "0.14.5", optional = true } # End of Quic related dependencies. diff --git a/src/crypto/tls/certificate.rs b/src/crypto/tls/certificate.rs index ada50e7fa..476b2bd41 100644 --- a/src/crypto/tls/certificate.rs +++ b/src/crypto/tls/certificate.rs @@ -29,6 +29,7 @@ use crate::{ // use libp2p_identity as identity; // use libp2p_identity::PeerId; +use rustls::pki_types::{CertificateDer, PrivateKeyDer, PrivatePkcs8KeyDer}; use x509_parser::{prelude::*, signature_algorithm::SignatureAlgorithm}; /// The libp2p Public Key Extension is a X.509 extension @@ -51,14 +52,16 @@ static P2P_SIGNATURE_ALGORITHM: &rcgen::SignatureAlgorithm = &rcgen::PKCS_ECDSA_ /// certificate extension containing the public key of the given keypair. pub fn generate( identity_keypair: &Keypair, -) -> Result<(rustls::Certificate, rustls::PrivateKey), GenError> { +) -> Result<(CertificateDer<'static>, PrivateKeyDer<'static>), GenError> { // Keypair used to sign the certificate. // SHOULD NOT be related to the host's key. // Endpoints MAY generate a new key and certificate // for every connection attempt, or they MAY reuse the same key // and certificate for multiple connections. let certificate_keypair = rcgen::KeyPair::generate_for(P2P_SIGNATURE_ALGORITHM)?; - let rustls_key = rustls::PrivateKey(certificate_keypair.serialize_der()); + let rustls_key = PrivateKeyDer::Pkcs8(PrivatePkcs8KeyDer::from( + certificate_keypair.serialize_der(), + )); let certificate = { let mut params = rcgen::CertificateParams::new(vec![])?; @@ -70,16 +73,61 @@ pub fn generate( params.self_signed(&certificate_keypair)? }; - let rustls_certificate = rustls::Certificate(certificate.der().to_vec()); + let rustls_certificate = certificate.der().clone(); Ok((rustls_certificate, rustls_key)) } +/// A `rustls` certificate resolver that always presents the same libp2p certificate. +/// +/// We resolve through this instead of `ConfigBuilder::with_single_cert` / +/// `with_client_auth_cert` because rustls 0.23 validates the certificate passed to those methods +/// and rejects the libp2p extension, which is marked critical. A resolver bypasses that check. +#[derive(Debug)] +pub struct AlwaysResolvesCert(std::sync::Arc); + +impl AlwaysResolvesCert { + pub fn new( + cert: CertificateDer<'static>, + key: &PrivateKeyDer<'_>, + ) -> Result { + let certified_key = rustls::sign::CertifiedKey::new( + vec![cert], + rustls::crypto::ring::sign::any_ecdsa_type(key)?, + ); + + Ok(Self(std::sync::Arc::new(certified_key))) + } +} + +impl rustls::client::ResolvesClientCert for AlwaysResolvesCert { + fn resolve( + &self, + _root_hint_subjects: &[&[u8]], + _sigschemes: &[rustls::SignatureScheme], + ) -> Option> { + Some(std::sync::Arc::clone(&self.0)) + } + + fn has_certs(&self) -> bool { + true + } +} + +impl rustls::server::ResolvesServerCert for AlwaysResolvesCert { + fn resolve( + &self, + _client_hello: rustls::server::ClientHello<'_>, + ) -> Option> { + Some(std::sync::Arc::clone(&self.0)) + } +} + /// Attempts to parse the provided bytes as a [`P2pCertificate`]. /// /// For this to succeed, the certificate must contain the specified extension and the signature must /// match the embedded public key. -pub fn parse(certificate: &rustls::Certificate) -> Result, ParseError> { +pub fn parse<'a>(certificate: &'a CertificateDer<'a>) -> Result, ParseError> { let certificate = parse_unverified(certificate.as_ref())?; certificate.verify()?; @@ -292,6 +340,8 @@ impl P2pCertificate<'_> { RSA_PKCS1_SHA1 => return Err(webpki::Error::UnsupportedSignatureAlgorithm), ECDSA_SHA1_Legacy => return Err(webpki::Error::UnsupportedSignatureAlgorithm), Unknown(_) => return Err(webpki::Error::UnsupportedSignatureAlgorithm), + // `rustls::SignatureScheme` is `#[non_exhaustive]` as of rustls 0.23. + _ => return Err(webpki::Error::UnsupportedSignatureAlgorithm), }; let spki = &self.certificate.tbs_certificate.subject_pki; let key = signature::UnparsedPublicKey::new( @@ -487,7 +537,8 @@ mod tests { #[test] fn rsa_pss_sha384() { - let cert = rustls::Certificate(include_bytes!("./test_assets/rsa_pss_sha384.der").to_vec()); + let cert = + CertificateDer::from(include_bytes!("./test_assets/rsa_pss_sha384.der").to_vec()); let cert = parse(&cert).unwrap(); @@ -508,7 +559,7 @@ mod tests { #[test] fn can_parse_certificate_with_ed25519_keypair() { - let certificate = rustls::Certificate(hex!("308201773082011ea003020102020900f5bd0debaa597f52300a06082a8648ce3d04030230003020170d3735303130313030303030305a180f34303936303130313030303030305a30003059301306072a8648ce3d020106082a8648ce3d030107034200046bf9871220d71dcb3483ecdfcbfcc7c103f8509d0974b3c18ab1f1be1302d643103a08f7a7722c1b247ba3876fe2c59e26526f479d7718a85202ddbe47562358a37f307d307b060a2b0601040183a25a01010101ff046a30680424080112207fda21856709c5ae12fd6e8450623f15f11955d384212b89f56e7e136d2e17280440aaa6bffabe91b6f30c35e3aa4f94b1188fed96b0ffdd393f4c58c1c047854120e674ce64c788406d1c2c4b116581fd7411b309881c3c7f20b46e54c7e6fe7f0f300a06082a8648ce3d040302034700304402207d1a1dbd2bda235ff2ec87daf006f9b04ba076a5a5530180cd9c2e8f6399e09d0220458527178c7e77024601dbb1b256593e9b96d961b96349d1f560114f61a87595").to_vec()); + let certificate = CertificateDer::from(hex!("308201773082011ea003020102020900f5bd0debaa597f52300a06082a8648ce3d04030230003020170d3735303130313030303030305a180f34303936303130313030303030305a30003059301306072a8648ce3d020106082a8648ce3d030107034200046bf9871220d71dcb3483ecdfcbfcc7c103f8509d0974b3c18ab1f1be1302d643103a08f7a7722c1b247ba3876fe2c59e26526f479d7718a85202ddbe47562358a37f307d307b060a2b0601040183a25a01010101ff046a30680424080112207fda21856709c5ae12fd6e8450623f15f11955d384212b89f56e7e136d2e17280440aaa6bffabe91b6f30c35e3aa4f94b1188fed96b0ffdd393f4c58c1c047854120e674ce64c788406d1c2c4b116581fd7411b309881c3c7f20b46e54c7e6fe7f0f300a06082a8648ce3d040302034700304402207d1a1dbd2bda235ff2ec87daf006f9b04ba076a5a5530180cd9c2e8f6399e09d0220458527178c7e77024601dbb1b256593e9b96d961b96349d1f560114f61a87595").to_vec()); let peer_id = parse(&certificate).unwrap().peer_id(); @@ -522,7 +573,7 @@ mod tests { #[test] fn fails_to_parse_bad_certificate_with_ed25519_keypair() { - let certificate = rustls::Certificate(hex!("308201773082011da003020102020830a73c5d896a1109300a06082a8648ce3d04030230003020170d3735303130313030303030305a180f34303936303130313030303030305a30003059301306072a8648ce3d020106082a8648ce3d03010703420004bbe62df9a7c1c46b7f1f21d556deec5382a36df146fb29c7f1240e60d7d5328570e3b71d99602b77a65c9b3655f62837f8d66b59f1763b8c9beba3be07778043a37f307d307b060a2b0601040183a25a01010101ff046a3068042408011220ec8094573afb9728088860864f7bcea2d4fd412fef09a8e2d24d482377c20db60440ecabae8354afa2f0af4b8d2ad871e865cb5a7c0c8d3dbdbf42de577f92461a0ebb0a28703e33581af7d2a4f2270fc37aec6261fcc95f8af08f3f4806581c730a300a06082a8648ce3d040302034800304502202dfb17a6fa0f94ee0e2e6a3b9fb6e986f311dee27392058016464bd130930a61022100ba4b937a11c8d3172b81e7cd04aedb79b978c4379c2b5b24d565dd5d67d3cb3c").to_vec()); + let certificate = CertificateDer::from(hex!("308201773082011da003020102020830a73c5d896a1109300a06082a8648ce3d04030230003020170d3735303130313030303030305a180f34303936303130313030303030305a30003059301306072a8648ce3d020106082a8648ce3d03010703420004bbe62df9a7c1c46b7f1f21d556deec5382a36df146fb29c7f1240e60d7d5328570e3b71d99602b77a65c9b3655f62837f8d66b59f1763b8c9beba3be07778043a37f307d307b060a2b0601040183a25a01010101ff046a3068042408011220ec8094573afb9728088860864f7bcea2d4fd412fef09a8e2d24d482377c20db60440ecabae8354afa2f0af4b8d2ad871e865cb5a7c0c8d3dbdbf42de577f92461a0ebb0a28703e33581af7d2a4f2270fc37aec6261fcc95f8af08f3f4806581c730a300a06082a8648ce3d040302034800304502202dfb17a6fa0f94ee0e2e6a3b9fb6e986f311dee27392058016464bd130930a61022100ba4b937a11c8d3172b81e7cd04aedb79b978c4379c2b5b24d565dd5d67d3cb3c").to_vec()); match parse(&certificate) { Ok(_) => unreachable!(), diff --git a/src/crypto/tls/mod.rs b/src/crypto/tls/mod.rs index e19976ae9..6bddd7899 100644 --- a/src/crypto/tls/mod.rs +++ b/src/crypto/tls/mod.rs @@ -40,14 +40,16 @@ pub fn make_server_config( ) -> Result { let (certificate, private_key) = certificate::generate(keypair)?; - let mut crypto = rustls::ServerConfig::builder() - .with_cipher_suites(verifier::CIPHERSUITES) - .with_safe_default_kx_groups() + let cert_resolver = Arc::new( + certificate::AlwaysResolvesCert::new(certificate, &private_key) + .expect("Server cert key DER is valid; qed"), + ); + + let mut crypto = rustls::ServerConfig::builder_with_provider(verifier::crypto_provider()) .with_protocol_versions(verifier::PROTOCOL_VERSIONS) .expect("Cipher suites and kx groups are configured; qed") .with_client_cert_verifier(Arc::new(verifier::Libp2pCertificateVerifier::new())) - .with_single_cert(vec![certificate], private_key) - .expect("Server cert key DER is valid; qed"); + .with_cert_resolver(cert_resolver); crypto.alpn_protocols = vec![P2P_ALPN.to_vec()]; Ok(crypto) @@ -60,16 +62,19 @@ pub fn make_client_config( ) -> Result { let (certificate, private_key) = certificate::generate(keypair)?; - let mut crypto = rustls::ClientConfig::builder() - .with_cipher_suites(verifier::CIPHERSUITES) - .with_safe_default_kx_groups() + let cert_resolver = Arc::new( + certificate::AlwaysResolvesCert::new(certificate, &private_key) + .expect("Client cert key DER is valid; qed"), + ); + + let mut crypto = rustls::ClientConfig::builder_with_provider(verifier::crypto_provider()) .with_protocol_versions(verifier::PROTOCOL_VERSIONS) .expect("Cipher suites and kx groups are configured; qed") + .dangerous() .with_custom_certificate_verifier(Arc::new( verifier::Libp2pCertificateVerifier::with_remote_peer_id(remote_peer_id), )) - .with_single_cert(vec![certificate], private_key) - .expect("Client cert key DER is valid; qed"); + .with_client_cert_resolver(cert_resolver); crypto.alpn_protocols = vec![P2P_ALPN.to_vec()]; Ok(crypto) diff --git a/src/crypto/tls/verifier.rs b/src/crypto/tls/verifier.rs index 470c43c29..5ead2647b 100644 --- a/src/crypto/tls/verifier.rs +++ b/src/crypto/tls/verifier.rs @@ -26,16 +26,21 @@ use crate::{crypto::tls::certificate, PeerId}; use rustls::{ - cipher_suite::{ - TLS13_AES_128_GCM_SHA256, TLS13_AES_256_GCM_SHA384, TLS13_CHACHA20_POLY1305_SHA256, + client::danger::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier}, + crypto::{ + ring::cipher_suite::{ + TLS13_AES_128_GCM_SHA256, TLS13_AES_256_GCM_SHA384, TLS13_CHACHA20_POLY1305_SHA256, + }, + CryptoProvider, }, - client::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier}, - internal::msgs::handshake::DigitallySignedStruct, - server::{ClientCertVerified, ClientCertVerifier}, - Certificate, DistinguishedNames, SignatureScheme, SupportedCipherSuite, - SupportedProtocolVersion, + pki_types::{CertificateDer, ServerName, UnixTime}, + server::danger::{ClientCertVerified, ClientCertVerifier}, + CertificateError, DigitallySignedStruct, DistinguishedName, SignatureScheme, + SupportedCipherSuite, SupportedProtocolVersion, }; +use std::sync::Arc; + /// The protocol versions supported by this verifier. /// /// The spec says: @@ -54,9 +59,23 @@ pub static CIPHERSUITES: &[SupportedCipherSuite] = &[ TLS13_AES_128_GCM_SHA256, ]; +/// The [`CryptoProvider`] used for libp2p TLS. +/// +/// It is the *ring* provider restricted to the TLS 1.3 cipher suites mandated by the libp2p spec. +/// rustls 0.23 no longer takes cipher suites and key-exchange groups on the config builder; they +/// are carried by the provider, which must be passed explicitly because no process-default +/// provider is installed (the `aws-lc-rs` default is disabled). +pub fn crypto_provider() -> Arc { + Arc::new(CryptoProvider { + cipher_suites: CIPHERSUITES.to_vec(), + ..rustls::crypto::ring::default_provider() + }) +} + /// Implementation of the `rustls` certificate verification traits for libp2p. /// /// Only TLS 1.3 is supported. TLS 1.2 should be disabled in the configuration of `rustls`. +#[derive(Debug)] pub struct Libp2pCertificateVerifier { /// The peer ID we intend to connect to remote_peer_id: Option, @@ -105,12 +124,11 @@ impl Libp2pCertificateVerifier { impl ServerCertVerifier for Libp2pCertificateVerifier { fn verify_server_cert( &self, - end_entity: &Certificate, - intermediates: &[Certificate], - _server_name: &rustls::ServerName, - _scts: &mut dyn Iterator, + end_entity: &CertificateDer<'_>, + intermediates: &[CertificateDer<'_>], + _server_name: &ServerName<'_>, _ocsp_response: &[u8], - _now: std::time::SystemTime, + _now: UnixTime, ) -> Result { let peer_id = verify_presented_certs(end_entity, intermediates)?; @@ -120,8 +138,8 @@ impl ServerCertVerifier for Libp2pCertificateVerifier { // the certificate matches the peer ID they intended to connect to, // and MUST abort the connection if there is a mismatch. if remote_peer_id != peer_id { - return Err(rustls::Error::PeerMisbehavedError( - "Wrong peer ID in p2p extension".to_string(), + return Err(rustls::Error::InvalidCertificate( + CertificateError::ApplicationVerificationFailure, )); } } @@ -132,7 +150,7 @@ impl ServerCertVerifier for Libp2pCertificateVerifier { fn verify_tls12_signature( &self, _message: &[u8], - _cert: &Certificate, + _cert: &CertificateDer<'_>, _dss: &DigitallySignedStruct, ) -> Result { unreachable!("`PROTOCOL_VERSIONS` only allows TLS 1.3") @@ -141,7 +159,7 @@ impl ServerCertVerifier for Libp2pCertificateVerifier { fn verify_tls13_signature( &self, message: &[u8], - cert: &Certificate, + cert: &CertificateDer<'_>, dss: &DigitallySignedStruct, ) -> Result { verify_tls13_signature(cert, dss.scheme, message, dss.signature()) @@ -164,15 +182,15 @@ impl ClientCertVerifier for Libp2pCertificateVerifier { true } - fn client_auth_root_subjects(&self) -> Option { - Some(vec![]) + fn root_hint_subjects(&self) -> &[DistinguishedName] { + &[] } fn verify_client_cert( &self, - end_entity: &Certificate, - intermediates: &[Certificate], - _now: std::time::SystemTime, + end_entity: &CertificateDer<'_>, + intermediates: &[CertificateDer<'_>], + _now: UnixTime, ) -> Result { let _: PeerId = verify_presented_certs(end_entity, intermediates)?; @@ -182,7 +200,7 @@ impl ClientCertVerifier for Libp2pCertificateVerifier { fn verify_tls12_signature( &self, _message: &[u8], - _cert: &Certificate, + _cert: &CertificateDer<'_>, _dss: &DigitallySignedStruct, ) -> Result { unreachable!("`PROTOCOL_VERSIONS` only allows TLS 1.3") @@ -191,7 +209,7 @@ impl ClientCertVerifier for Libp2pCertificateVerifier { fn verify_tls13_signature( &self, message: &[u8], - cert: &Certificate, + cert: &CertificateDer<'_>, dss: &DigitallySignedStruct, ) -> Result { verify_tls13_signature(cert, dss.scheme, message, dss.signature()) @@ -209,8 +227,8 @@ impl ClientCertVerifier for Libp2pCertificateVerifier { /// Endpoints MUST abort the connection attempt if more than one certificate is received, /// or if the certificate’s self-signature is not valid. fn verify_presented_certs( - end_entity: &Certificate, - intermediates: &[Certificate], + end_entity: &CertificateDer<'_>, + intermediates: &[CertificateDer<'_>], ) -> Result { if !intermediates.is_empty() { return Err(rustls::Error::General( @@ -224,7 +242,7 @@ fn verify_presented_certs( } fn verify_tls13_signature( - cert: &Certificate, + cert: &CertificateDer<'_>, signature_scheme: SignatureScheme, message: &[u8], signature: &[u8], @@ -238,8 +256,10 @@ impl From for rustls::Error { fn from(certificate::ParseError(e): certificate::ParseError) -> Self { use webpki::Error::*; match e { - BadDer => rustls::Error::InvalidCertificateEncoding, - e => rustls::Error::InvalidCertificateData(format!("invalid peer certificate: {e}")), + BadDer => rustls::Error::InvalidCertificate(CertificateError::BadEncoding), + e => rustls::Error::InvalidCertificate(CertificateError::Other(rustls::OtherError( + std::sync::Arc::new(e), + ))), } } } @@ -247,10 +267,14 @@ impl From for rustls::Error { fn from(certificate::VerificationError(e): certificate::VerificationError) -> Self { use webpki::Error::*; match e { - InvalidSignatureForPublicKey => rustls::Error::InvalidCertificateSignature, - UnsupportedSignatureAlgorithm | UnsupportedSignatureAlgorithmForPublicKey => - rustls::Error::InvalidCertificateSignatureType, - e => rustls::Error::InvalidCertificateData(format!("invalid peer certificate: {e}")), + InvalidSignatureForPublicKey => + rustls::Error::InvalidCertificate(CertificateError::BadSignature), + // The unsupported-algorithm cases (and anything else) are forwarded as the underlying + // webpki error: `CertificateError::UnsupportedSignatureAlgorithm` is deprecated in + // rustls 0.23 and its replacement requires context we don't have here. + e => rustls::Error::InvalidCertificate(CertificateError::Other(rustls::OtherError( + std::sync::Arc::new(e), + ))), } } } diff --git a/src/error.rs b/src/error.rs index 920591838..333fae880 100644 --- a/src/error.rs +++ b/src/error.rs @@ -127,7 +127,7 @@ pub enum Error { #[error("Failed to dial peer immediately")] ImmediateDialError(#[from] ImmediateDialError), #[error("Cannot read system DNS config: `{0}`")] - CannotReadSystemDnsConfig(hickory_resolver::ResolveError), + CannotReadSystemDnsConfig(hickory_resolver::net::NetError), } /// Error type for address parsing. diff --git a/src/lib.rs b/src/lib.rs index 26b9b11ac..e998bea2d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -54,7 +54,7 @@ use crate::transport::webrtc::WebRtcTransport; #[cfg(feature = "websocket")] use crate::transport::websocket::WebSocketTransport; -use hickory_resolver::{name_server::TokioConnectionProvider, TokioResolver}; +use hickory_resolver::{net::runtime::TokioRuntimeProvider, TokioResolver}; use multiaddr::{Multiaddr, Protocol}; use transport::Endpoint; use types::ConnectionId; @@ -160,14 +160,15 @@ impl Litep2p { let (resolver_config, resolver_opts) = if litep2p_config.use_system_dns_config { hickory_resolver::system_conf::read_system_conf() - .map_err(Error::CannotReadSystemDnsConfig)? + .map_err(|error| Error::CannotReadSystemDnsConfig(error.into()))? } else { (Default::default(), Default::default()) }; let resolver = Arc::new( - TokioResolver::builder_with_config(resolver_config, TokioConnectionProvider::default()) + TokioResolver::builder_with_config(resolver_config, TokioRuntimeProvider::default()) .with_options(resolver_opts) - .build(), + .build() + .map_err(|error| Error::Other(format!("failed to build DNS resolver: {error}")))?, ); let supported_transports = Self::supported_transports(&litep2p_config); diff --git a/src/transport/quic/listener.rs b/src/transport/quic/listener.rs index 62ad42069..ce621d3de 100644 --- a/src/transport/quic/listener.rs +++ b/src/transport/quic/listener.rs @@ -27,7 +27,7 @@ use crate::{ use futures::{future::BoxFuture, stream::FuturesUnordered, FutureExt, Stream, StreamExt}; use multiaddr::{Multiaddr, Protocol}; -use quinn::{Connecting, Endpoint, ServerConfig}; +use quinn::{crypto::rustls::QuicServerConfig, Connecting, Endpoint, ServerConfig}; use std::{ net::{IpAddr, SocketAddr}, @@ -39,6 +39,29 @@ use std::{ /// Logging target for the file. const LOG_TARGET: &str = "litep2p::quic::listener"; +/// Await the next inbound connection on `listener`. +/// +/// quinn 0.11 surfaces inbound connections as [`quinn::Incoming`], which must be explicitly +/// accepted before it becomes a [`Connecting`]. We accept every incoming connection, skipping the +/// ones that fail to be accepted (e.g. the peer went away), and resolve to `None` once the +/// endpoint is closed. +async fn accept_connection(index: usize, listener: Endpoint) -> Option<(usize, Connecting)> { + loop { + let incoming = listener.accept().await?; + + match incoming.accept() { + Ok(connecting) => return Some((index, connecting)), + Err(error) => { + tracing::debug!( + target: LOG_TARGET, + ?error, + "failed to accept inbound quic connection", + ); + } + } + } +} + /// QUIC listener. pub struct QuicListener { /// Listen addresses. @@ -57,7 +80,7 @@ impl QuicListener { keypair: &Keypair, addresses: Vec, ) -> crate::Result<(Self, Vec)> { - let (mut listeners, listen_addresses): (Vec, Vec) = addresses + let (listeners, listen_addresses): (Vec, Vec) = addresses .into_iter() .filter_map(|address| { let bind_address = match Self::get_socket_address(&address).ok()?.0 { @@ -72,8 +95,12 @@ impl QuicListener { return None; } }; - let crypto_config = Arc::new(make_server_config(keypair).expect("to succeed")); - let server_config = ServerConfig::with_crypto(crypto_config); + let crypto_config = make_server_config(keypair).expect("to succeed"); + let quic_crypto = Arc::new( + QuicServerConfig::try_from(crypto_config) + .expect("TLS config to be valid for QUIC; qed"), + ); + let server_config = ServerConfig::with_crypto(quic_crypto); let listener = match Endpoint::server(server_config, bind_address) { Ok(listener) => listener, Err(error) => { @@ -105,13 +132,9 @@ impl QuicListener { Ok(( Self { incoming: listeners - .iter_mut() + .iter() .enumerate() - .map(|(i, listener)| { - let inner = listener.clone(); - async move { inner.accept().await.map(|connecting| (i, connecting)) } - .boxed() - }) + .map(|(i, listener)| accept_connection(i, listener.clone()).boxed()) .collect(), listeners, _listen_addresses: listen_addresses, @@ -232,10 +255,7 @@ impl Stream for QuicListener { Some(None) => Poll::Ready(None), Some(Some((listener, future))) => { let inner = self.listeners[listener].clone(); - self.incoming.push( - async move { inner.accept().await.map(|connecting| (listener, connecting)) } - .boxed(), - ); + self.incoming.push(accept_connection(listener, inner).boxed()); Poll::Ready(Some(future)) } @@ -248,7 +268,7 @@ mod tests { use crate::crypto::tls::make_client_config; use super::*; - use quinn::ClientConfig; + use quinn::{crypto::rustls::QuicClientConfig, ClientConfig}; use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}; fn peer_id() -> PeerId { @@ -405,7 +425,9 @@ mod tests { let crypto_config = Arc::new(make_client_config(&Keypair::generate(), Some(peer)).expect("to succeed")); - let client_config = ClientConfig::new(crypto_config); + let client_config = ClientConfig::new(Arc::new( + QuicClientConfig::try_from(crypto_config).expect("to succeed"), + )); let client = Endpoint::client(SocketAddr::new(IpAddr::V6(Ipv6Addr::UNSPECIFIED), 0)).unwrap(); let connection = client @@ -451,7 +473,9 @@ mod tests { let crypto_config1 = Arc::new(make_client_config(&Keypair::generate(), Some(peer)).expect("to succeed")); - let client_config1 = ClientConfig::new(crypto_config1); + let client_config1 = ClientConfig::new(Arc::new( + QuicClientConfig::try_from(crypto_config1).expect("to succeed"), + )); let client1 = Endpoint::client(SocketAddr::new(IpAddr::V6(Ipv6Addr::UNSPECIFIED), 0)).unwrap(); let connection1 = client1 @@ -464,7 +488,9 @@ mod tests { let crypto_config2 = Arc::new(make_client_config(&Keypair::generate(), Some(peer)).expect("to succeed")); - let client_config2 = ClientConfig::new(crypto_config2); + let client_config2 = ClientConfig::new(Arc::new( + QuicClientConfig::try_from(crypto_config2).expect("to succeed"), + )); let client2 = Endpoint::client(SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 0)).unwrap(); let connection2 = client2 @@ -519,7 +545,9 @@ mod tests { let crypto_config1 = Arc::new(make_client_config(&Keypair::generate(), Some(peer)).expect("to succeed")); - let client_config1 = ClientConfig::new(crypto_config1); + let client_config1 = ClientConfig::new(Arc::new( + QuicClientConfig::try_from(crypto_config1).expect("to succeed"), + )); let client1 = Endpoint::client(SocketAddr::new(IpAddr::V6(Ipv6Addr::UNSPECIFIED), 0)).unwrap(); let connection1 = client1 @@ -532,7 +560,9 @@ mod tests { let crypto_config2 = Arc::new(make_client_config(&Keypair::generate(), Some(peer)).expect("to succeed")); - let client_config2 = ClientConfig::new(crypto_config2); + let client_config2 = ClientConfig::new(Arc::new( + QuicClientConfig::try_from(crypto_config2).expect("to succeed"), + )); let client2 = Endpoint::client(SocketAddr::new(IpAddr::V6(Ipv6Addr::UNSPECIFIED), 0)).unwrap(); let connection2 = client2 diff --git a/src/transport/quic/mod.rs b/src/transport/quic/mod.rs index c05df6c56..5eb57f844 100644 --- a/src/transport/quic/mod.rs +++ b/src/transport/quic/mod.rs @@ -41,7 +41,9 @@ use futures::{ }; use hickory_resolver::TokioResolver; use multiaddr::{Multiaddr, Protocol}; -use quinn::{ClientConfig, Connecting, Connection, Endpoint, IdleTimeout}; +use quinn::{ + crypto::rustls::QuicClientConfig, ClientConfig, Connecting, Connection, Endpoint, IdleTimeout, +}; use std::{ collections::HashMap, @@ -134,7 +136,7 @@ pub(crate) struct QuicTransport { impl QuicTransport { /// Attempt to extract `PeerId` from connection certificates. fn extract_peer_id(connection: &Connection) -> Option { - let certificates: Box> = + let certificates: Box>> = connection.peer_identity()?.downcast().ok()?; let p2p_cert = crate::crypto::tls::certificate::parse(certificates.first()?) .expect("the certificate was validated during TLS handshake; qed"); @@ -288,12 +290,15 @@ impl Transport for QuicTransport { Ok(Ok(address)) => address, }; - let crypto_config = - Arc::new(make_client_config(&keypair, Some(peer)).expect("to succeed")); + let crypto_config = make_client_config(&keypair, Some(peer)).expect("to succeed"); + let quic_crypto = Arc::new( + QuicClientConfig::try_from(crypto_config) + .expect("TLS config to be valid for QUIC; qed"), + ); let mut transport_config = quinn::TransportConfig::default(); let timeout = IdleTimeout::try_from(connection_open_timeout).expect("to succeed"); transport_config.max_idle_timeout(Some(timeout)); - let mut client_config = ClientConfig::new(crypto_config); + let mut client_config = ClientConfig::new(quic_crypto); client_config.transport_config(Arc::new(transport_config)); let client_listen_address = if socket_address.is_ipv4() { @@ -428,12 +433,16 @@ impl Transport for QuicTransport { }; let crypto_config = - Arc::new(make_client_config(&keypair, Some(peer)).expect("to succeed")); + make_client_config(&keypair, Some(peer)).expect("to succeed"); + let quic_crypto = Arc::new( + QuicClientConfig::try_from(crypto_config) + .expect("TLS config to be valid for QUIC; qed"), + ); let mut transport_config = quinn::TransportConfig::default(); let timeout = IdleTimeout::try_from(connection_open_timeout).expect("to succeed"); transport_config.max_idle_timeout(Some(timeout)); - let mut client_config = ClientConfig::new(crypto_config); + let mut client_config = ClientConfig::new(quic_crypto); client_config.transport_config(Arc::new(transport_config)); let client_listen_address = if socket_address.is_ipv4() { @@ -673,7 +682,7 @@ mod tests { }, )]), }; - let resolver = Arc::new(TokioResolver::builder_tokio().unwrap().build()); + let resolver = Arc::new(TokioResolver::builder_tokio().unwrap().build().unwrap()); let (mut transport1, listen_addresses) = QuicTransport::new(handle1, Default::default(), resolver.clone()).unwrap(); diff --git a/src/transport/quic/substream.rs b/src/transport/quic/substream.rs index 8176e6aff..9ec2016e7 100644 --- a/src/transport/quic/substream.rs +++ b/src/transport/quic/substream.rs @@ -84,7 +84,11 @@ impl TokioAsyncRead for Substream { cx: &mut Context<'_>, buf: &mut tokio::io::ReadBuf<'_>, ) -> Poll> { - match futures::ready!(Pin::new(&mut self.recv_stream).poll_read(cx, buf)) { + match futures::ready!(TokioAsyncRead::poll_read( + Pin::new(&mut self.recv_stream), + cx, + buf + )) { Err(error) => Poll::Ready(Err(error)), Ok(res) => { self.bandwidth_sink.increase_inbound(buf.filled().len()); @@ -100,7 +104,13 @@ impl TokioAsyncWrite for Substream { cx: &mut Context<'_>, buf: &[u8], ) -> Poll> { - match futures::ready!(Pin::new(&mut self.send_stream).poll_write(cx, buf)) { + // `quinn::SendStream` has an inherent `poll_write` returning `quinn::WriteError`; call the + // tokio `AsyncWrite` impl explicitly so we keep yielding `io::Error`. + match futures::ready!(TokioAsyncWrite::poll_write( + Pin::new(&mut self.send_stream), + cx, + buf + )) { Err(error) => Poll::Ready(Err(error)), Ok(nwritten) => { self.bandwidth_sink.increase_outbound(nwritten); @@ -110,14 +120,14 @@ impl TokioAsyncWrite for Substream { } fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - Pin::new(&mut self.send_stream).poll_flush(cx) + TokioAsyncWrite::poll_flush(Pin::new(&mut self.send_stream), cx) } fn poll_shutdown( mut self: Pin<&mut Self>, cx: &mut Context<'_>, ) -> Poll> { - Pin::new(&mut self.send_stream).poll_shutdown(cx) + TokioAsyncWrite::poll_shutdown(Pin::new(&mut self.send_stream), cx) } } @@ -151,7 +161,7 @@ impl AsyncRead for NegotiatingSubstream { cx: &mut Context<'_>, buf: &mut [u8], ) -> Poll> { - Pin::new(&mut self.recv_stream).poll_read(cx, buf) + AsyncRead::poll_read(Pin::new(&mut self.recv_stream), cx, buf) } } @@ -161,14 +171,14 @@ impl AsyncWrite for NegotiatingSubstream { cx: &mut Context<'_>, buf: &[u8], ) -> Poll> { - Pin::new(&mut self.send_stream).poll_write(cx, buf) + AsyncWrite::poll_write(Pin::new(&mut self.send_stream), cx, buf) } fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - Pin::new(&mut self.send_stream).poll_flush(cx) + AsyncWrite::poll_flush(Pin::new(&mut self.send_stream), cx) } fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - Pin::new(&mut self.send_stream).poll_close(cx) + AsyncWrite::poll_close(Pin::new(&mut self.send_stream), cx) } } diff --git a/src/transport/tcp/connection.rs b/src/transport/tcp/connection.rs index 7f296952d..290aae952 100644 --- a/src/transport/tcp/connection.rs +++ b/src/transport/tcp/connection.rs @@ -780,7 +780,7 @@ mod tests { use crate::transport::tcp::TcpTransport; use super::*; - use hickory_resolver::{name_server::TokioConnectionProvider, TokioResolver}; + use hickory_resolver::{net::runtime::TokioRuntimeProvider, TokioResolver}; use tokio::{io::AsyncWriteExt, net::TcpListener}; #[tokio::test] @@ -807,9 +807,10 @@ mod tests { Arc::new( TokioResolver::builder_with_config( Default::default(), - TokioConnectionProvider::default(), + TokioRuntimeProvider::default(), ) - .build(), + .build() + .unwrap(), ), ) .await @@ -909,9 +910,10 @@ mod tests { Arc::new( TokioResolver::builder_with_config( Default::default(), - TokioConnectionProvider::default(), + TokioRuntimeProvider::default(), ) - .build(), + .build() + .unwrap(), ), ) .await @@ -1058,9 +1060,10 @@ mod tests { Arc::new( TokioResolver::builder_with_config( Default::default(), - TokioConnectionProvider::default(), + TokioRuntimeProvider::default(), ) - .build(), + .build() + .unwrap(), ), ) .await @@ -1111,9 +1114,10 @@ mod tests { Arc::new( TokioResolver::builder_with_config( Default::default(), - TokioConnectionProvider::default(), + TokioRuntimeProvider::default(), ) - .build(), + .build() + .unwrap(), ), ) .await @@ -1291,9 +1295,10 @@ mod tests { Arc::new( TokioResolver::builder_with_config( Default::default(), - TokioConnectionProvider::default(), + TokioRuntimeProvider::default(), ) - .build(), + .build() + .unwrap(), ), ) .await @@ -1426,9 +1431,10 @@ mod tests { Arc::new( TokioResolver::builder_with_config( Default::default(), - TokioConnectionProvider::default(), + TokioRuntimeProvider::default(), ) - .build(), + .build() + .unwrap(), ), ) .await diff --git a/src/transport/tcp/mod.rs b/src/transport/tcp/mod.rs index 6245b730d..36f5e2b7a 100644 --- a/src/transport/tcp/mod.rs +++ b/src/transport/tcp/mod.rs @@ -772,7 +772,7 @@ mod tests { listen_addresses: vec!["/ip6/::1/tcp/0".parse().unwrap()], ..Default::default() }; - let resolver = Arc::new(TokioResolver::builder_tokio().unwrap().build()); + let resolver = Arc::new(TokioResolver::builder_tokio().unwrap().build().unwrap()); let (mut transport1, listen_addresses) = TcpTransport::new(handle1, transport_config1, resolver.clone()).unwrap(); @@ -868,7 +868,7 @@ mod tests { listen_addresses: vec!["/ip6/::1/tcp/0".parse().unwrap()], ..Default::default() }; - let resolver = Arc::new(TokioResolver::builder_tokio().unwrap().build()); + let resolver = Arc::new(TokioResolver::builder_tokio().unwrap().build().unwrap()); let (mut transport1, listen_addresses) = TcpTransport::new(handle1, transport_config1, resolver.clone()).unwrap(); @@ -955,7 +955,7 @@ mod tests { }, )]), }; - let resolver = Arc::new(TokioResolver::builder_tokio().unwrap().build()); + let resolver = Arc::new(TokioResolver::builder_tokio().unwrap().build().unwrap()); let (mut transport1, _) = TcpTransport::new(handle1, Default::default(), resolver.clone()).unwrap(); @@ -1028,7 +1028,7 @@ mod tests { async fn dial_error_reported_for_outbound_connections() { let mut manager = TransportManagerBuilder::new().build(); let handle = manager.transport_handle(Arc::new(DefaultExecutor {})); - let resolver = Arc::new(TokioResolver::builder_tokio().unwrap().build()); + let resolver = Arc::new(TokioResolver::builder_tokio().unwrap().build().unwrap()); manager.register_transport( SupportedTransport::Tcp, Box::new(crate::transport::dummy::DummyTransport::new()), diff --git a/src/transport/websocket/connection.rs b/src/transport/websocket/connection.rs index 7c1055390..7fc37beb8 100644 --- a/src/transport/websocket/connection.rs +++ b/src/transport/websocket/connection.rs @@ -673,7 +673,7 @@ mod tests { Default::default(), Duration::from_secs(10), false, - Arc::new(TokioResolver::builder_tokio().unwrap().build()), + Arc::new(TokioResolver::builder_tokio().unwrap().build().unwrap()), ) .await .unwrap(); @@ -789,7 +789,7 @@ mod tests { Default::default(), Duration::from_secs(10), false, - Arc::new(TokioResolver::builder_tokio().unwrap().build()), + Arc::new(TokioResolver::builder_tokio().unwrap().build().unwrap()), ) .await .unwrap(); @@ -1061,7 +1061,7 @@ mod tests { Default::default(), Duration::from_secs(10), false, - Arc::new(TokioResolver::builder_tokio().unwrap().build()), + Arc::new(TokioResolver::builder_tokio().unwrap().build().unwrap()), ) .await .unwrap(); @@ -1229,7 +1229,7 @@ mod tests { Default::default(), Duration::from_secs(10), false, - Arc::new(TokioResolver::builder_tokio().unwrap().build()), + Arc::new(TokioResolver::builder_tokio().unwrap().build().unwrap()), ) .await .unwrap(); @@ -1383,7 +1383,7 @@ mod tests { Default::default(), Duration::from_secs(10), false, - Arc::new(TokioResolver::builder_tokio().unwrap().build()), + Arc::new(TokioResolver::builder_tokio().unwrap().build().unwrap()), ) .await .unwrap();