From fc929e268f30ea6ec889dc69441ec143cea9d88a Mon Sep 17 00:00:00 2001 From: Leonard Hecker Date: Wed, 4 Nov 2026 21:46:41 +0100 Subject: [PATCH] Update all dependencies --- .cargo/config.toml | 23 +- .cargo/ms-toolchain-config.toml | 47 ++-- Cargo.lock | 452 +++++++++++++++++--------------- Cargo.toml | 47 ++-- sudo/Cargo.toml | 60 ++--- sudo/build.rs | 4 +- sudo/src/elevate_handler.rs | 8 +- sudo/src/helpers.rs | 236 ++++++----------- sudo/src/logging_bindings.rs | 6 +- sudo/src/main.rs | 191 ++++++-------- sudo/src/rpc_bindings.rs | 2 +- sudo/src/rpc_bindings_server.rs | 12 +- sudo/src/run_handler.rs | 17 +- sudo/src/tests/mod.rs | 5 +- sudo/sudo.rc | 20 -- 15 files changed, 504 insertions(+), 626 deletions(-) diff --git a/.cargo/config.toml b/.cargo/config.toml index 12854ce..f333e7b 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,22 +1,9 @@ -# -Ccontrol-flow-guard: Enable Control Flow Guard, needed for OneBranch's post-build analysis (https://learn.microsoft.com/en-us/cpp/build/reference/guard-enable-control-flow-guard). [target.'cfg(target_os = "windows")'] rustflags = [ - "-Dwarnings", - "-Ccontrol-flow-guard", "-Ctarget-feature=+crt-static", - "-Clink-args=/DEFAULTLIB:ucrt.lib /NODEFAULTLIB:vcruntime.lib /NODEFAULTLIB:msvcrt.lib /NODEFAULTLIB:libucrt.lib" + "-Clink-args=/DEFAULTLIB:ucrt.lib", + "-Clink-args=/NODEFAULTLIB:vcruntime.lib", + "-Clink-args=/NODEFAULTLIB:msvcrt.lib", + "-Clink-args=/NODEFAULTLIB:libucrt.lib", + "-lrpcrt4", ] - -# This fixes the following linker error on x86: -# error LNK2019: unresolved external symbol _NdrClientCall4 referenced in function ... -[target.'cfg(all(target_os = "windows", target_arch = "x86"))'] -rustflags = ["-Clink-args=/DEFAULTLIB:rpcrt4.lib"] - -# -Clink-args=/DYNAMICBASE /CETCOMPAT: Enable "shadow stack" (https://learn.microsoft.com/en-us/cpp/build/reference/cetcompat) -[target.'cfg(all(target_os = "windows", any(target_arch = "x86", target_arch = "x86_64")))'] -rustflags = ["-Clink-args=/DYNAMICBASE /CETCOMPAT"] - -[registries] -Sudo_PublicPackages = { index = "sparse+https://pkgs.dev.azure.com/shine-oss/sudo/_packaging/Sudo_PublicPackages/Cargo/index/" } -[source.crates-io] -replace-with = "Sudo_PublicPackages" diff --git a/.cargo/ms-toolchain-config.toml b/.cargo/ms-toolchain-config.toml index c0ede21..ee4c139 100644 --- a/.cargo/ms-toolchain-config.toml +++ b/.cargo/ms-toolchain-config.toml @@ -1,25 +1,40 @@ -# -Cehcont_guard: Enable EH Continuation Metadata (https://learn.microsoft.com/en-us/cpp/build/reference/guard-enable-eh-continuation-metadata). -# -Ccontrol-flow-guard: Enable Control Flow Guard, needed for OneBranch's post-build analysis (https://learn.microsoft.com/en-us/cpp/build/reference/guard-enable-control-flow-guard). +global-credential-providers = [ + "artifacts-cargo-credprovider", + "cargo:token", + "cargo:wincred", +] + +[registries] +Sudo_PublicPackages = { index = "sparse+https://pkgs.dev.azure.com/shine-oss/sudo/_packaging/Sudo_PublicPackages/Cargo/index/" } + +[source.crates-io] +replace-with = "Sudo_PublicPackages" + [target.'cfg(target_os = "windows")'] rustflags = [ + "-Dwarnings", "-Cehcont_guard", - "-Ccontrol-flow-guard", + "-Ccontrol_flow_guard", "-Ctarget-feature=+crt-static", - "-Clink-args=/DEFAULTLIB:ucrt.lib /NODEFAULTLIB:vcruntime.lib /NODEFAULTLIB:msvcrt.lib /NODEFAULTLIB:libucrt.lib" + "-Clink-args=/DEFAULTLIB:ucrt.lib", + "-Clink-args=/NODEFAULTLIB:vcruntime.lib", + "-Clink-args=/NODEFAULTLIB:msvcrt.lib", + "-Clink-args=/NODEFAULTLIB:libucrt.lib", + "-lrpcrt4", ] -# This fixes the following linker error on x86: -# error LNK2019: unresolved external symbol _NdrClientCall4 referenced in function ... -[target.'cfg(all(target_os = "windows", target_arch = "x86"))'] -rustflags = ["-Clink-args=/DEFAULTLIB:rpcrt4.lib"] - # -Clink-args=/DYNAMICBASE /CETCOMPAT: Enable "shadow stack" (https://learn.microsoft.com/en-us/cpp/build/reference/cetcompat) [target.'cfg(all(target_os = "windows", any(target_arch = "x86", target_arch = "x86_64")))'] -rustflags = ["-Clink-args=/DYNAMICBASE /CETCOMPAT"] +rustflags = [ + "-Clink-args=/DYNAMICBASE", + "-Clink-args=/CETCOMPAT", +] -# Setup the ADO Artifacts feed as a Registry: you'll need to use your own feed in your project that upstreams from crates.io. -# For more details see https://eng.ms/docs/cloud-ai-platform/devdiv/one-engineering-system-1es/1es-docs/azure-artifacts/cargo -[registries] -Sudo_PublicPackages = { index = "sparse+https://pkgs.dev.azure.com/shine-oss/sudo/_packaging/Sudo_PublicPackages/Cargo/index/" } -[source.crates-io] -replace-with = "Sudo_PublicPackages" +# The backtrace code for panics in Rust is almost as large as the entire editor. +# = Huge reduction in binary size by removing all that. +[profile.release] +panic = "immediate-abort" + +[unstable] +panic-immediate-abort = true +build-std = ["std", "panic_abort"] diff --git a/Cargo.lock b/Cargo.lock index bf42bf8..111bc32 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,93 +4,96 @@ version = 4 [[package]] name = "anstream" -version = "0.6.12" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96b09b5178381e0874812a9b157f7fe84982617e48f71f4e3235482775e5b540" +checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", + "is_terminal_polyfill", "utf8parse", ] [[package]] name = "anstyle" -version = "1.0.6" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" [[package]] name = "anstyle-parse" -version = "0.2.3" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.2" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ "windows-sys", ] [[package]] name = "anstyle-wincon" -version = "3.0.2" +version = "3.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", + "once_cell_polyfill", "windows-sys", ] [[package]] name = "bitflags" -version = "1.3.2" +version = "2.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +checksum = "3ded4057c258ba199e2d26386d3af3780957ecaee6c4ef4041c6b4b8b97c0b06" [[package]] -name = "bitflags" -version = "2.4.2" +name = "bumpalo" +version = "3.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" - -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" [[package]] name = "cc" -version = "1.2.27" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d487aa071b5f64da6f19a3e848e3578944b726ee5a4854b82172f02aa876bfdc" +checksum = "375989decec1a0fa424442bed520fa12ede43a48475ce8c7417d2c69b32b5f6b" dependencies = [ + "find-msvc-tools", "shlex", ] +[[package]] +name = "cfg-if" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7648175b45a9a48536d676f68d918270699102aa8dab5496df06904c914600" + [[package]] name = "clap" -version = "4.5.1" +version = "4.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c918d541ef2913577a0f9566e9ce27cb35b6df072075769e0b26cb5a554520da" +checksum = "aa8876b300ab35ba921adea3dfd70157a46249b33f95c9084ae5709785478946" dependencies = [ "clap_builder", ] [[package]] name = "clap_builder" -version = "4.5.1" +version = "4.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f3e7391dad68afb0c2ede1bf619f579a3dc9c2ec67f089baa397123a2f3d1eb" +checksum = "ec0797fb7aeb1406c84efac526901f7ec3ead2124f946b494e72879d4b54704d" dependencies = [ "anstream", "anstyle", @@ -99,127 +102,157 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" +checksum = "1c133bc6a41be0d194c306b5506d15e6feeea7b1d6604bd3f8310dfb2ca96486" [[package]] name = "colorchoice" -version = "1.0.0" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" [[package]] -name = "either" -version = "1.10.0" +name = "embed-manifest" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" +checksum = "ba92c8f4591bf29f89716b45e5f5f56577adbb81426e5620c6e994da7c88bb7a" [[package]] -name = "embed-manifest" -version = "1.4.0" +name = "find-msvc-tools" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41cd446c890d6bed1d8b53acef5f240069ebef91d6fae7c5f52efe61fe8b5eae" +checksum = "1c66915cc5391097de7a2b0b972e8505aa33c0df401fd3a6811dbdb32881ba48" [[package]] -name = "errno" -version = "0.3.8" +name = "futures-core" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +checksum = "92d699e522242e69e3003b94ecc1f960f3a5e015aa7c5d7486e65ad01dd94f5e" + +[[package]] +name = "futures-task" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd417de3d1d015fc3bfd2b1ea46dfc7bab72ef86f1cc7cc9c78e728b34a6d1fd" + +[[package]] +name = "futures-util" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d50a92467f8ba5dd6e3ee5d4bd04d73ab2e4e1c44474a0674821dfce14b79bc" dependencies = [ - "libc", - "windows-sys", + "futures-core", + "futures-task", + "pin-project-lite", + "slab", ] [[package]] -name = "home" -version = "0.5.9" +name = "is_terminal_polyfill" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" + +[[package]] +name = "js-sys" +version = "0.3.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8dc09d2154098bbf4ef54eab6b117a3c24cbbffe94046b16ee6d6d4510584d3a" dependencies = [ - "windows-sys", + "cfg-if", + "futures-util", + "wasm-bindgen", ] [[package]] name = "libc" -version = "0.2.174" +version = "0.2.191" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" +checksum = "65cd87c9a6d60536580b316ad985726104730a5151c99845f2490428ef91240a" [[package]] -name = "linux-raw-sys" -version = "0.4.13" +name = "once_cell_polyfill" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" [[package]] -name = "once_cell" -version = "1.19.0" +name = "pin-project-lite" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" [[package]] name = "proc-macro2" -version = "1.0.78" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" +checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.35" +version = "1.0.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001" dependencies = [ "proc-macro2", ] [[package]] -name = "rustix" -version = "0.38.31" +name = "rustversion" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f" + +[[package]] +name = "serde" +version = "1.0.229" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" +checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba" dependencies = [ - "bitflags 2.4.2", - "errno", - "libc", - "linux-raw-sys", - "windows-sys", + "serde_core", ] [[package]] -name = "serde" -version = "1.0.196" +name = "serde_core" +version = "1.0.229" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32" +checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.196" +version = "1.0.229" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67" +checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" dependencies = [ "proc-macro2", "quote", - "syn 2.0.49", + "syn 3.0.9", ] [[package]] name = "sha1_smol" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" +checksum = "bbfa15b3dddfee50a0fff136974b3e1bde555604ba463834a7eb7deb6417705d" [[package]] name = "shlex" -version = "1.3.0" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" + +[[package]] +name = "slab" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "sudo" @@ -232,7 +265,6 @@ dependencies = [ "which", "win32resources", "windows", - "windows-registry", "winres", ] @@ -246,9 +278,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.109" +version = "2.0.119" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297" dependencies = [ "proc-macro2", "quote", @@ -257,9 +289,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.49" +version = "3.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "915aea9e586f80826ee59f8453c1101f9d1c4b3964cd2460185ee8e299ada496" +checksum = "d78c8dee4c7bf0e14673097256fed6142ce9d3b85a408189d07482442145823b" dependencies = [ "proc-macro2", "quote", @@ -277,52 +309,85 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "a2c754d6c33795a1c324727428e5a7dedb5b06195f9890bdbcba760d3e246563" [[package]] name = "utf8parse" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.7.0" +version = "1.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a" +checksum = "4a0e2d11620c50695fe12bbbfde96b3477fe606e7284c22d505c12ce51214514" dependencies = [ + "js-sys", "sha1_smol", + "wasm-bindgen", ] [[package]] -name = "w32-error" -version = "1.0.0" +name = "wasm-bindgen" +version = "0.2.130" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0181c14ddd6c7b8b0b0132a5f1ea2f32be0d893cd3ea97b6e3b28886b8a3d1c" +dependencies = [ + "cfg-if", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.130" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e931a02a39abdbf66966fc35902b5ed58344750a70885bed4ebb3d8eaf28ed9" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.130" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ca4b54280e455bd831e33a6b8e734baf432fe63fbc35c42ac14ce67a043a53a" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn 3.0.9", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.130" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7c61a6bd91e168c12fc170985725340f6b458eb6f971d1cf6c34f74ffafb43" +checksum = "3b1f9c3798725016c6ee5f2f57869ec0831e8bbc0ab0310a86e787e97f41389e" dependencies = [ - "winapi", + "unicode-ident", ] [[package]] name = "which" -version = "6.0.0" +version = "8.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fa5e0c10bf77f44aac573e498d1a82d5fbd5e91f6fc0a99e7be4b38e85e101c" +checksum = "bae2f2b2b816647a1cab1acc91f5bd20812d53cb344382635ec2181940c8034f" dependencies = [ - "either", - "home", - "once_cell", - "rustix", - "windows-sys", + "libc", ] [[package]] name = "widestring" -version = "1.0.2" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "653f141f39ec16bba3c5abe400a0c60da7468261cc2cbf36805022876bc721a8" +checksum = "72069c3113ab32ab29e5584db3c6ec55d416895e60715417b5b883a357c3e471" [[package]] name = "win32resources" @@ -330,197 +395,157 @@ version = "0.1.0" [[package]] name = "win_etw_macros" -version = "0.1.9" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ec5071e615bb8b34c39dc852f82df53f29cb7108a93324a7101f7b2e6284b0e" +checksum = "8ceb3b134affad802f6509077e40a4fc4982981a4687ce020d0b03779b589642" dependencies = [ "proc-macro2", "quote", "sha1_smol", - "syn 1.0.109", + "syn 2.0.119", "uuid", "win_etw_metadata", ] [[package]] name = "win_etw_metadata" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e50d0fa665033a19ecefd281b4fb5481eba2972dedbb5ec129c9392a206d652f" +checksum = "f5113ede807966842887ba64b2bba9e1079e19efaea612b6e83449af29b4b194" dependencies = [ - "bitflags 1.3.2", + "bitflags", ] [[package]] name = "win_etw_provider" -version = "0.1.9" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7f61e9dfafedf5eb4348902f2a32d326f2371245d05f012cdc67b9251ad6ea3" +checksum = "d57b25caee8f665da0fb8c9b47b3b0d34752c90436ea9c6c97030e3bf80ca527" dependencies = [ - "w32-error", "widestring", "win_etw_metadata", - "winapi", + "windows-sys", "zerocopy", ] [[package]] -name = "winapi" -version = "0.3.9" +name = "windows" +version = "0.62.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +checksum = "527fadee13e0c05939a6a05d5bd6eec6cd2e3dbd648b9f8e447c6518133d8580" dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", + "windows-collections", + "windows-core", + "windows-future", + "windows-numerics", ] [[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" +name = "windows-collections" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "windows" -version = "0.57.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12342cb4d8e3b046f3d80effd474a7a02447231330ef77d71daa6fbc40681143" +checksum = "23b2d95af1a8a14a3c7367e1ed4fc9c20e0a26e79551b1454d72583c97cc6610" dependencies = [ "windows-core", - "windows-targets", ] [[package]] name = "windows-core" -version = "0.57.0" +version = "0.62.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2ed2439a290666cd67ecce2b0ffaad89c2a56b976b736e6ece670297897832d" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" dependencies = [ "windows-implement", "windows-interface", + "windows-link", "windows-result", - "windows-targets", + "windows-strings", +] + +[[package]] +name = "windows-future" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1d6f90251fe18a279739e78025bd6ddc52a7e22f921070ccdc67dde84c605cb" +dependencies = [ + "windows-core", + "windows-link", + "windows-threading", ] [[package]] name = "windows-implement" -version = "0.57.0" +version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.49", + "syn 2.0.119", ] [[package]] name = "windows-interface" -version = "0.57.0" +version = "0.59.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.49", + "syn 2.0.119", ] [[package]] -name = "windows-registry" -version = "0.1.0" +name = "windows-link" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e885d2dff8cad07e7451b78eac1ff62f958825c4598d6ddf87e7d2661980c1c" -dependencies = [ - "windows-result", - "windows-targets", -] +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] -name = "windows-result" -version = "0.1.1" +name = "windows-numerics" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "749f0da9cc72d82e600d8d2e44cadd0b9eedb9038f71a1c58556ac1c5791813b" +checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26" dependencies = [ - "windows-targets", + "windows-core", + "windows-link", ] [[package]] -name = "windows-sys" -version = "0.52.0" +name = "windows-result" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" dependencies = [ - "windows-targets", + "windows-link", ] [[package]] -name = "windows-targets" -version = "0.52.5" +name = "windows-strings" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows-link", ] [[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.5" +name = "windows-sys" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] [[package]] -name = "windows_x86_64_msvc" -version = "0.52.5" +name = "windows-threading" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" +checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37" +dependencies = [ + "windows-link", +] [[package]] name = "winres" @@ -533,21 +558,20 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.7.32" +version = "0.8.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +checksum = "e5fe1f8f1b06191a00962174c61aa5005e0bb391a6d80d07e24d115c01a92ed8" dependencies = [ - "byteorder", "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.32" +version = "0.8.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +checksum = "863ad3ac83293fb4d740aedbfdc9240dd8d1a50c1099acd76ce80ce7c7230c7f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.49", + "syn 2.0.119", ] diff --git a/Cargo.toml b/Cargo.toml index 47edb88..13ce501 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,39 +7,26 @@ members = [ "win32resources", ] -# This list of dependencies allows us to specify version numbers for dependency in a single place. -# The dependencies in this list are _not_ automatically added to crates (Cargo.toml files). -# Each individual Cargo.toml file must explicitly declare its dependencies. To use a dependency -# from this list, specify "foo.workspace = true". For example: -# -# [dependencies] -# log.workspace = true -# -# See: https://doc.rust-lang.org/cargo/reference/workspaces.html#the-dependencies-table -# [workspace.dependencies] cc = "1.2" -# We're disabling the default features for clap because we don't need the -# "suggestions" feature. That provides really amazing suggestions for typos, but -# it unfortunately does not seem to support localization. -# -# To use clap at all, you do need the std feature enabled, so enable that. -# -# See: https://docs.rs/clap/latest/clap/_features/index.html -clap = { version = "4.4.7", default-features = false, features = ["std"] } +clap = { version = "4.4", default-features = false, features = ["std"] } embed-manifest = "1.4" -which = "6.0" -win_etw_provider = "0.1.8" -win_etw_macros = "0.1.8" -windows = "0.57" -windows-registry = "0.1" +which = "8.0" +win_etw_provider = "0.1" +win_etw_macros = "0.1" +windows = "0.62" winres = "0.1" -# For more profile settings, and details on the ones below, see https://doc.rust-lang.org/cargo/reference/profiles.html#profile-settings [profile.release] -# Enable full debug info for optimized builds. -debug = "full" -# Split debuginfo into its own file to reduce binary size. -split-debuginfo = "packed" -lto = true -panic = "abort" +codegen-units = 1 # reduces binary size by ~2% +debug = "full" # No one needs an undebuggable release binary +lto = true # reduces binary size by ~14% +opt-level = 3 # reduces binary size by ~25% +panic = "abort" # reduces binary size by ~50% in combination with -Zbuild-std-features=panic_immediate_abort +split-debuginfo = "packed" # generates a separate *.dwp/*.dSYM so the binary can get stripped +strip = "symbols" # See split-debuginfo - allows us to drop the size by ~65% +incremental = true # Improves re-compile times + +[profile.bench] +codegen-units = 16 # Make compiling criterion faster (16 is the default, but profile.release sets it to 1) +lto = "thin" # Similarly, speed up linking by a ton diff --git a/sudo/Cargo.toml b/sudo/Cargo.toml index c09c8dd..6e2755a 100644 --- a/sudo/Cargo.toml +++ b/sudo/Cargo.toml @@ -12,45 +12,45 @@ test = true name = "sudo" [build-dependencies] -winres.workspace = true -cc.workspace = true -embed-manifest.workspace = true +winres = { workspace = true } +cc = { workspace = true } +embed-manifest = { workspace = true } which = { workspace = true } [dependencies] clap = { workspace = true, default-features = false, features = ["color", "help", "usage", "error-context"] } which = { workspace = true } -windows-registry = { workspace = true } sudo_events = { path = "../sudo_events" } win32resources = { path = "../win32resources" } - -[dependencies.windows] -workspace = true -features = [ - "Wdk_Foundation", - "Wdk_System_Threading", - "Win32_Foundation", - "Win32_Globalization", - "Win32_Security", - "Win32_Security_Authorization", - "Win32_Storage_FileSystem", - "Win32_System_Console", - "Win32_System_Diagnostics_Debug", - "Win32_System_Diagnostics_Etw", - "Win32_System_Environment", - "Win32_System_Kernel", - "Win32_System_Memory", - "Win32_System_Registry", - "Win32_System_Rpc", - "Win32_System_SystemInformation", - "Win32_System_SystemServices", - "Win32_System_Threading", - "Win32_System_WindowsProgramming", - "Win32_UI_Shell", - "Win32_UI_WindowsAndMessaging", -] +windows = { + workspace = true, + features = [ + "Wdk_Foundation", + "Wdk_System_Threading", + "Win32_Foundation", + "Win32_Globalization", + "Win32_Security_Authorization", + "Win32_Security_Cryptography", + "Win32_Security", + "Win32_Storage_FileSystem", + "Win32_System_Console", + "Win32_System_Diagnostics_Debug", + "Win32_System_Diagnostics_Etw", + "Win32_System_Environment", + "Win32_System_Kernel", + "Win32_System_Memory", + "Win32_System_Registry", + "Win32_System_Rpc", + "Win32_System_SystemInformation", + "Win32_System_SystemServices", + "Win32_System_Threading", + "Win32_System_WindowsProgramming", + "Win32_UI_Shell", + "Win32_UI_WindowsAndMessaging", + ], +} [features] # We attempt to use feature flags in a similar way to how the rest of the diff --git a/sudo/build.rs b/sudo/build.rs index 78557b2..44358fe 100644 --- a/sudo/build.rs +++ b/sudo/build.rs @@ -26,7 +26,7 @@ fn get_sdk_path() -> Option { // the path to the appropriate midl.exe in it. let link_exe = cc::windows_registry::find_tool(target.as_str(), "link.exe") .expect("Failed to find link.exe"); - link_exe.env().iter().for_each(|(k, v)| { + link_exe.get_envs().for_each(|(k, v)| { if k == "PATH" { let elements = (v.to_str().expect("path exploded")) .split(';') @@ -295,7 +295,7 @@ fn main() -> io::Result<()> { // witchcraft to get windows.h from the SDK to be able to be found, for the resource compiler let target = env::var("TARGET").unwrap(); if let Some(tool) = cc::windows_registry::find_tool(target.as_str(), "cl.exe") { - for (key, value) in tool.env() { + for (key, value) in tool.get_envs() { env::set_var(key, value); } } diff --git a/sudo/src/elevate_handler.rs b/sudo/src/elevate_handler.rs index 82f1d4e..2876f96 100644 --- a/sudo/src/elevate_handler.rs +++ b/sudo/src/elevate_handler.rs @@ -28,14 +28,14 @@ fn handle_to_stdio(h: HANDLE) -> Stdio { /// Prepare the target process, spawn it, and hand back the Child process. This will take care of setting up the handles for redirected input/output, and setting the environment variables. pub fn spawn_target_for_request(request: &ElevateRequest) -> Result { - tracing::trace_log_message(&format!("Spawning: {}...", &request.application)); + tracing::trace_log_message(&format!("Spawning: {}...", request.application)); let mut command_args = std::process::Command::new(request.application.clone()); command_args.current_dir(request.target_dir.clone()); command_args.args(request.args.clone()); - tracing::trace_log_message(&format!("args: {:?}", &request.args)); + tracing::trace_log_message(&format!("args: {:?}", request.args)); if !request.env_vars.is_empty() { command_args.env_clear(); @@ -83,8 +83,8 @@ pub fn handle_elevation_request(request: &ElevateRequest) -> Result allowed_mode { tracing::trace_log_message(&format!( "Requested sudo mode is not allowed: {:?} ({:?})", diff --git a/sudo/src/helpers.rs b/sudo/src/helpers.rs index eec5817..b491e29 100644 --- a/sudo/src/helpers.rs +++ b/sudo/src/helpers.rs @@ -11,7 +11,9 @@ use std::slice::{from_raw_parts, from_raw_parts_mut}; use windows::Win32::Storage::FileSystem::GetFullPathNameW; use windows::Win32::System::Diagnostics::Debug::{IMAGE_NT_HEADERS32, IMAGE_SUBSYSTEM}; use windows::Win32::System::Environment::{FreeEnvironmentStringsW, GetEnvironmentStringsW}; -use windows::Win32::System::Rpc::RPC_STATUS; +use windows::Win32::System::Registry::{ + RegGetValueW, RegSetKeyValueW, HKEY, HKEY_LOCAL_MACHINE, REG_DWORD, RRF_RT_REG_DWORD, +}; use windows::Win32::System::SystemServices::{ IMAGE_DOS_HEADER, IMAGE_DOS_SIGNATURE, IMAGE_NT_SIGNATURE, SE_TOKEN_USER, SE_TOKEN_USER_1, }; @@ -20,10 +22,6 @@ use windows::{ Win32::System::Console::*, Win32::System::Threading::*, }; -// https://github.com/microsoft/win32metadata/issues/1857 -pub const RPC_S_ACCESS_DENIED: RPC_STATUS = RPC_STATUS(ERROR_ACCESS_DENIED.0 as i32); - -pub const E_FILENOTFOUND: HRESULT = ERROR_FILE_NOT_FOUND.to_hresult(); pub const E_CANCELLED: HRESULT = ERROR_CANCELLED.to_hresult(); pub const MSG_DIR_BAD_COMMAND_OR_FILE: WIN32_ERROR = WIN32_ERROR(9009); pub const E_DIR_BAD_COMMAND_OR_FILE: HRESULT = MSG_DIR_BAD_COMMAND_OR_FILE.to_hresult(); @@ -82,7 +80,7 @@ impl Drop for OwnedLocalAlloc { unsafe { let ptr: HLOCAL = std::mem::transmute_copy(self); if !ptr.0.is_null() { - LocalFree(ptr); + LocalFree(Some(ptr)); } } } @@ -197,7 +195,7 @@ pub fn get_current_user() -> Result { let mut str_sid = OwnedLocalAlloc::default(); ConvertSidToStringSidW(PSID(&user.Sid as *const _ as _), &mut *str_sid)?; - str_sid.to_hstring() + Ok(str_sid.to_hstring()) } } @@ -393,63 +391,89 @@ pub fn unpack_string_list_from_rpc(args: Utf8Str) -> Result> { .collect()) } -pub trait ConfigProvider { - fn get_setting_mode(&self) -> Result; - fn get_policy_mode(&self) -> Result; -} - -#[derive(Default)] -pub struct RegistryConfigProvider; -impl ConfigProvider for RegistryConfigProvider { - fn get_setting_mode(&self) -> Result { - windows_registry::LOCAL_MACHINE - .open("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Sudo") - .and_then(|key| key.get_u32("Enabled")) - } - fn get_policy_mode(&self) -> Result { - windows_registry::LOCAL_MACHINE - .open("SOFTWARE\\Policies\\Microsoft\\Windows\\Sudo") - .and_then(|key| key.get_u32("Enabled")) +pub fn reg_get_u32(key: HKEY, subkey: PCWSTR, value: PCWSTR) -> Result> { + let mut data = 0u32; + let mut size = size_of_val(&data) as _; + let res = unsafe { + RegGetValueW( + key, + subkey, + value, + RRF_RT_REG_DWORD, + None, + Some(&raw mut data as _), + Some(&raw mut size), + ) + }; + if res.is_err() { + if res == ERROR_FILE_NOT_FOUND { + Ok(None) + } else { + Err(res.into()) + } + } else { + Ok(Some(data)) } } -/// Get the current mode allowed by policy. -/// * If the policy isn't set (we fail to read the reg key), we'll return Ok(3) -/// (to indicate that all modes up to inline are allowed). -/// * If the policy is set, we'll return the value from the policy. -/// * If we fail to read the policy for any other reason, we'll return an error -/// (which should be treated as "disabled by policy") -pub fn get_allowed_mode_from_policy(config: &impl ConfigProvider) -> Result { - match config.get_policy_mode() { - Ok(v) => v.min(3).try_into(), - // This is okay! No policy state really means that it's _not_ disabled by policy. - Err(e) if e.code() == E_FILENOTFOUND => Ok(SudoMode::Normal), - Err(e) => Err(e), - } +pub fn reg_set_u32(key: HKEY, subkey: PCWSTR, value: PCWSTR, data: u32) -> Result<()> { + unsafe { + RegSetKeyValueW( + key, + subkey, + value, + REG_DWORD.0, + Some(&raw const data as _), + size_of_val(&data) as _, + ) + .ok()? + }; + Ok(()) } -/// Get the current setting mode from the registry. If the setting isn't there, -/// we're disabled. If we fail to read the setting, we're disabled. Errors -/// should be treated as disabled. -pub fn get_setting_mode(config: &impl ConfigProvider) -> Result { - match config.get_setting_mode() { - Ok(v) => v.min(3).try_into(), - Err(e) if e.code() == E_FILENOTFOUND => Ok(SudoMode::Disabled), - Err(e) => Err(e), - } -} +pub struct PolicyConfig { + pub policy_mode: SudoMode, + pub setting_mode: SudoMode, + pub allowed_mode: SudoMode, +} + +impl PolicyConfig { + pub fn from_registry() -> Result { + // Get the current mode allowed by policy. + // * If the policy isn't set (we fail to read the reg key), we'll return Ok(3) + // (to indicate that all modes up to inline are allowed). + // * If the policy is set, we'll return the value from the policy. + // * If we fail to read the policy for any other reason, we'll return an error + // (which should be treated as "disabled by policy") + let policy_mode = reg_get_u32( + HKEY_LOCAL_MACHINE, + w!(r"SOFTWARE\Policies\Microsoft\Windows\Sudo"), + w!("Enabled"), + )?; -pub fn get_allowed_mode(config: &impl ConfigProvider) -> Result { - let allowed_mode_from_policy = get_allowed_mode_from_policy(config)?; - if allowed_mode_from_policy == SudoMode::Disabled { - return Err(E_ACCESS_DISABLED_BY_POLICY.into()); - } - let setting_mode = get_setting_mode(config).unwrap_or(SudoMode::Disabled); + // Get the current setting mode from the registry. If the setting isn't there, + // we're disabled. If we fail to read the setting, we're disabled. Errors + // should be treated as disabled. + let setting_mode = reg_get_u32( + HKEY_LOCAL_MACHINE, + w!(r"SOFTWARE\Microsoft\Windows\CurrentVersion\Sudo"), + w!("Enabled"), + )?; + + let policy_mode = policy_mode + .and_then(|v| v.try_into().ok()) + .unwrap_or(SudoMode::Normal); + + let setting_mode = setting_mode + .and_then(|v| v.try_into().ok()) + .unwrap_or(SudoMode::Disabled); - SudoMode::try_from(std::cmp::min::( - allowed_mode_from_policy.into(), - setting_mode.into(), - )) + Ok(Self { + policy_mode, + setting_mode, + allowed_mode: policy_mode.min(setting_mode), + }) + } } pub fn get_process_path_from_handle(process: HANDLE) -> Result { @@ -521,7 +545,7 @@ pub fn absolute_path(path: &Path) -> Result { // GetFullPathNameW will return the required buffer size if the buffer is too small. let res = unsafe { GetFullPathNameW(&lpfilename, Some(buffer.as_mut_slice()), None) }; match res as usize { - 0 => return Err(Error::from_win32()), // returns GLE + 0 => return Err(Error::from_thread()), // returns GLE len if len <= buffer.len() => { return Ok(PathBuf::from(OsString::from_wide(&buffer[..len]))) } @@ -635,100 +659,4 @@ mod tests { get_exe_subsystem(r"C:\Windows\notepad.exe") ); } - - /// config tests - struct TestConfigProvider { - setting_mode: Result, - policy_mode: Result, - } - - impl ConfigProvider for TestConfigProvider { - fn get_setting_mode(&self) -> Result { - self.setting_mode.clone() - } - fn get_policy_mode(&self) -> Result { - self.policy_mode.clone() - } - } - - #[test] - fn test_get_allowed_mode_from_policy() { - // no setting at all - let config = TestConfigProvider { - setting_mode: Err(E_FILENOTFOUND.into()), - policy_mode: Err(E_FILENOTFOUND.into()), - }; - assert_eq!(get_setting_mode(&config).unwrap(), SudoMode::Disabled); - assert_eq!( - get_allowed_mode_from_policy(&config).unwrap(), - SudoMode::Normal - ); - assert_eq!(get_allowed_mode(&config).unwrap(), SudoMode::Disabled); - - // Setting set to 3 (normal), but policy only allows 2 (disable input) - let config = TestConfigProvider { - setting_mode: Ok(3), - policy_mode: Ok(2), - }; - assert_eq!(get_setting_mode(&config).unwrap(), SudoMode::Normal); - assert_eq!( - get_allowed_mode_from_policy(&config).unwrap(), - SudoMode::DisableInput - ); - assert_eq!(get_allowed_mode(&config).unwrap(), SudoMode::DisableInput); - - // policy is out of range - let config = TestConfigProvider { - setting_mode: Ok(3), - policy_mode: Ok(4), - }; - assert_eq!(get_setting_mode(&config).unwrap(), SudoMode::Normal); - assert_eq!( - get_allowed_mode_from_policy(&config).unwrap(), - SudoMode::Normal - ); - assert_eq!(get_allowed_mode(&config).unwrap(), SudoMode::Normal); - - // entirely disabled by policy - let config = TestConfigProvider { - setting_mode: Ok(3), - policy_mode: Ok(0), - }; - assert_eq!(get_setting_mode(&config).unwrap(), SudoMode::Normal); - assert_eq!( - get_allowed_mode_from_policy(&config).unwrap(), - SudoMode::Disabled - ); - assert_eq!( - get_allowed_mode(&config), - Err(E_ACCESS_DISABLED_BY_POLICY.into()) - ); - - // No policy config found - let config = TestConfigProvider { - setting_mode: Ok(3), - policy_mode: Err(E_FILENOTFOUND.into()), - }; - assert_eq!(get_setting_mode(&config).unwrap(), SudoMode::Normal); - assert_eq!( - get_allowed_mode_from_policy(&config).unwrap(), - SudoMode::Normal - ); - assert_eq!(get_allowed_mode(&config).unwrap(), SudoMode::Normal); - - // not set, but disabled by policy - let config = TestConfigProvider { - setting_mode: Err(E_FILENOTFOUND.into()), - policy_mode: Ok(0), - }; - assert_eq!(get_setting_mode(&config).unwrap(), SudoMode::Disabled); - assert_eq!( - get_allowed_mode_from_policy(&config).unwrap(), - SudoMode::Disabled - ); - assert_eq!( - get_allowed_mode(&config), - Err(E_ACCESS_DISABLED_BY_POLICY.into()) - ); - } } diff --git a/sudo/src/logging_bindings.rs b/sudo/src/logging_bindings.rs index c40346a..2ce9223 100644 --- a/sudo/src/logging_bindings.rs +++ b/sudo/src/logging_bindings.rs @@ -17,11 +17,11 @@ extern "C" { #[repr(transparent)] #[derive(Default)] -struct OwnedReghandle(pub u64); +struct OwnedReghandle(pub REGHANDLE); impl Drop for OwnedReghandle { fn drop(&mut self) { - if self.0 != 0 { + if self.0 .0 != 0 { unsafe { EventUnregister(self.0); } @@ -30,7 +30,7 @@ impl Drop for OwnedReghandle { } impl Deref for OwnedReghandle { - type Target = u64; + type Target = REGHANDLE; fn deref(&self) -> &Self::Target { &self.0 diff --git a/sudo/src/main.rs b/sudo/src/main.rs index 5765012..c06ffd5 100644 --- a/sudo/src/main.rs +++ b/sudo/src/main.rs @@ -16,42 +16,43 @@ use helpers::*; use run_handler::run_target; use std::env; use tracing::*; -use windows::{core::*, Win32::Foundation::*, Win32::System::Console::*}; +use windows::{ + core::*, + Win32::{ + Foundation::*, + System::{Console::*, Registry::HKEY_LOCAL_MACHINE}, + }, +}; // Clap does provide a nice macro for args, which defines args with a syntax // close to what the actual help text would be. Unfortunately, we're not using // that macro, because it doesn't play well with localization. The comments // throughout here help show how the macro would have worked. -fn sudo_cli(allowed_mode: i32) -> Command { - const POLICY_DENIED_LABEL: i32 = E_ACCESS_DISABLED_BY_POLICY.0; - +fn sudo_cli(config: &PolicyConfig) -> Command { let mut app = Command::new(env!("CARGO_CRATE_NAME")); - match allowed_mode { - 0 => { - // In this case, our error message has some VT in it, so we need to - // turn VT on before we eventually print the message. Fortunately, - // the `check_enabled_or_bail` will make sure to enable & restore VT - // mode before printing that error. - - // Sudo is disabled. We want to inform them when they see the help text. - app = app - .about(r::IDS_SUDONAME.get()) - .long_about(r::IDS_DISABLEDLONGABOUT.get()) - .override_help(r::IDS_DISABLEDLONGABOUT.get()); - } - POLICY_DENIED_LABEL => { - // Sudo is disabled by policy. The help text will be more specific. - app = app - .about(r::IDS_SUDONAME.get()) - .long_about(r::IDS_DISABLEDBYPOLICY.get()) - .override_help(r::IDS_DISABLEDBYPOLICY.get()); - } - _ => { - // Sudo is enabled. The help text will be standard. - app = app - .about(r::IDS_SUDONAME.get()) - .long_about(r::IDS_LONGABOUT.get()); - } + + if config.policy_mode == SudoMode::Disabled { + // Sudo is disabled by policy. The help text will be more specific. + app = app + .about(r::IDS_SUDONAME.get()) + .long_about(r::IDS_DISABLEDBYPOLICY.get()) + .override_help(r::IDS_DISABLEDBYPOLICY.get()); + } else if config.allowed_mode == SudoMode::Disabled { + // In this case, our error message has some VT in it, so we need to + // turn VT on before we eventually print the message. Fortunately, + // the `check_enabled_or_bail` will make sure to enable & restore VT + // mode before printing that error. + + // Sudo is disabled. We want to inform them when they see the help text. + app = app + .about(r::IDS_SUDONAME.get()) + .long_about(r::IDS_DISABLEDLONGABOUT.get()) + .override_help(r::IDS_DISABLEDLONGABOUT.get()); + } else { + // Sudo is enabled. The help text will be standard. + app = app + .about(r::IDS_SUDONAME.get()) + .long_about(r::IDS_LONGABOUT.get()); } app = app @@ -185,81 +186,33 @@ fn run_args() -> Vec { args } -fn log_modes(requested_mode: Option) { - let config: RegistryConfigProvider = Default::default(); - let setting_mode = get_setting_mode(&config).unwrap_or(SudoMode::Disabled) as u32; - let policy_mode = { - let policy_enabled = windows_registry::LOCAL_MACHINE - .open("SOFTWARE\\Policies\\Microsoft\\Windows\\Sudo") - .and_then(|key| key.get_u32("Enabled")); - if let Err(e) = &policy_enabled { - if e.code() == E_FILENOTFOUND { - 0xffffffff - } else { - 0 - } - } else { - policy_enabled.unwrap_or(0) - } - }; +fn log_modes(config: &PolicyConfig, requested_mode: Option) { // Trace "disabled" as "they didn't pass a mode manually". trace_modes( requested_mode.unwrap_or(SudoMode::Disabled) as u32, - setting_mode, - policy_mode, + config.setting_mode as u32, + config.policy_mode as u32, ); } -fn check_enabled_or_bail() -> SudoMode { - let config: RegistryConfigProvider = Default::default(); +fn check_enabled_or_bail(config: &PolicyConfig) -> SudoMode { // First things first: Make sure we're enabled. - match get_allowed_mode(&config) { - Err(e) => { - if e.code() == E_ACCESSDENIED { - // Any time you want to use IDS_DISABLEDLONGABOUT, make sure you turned on VT first - let mode = enable_vt(); - eprintln!("{}", r::IDS_DISABLEDLONGABOUT.get()); - _ = restore_console_mode(mode); - } else if e.code() == ERROR_ACCESS_DISABLED_BY_POLICY.into() { - eprintln!("{}", r::IDS_DISABLEDBYPOLICY.get()); - } else { - eprintln!("{} {}", r::IDS_UNKNOWNERROR.get(), e); - } - std::process::exit(e.code().0); - } - Ok(SudoMode::Disabled) => { - // Any time you want to use IDS_DISABLEDLONGABOUT, make sure you turned on VT first - let mode = enable_vt(); - eprintln!("{}", r::IDS_DISABLEDLONGABOUT.get()); - _ = restore_console_mode(mode); - std::process::exit(E_ACCESSDENIED.0); - } - Ok(mode) => mode, + if config.policy_mode == SudoMode::Disabled { + eprintln!("{}", r::IDS_DISABLEDBYPOLICY.get()); + std::process::exit(E_ACCESS_DISABLED_BY_POLICY.0); } -} -/// We want to be able to conditionally control what the help text shows, -/// depending on if sudo is enabled, disabled, or disabled by policy. This -/// helper lets us do that more easily. This will return: -/// * 0 if sudo is disabled -/// * E_ACCESS_DISABLED_BY_POLICY if sudo is disabled by policy -/// * or the current mode (>0), if sudo is enabled. -fn allowed_mode_for_help() -> i32 { - let config: RegistryConfigProvider = Default::default(); - match get_allowed_mode(&config) { - Err(e) => { - if e.code() == E_ACCESSDENIED { - 0 - } else if e.code() == E_ACCESS_DISABLED_BY_POLICY { - E_ACCESS_DISABLED_BY_POLICY.0 - } else { - 0 - } - } - Ok(SudoMode::Disabled) => 0, - Ok(mode) => mode.into(), + if config.allowed_mode == SudoMode::Disabled { + // Any time you want to use IDS_DISABLEDLONGABOUT, make sure you turned on VT first + let mode = enable_vt(); + eprintln!("{}", r::IDS_DISABLEDLONGABOUT.get()); + _ = restore_console_mode(mode); + std::process::exit(E_ACCESSDENIED.0); } + + config.allowed_mode } + /// Try to enable VT processing in the console, but also ignore any errors. fn enable_vt() -> CONSOLE_MODE { enable_vt_or_err().unwrap_or_default() @@ -289,15 +242,16 @@ fn main() { enable_tracing(); trace_log_message(&format!("raw commandline: {:?}", env::args_os())); - let mode_for_help = allowed_mode_for_help(); - let matches = sudo_cli(mode_for_help).get_matches(); - - let res = match matches.subcommand() { - Some(("elevate", sub_matches)) => do_elevate(sub_matches), - Some(("run", sub_matches)) => do_run(sub_matches), - Some(("config", sub_matches)) => do_config(sub_matches), - _ => do_run(&matches), - }; + + let res = PolicyConfig::from_registry().and_then(|config| { + let matches = sudo_cli(&config).get_matches(); + match matches.subcommand() { + Some(("elevate", sub_matches)) => do_elevate(&config, sub_matches), + Some(("run", sub_matches)) => do_run(&config, sub_matches), + Some(("config", sub_matches)) => do_config(&config, sub_matches), + _ => do_run(&config, &matches), + } + }); let code = res.unwrap_or_else(|err| { let hr = err.code(); @@ -325,7 +279,7 @@ fn main() { std::process::exit(code) } -fn do_run(matches: &ArgMatches) -> Result { +fn do_run(config: &PolicyConfig, matches: &ArgMatches) -> Result { let commandline = matches .get_many::("COMMANDLINE") .into_iter() @@ -339,7 +293,7 @@ fn do_run(matches: &ArgMatches) -> Result { return Ok(commandline.is_empty().into()); } let requested_dir: Option = matches.get_one::("chdir").map(|s| s.into()); - let allowed_mode = check_enabled_or_bail(); + let allowed_mode = check_enabled_or_bail(config); let copy_env = matches.get_flag("copyEnv"); if !can_current_user_elevate()? { @@ -358,7 +312,7 @@ fn do_run(matches: &ArgMatches) -> Result { None }; - log_modes(requested_mode); + log_modes(config, requested_mode); if let Some(mode) = requested_mode { if mode > allowed_mode { @@ -377,8 +331,8 @@ fn do_run(matches: &ArgMatches) -> Result { run_target(copy_env, &commandline, actual_mode, requested_dir) } -fn do_elevate(matches: &ArgMatches) -> Result { - _ = check_enabled_or_bail(); +fn do_elevate(config: &PolicyConfig, matches: &ArgMatches) -> Result { + _ = check_enabled_or_bail(config); let parent_pid = matches.get_one::("PARENT").unwrap().parse::(); let nonce = matches.get_one::("NONCE").unwrap().parse::(); @@ -407,7 +361,7 @@ fn do_elevate(matches: &ArgMatches) -> Result { result } -fn do_config(matches: &ArgMatches) -> Result { +fn do_config(config: &PolicyConfig, matches: &ArgMatches) -> Result { let mode = match matches.get_one::("enable") { Some(mode) => { let mode = match mode.as_str() { @@ -422,10 +376,10 @@ fn do_config(matches: &ArgMatches) -> Result { std::process::exit(-1); } }; - try_enable_sudo(mode)?; + try_enable_sudo(config, mode)?; mode } - None => check_enabled_or_bail(), + None => check_enabled_or_bail(config), }; match mode { @@ -438,14 +392,13 @@ fn do_config(matches: &ArgMatches) -> Result { Ok(0) } -fn try_enable_sudo(requested_mode: SudoMode) -> Result<()> { +fn try_enable_sudo(config: &PolicyConfig, requested_mode: SudoMode) -> Result<()> { let elevated = is_running_elevated()?; if !elevated { eprintln!("{}", r::IDS_REQUIREADMINTOCONFIG.get()); std::process::exit(-1); } - let config: RegistryConfigProvider = Default::default(); - let max_mode = get_allowed_mode_from_policy(&config)?; + let max_mode = config.policy_mode; if requested_mode > max_mode { match max_mode { SudoMode::Disabled => eprintln!("{}", r::IDS_DISABLEDBYPOLICY.get()), @@ -456,10 +409,12 @@ fn try_enable_sudo(requested_mode: SudoMode) -> Result<()> { std::process::exit(-1); } - let result = windows_registry::LOCAL_MACHINE - .create("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Sudo") - .and_then(|key| key.set_u32("Enabled", requested_mode.into())); - + let result = reg_set_u32( + HKEY_LOCAL_MACHINE, + w!(r"SOFTWARE\Microsoft\Windows\CurrentVersion\Sudo"), + w!("Enabled"), + requested_mode.into(), + ); if let Err(err) = result { eprintln!("{} {}", r::IDS_ERRORSETTINGMODE.get(), err); return Err(err); diff --git a/sudo/src/rpc_bindings.rs b/sudo/src/rpc_bindings.rs index 59f75f7..a954fd0 100644 --- a/sudo/src/rpc_bindings.rs +++ b/sudo/src/rpc_bindings.rs @@ -13,7 +13,7 @@ pub struct Utf8Str<'a> { } impl<'a> Utf8Str<'a> { - pub fn new(s: &str) -> Utf8Str { + pub fn new(s: &str) -> Utf8Str<'_> { Utf8Str { length: min(s.len(), u32::MAX as usize) as u32, data: s.as_ptr(), diff --git a/sudo/src/rpc_bindings_server.rs b/sudo/src/rpc_bindings_server.rs index 018b18e..c2e04bc 100644 --- a/sudo/src/rpc_bindings_server.rs +++ b/sudo/src/rpc_bindings_server.rs @@ -6,7 +6,7 @@ use std::ffi::{c_void, CStr}; use std::mem::{size_of, take}; use std::ptr::null_mut; use std::sync::atomic::{AtomicBool, Ordering}; -use windows::Win32::Foundation::{ERROR_BUSY, GENERIC_ALL, HANDLE, PSID}; +use windows::Win32::Foundation::{ERROR_BUSY, GENERIC_ALL, HANDLE}; use windows::{ core::*, Win32::Security::Authorization::*, Win32::Security::*, Win32::System::Memory::*, Win32::System::Rpc::*, Win32::System::SystemServices::*, Win32::System::Threading::*, @@ -109,7 +109,7 @@ fn create_security_descriptor_for_process(pid: u32) -> Result() + size_of::(); @@ -250,7 +250,13 @@ fn wrap_elevate_request( let handles = unsafe { let pipes = &*pipe_handles; let files = &*file_handles; - std::array::from_fn(|i| if pipes[i].0 != 0 { pipes[i] } else { files[i] }) + std::array::from_fn(|i| { + if !pipes[i].0.is_null() { + pipes[i] + } else { + files[i] + } + }) }; Ok(ElevateRequest { diff --git a/sudo/src/run_handler.rs b/sudo/src/run_handler.rs index 2c35193..dd4d356 100644 --- a/sudo/src/run_handler.rs +++ b/sudo/src/run_handler.rs @@ -11,6 +11,7 @@ use std::env; use std::ffi::{CString, OsStr}; use std::path::Path; use windows::Wdk::Foundation::{NtQueryObject, ObjectBasicInformation}; +use windows::Win32::Security::Cryptography::ProcessPrng; use windows::Win32::System::WindowsProgramming::PUBLIC_OBJECT_BASIC_INFORMATION; use windows::{ core::*, Wdk::System::Threading::*, Win32::Foundation::*, Win32::Storage::FileSystem::*, @@ -347,18 +348,12 @@ fn do_request(req: ElevateRequest, copy_env: bool, manually_requested_dir: bool) /// `RtlGenRandom` to generate the number. This is how the core language does it: /// https://github.com/rust-lang/rust/pull/45370 fn random_nonce() -> u32 { - #[link(name = "advapi32")] - extern "system" { - // This function's real name is `RtlGenRandom`. - fn SystemFunction036(RandomBuffer: *mut u8, RandomBufferLength: u32) -> BOOLEAN; - } - let mut nonce = 0u32; unsafe { - SystemFunction036( - (&mut nonce as *mut u32) as *mut u8, - std::mem::size_of::() as _, - ); + _ = ProcessPrng(std::slice::from_raw_parts_mut( + &raw mut nonce as *mut u8, + size_of::(), + )); } nonce } @@ -480,7 +475,7 @@ fn send_request_via_rpc(req: &ElevateRequest, nonce: u32) -> Result { unsafe { let mut info: PUBLIC_OBJECT_BASIC_INFORMATION = Default::default(); NtQueryObject( - *child_handle, + Some(*child_handle), ObjectBasicInformation, Some(&mut info as *mut _ as _), std::mem::size_of_val(&info) as _, diff --git a/sudo/src/tests/mod.rs b/sudo/src/tests/mod.rs index b5e8aae..7642768 100644 --- a/sudo/src/tests/mod.rs +++ b/sudo/src/tests/mod.rs @@ -1,8 +1,9 @@ #[allow(clippy::module_inception)] #[cfg(test)] mod tests { - use crate::helpers::*; - use windows::Win32::Foundation::*; + use windows::Win32::Foundation::ERROR_INVALID_PARAMETER; + + use crate::helpers::{generate_rpc_endpoint_name, SudoMode}; #[test] fn test_try_from_u32_for_sudo_mode() { diff --git a/sudo/sudo.rc b/sudo/sudo.rc index 4e8e780..d8a57f0 100644 --- a/sudo/sudo.rc +++ b/sudo/sudo.rc @@ -1,24 +1,4 @@ -// Resource file (.rc) template for sudo. -// -// Our string resources are all auto-generated from our resw file. They'll be -// consumed from a generated .rc file, which will start with the content of this file. - #include -// Here, you'd usually want to -// -// #include "resource.h" -// -// To include your resource ID's. That doesn't work for us! -// We want to use the winres crate to auto-generate FILEVERSION et. al. If we -// want that to work, then we need to append the content of our generated file -// to the content winres generates (using append_rc_content). -// However, when we do it that way, the ultimate .rc file we end up using is one -// that's generated in our OUT_DIR, and that means it can't find the relative -// resource.h -// -// Instead, we'll use append_rc_content to _also_ include the header literally -// in the output .rc file. - // Make sure to declare our exe icon here IDI_APPICON ICON "..\\img\\ico\\sudo.ico"