From 10467704e0c2f00872348f8376a180e43b0c3f6f Mon Sep 17 00:00:00 2001 From: Richard T Bonhomme Date: Tue, 30 Jan 2024 01:55:39 +0000 Subject: [PATCH] Windows: Introduce 'Non-Admin' mode This allows Easy-RSA to be run in a User's Home directory. The problem is ONLY caused by 'Windows User Access Control' feedback: Easy-RSA executable 'mkdir.exe' does not receive an error-on-failure when Windows UAC has not granted write access to the OpenVPN system directory: '\Program Files\Openvpn\easy-rsa' This means that easyrsa cannot successful verify directory creation by using only the exit status of command 'mkdir.exe'. Instead, easyrsa must also check that the directory was created via '[ -d pki ] || foo'. The following changes are required: * Changes to 'easyrsa-shell-init.sh': Allow options to be passed from the command line. The only supported options are: /na or --no-admin This non_admin mode will change directory to the User's Home directory and the make full write access checks on the Home directory. In standard mode, the full write access checks will be run in the default system folder. And, unless the Windows UAC has granted write access, these tests will fail as intended. A helpful error message is then printed. * Changes to 'EasyRSA-Start.bat': Allow command line options to be passed onto 'easyrsa-shell-init.sh' For Openvpn-build: This also allows the creation of a new Windows-Start Menu item: * 'Start EasyRSA Shell (Non-Admin)' Which can pass the '/na' or '--no-admin' flag to 'EasyRSA-Start.bat' Signed-off-by: Richard T Bonhomme --- distro/windows/EasyRSA-Start.bat | 2 +- distro/windows/bin/easyrsa-shell-init.sh | 96 +++++++++++++++++++++++- 2 files changed, 95 insertions(+), 3 deletions(-) diff --git a/distro/windows/EasyRSA-Start.bat b/distro/windows/EasyRSA-Start.bat index 198375144..8c28e862c 100644 --- a/distro/windows/EasyRSA-Start.bat +++ b/distro/windows/EasyRSA-Start.bat @@ -1,2 +1,2 @@ @echo OFF -bin\sh.exe bin\easyrsa-shell-init.sh +bin\sh.exe bin\easyrsa-shell-init.sh %* diff --git a/distro/windows/bin/easyrsa-shell-init.sh b/distro/windows/bin/easyrsa-shell-init.sh index 82d4dec1b..aff1ec612 100644 --- a/distro/windows/bin/easyrsa-shell-init.sh +++ b/distro/windows/bin/easyrsa-shell-init.sh @@ -1,5 +1,5 @@ #!/bin/sh -# shellcheck disable=SC2161,SC1091 +# shellcheck disable=SC2161,SC1091,SC2028 # This script is a frontend designed to create & launch a POSIX shell # environment suitable for use with Easy-RSA. mksh/Win32 is used with this @@ -31,6 +31,95 @@ for f in $extern_list; do fi done +# Allow options +non_admin="" +while [ "$1" ]; do + case "$1" in + /[Nn][Aa]|--no-adm*) + non_admin=1 + echo "Using no-admin mode" + ;; + *) + echo "Ignoring unknown option: '$1'" + esac + shift +done + +# Access denied +access_denied() { + echo "Access error: $1" + echo " +To use Easy-RSA in a protected system directory, you must have +elevated privileges via 'Windows User Access Control'. +You can try 'run-as admin' but that may also fail. + +It is recommended to use Easy-RSA in your User/home directory. + +Please try using one of the following solutions: +* Use the Start Menu item: 'Start Easy-RSA Shell (Non-Admin)' +* Or, in a Non-Admin command prompt window, run two commands: + + cd '\Program Files\Openvpn\easy-rsa\' + EasyRSA-Start.bat /no-admin + +These will start EasyRSA in your user's 'home directory/easy-rsa' + +Press enter to exit." + + #shellcheck disable=SC2162 + read + exit 1 +} + +# Use home directory/easy-rsa +if [ "$non_admin" ]; then + [ "${HOMEDRIVE}" ] || \ + access_denied "Undefined: HOMEDRIVE" + user_home_drv="${HOMEDRIVE}" + + [ "${HOMEPATH}" ] || \ + access_denied "Undefined: HOMEPATH" + eval "user_home_dir='\\${HOMEPATH}'" + + # shellcheck disable=SC2154 # user_home_dir is not assigned + user_home="${user_home_drv}${user_home_dir}" + + [ -d "$user_home" ] || \ + access_denied "Missing: $user_home" + + cd "$user_home" 2>/dev/null || \ + access_denied "Access: $user_home" + + if [ ! -d easy-rsa ]; then + mkdir easy-rsa 2>/dev/null || \ + access_denied "mkdir: easy-rsa" + # Required test + [ -d easy-rsa ] || \ + access_denied "Missing: easy-rsa" + fi + + cd easy-rsa 2>/dev/null || \ + access_denied "Access: easy-rsa" + + export HOME="$PWD" + unset -v user_home_drv user_home_dir user_home +fi + +# Check for broken administrator access +# https://github.com/OpenVPN/easy-rsa/issues/1072 +[ -d "$HOME" ] || access_denied "-d HOME" +win_tst_d="$HOME"/easyrsa-write-test + +# Required tests +mkdir "$win_tst_d" 2>/dev/null || access_denied "mkdir" +[ -d "$win_tst_d" ] || access_denied "-d" +echo 1 > "$win_tst_d"/1 2>/dev/null || access_denied "write" +[ -f "$win_tst_d"/1 ] || access_denied "-f" +rm -rf "$win_tst_d" 2>/dev/null || access_denied "rm" +[ ! -d "$win_tst_d" ] || access_denied "! -d" +unset -v win_tst_d +unset -f access_denied + # set_var is defined as any vars file needs it. # This is the same as in easyrsa, but we _don't_ export set_var() { @@ -62,6 +151,9 @@ echo "Welcome to the EasyRSA 3 Shell for Windows." echo "Easy-RSA 3 is available under a GNU GPLv2 license." echo "" echo "Invoke './easyrsa' to call the program. Without commands, help is displayed." +echo "" +echo "Using directory: $HOME" +echo "" # Drop to a shell and await input -bin/sh +sh.exe