Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,8 @@ 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"
4 changes: 2 additions & 2 deletions .cargo/ms-toolchain-config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,6 @@ rustflags = ["-Clink-args=/DYNAMICBASE /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_public_cargo = { index = "sparse+https://pkgs.dev.azure.com/microsoft/Dart/_packaging/sudo_public_cargo/Cargo/index/" }
Sudo_PublicPackages = { index = "sparse+https://pkgs.dev.azure.com/shine-oss/sudo/_packaging/Sudo_PublicPackages/Cargo/index/" }
[source.crates-io]
replace-with = "sudo_public_cargo"
replace-with = "Sudo_PublicPackages"
13 changes: 13 additions & 0 deletions Building.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,16 @@ cargo build --config .cargo\ms-toolchain-config.toml
```

Note, if you run that on the public toolchain, you'll most definitely run into ``error: unknown codegen option: `ehcont_guard` `` when building.

### Notes on updating the cargo feed

For internal reasons, we need to maintain a separate Azure Artifacts cargo feed. Largely we just pull dependencies through from crates.io into that feed. Hence the config to replace the default cargo feed with our own.

As a maintainer, if you need to update that feed, then you'll need to do the following:

```cmd
az login
az account get-access-token --query "join(' ', ['Bearer', accessToken])" --output tsv | cargo login --registry Sudo_PublicPackages
```

That'll log you in via the Azure CLI and then log you into the cargo feed. That'll let you pull down the packages but oh yikes everything is awful.
72 changes: 1 addition & 71 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ cc = "1.0"
# See: https://docs.rs/clap/latest/clap/_features/index.html
clap = { version = "4.4.7", 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"
Expand Down
8 changes: 6 additions & 2 deletions sudo/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,16 @@ name = "sudo"
winres.workspace = true
cc.workspace = true
embed-manifest.workspace = true
which = { workspace = true }

[build-dependencies.windows]
workspace = true
features = [
"Win32_Storage_FileSystem",
]

[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" }
Expand Down
19 changes: 17 additions & 2 deletions sudo/build.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use embed_manifest::embed_manifest_file;
use std::path::PathBuf;
use std::process::Command;
use windows::{core::*, Win32::Storage::FileSystem::*};
use {
std::{env, io},
winres::WindowsResource,
Expand Down Expand Up @@ -32,6 +33,21 @@ fn get_sdk_path() -> Option<String> {
sdk_path
}

fn search_path(filename: &str) -> Result<String> {
let filename = &HSTRING::from(filename);
let len = unsafe { SearchPathW(None, filename, None, None, None) };

if len == 0 {
return Err(Error::from_win32());
}

let mut buffer = vec![0; len as usize];
let len = unsafe { SearchPathW(None, filename, None, Some(&mut buffer), None) };
buffer.truncate(len as usize);

Ok(String::from_utf16(&buffer)?)
}

fn get_sdk_tool(sdk_path: &Option<String>, tool_name: &str) -> String {
// seems like, in a VS tools prompt, midl.exe is in the path so the above
// doesn't include the path. kinda weird but okay?
Expand All @@ -47,8 +63,7 @@ fn get_sdk_tool(sdk_path: &Option<String>, tool_name: &str) -> String {
// we can just get the absolute path to the exe using the windows
// path search.

let tool_path = which::which(tool_name).expect("Failed to find tool in path");
tool_path.to_str().unwrap().to_owned()
search_path(tool_name).expect("Failed to find tool in path")
}
};
tool_path
Expand Down
21 changes: 19 additions & 2 deletions sudo/src/run_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,21 @@ pub fn run_target(
do_request(req, copy_env, manually_requested_dir)
}

fn search_path(filename: &str) -> Result<String> {
let filename = &HSTRING::from(filename);
Comment thread
zadjii-msft marked this conversation as resolved.
Outdated
let len = unsafe { SearchPathW(None, filename, None, None, None) };

if len == 0 {
return Err(Error::from_win32());
}

let mut buffer = vec![0; len as usize];
let len = unsafe { SearchPathW(None, filename, None, Some(&mut buffer), None) };
buffer.truncate(len as usize);
Comment thread
zadjii-msft marked this conversation as resolved.
Outdated

Ok(String::from_utf16(&buffer)?)
}

/// Constructs an ElevateRequest from the given arguments. We'll package up
/// handles, we'll separate out the application and args, and we'll do some
/// other work to make sure the request is ready to go.
Expand Down Expand Up @@ -262,7 +277,7 @@ fn prepare_request(
event_log_request(true, &req);

// Does the application exist somewhere on the path?
let where_result = which::which(&req.application);
let where_result = search_path(&req.application);

if let Ok(path) = where_result {
// It's a real file that exists on the PATH.
Expand All @@ -271,7 +286,9 @@ fn prepare_request(
// ensures that the elevated sudo will execute the same thing that was
// found here in the unelevated context.

req.application = absolute_path(&path)?.to_string_lossy().to_string();
req.application = absolute_path(Path::new(&path))?
.to_string_lossy()
.to_string();
adjust_args_for_gui_exes(&mut req);
} else {
tracing::trace_command_not_found(&req.application);
Expand Down