Skip to content

Commit c1ab429

Browse files
authored
Merge pull request #9 from pnyani/main
feat: add Windows administrator privilege check
2 parents f582cb3 + d472362 commit c1ab429

6 files changed

Lines changed: 159 additions & 13 deletions

File tree

.github/workflows/ci.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,11 @@ jobs:
2121
- uses: actions/checkout@v4
2222
- name: Build
2323
run: cargo build
24+
25+
test-windows:
26+
runs-on: windows-latest
27+
28+
steps:
29+
- uses: actions/checkout@v4
30+
- name: Build
31+
run: cargo build

Cargo.lock

Lines changed: 84 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,21 @@ derive_more = { version = "2.1.1", features = ["from", "into", "from_str", "add"
1212
dirs = "6.0.0"
1313
efivar = "2.0.0"
1414
inquire = "0.9.2"
15-
libc = "0.2.180"
1615
miette = { version = "7.6.0", features = ["fancy"] }
1716
serde = { version = "1.0.228", features = ["derive"] }
1817
serde_yaml = "0.9"
1918
system_shutdown = "4.1.0"
2019
which = "8.0.0"
2120

21+
[target.'cfg(unix)'.dependencies]
22+
libc = "0.2.180"
23+
2224
[target.'cfg(target_os = "linux")'.dependencies]
2325
nix = { version = "0.31.1", features = ["fs", "user"] }
26+
27+
[target.'cfg(target_os = "windows")'.dependencies]
28+
windows-sys = { version = "0.59", features = [
29+
"Win32_Security",
30+
"Win32_System_Threading",
31+
"Win32_Foundation",
32+
] }

src/bin/it.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,12 @@ fn main() {
99
Err(e) => {
1010
eprintln!("Error: Failed to execute 'bootit' command: {}", e);
1111
eprintln!("Make sure 'bootit' is installed and in your PATH.");
12+
13+
#[cfg(windows)]
14+
eprintln!(
15+
"\nIf you are not running as Administrator, try opening an elevated terminal."
16+
);
17+
1218
std::process::exit(127);
1319
}
1420
};

src/command/allow_non_admin.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,15 @@ pub fn allow_non_admin(it_path: Option<PathBuf>) -> miette::Result<()> {
3535
println!("Non-admin users can now use it command to boot.");
3636
}
3737

38-
#[cfg(not(target_os = "linux"))]
38+
#[cfg(target_os = "windows")]
3939
{
40-
println!("Setting setuid bit is not supported on this operating system.");
40+
println!("The setuid mechanism is not available on Windows.");
41+
println!("Run bootit from an elevated terminal (right-click -> Run as administrator).");
42+
}
43+
44+
#[cfg(not(any(target_os = "linux", target_os = "windows")))]
45+
{
46+
println!("allow-non-admin is not supported on this operating system.");
4147
}
4248

4349
Ok(())

src/util.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,52 @@ pub fn check_privileges() -> miette::Result<()> {
1313
));
1414
}
1515
}
16+
17+
#[cfg(windows)]
18+
{
19+
if !is_elevated() {
20+
return Err(miette!(
21+
"This program must be run as Administrator (try: run terminal as administrator)"
22+
));
23+
}
24+
}
25+
1626
Ok(())
1727
}
1828

29+
#[cfg(windows)]
30+
fn is_elevated() -> bool {
31+
use std::ptr::null_mut;
32+
use windows_sys::Win32::Foundation::{CloseHandle, HANDLE};
33+
use windows_sys::Win32::Security::{
34+
GetTokenInformation, TokenElevation, TOKEN_ELEVATION, TOKEN_QUERY,
35+
};
36+
use windows_sys::Win32::System::Threading::{GetCurrentProcess, OpenProcessToken};
37+
38+
unsafe {
39+
let mut token_handle: HANDLE = null_mut();
40+
if OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &mut token_handle) == 0 {
41+
return false;
42+
}
43+
44+
let mut elevation = TOKEN_ELEVATION { TokenIsElevated: 0 };
45+
let mut return_length: u32 = 0;
46+
let size = std::mem::size_of::<TOKEN_ELEVATION>() as u32;
47+
48+
let result = GetTokenInformation(
49+
token_handle,
50+
TokenElevation,
51+
&mut elevation as *mut _ as *mut _,
52+
size,
53+
&mut return_length,
54+
);
55+
56+
CloseHandle(token_handle);
57+
58+
result != 0 && elevation.TokenIsElevated != 0
59+
}
60+
}
61+
1962
#[allow(unused)]
2063
pub fn find_it() -> miette::Result<PathBuf> {
2164
if let Ok(path) = which("it") {

0 commit comments

Comments
 (0)