This commit is contained in:
lubeilin
2023-07-17 22:56:37 +08:00
parent 8d44934382
commit 6b988e0612
13 changed files with 148 additions and 38 deletions
+11 -6
View File
@@ -10,6 +10,7 @@ use switch::handle::registration_handler::ReqEnum;
mod command;
mod console_out;
mod root_check;
#[tokio::main]
async fn main() {
@@ -25,8 +26,8 @@ async fn main() {
opts.optopt("s", "", "注册和中继服务器地址", "<server>");
opts.optopt("e", "", "NAT探测服务器地址,使用逗号分隔", "<addr1,addr2>");
opts.optflag("a", "", "使用tap模式,默认使用tun模式");
opts.optmulti("i", "", "配置点对网(IP代理)时使用,--in-ip 192.168.10.0/24,10.26.0.3,表示允许接收网段192.168.10.0/24的数据并转发到10.26.0.3", "<in-ip>");
opts.optmulti("o", "", "配置点对网时使用,--out-ip 192.168.10.0/24,192.168.1.10,表示允许目标为192.168.10.0/24的数据从网卡192.168.1.10转发出去", "<out-ip>");
opts.optmulti("i", "", "配置点对网(IP代理)时使用,-i 192.168.10.0/24,10.26.0.3,表示允许接收网段192.168.10.0/24的数据并转发到10.26.0.3", "<in-ip>");
opts.optmulti("o", "", "配置点对网时使用,-o 192.168.10.0/24,192.168.1.10,表示允许目标为192.168.10.0/24的数据从网卡192.168.1.10转发出去", "<out-ip>");
opts.optopt("w", "", "使用该密码生成的密钥对客户端数据进行加密,并且服务端无法解密,使用相同密码的客户端才能通信", "<password>");
opts.optflag("m", "", "模拟组播,默认情况下组播数据会被当作广播发送,开启后会模拟真实组播的数据发送");
opts.optopt("u", "", "虚拟网卡mtu值", "<mtu>");
@@ -45,6 +46,14 @@ async fn main() {
return;
}
};
if matches.opt_present("h") || args.len() == 1 {
print_usage(&program, opts);
return;
}
if !root_check::is_app_elevated() {
println!("Please run it with administrator or root privileges");
return;
}
if matches.opt_present("list") {
command::command(command::CommandEnum::List);
return;
@@ -61,10 +70,6 @@ async fn main() {
command::command(command::CommandEnum::All);
return;
}
if matches.opt_present("h") {
print_usage(&program, opts);
return;
}
if !matches.opt_present("k") {
print_usage(&program, opts);
println!("parameter -k not found .");
+11
View File
@@ -0,0 +1,11 @@
#[cfg(target_os = "windows")]
mod windows;
#[cfg(target_os = "windows")]
pub use windows::is_app_elevated;
#[cfg(any(target_os = "linux", target_os = "macos"))]
mod unix;
#[cfg(any(target_os = "linux", target_os = "macos"))]
pub use unix::is_app_elevated;
+3
View File
@@ -0,0 +1,3 @@
pub fn is_app_elevated() -> bool {
sudo::RunningAs::Root == sudo::check()
}
+76
View File
@@ -0,0 +1,76 @@
/// 使用 https://github.com/spa5k/is_sudo/blob/main/src/window.rs
use std::io::Error;
use std::ptr;
use winapi::um::handleapi::CloseHandle;
use winapi::um::processthreadsapi::{GetCurrentProcess, OpenProcessToken};
use winapi::um::securitybaseapi::GetTokenInformation;
use winapi::um::winnt::{TokenElevation, HANDLE, TOKEN_ELEVATION, TOKEN_QUERY};
// Use std::io::Error::last_os_error for errors.
// NOTE: For this example I'm simple passing on the OS error.
// However, customising the error could provide more context
/// Returns true if the current process has admin rights, otherwise false.
pub fn is_app_elevated() -> bool {
_is_app_elevated().unwrap_or(false)
}
/// On success returns a bool indicating if the current process has admin rights.
/// Otherwise returns an OS error.
///
/// This is unlikely to fail but if it does it's even more unlikely that you have admin permissions anyway.
/// Therefore the public function above simply eats the error and returns a bool.
fn _is_app_elevated() -> Result<bool, Error> {
let token = QueryAccessToken::from_current_process()?;
token.is_elevated()
}
/// A safe wrapper around querying Windows access tokens.
pub struct QueryAccessToken(HANDLE);
impl QueryAccessToken {
pub fn from_current_process() -> Result<Self, Error> {
unsafe {
let mut handle: HANDLE = ptr::null_mut();
let result = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &mut handle);
if result != 0 {
Ok(Self(handle))
} else {
Err(Error::last_os_error())
}
}
}
/// On success returns a bool indicating if the access token has elevated privilidges.
/// Otherwise returns an OS error.
pub fn is_elevated(&self) -> Result<bool, Error> {
unsafe {
let mut elevation = TOKEN_ELEVATION::default();
let size = std::mem::size_of::<TOKEN_ELEVATION>() as u32;
let mut ret_size = size;
// The weird looking repetition of `as *mut _` is casting the reference to a c_void pointer.
if GetTokenInformation(
self.0,
TokenElevation,
&mut elevation as *mut _ as *mut _,
size,
&mut ret_size,
) != 0
{
Ok(elevation.TokenIsElevated != 0)
} else {
Err(Error::last_os_error())
}
}
}
}
impl Drop for QueryAccessToken {
fn drop(&mut self) {
if !self.0.is_null() {
unsafe { CloseHandle(self.0) };
}
}
}