diff --git a/main/NekoRay.cpp b/main/NekoRay.cpp index 1de4cbeba..49f97d2b2 100644 --- a/main/NekoRay.cpp +++ b/main/NekoRay.cpp @@ -73,6 +73,9 @@ namespace NekoRay { _add(new configItem("log_ignore", &log_ignore, itemType::stringList)); _add(new configItem("start_minimal", &start_minimal, itemType::boolean)); _add(new configItem("max_log_line", &max_log_line, itemType::integer)); +#ifndef Q_OS_WIN + _add(new configItem("vpn_already_admin", &vpn_already_admin, itemType::boolean)); +#endif } void DataStore::UpdateStartedId(int id) { diff --git a/main/NekoRay_DataStore.hpp b/main/NekoRay_DataStore.hpp index c2a7b6f14..a67b4cc3b 100644 --- a/main/NekoRay_DataStore.hpp +++ b/main/NekoRay_DataStore.hpp @@ -136,6 +136,7 @@ namespace NekoRay { bool vpn_hide_console = false; bool vpn_strict_route = false; bool vpn_rule_white = false; + bool vpn_already_admin = false; // not saved on Windows QString vpn_rule_process = ""; QString vpn_rule_cidr = ""; diff --git a/res/vpn/vpn-run-root.sh b/res/vpn/vpn-run-root.sh index d36d3227b..dae152383 100755 --- a/res/vpn/vpn-run-root.sh +++ b/res/vpn/vpn-run-root.sh @@ -3,8 +3,7 @@ set -e set -x if [ "$EUID" -ne 0 ]; then - echo "Please run as root" - exit + echo "[Warning] vpn script not running as root" fi if [ "$(uname)" == "Darwin" ]; then diff --git a/sys/windows/guihelper.cpp b/sys/windows/guihelper.cpp index a297415d1..f29ebc1f2 100644 --- a/sys/windows/guihelper.cpp +++ b/sys/windows/guihelper.cpp @@ -4,8 +4,9 @@ #include #include +#include -void Windows_QWidget_SetForegroundWindow(QWidget* w) { +void Windows_QWidget_SetForegroundWindow(QWidget *w) { HWND hForgroundWnd = GetForegroundWindow(); DWORD dwForeID = ::GetWindowThreadProcessId(hForgroundWnd, NULL); DWORD dwCurID = ::GetCurrentThreadId(); @@ -13,3 +14,11 @@ void Windows_QWidget_SetForegroundWindow(QWidget* w) { ::SetForegroundWindow((HWND) w->winId()); ::AttachThreadInput(dwCurID, dwForeID, FALSE); } + +int isThisAdmin = -1; // cached + +bool Windows_IsInAdmin() { + if (isThisAdmin >= 0) return isThisAdmin; + isThisAdmin = IsUserAnAdmin(); + return isThisAdmin; +} diff --git a/sys/windows/guihelper.h b/sys/windows/guihelper.h index d7afb91bf..3969b4c30 100644 --- a/sys/windows/guihelper.h +++ b/sys/windows/guihelper.h @@ -3,3 +3,5 @@ class QWidget; void Windows_QWidget_SetForegroundWindow(QWidget* w); + +bool Windows_IsInAdmin(); diff --git a/translations/fa_IR.ts b/translations/fa_IR.ts index a90ab6ae0..a9c9b49a0 100644 --- a/translations/fa_IR.ts +++ b/translations/fa_IR.ts @@ -630,6 +630,14 @@ https://matsuridayo.github.io/n-configuration/#vpn-tun Cancel لغو کردن + + Don't ask for privilege elevation + + + + Already Admin + + EditChain diff --git a/translations/zh_CN.ts b/translations/zh_CN.ts index 24b92f14b..598215299 100644 --- a/translations/zh_CN.ts +++ b/translations/zh_CN.ts @@ -639,6 +639,14 @@ https://matsuridayo.github.io/n-configuration/#vpn-tun Cancel 取消 + + Don't ask for privilege elevation + 不请求特权提升 + + + Already Admin + 已是管理员 + EditChain diff --git a/ui/dialog_vpn_settings.cpp b/ui/dialog_vpn_settings.cpp index b3656e6d7..b58c7a547 100644 --- a/ui/dialog_vpn_settings.cpp +++ b/ui/dialog_vpn_settings.cpp @@ -18,7 +18,10 @@ DialogVPNSettings::DialogVPNSettings(QWidget *parent) : QDialog(parent), ui(new ui->vpn_mtu->setCurrentText(Int2String(NekoRay::dataStore->vpn_mtu)); ui->vpn_ipv6->setChecked(NekoRay::dataStore->vpn_ipv6); ui->hide_console->setChecked(NekoRay::dataStore->vpn_hide_console); -#ifndef Q_OS_WIN + ui->vpn_already_admin->setChecked(NekoRay::dataStore->vpn_already_admin); +#ifdef Q_OS_WIN + ui->vpn_already_admin->setVisible(false); +#else ui->hide_console->setVisible(false); #endif ui->strict_route->setChecked(NekoRay::dataStore->vpn_strict_route); @@ -53,6 +56,7 @@ void DialogVPNSettings::accept() { NekoRay::dataStore->vpn_hide_console = ui->hide_console->isChecked(); NekoRay::dataStore->vpn_strict_route = ui->strict_route->isChecked(); NekoRay::dataStore->vpn_rule_white = ui->whitelist_mode->isChecked(); + NekoRay::dataStore->vpn_already_admin = ui->vpn_already_admin->isChecked(); // D_SAVE_STRING_QTEXTEDIT(vpn_rule_cidr) D_SAVE_STRING_QTEXTEDIT(vpn_rule_process) diff --git a/ui/dialog_vpn_settings.ui b/ui/dialog_vpn_settings.ui index 9fa00d460..e45c0c424 100644 --- a/ui/dialog_vpn_settings.ui +++ b/ui/dialog_vpn_settings.ui @@ -114,6 +114,16 @@ + + + + Don't ask for privilege elevation + + + Already Admin + + + diff --git a/ui/mainwindow.cpp b/ui/mainwindow.cpp index be1234dfc..4964269dd 100644 --- a/ui/mainwindow.cpp +++ b/ui/mainwindow.cpp @@ -715,6 +715,9 @@ void MainWindow::refresh_status(const QString &traffic_update) { auto make_title = [=](bool isTray) { QStringList tt; +#ifdef Q_OS_WIN + if (!isTray && Windows_IsInAdmin()) tt << "[Admin]"; +#endif if (select_mode) tt << "[" + tr("Select") + "]"; if (!title_error.isEmpty()) tt << "[" + title_error + "]"; if (NekoRay::dataStore->running_spmode == NekoRay::SystemProxyMode::SYSTEM_PROXY) { @@ -1676,7 +1679,11 @@ bool MainWindow::StartVPNProcess() { vpn_process->start("osascript", {"-e", QString("do shell script \"%1\" with administrator privileges") .arg("bash " + scriptPath)}); #else - vpn_process->start("pkexec", {"bash", scriptPath}); + if (NekoRay::dataStore->vpn_already_admin) { + vpn_process->start("bash", {scriptPath}); + } else { + vpn_process->start("pkexec", {"bash", scriptPath}); + } #endif vpn_process->waitForStarted(); vpn_pid = vpn_process->processId(); // actually it's pkexec or bash PID @@ -1699,10 +1706,14 @@ bool MainWindow::StopVPNProcess(bool unconditional) { p.start("osascript", {"-e", QString("do shell script \"%1\" with administrator privileges") .arg("pkill -2 -U 0 nekobox_core")}); #else - if (unconditional) { - p.start("pkexec", {"killall", "nekobox_core"}); + if (NekoRay::dataStore->vpn_already_admin) { + p.start("bash", {"kill", "-2", Int2String(vpn_pid)}); } else { - p.start("pkexec", {"pkill", "-2", "-P", Int2String(vpn_pid)}); + if (unconditional) { + p.start("pkexec", {"killall", "-2", "nekobox_core"}); + } else { + p.start("pkexec", {"pkill", "-2", "-P", Int2String(vpn_pid)}); + } } #endif p.waitForFinished();