diff --git a/Cargo.lock b/Cargo.lock index 23b6e7d77..c8ad22937 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,15 +2,6 @@ # It is not intended for manual editing. version = 4 -[[package]] -name = "addr2line" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" -dependencies = [ - "gimli", -] - [[package]] name = "adler2" version = "2.0.1" @@ -224,7 +215,7 @@ dependencies = [ "log", "pin-utils", "pkg-config", - "tokio 1.46.1", + "tokio 1.48.0", "winapi", ] @@ -388,7 +379,7 @@ dependencies = [ "serde_urlencoded", "sha1", "sync_wrapper 1.0.2", - "tokio 1.46.1", + "tokio 1.48.0", "tokio-tungstenite 0.28.0", "tower 0.5.2", "tower-layer", @@ -453,7 +444,7 @@ dependencies = [ "serde_core", "serde_html_form", "serde_path_to_error", - "tokio 1.46.1", + "tokio 1.48.0", "tokio-util", "tower-layer", "tower-service", @@ -471,21 +462,6 @@ dependencies = [ "rand 0.8.5", ] -[[package]] -name = "backtrace" -version = "0.3.75" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" -dependencies = [ - "addr2line", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", - "windows-targets 0.52.6", -] - [[package]] name = "base-x" version = "0.2.11" @@ -550,7 +526,7 @@ checksum = "212d8b8e1a22743d9241575c6ba822cf9c8fef34771c86ab7e477a4fbfd254e5" dependencies = [ "futures-util", "parking_lot", - "tokio 1.46.1", + "tokio 1.48.0", ] [[package]] @@ -560,7 +536,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e570e6557cd0f88d28d32afa76644873271a70dc22656df565b2021c4036aa9c" dependencies = [ "bb8", - "tokio 1.46.1", + "tokio 1.48.0", "tokio-postgres", ] @@ -1196,7 +1172,7 @@ dependencies = [ "sha2", "tap", "thiserror 2.0.17", - "tokio 1.46.1", + "tokio 1.48.0", "tokio-rustls", "tracing", "uuid", @@ -1250,12 +1226,12 @@ dependencies = [ "http-body-util", "hyper 1.6.0", "hyper-util", - "ironrdp-acceptor 0.5.0", - "ironrdp-connector 0.5.1", + "ironrdp-acceptor 0.6.0", + "ironrdp-connector 0.6.0", "ironrdp-core", "ironrdp-pdu 0.5.0", "ironrdp-rdcleanpath", - "ironrdp-tokio 0.5.1", + "ironrdp-tokio 0.6.0", "jmux-proxy", "job-queue", "job-queue-libsql", @@ -1290,7 +1266,7 @@ dependencies = [ "terminal-streamer", "thiserror 2.0.17", "time", - "tokio 1.46.1", + "tokio 1.48.0", "tokio-rustls", "tokio-test", "tokio-tungstenite 0.26.2", @@ -1327,7 +1303,7 @@ name = "devolutions-gateway-task" version = "0.0.0" dependencies = [ "async-trait", - "tokio 1.46.1", + "tokio 1.48.0", ] [[package]] @@ -1338,7 +1314,7 @@ dependencies = [ "async-trait", "camino", "devolutions-gateway-task", - "tokio 1.46.1", + "tokio 1.48.0", "tracing", "tracing-appender", "tracing-subscriber", @@ -1374,7 +1350,7 @@ dependencies = [ "serde_json", "sha1", "sha2", - "tokio 1.46.1", + "tokio 1.48.0", "tokio-postgres", "tower 0.5.2", "tower-http 0.5.2", @@ -1425,7 +1401,7 @@ dependencies = [ "schemars", "serde", "serde_json", - "tokio 1.46.1", + "tokio 1.48.0", "tower 0.3.1", "uuid", "win-api-wrappers", @@ -1440,7 +1416,7 @@ dependencies = [ "embed-resource", "fs_extra", "parking_lot", - "tokio 1.46.1", + "tokio 1.48.0", "win-api-wrappers", "windows-core 0.61.2", ] @@ -1465,7 +1441,7 @@ dependencies = [ "tap", "tempfile", "thiserror 2.0.17", - "tokio 1.46.1", + "tokio 1.48.0", "tracing", "win-api-wrappers", "windows 0.61.3", @@ -2058,12 +2034,6 @@ dependencies = [ "polyval", ] -[[package]] -name = "gimli" -version = "0.31.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" - [[package]] name = "glob" version = "0.3.3" @@ -2095,7 +2065,7 @@ dependencies = [ "http 0.2.12", "indexmap 2.10.0", "slab", - "tokio 1.46.1", + "tokio 1.48.0", "tokio-util", "tracing", ] @@ -2114,7 +2084,7 @@ dependencies = [ "http 1.3.1", "indexmap 2.10.0", "slab", - "tokio 1.46.1", + "tokio 1.48.0", "tokio-util", "tracing", ] @@ -2345,7 +2315,7 @@ dependencies = [ "itoa", "pin-project-lite 0.2.16", "socket2 0.5.10", - "tokio 1.46.1", + "tokio 1.48.0", "tower-service", "tracing", "want", @@ -2368,7 +2338,7 @@ dependencies = [ "itoa", "pin-project-lite 0.2.16", "smallvec", - "tokio 1.46.1", + "tokio 1.48.0", "want", ] @@ -2384,7 +2354,7 @@ dependencies = [ "rustls 0.23.33", "rustls-native-certs", "rustls-pki-types", - "tokio 1.46.1", + "tokio 1.48.0", "tokio-rustls", "tower-service", ] @@ -2397,7 +2367,7 @@ checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" dependencies = [ "hyper 0.14.32", "pin-project-lite 0.2.16", - "tokio 1.46.1", + "tokio 1.48.0", "tokio-io-timeout", ] @@ -2410,7 +2380,7 @@ dependencies = [ "bytes 1.10.1", "hyper 0.14.32", "native-tls", - "tokio 1.46.1", + "tokio 1.48.0", "tokio-native-tls", ] @@ -2434,7 +2404,7 @@ dependencies = [ "pin-project-lite 0.2.16", "socket2 0.6.0", "system-configuration", - "tokio 1.46.1", + "tokio 1.48.0", "tower-service", "tracing", "windows-registry", @@ -2650,17 +2620,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "io-uring" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b86e202f00093dcba4275d4636b93ef9dd75d025ae560d2521b45ea28ab49013" -dependencies = [ - "bitflags 2.9.4", - "cfg-if", - "libc", -] - [[package]] name = "ipconfig" version = "0.3.2" @@ -2712,12 +2671,12 @@ dependencies = [ [[package]] name = "ironrdp-acceptor" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad348cb50d990c23b7c6f4f8f4c42b6678d5d0c6d7acd57f14685b41d77d9ff7" +checksum = "a7bbe1fd9a54d5e9669e4006f4840ea89339cebff2a7fb345dc925b17547925b" dependencies = [ - "ironrdp-async 0.5.0", - "ironrdp-connector 0.5.1", + "ironrdp-async 0.6.0", + "ironrdp-connector 0.6.0", "ironrdp-core", "ironrdp-pdu 0.5.0", "ironrdp-svc 0.4.1", @@ -2749,12 +2708,12 @@ dependencies = [ [[package]] name = "ironrdp-async" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bb8b3d345988b6791fd780befc08df35c81a030603e4588c6fb9bf4b14dd3ab" +checksum = "724ce488772b7850f6307b4d82559d87dadb7afdf816a35f6cf6e5a989a716f0" dependencies = [ "bytes 1.10.1", - "ironrdp-connector 0.5.1", + "ironrdp-connector 0.6.0", "ironrdp-core", "ironrdp-pdu 0.5.0", "tracing", @@ -2789,9 +2748,9 @@ dependencies = [ [[package]] name = "ironrdp-connector" -version = "0.5.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "131d5060ff071a244f69e43d3efa19704b2930a41700e0288685d2f3c91d2e28" +checksum = "0cb98a29bdd7ef95b490050ddabe4ddd816e527ea0df9f25cc7a9a30d2584dc1" dependencies = [ "ironrdp-core", "ironrdp-error 0.1.3", @@ -2801,7 +2760,7 @@ dependencies = [ "picky-asn1-der 0.5.2", "picky-asn1-x509 0.14.4", "rand_core 0.6.4", - "sspi 0.15.14", + "sspi 0.16.1", "tracing", "url", ] @@ -2948,7 +2907,7 @@ dependencies = [ "ironrdp-rdpsnd", "ironrdp-svc 0.1.0", "ironrdp-tokio 0.1.0", - "tokio 1.46.1", + "tokio 1.48.0", "tokio-rustls", "tracing", ] @@ -2980,18 +2939,18 @@ source = "git+https://github.com/Devolutions/IronRDP?rev=2e1a9ac88e38e7d92d89300 dependencies = [ "bytes 1.10.1", "ironrdp-async 0.1.0", - "tokio 1.46.1", + "tokio 1.48.0", ] [[package]] name = "ironrdp-tokio" -version = "0.5.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95af93439e7322763477bafd4b153ab64fe29b138f87fe80c188fcfa04634584" +checksum = "6a5815ae4dd7866a6730efb653281406a77fd1f5426d77dd959fc04e3512410f" dependencies = [ "bytes 1.10.1", - "ironrdp-async 0.5.0", - "tokio 1.46.1", + "ironrdp-async 0.6.0", + "tokio 1.48.0", ] [[package]] @@ -3049,7 +3008,7 @@ dependencies = [ "sysinfo", "test-utils", "tinyjson", - "tokio 1.46.1", + "tokio 1.48.0", "tokio-tungstenite 0.26.2", "tracing", "tracing-appender", @@ -3087,7 +3046,7 @@ dependencies = [ "futures-util", "jmux-proto", "socket2 0.5.10", - "tokio 1.46.1", + "tokio 1.48.0", "tokio-util", "tracing", ] @@ -3315,7 +3274,7 @@ dependencies = [ "serde", "serde_json", "thiserror 1.0.69", - "tokio 1.46.1", + "tokio 1.48.0", "tokio-stream", "tokio-util", "tonic", @@ -3414,7 +3373,7 @@ dependencies = [ "prost", "serde", "thiserror 1.0.69", - "tokio 1.46.1", + "tokio 1.48.0", "tokio-stream", "tokio-util", "tonic", @@ -3531,7 +3490,7 @@ version = "0.0.0" dependencies = [ "anyhow", "tinyjson", - "tokio 1.46.1", + "tokio 1.48.0", "tracing", "ureq", ] @@ -3632,7 +3591,7 @@ name = "mock-net" version = "0.0.0" dependencies = [ "loom", - "tokio 1.46.1", + "tokio 1.48.0", ] [[package]] @@ -3661,7 +3620,7 @@ dependencies = [ "pin-project 1.1.10", "rand 0.8.5", "thiserror 1.0.69", - "tokio 1.46.1", + "tokio 1.48.0", "tokio-util", "tracing", ] @@ -3744,7 +3703,7 @@ dependencies = [ "futures", "libc", "log", - "tokio 1.46.1", + "tokio 1.48.0", ] [[package]] @@ -3768,7 +3727,7 @@ dependencies = [ "network-scanner-net", "thiserror 2.0.17", "time", - "tokio 1.46.1", + "tokio 1.48.0", "tokio-util", "tracing", ] @@ -3791,7 +3750,7 @@ dependencies = [ "rtnetlink", "socket2 0.5.10", "thiserror 2.0.17", - "tokio 1.46.1", + "tokio 1.48.0", "tracing", "tracing-subscriber", "typed-builder", @@ -3807,7 +3766,7 @@ dependencies = [ "polling 3.8.0", "socket2 0.5.10", "thiserror 2.0.17", - "tokio 1.46.1", + "tokio 1.48.0", "tracing", "tracing-cov-mark", "tracing-subscriber", @@ -3842,7 +3801,7 @@ dependencies = [ "serde", "serde_json", "thiserror 1.0.69", - "tokio 1.46.1", + "tokio 1.48.0", "tokio-retry", "tokio-util", "tracing", @@ -4067,15 +4026,6 @@ dependencies = [ "objc2-core-foundation", ] -[[package]] -name = "object" -version = "0.36.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" -dependencies = [ - "memchr", -] - [[package]] name = "oid" version = "0.2.1" @@ -4844,7 +4794,7 @@ dependencies = [ "proptest", "proxy-generators", "proxy-types", - "tokio 1.46.1", + "tokio 1.48.0", ] [[package]] @@ -4854,7 +4804,7 @@ dependencies = [ "proxy-http", "proxy-socks", "proxy-types", - "tokio 1.46.1", + "tokio 1.48.0", ] [[package]] @@ -4864,7 +4814,7 @@ dependencies = [ "proptest", "proxy-generators", "proxy-types", - "tokio 1.46.1", + "tokio 1.48.0", "tokio-test", ] @@ -4874,7 +4824,7 @@ version = "0.0.0" dependencies = [ "proxy-http", "proxy-socks", - "tokio 1.46.1", + "tokio 1.48.0", ] [[package]] @@ -4915,7 +4865,7 @@ dependencies = [ "rustls 0.23.33", "socket2 0.5.10", "thiserror 2.0.17", - "tokio 1.46.1", + "tokio 1.48.0", "tracing", "web-time", ] @@ -5158,7 +5108,7 @@ dependencies = [ "serde_json", "serde_urlencoded", "sync_wrapper 1.0.2", - "tokio 1.46.1", + "tokio 1.48.0", "tokio-rustls", "tokio-util", "tower 0.5.2", @@ -5292,15 +5242,9 @@ dependencies = [ "netlink-sys", "nix 0.27.1", "thiserror 1.0.69", - "tokio 1.46.1", + "tokio 1.48.0", ] -[[package]] -name = "rustc-demangle" -version = "0.1.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f" - [[package]] name = "rustc-hash" version = "1.1.0" @@ -5936,7 +5880,7 @@ dependencies = [ "sha1", "sha2", "time", - "tokio 1.46.1", + "tokio 1.48.0", "tracing", "url", "uuid", @@ -5949,9 +5893,9 @@ dependencies = [ [[package]] name = "sspi" -version = "0.15.14" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "214ee905dcdd4b7ab11404b616e58dc6944d80fe8592fbdc13abc87d7e2bff0a" +checksum = "523f6a99e26c1e6476a424d54bbda5354a01ee7f18b9d93dc48a8fd45ae8189b" dependencies = [ "async-dnssd", "async-recursion", @@ -5981,7 +5925,7 @@ dependencies = [ "sha1", "sha2", "time", - "tokio 1.46.1", + "tokio 1.48.0", "tracing", "url", "uuid", @@ -6176,7 +6120,7 @@ name = "terminal-streamer" version = "0.1.0" dependencies = [ "anyhow", - "tokio 1.46.1", + "tokio 1.48.0", "tracing", ] @@ -6194,7 +6138,7 @@ dependencies = [ "futures-util", "portpicker", "proptest", - "tokio 1.46.1", + "tokio 1.48.0", "tokio-tungstenite 0.26.2", "transport", ] @@ -6219,7 +6163,7 @@ dependencies = [ "sysevent-winevent", "tempfile", "test-utils", - "tokio 1.46.1", + "tokio 1.48.0", "tokio-rustls", "tokio-tungstenite 0.26.2", "typed-builder", @@ -6382,23 +6326,20 @@ dependencies = [ [[package]] name = "tokio" -version = "1.46.1" +version = "1.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cc3a2344dafbe23a245241fe8b09735b521110d30fcefbbd5feb1797ca35d17" +checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" dependencies = [ - "backtrace", "bytes 1.10.1", - "io-uring", "libc", "mio", "parking_lot", "pin-project-lite 0.2.16", "signal-hook-registry", - "slab", - "socket2 0.5.10", + "socket2 0.6.0", "tokio-macros", "tracing", - "windows-sys 0.52.0", + "windows-sys 0.61.1", ] [[package]] @@ -6408,14 +6349,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf" dependencies = [ "pin-project-lite 0.2.16", - "tokio 1.46.1", + "tokio 1.48.0", ] [[package]] name = "tokio-macros" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" +checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" dependencies = [ "proc-macro2 1.0.95", "quote 1.0.40", @@ -6429,7 +6370,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" dependencies = [ "native-tls", - "tokio 1.46.1", + "tokio 1.48.0", ] [[package]] @@ -6453,7 +6394,7 @@ dependencies = [ "postgres-types", "rand 0.9.1", "socket2 0.6.0", - "tokio 1.46.1", + "tokio 1.48.0", "tokio-util", "whoami", ] @@ -6466,7 +6407,7 @@ checksum = "7f57eb36ecbe0fc510036adff84824dd3c24bb781e21bfa67b69d556aa85214f" dependencies = [ "pin-project 1.1.10", "rand 0.8.5", - "tokio 1.46.1", + "tokio 1.48.0", ] [[package]] @@ -6476,7 +6417,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" dependencies = [ "rustls 0.23.33", - "tokio 1.46.1", + "tokio 1.48.0", ] [[package]] @@ -6487,7 +6428,7 @@ checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" dependencies = [ "futures-core", "pin-project-lite 0.2.16", - "tokio 1.46.1", + "tokio 1.48.0", ] [[package]] @@ -6499,7 +6440,7 @@ dependencies = [ "async-stream", "bytes 1.10.1", "futures-core", - "tokio 1.46.1", + "tokio 1.48.0", "tokio-stream", ] @@ -6515,7 +6456,7 @@ dependencies = [ "rustls 0.23.33", "rustls-native-certs", "rustls-pki-types", - "tokio 1.46.1", + "tokio 1.48.0", "tokio-native-tls", "tokio-rustls", "tungstenite 0.26.2", @@ -6529,7 +6470,7 @@ checksum = "d25a406cddcc431a75d3d9afc6a7c0f7428d4891dd973e4d54c56b46127bf857" dependencies = [ "futures-util", "log", - "tokio 1.46.1", + "tokio 1.48.0", "tungstenite 0.28.0", ] @@ -6544,7 +6485,7 @@ dependencies = [ "futures-io", "futures-sink", "pin-project-lite 0.2.16", - "tokio 1.46.1", + "tokio 1.48.0", ] [[package]] @@ -6622,7 +6563,7 @@ dependencies = [ "percent-encoding", "pin-project 1.1.10", "prost", - "tokio 1.46.1", + "tokio 1.48.0", "tokio-stream", "tower 0.4.13", "tower-layer", @@ -6681,7 +6622,7 @@ dependencies = [ "pin-project-lite 0.2.16", "rand 0.8.5", "slab", - "tokio 1.46.1", + "tokio 1.48.0", "tokio-util", "tower-layer", "tower-service", @@ -6698,7 +6639,7 @@ dependencies = [ "futures-util", "pin-project-lite 0.2.16", "sync_wrapper 1.0.2", - "tokio 1.46.1", + "tokio 1.48.0", "tower-layer", "tower-service", "tracing", @@ -6767,7 +6708,7 @@ dependencies = [ "mime_guess", "percent-encoding", "pin-project-lite 0.2.16", - "tokio 1.46.1", + "tokio 1.48.0", "tokio-util", "tower-layer", "tower-service", @@ -6980,7 +6921,7 @@ dependencies = [ "async-trait", "libsql", "tempfile", - "tokio 1.46.1", + "tokio 1.48.0", "tracing", "traffic-audit", "uuid", @@ -6999,7 +6940,7 @@ dependencies = [ "pin-project-lite 0.2.16", "proptest", "test-utils", - "tokio 1.46.1", + "tokio 1.48.0", "tracing", ] @@ -7233,9 +7174,9 @@ dependencies = [ [[package]] name = "uuid" -version = "1.17.0" +version = "1.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d" +checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2" dependencies = [ "getrandom 0.3.3", "js-sys", @@ -7273,7 +7214,7 @@ dependencies = [ "futures-util", "num_cpus", "thiserror 2.0.17", - "tokio 1.46.1", + "tokio 1.48.0", "tokio-tungstenite 0.26.2", "tokio-util", "tracing", @@ -7755,6 +7696,15 @@ dependencies = [ "windows-targets 0.53.2", ] +[[package]] +name = "windows-sys" +version = "0.61.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f109e41dd4a3c848907eb83d5a42ea98b3769495597450cf6d153507b166f0f" +dependencies = [ + "windows-link 0.2.0", +] + [[package]] name = "windows-targets" version = "0.42.2" diff --git a/devolutions-gateway/Cargo.toml b/devolutions-gateway/Cargo.toml index 280442959..32810c2b1 100644 --- a/devolutions-gateway/Cargo.toml +++ b/devolutions-gateway/Cargo.toml @@ -37,9 +37,9 @@ sysevent-codes.path = "../crates/sysevent-codes" ironrdp-pdu = { version = "0.5", features = ["std"] } ironrdp-core = { version = "0.1", features = ["std"] } ironrdp-rdcleanpath = "0.1" -ironrdp-tokio = "0.5" -ironrdp-connector = { version = "0.5" } -ironrdp-acceptor = { version = "0.5" } +ironrdp-tokio = "0.6" +ironrdp-connector = { version = "0.6" } +ironrdp-acceptor = { version = "0.6" } ceviche = "0.7" picky-krb = "0.11" diff --git a/devolutions-gateway/src/api/kdc_proxy.rs b/devolutions-gateway/src/api/kdc_proxy.rs index 29017d74f..0943302e7 100644 --- a/devolutions-gateway/src/api/kdc_proxy.rs +++ b/devolutions-gateway/src/api/kdc_proxy.rs @@ -11,6 +11,7 @@ use tokio::net::{TcpStream, UdpSocket}; use crate::DgwState; use crate::http::{HttpError, HttpErrorBuilder}; +use crate::target_addr::TargetAddr; use crate::token::AccessTokenClaims; pub fn make_router(state: DgwState) -> Router { @@ -87,11 +88,55 @@ async fn kdc_proxy( &claims.krb_kdc }; + let kdc_reply_message = send_krb_message(kdc_addr, &kdc_proxy_message.kerb_message.0.0).await?; + + let kdc_reply_message = KdcProxyMessage::from_raw_kerb_message(&kdc_reply_message) + .map_err(HttpError::internal().with_msg("couldn’t create KDC proxy reply").err())?; + + trace!(?kdc_reply_message, "Sending back KDC reply"); + + kdc_reply_message.to_vec().map_err(HttpError::internal().err()) +} + +async fn read_kdc_reply_message(connection: &mut TcpStream) -> io::Result> { + let len = connection.read_u32().await?; + let mut buf = vec![0; (len + 4).try_into().expect("u32-to-usize")]; + buf[0..4].copy_from_slice(&(len.to_be_bytes())); + connection.read_exact(&mut buf[4..]).await?; + Ok(buf) +} + +#[track_caller] +fn unable_to_reach_kdc_server_err(error: io::Error) -> HttpError { + use io::ErrorKind; + + let builder = match error.kind() { + ErrorKind::TimedOut => HttpErrorBuilder::new(StatusCode::GATEWAY_TIMEOUT), + ErrorKind::ConnectionRefused => HttpError::bad_gateway(), + ErrorKind::ConnectionAborted => HttpError::bad_gateway(), + ErrorKind::ConnectionReset => HttpError::bad_gateway(), + ErrorKind::BrokenPipe => HttpError::bad_gateway(), + ErrorKind::OutOfMemory => HttpError::internal(), + // FIXME: once stabilized use new IO error variants + // - https://github.com/rust-lang/rust/pull/106375 + // - https://github.com/rust-lang/rust/issues/86442 + // ErrorKind::NetworkDown => HttpErrorBuilder::new(StatusCode::SERVICE_UNAVAILABLE), + // ErrorKind::NetworkUnreachable => HttpError::bad_gateway(), + // ErrorKind::HostUnreachable => HttpError::bad_gateway(), + // TODO: When the above is applied, we can return an internal error in the fallback branch. + _ => HttpError::bad_gateway(), + }; + + builder.with_msg("unable to reach KDC server").build(error) +} + +/// Sends the Kerberos message to the specified KDC address. +pub async fn send_krb_message(kdc_addr: &TargetAddr, message: &[u8]) -> Result, HttpError> { let protocol = kdc_addr.scheme(); debug!("Connecting to KDC server located at {kdc_addr} using protocol {protocol}..."); - let kdc_reply_message = if protocol == "tcp" { + if protocol == "tcp" { #[allow(clippy::redundant_closure)] // We get a better caller location for the error by using a closure. let mut connection = TcpStream::connect(kdc_addr.as_addr()).await.map_err(|e| { error!(%kdc_addr, "failed to connect to KDC server"); @@ -100,22 +145,19 @@ async fn kdc_proxy( trace!("Connected! Forwarding KDC message..."); - connection - .write_all(&kdc_proxy_message.kerb_message.0.0) - .await - .map_err( - HttpError::bad_gateway() - .with_msg("unable to send the message to the KDC server") - .err(), - )?; + connection.write_all(message).await.map_err( + HttpError::bad_gateway() + .with_msg("unable to send the message to the KDC server") + .err(), + )?; trace!("Reading KDC reply..."); - read_kdc_reply_message(&mut connection).await.map_err( + Ok(read_kdc_reply_message(&mut connection).await.map_err( HttpError::bad_gateway() .with_msg("unable to read KDC reply message") .err(), - )? + )?) } else { // We assume that ticket length is not bigger than 2048 bytes. let mut buf = [0; 2048]; @@ -133,7 +175,7 @@ async fn kdc_proxy( // First 4 bytes contains message length. We don't need it for UDP. #[allow(clippy::redundant_closure)] // We get a better caller location for the error by using a closure. udp_socket - .send_to(&kdc_proxy_message.kerb_message.0.0[4..], kdc_addr.as_addr()) + .send_to(&message[4..], kdc_addr.as_addr()) .await .map_err(|e| unable_to_reach_kdc_server_err(e))?; @@ -148,45 +190,7 @@ async fn kdc_proxy( let mut reply_buf = Vec::new(); reply_buf.extend_from_slice(&u32::try_from(n).expect("n not too big").to_be_bytes()); reply_buf.extend_from_slice(&buf[0..n]); - reply_buf - }; - - let kdc_reply_message = KdcProxyMessage::from_raw_kerb_message(&kdc_reply_message) - .map_err(HttpError::internal().with_msg("couldn’t create KDC proxy reply").err())?; - - trace!(?kdc_reply_message, "Sending back KDC reply"); - - kdc_reply_message.to_vec().map_err(HttpError::internal().err()) -} - -async fn read_kdc_reply_message(connection: &mut TcpStream) -> io::Result> { - let len = connection.read_u32().await?; - let mut buf = vec![0; (len + 4).try_into().expect("u32-to-usize")]; - buf[0..4].copy_from_slice(&(len.to_be_bytes())); - connection.read_exact(&mut buf[4..]).await?; - Ok(buf) -} - -#[track_caller] -fn unable_to_reach_kdc_server_err(error: io::Error) -> HttpError { - use io::ErrorKind; - let builder = match error.kind() { - ErrorKind::TimedOut => HttpErrorBuilder::new(StatusCode::GATEWAY_TIMEOUT), - ErrorKind::ConnectionRefused => HttpError::bad_gateway(), - ErrorKind::ConnectionAborted => HttpError::bad_gateway(), - ErrorKind::ConnectionReset => HttpError::bad_gateway(), - ErrorKind::BrokenPipe => HttpError::bad_gateway(), - ErrorKind::OutOfMemory => HttpError::internal(), - // FIXME: once stabilized use new IO error variants - // - https://github.com/rust-lang/rust/pull/106375 - // - https://github.com/rust-lang/rust/issues/86442 - // ErrorKind::NetworkDown => HttpErrorBuilder::new(StatusCode::SERVICE_UNAVAILABLE), - // ErrorKind::NetworkUnreachable => HttpError::bad_gateway(), - // ErrorKind::HostUnreachable => HttpError::bad_gateway(), - // TODO: When the above is applied, we can return an internal error in the fallback branch. - _ => HttpError::bad_gateway(), - }; - - builder.with_msg("unable to reach KDC server").build(error) + Ok(reply_buf) + } } diff --git a/devolutions-gateway/src/config.rs b/devolutions-gateway/src/config.rs index 6270a44b7..682ba2ae5 100644 --- a/devolutions-gateway/src/config.rs +++ b/devolutions-gateway/src/config.rs @@ -1137,6 +1137,55 @@ pub mod dto { } } + /// Domain user credentials. + #[derive(PartialEq, Eq, Debug, Clone, Serialize, Deserialize)] + pub struct DomainUser { + /// Username in FQDN format (e.g. "pw13@example.com"). + pub username: String, + /// User password. + pub password: String, + /// Salt for generating the user's key. + /// + /// Usually, it is equal to `{REALM}{username}` (e.g. "EXAMPLEpw13"). + pub salt: String, + } + + /// Kerberos server config + /// + /// This config is used to configure the Kerberos server during RDP proxying. + #[derive(PartialEq, Eq, Debug, Clone, Serialize, Deserialize)] + pub struct KerberosServer { + /// KDC and Kerberos Application Server realm. + /// + /// For example, `cd9bee03-b0aa-49dd-bad7-568b595c8024.jet`. + pub realm: String, + /// Users credentials inside fake KDC. + pub users: Vec, + /// The maximum allowed time difference between client and proxy clocks + /// + /// The value is expressed in seconds. + pub max_time_skew: u64, + /// krbtgt service key. + /// + /// This key is used to encrypt/decrypt TGT tickets. + pub krbtgt_key: Vec, + /// Ticket decryption key + /// + /// This key is used to decrypt the TGS ticket sent by the client. If you do not plan + /// to use Kerberos U2U authentication, then the `ticket_decryption_key` is required. + pub ticket_decryption_key: Option>, + /// The domain user credentials for the Kerberos U2U authentication + /// + /// This field is needed only for Kerberos User-to-User authentication. If you do not plan + /// to use Kerberos U2U, do not specify it. + pub service_user: Option, + /// KDC server url. + /// + /// **Only TCP and UDP schemas are supported.** + /// If the DNS is configured, you can omit it. + pub kdc_url: Option, + } + /// Unsafe debug options that should only ever be used at development stage /// /// These options might change or get removed without further notice. @@ -1177,6 +1226,11 @@ pub mod dto { #[serde(default = "ws_keep_alive_interval_default_value")] pub ws_keep_alive_interval: u64, + /// Kerberos application server configuration + /// + /// It is used only during RDP proxying. + pub kerberos_server: Option, + /// Enable unstable features which may break at any point #[serde(default)] pub enable_unstable: bool, @@ -1194,6 +1248,7 @@ pub mod dto { capture_path: None, lib_xmf_path: None, enable_unstable: false, + kerberos_server: None, ws_keep_alive_interval: ws_keep_alive_interval_default_value(), } } diff --git a/devolutions-gateway/src/rdp_proxy.rs b/devolutions-gateway/src/rdp_proxy.rs index fce931d80..5fd63e74a 100644 --- a/devolutions-gateway/src/rdp_proxy.rs +++ b/devolutions-gateway/src/rdp_proxy.rs @@ -1,13 +1,25 @@ use std::net::{IpAddr, SocketAddr}; use std::sync::Arc; +use std::time::Duration; +use crate::api::kdc_proxy::send_krb_message; use crate::config::Conf; +use crate::config::dto::{DomainUser, KerberosServer}; use crate::credential::{AppCredentialMapping, ArcCredentialEntry}; use crate::proxy::Proxy; use crate::session::{DisconnectInterest, SessionInfo, SessionMessageSender}; use crate::subscriber::SubscriberSender; +use crate::target_addr::TargetAddr; use anyhow::Context as _; +use ironrdp_acceptor::credssp::CredsspProcessGenerator as CredsspServerProcessGenerator; +use ironrdp_connector::credssp::{CredsspProcessGenerator as CredsspClientProcessGenerator, KerberosConfig}; +use ironrdp_connector::sspi::credssp::{ClientState, ServerError, ServerState}; +use ironrdp_connector::sspi::generator::{GeneratorState, NetworkRequest}; +use ironrdp_connector::sspi::kerberos::ServerProperties; +use ironrdp_connector::sspi::{ + self, AuthIdentityBuffers, CredentialsBuffers, KerberosConfig as SspiKerberosConfig, KerberosServerConfig, +}; use ironrdp_pdu::{mcs, nego, x224}; use tokio::io::{AsyncRead, AsyncWrite, AsyncWriteExt}; use typed_builder::TypedBuilder; @@ -63,13 +75,14 @@ where .tls .as_ref() .context("TLS configuration required for credential injection feature")?; + let gateway_hostname = conf.hostname.clone(); let credential_mapping = credential_entry.mapping.as_ref().context("no credential mapping")?; // -- Retrieve the Gateway TLS public key that must be used for client-proxy CredSSP later on -- // let gateway_public_key_handle = tokio::spawn(get_cached_gateway_public_key( - conf.hostname.clone(), + gateway_hostname.clone(), tls_conf.acceptor.clone(), )); @@ -103,20 +116,87 @@ where let mut client_framed = ironrdp_tokio::TokioFramed::new(client_stream); let mut server_framed = ironrdp_tokio::TokioFramed::new(server_stream); + let (krb_server_config, network_client) = if conf.debug.enable_unstable + && let Some(KerberosServer { + realm: _, + users: _, + krbtgt_key: _, + max_time_skew, + ticket_decryption_key, + service_user, + kdc_url: _, + }) = conf.debug.kerberos_server.as_ref() + { + let user = service_user.as_ref().map(|user| { + let DomainUser { + username, + password, + salt: _, + } = user; + // The username is in the FQDN format. Thus, the domain field can be empty. + CredentialsBuffers::AuthIdentity(AuthIdentityBuffers::from_utf8(username, "", password)) + }); + + ( + Some(KerberosServerConfig { + kerberos_config: SspiKerberosConfig { + // The sspi-rs can automatically resolve the KDC host via DNS and/or env variable. + kdc_url: None, + client_computer_name: Some(client_addr.to_string()), + }, + server_properties: ServerProperties::new( + &["TERMSRV", &gateway_hostname], + user, + Duration::from_secs(*max_time_skew), + ticket_decryption_key.clone(), + )?, + }), + Some(NetworkClient::new()), + ) + } else { + (None, None) + }; + let client_credssp_fut = perform_credssp_with_client( &mut client_framed, client_addr.ip(), gateway_public_key, handshake_result.client_security_protocol, &credential_mapping.proxy, + network_client, + krb_server_config, ); + let (krb_client_config, network_client) = if conf.debug.enable_unstable + && let Some(KerberosServer { + realm: _, + users: _, + krbtgt_key: _, + max_time_skew: _, + ticket_decryption_key: _, + service_user: _, + kdc_url, + }) = conf.debug.kerberos_server.as_ref() + { + ( + Some(KerberosConfig { + kdc_proxy_url: kdc_url.clone(), + hostname: None, + }), + Some(NetworkClient::new()), + ) + } else { + (None, None) + }; + let server_credssp_fut = perform_credssp_with_server( &mut server_framed, server_dns_name, server_public_key, handshake_result.server_security_protocol, &credential_mapping.target, + krb_client_config, + network_client, ); let (client_credssp_res, server_credssp_res) = tokio::join!(client_credssp_fut, server_credssp_fut); @@ -323,6 +403,8 @@ async fn perform_credssp_with_server( server_public_key: Vec, security_protocol: nego::SecurityProtocol, credentials: &crate::credential::AppCredential, + kerberos_config: Option, + network_client: Option, ) -> anyhow::Result<()> where S: ironrdp_tokio::FramedRead + ironrdp_tokio::FramedWrite, @@ -344,15 +426,21 @@ where security_protocol, ironrdp_connector::ServerName::new(server_name), server_public_key, - None, + kerberos_config, )?; let mut buf = ironrdp_pdu::WriteBuf::new(); loop { - let mut generator = sequence.process_ts_request(ts_request); - let client_state = generator.resolve_to_result().context("sspi generator resolve")?; - drop(generator); + let client_state = { + let mut generator = sequence.process_ts_request(ts_request); + + if let Some(network_client_ref) = network_client.as_ref() { + resolve_client_generator(&mut generator, network_client_ref).await? + } else { + generator.resolve_to_result().context("sspi generator resolve")? + } + }; // drop generator buf.clear(); let written = sequence.handle_process_result(client_state, &mut buf)?; @@ -381,6 +469,49 @@ where Ok(()) } +async fn resolve_server_generator( + generator: &mut CredsspServerProcessGenerator<'_>, + network_client: &NetworkClient, +) -> Result { + let mut state = generator.start(); + + loop { + match state { + GeneratorState::Suspended(request) => { + let response = network_client.send(&request).await.map_err(|err| ServerError { + ts_request: None, + error: sspi::Error::new(sspi::ErrorKind::InternalError, err), + })?; + state = generator.resume(Ok(response)); + } + GeneratorState::Completed(client_state) => { + break client_state; + } + } + } +} + +async fn resolve_client_generator( + generator: &mut CredsspClientProcessGenerator<'_>, + network_client: &NetworkClient, +) -> anyhow::Result { + let mut state = generator.start(); + + loop { + match state { + GeneratorState::Suspended(request) => { + let response = network_client.send(&request).await?; + state = generator.resume(Ok(response)); + } + GeneratorState::Completed(client_state) => { + break Ok(client_state.map_err(|e| { + ironrdp_connector::ConnectorError::new("CredSSP", ironrdp_connector::ConnectorErrorKind::Credssp(e)) + })?); + } + }; + } +} + #[instrument(name = "client_credssp", level = "debug", ret, skip_all)] async fn perform_credssp_with_client( framed: &mut ironrdp_tokio::Framed, @@ -388,6 +519,8 @@ async fn perform_credssp_with_client( gateway_public_key: Vec, security_protocol: nego::SecurityProtocol, credentials: &crate::credential::AppCredential, + network_client: Option, + kerberos_server_config: Option, ) -> anyhow::Result<()> where S: ironrdp_tokio::FramedRead + ironrdp_tokio::FramedWrite, @@ -401,7 +534,16 @@ where // But this does not seem to matter so far, so we stringify the IP address of the client instead. let client_computer_name = ironrdp_connector::ServerName::new(client_addr.to_string()); - let result = credssp_loop(framed, &mut buf, client_computer_name, gateway_public_key, credentials).await; + let result = credssp_loop( + framed, + &mut buf, + client_computer_name, + gateway_public_key, + credentials, + network_client, + kerberos_server_config, + ) + .await; if security_protocol.intersects(nego::SecurityProtocol::HYBRID_EX) { trace!(?result, "HYBRID_EX"); @@ -426,21 +568,27 @@ where client_computer_name: ironrdp_connector::ServerName, public_key: Vec, credentials: &crate::credential::AppCredential, + network_client: Option, + kerberos_server_config: Option, ) -> anyhow::Result<()> where S: ironrdp_tokio::FramedRead + ironrdp_tokio::FramedWrite, { let crate::credential::AppCredential::UsernamePassword { username, password } = credentials; - let username = ironrdp_connector::sspi::Username::parse(username).context("invalid username")?; + let username = sspi::Username::parse(username).context("invalid username")?; - let identity = ironrdp_connector::sspi::AuthIdentity { + let identity = sspi::AuthIdentity { username, password: password.expose_secret().to_owned().into(), }; - let mut sequence = - ironrdp_acceptor::credssp::CredsspSequence::init(&identity, client_computer_name, public_key, None)?; + let mut sequence = ironrdp_acceptor::credssp::CredsspSequence::init( + &identity, + client_computer_name, + public_key, + kerberos_server_config, + )?; loop { let Some(next_pdu_hint) = sequence.next_pdu_hint()? else { @@ -456,7 +604,16 @@ where break; }; - let result = sequence.process_ts_request(ts_request); + let result = { + let mut generator = sequence.process_ts_request(ts_request); + + if let Some(network_client_ref) = network_client.as_ref() { + resolve_server_generator(&mut generator, network_client_ref).await + } else { + generator.resolve_to_result() + } + }; // drop generator + buf.clear(); let written = sequence.handle_process_result(result, buf)?; @@ -574,3 +731,19 @@ where framed.write_all(&payload).await.context("failed to write PDU")?; Ok(()) } + +struct NetworkClient; + +impl NetworkClient { + fn new() -> Self { + Self {} + } + + async fn send(&self, request: &NetworkRequest) -> anyhow::Result> { + let target_addr = TargetAddr::parse(request.url.as_str(), Some(88))?; + + send_krb_message(&target_addr, &request.data) + .await + .map_err(|err| anyhow::Error::msg("failed to send KDC message").context(err)) + } +}