diff --git a/ChangeLog b/ChangeLog index 4e95ed638..d5ed946ee 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,6 +2,15 @@ Easy-RSA 3 ChangeLog 3.2.4 (TBD) + * help: Correct build-ca 'rawca' command option (0447f42) (#1374) + * Windows easyrsa-shell-init.sh: Modernize prompt (5bf2e99) (#1374) + * Windows UT: Update 'wop-test.sh' to latest 'easyrsa-shell-init.sh' (ea5b168) (#1374) + * verify_openvpn(): Convert Windows path '\' to *nix path '/' (75a8fdd) (#1374) + * verify_openvpn(): Windows, add check for 'openvpn.exe' (10c6267) (#1374) + * gen-crl: Replace file-move with file-copy-preserve-attribs (4cc1d48) (#1374) + * Windows easyrsa-shell-init.sh: Add non-fatal check for 'openvpn.exe' (bb78615) (#1374) + * Windows easyrsa-shell-init.sh: Require confirmation for User-Home mode (bfa6cfd) (#1374) + * Windows easyrsa-shell-init.sh: Allow Easy-RSA to use '\User\$HOME' (f194da5) (#1374) * mutual_exclusions(): Include basic checks for --startdate/--enddate (e1478c3) (#1372) * Windows easyrsa-shell-init.sh: Replace 'read -p' (49b2181) (#1371) * inline: Include missing OpenVPN TLS key to cause INCOMPLETE warning (d98eee6) (#1368) diff --git a/distro/windows/bin/easyrsa-shell-init.sh b/distro/windows/bin/easyrsa-shell-init.sh index 011730095..f2f265deb 100644 --- a/distro/windows/bin/easyrsa-shell-init.sh +++ b/distro/windows/bin/easyrsa-shell-init.sh @@ -1,115 +1,90 @@ #!/bin/sh -# 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 # project; use with other POSIX shells for Windows may require modification to # this wrapper script. -echo "Easy-RSA starting.." - -setup_path="${EASYRSA:-$PWD}" -export PATH="$setup_path;$setup_path/bin;$PATH" -export HOME="$setup_path" - -# This prevents reading from a user's .mkshrc if they have one. -# A user who runs mksh for other purposes might have it -export ENV="/disable-env" +# SC2162 - read without -r will mangle backslashes +# SC1091 - Not following source file +# SC1003 - (info): Want to escape a single quote? +# shellcheck disable=SC2162,SC1091,SC1003 + +# intent confirmation helper func +# modified from easyrsa +confirm() { + prompt="$1" + value="$2" + msg="$3" + input="" + print "\ +$msg + +Type the word '$value' to continue, or any other input to abort." + printf %s " $prompt" + # shellcheck disable=SC2162 # read without -r - confirm() + read input + printf '\n' + [ "$input" = "$value" ] && return + unset -v EASYRSA_SILENT + notice "Aborting without confirmation." + exit 1 +} # => confirm() -# Verify required externals are present -extern_list="which awk cat cp mkdir printf rm" -for f in $extern_list; do - if ! which "${f}.exe" >/dev/null 2>&1; then - echo "" - echo "FATAL: EasyRSA Shell init is missing a required external file:" - echo " ${f}.exe" - echo " Your installation is incomplete and cannot function without the required" - echo " files." - echo "" - #shellcheck disable=SC2162 - echo "Press Enter to exit." +# Access denied error +access_denied() { + echo "Cannot locate or use a User-Home directory." + echo "Press [Enter] to exit." read exit 1 +} # => access_denied() + +# Administrator access Required tests +admin_access() { + mkdir "$1" 2>/dev/null || return 1 + [ -d "$1" ] || return 1 + echo 1 >"$1"/1 2>/dev/null || return 1 + [ -f "$1"/1 ] || return 1 + rm -rf "$1" 2>/dev/null || return 1 + [ ! -d "$1" ] || return 1 +} # => admin_access() + +# Setup "$HOMEDRIVE\$HOMEPATH\OpenVPN\easy-rsa" directory +use_home_dir() { + if [ "$USERPROFILE" ]; then + # Use $USERPROFILE + user_home="$USERPROFILE" + elif [ "$HOMEDRIVE" ]; then + if [ "$HOMEPATH" ]; then + # Use $HOMEDRIVE and $HOMEPATH + user_home="${HOMEDRIVE}${HOMEPATH}" + else + user_home= + fi + else + user_home= fi -done -# Allow options -non_admin="" -while [ "$1" ]; do - case "$1" in - /[Nn][Aa]|/no-adm*|--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 -full administrator privileges via Windows User Access Control." - echo "" - - #shellcheck disable=SC2162 - echo "Press Enter to exit." - read - exit 1 -} + # If no $user_home was identified + [ "$user_home" ] || access_denied -# 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" + # Use $user_home/openvpn directory + cd "$user_home"/openvpn || access_denied + # Create $user_home/openvpn/easy-rsa directory if [ ! -d easy-rsa ]; then - mkdir easy-rsa 2>/dev/null || \ - access_denied "mkdir: easy-rsa" + mkdir easy-rsa 2>/dev/null || access_denied # Required test - [ -d easy-rsa ] || \ - access_denied "Missing: easy-rsa" + [ -d easy-rsa ] || access_denied fi - cd easy-rsa 2>/dev/null || \ - access_denied "Access: easy-rsa" + # Use $user_home/openvpn/easy-rsa directory + cd easy-rsa 2>/dev/null || access_denied export HOME="$PWD" export PATH="$HOME;$PATH" - 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 + unset -v user_home +} # => use_home_dir() # set_var is defined as any vars file needs it. # This is the same as in easyrsa, but we _don't_ export @@ -120,6 +95,54 @@ set_var() { eval "$var=\"\${$var-$value}\"" } #=> set_var() +######################################## +# Invocation entry point: + +echo "Starting Easy-RSA shell.." + +setup_path="${EASYRSA:-$PWD}" +export PATH="$setup_path;$setup_path/bin;$PATH" +export HOME="$setup_path" + +# This prevents reading from a user's .mkshrc if they have one. +# A user who runs mksh for other purposes might have it +export ENV="/disable-env" + +# Check for broken administrator access +# https://github.com/OpenVPN/easy-rsa/issues/1072 +if admin_access "$HOME"/easyrsa-write-test; then + sec_lev='#' +else + echo " +To use Easy-RSA in a protected system directory, you must have +full administrator privileges via Windows User Access Control." + + confirm "Continue without administrator access ? " yes " +Easy-RSA will now try to use your User-Home directory." + + use_home_dir + sec_lev='$' + echo " +NOTICE: +Easy-RSA has been auto-configured to run in your User-Home directory." +fi + +# Verify required externals are present +extern_list="which awk cat cp mkdir printf rm grep sed" +for f in $extern_list; do + if ! which "${f}.exe" >/dev/null 2>&1; then + echo "" + echo "FATAL: EasyRSA Shell init is missing a required external file:" + echo " ${f}.exe" + echo " Your installation is incomplete and cannot function without" + echo " the required files." + echo "" + echo "Press Enter to exit." + read + exit 1 + fi +done + # Check for a usable openssl bin, referencing vars if present [ -r "vars" ] && EASYRSA_CALLER=1 . "vars" 2>/dev/null if [ -z "$EASYRSA_OPENSSL" ] && ! which openssl.exe >/dev/null 2>&1; then @@ -135,18 +158,30 @@ fi exit 1 } +# Check for openvpn executable +if which openvpn.exe >/dev/null 2>&1; then + EASYRSA_OPENVPN="$(which openvpn.exe | sed s/'\\'/'\/'/g)" || { + echo "verify_openvpn - Failed to convert openvpn path." + echo "Press Enter to exit." + read + exit 1 + } + export EASYRSA_OPENVPN="$EASYRSA_OPENVPN" +else + echo "WARNING: openvpn.exe is not in your system PATH." + echo "EasyRSA will not be able to generate OpenVPN TLS keys." +fi + # Set prompt and welcome message -export PS1=' -EasyRSA Shell -# ' +export PS1="$USERNAME@$COMPUTERNAME $HOME +EasyRSA-Shell: $sec_lev " + echo "" 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 sh.exe diff --git a/easyrsa3/easyrsa b/easyrsa3/easyrsa index 5865c3209..2537d9e7a 100755 --- a/easyrsa3/easyrsa +++ b/easyrsa3/easyrsa @@ -149,7 +149,8 @@ Command list: serial|check-serial display-dn
show-eku | - rand " + rand +" } # => usage() # Detailed command help @@ -187,8 +188,8 @@ Usage: easyrsa [ OPTIONS.. ] [ cmd-opts.. ]" Creates a new CA" opts=" - * raw-ca - ONLY use SSL binary to input CA password - raw (Equivalent to global option '--raw-ca') + * rawca - ONLY use SSL binary to input CA password + (Equivalent to global option '--rawca|--raw-ca') * nopass - Do not encrypt the private key (Default: encrypted) (Equivalent to global option '--nopass|--no-pass') @@ -1567,7 +1568,7 @@ build_ca() { nopass) [ "$prohibit_no_pass" ] || EASYRSA_NO_PASS=1 ;; - rawca|raw-ca) + rawca) # option --raw-ca demands user interaction # which forbids --batch [ "$EASYRSA_BATCH" ] && user_error \ @@ -3546,11 +3547,7 @@ gen_crl() { die "CRL Generation failed." # Move temp-files to target-files - mv "$out_file_tmp" "$out_file" || mv_temp_error=1 - if [ "$mv_temp_error" ]; then - #rm -f "$out_file" - die "Failed to move temp CRL file." - fi + cp -p "$out_file_tmp" "$out_file" || die "Failed to move temp CRL file." # Copy to DER - As published by OpenSSL if "$EASYRSA_OPENSSL" crl -in "$out_file" -out "$out_der" \ @@ -3972,14 +3969,32 @@ ${cipher:+You will then enter a new password for this key.$NL}" # Verify OpenVPN binary verify_openvpn() { - # Try to find openvpn - set_var EASYRSA_OPENVPN "$(which openvpn)" if [ -f "$EASYRSA_OPENVPN" ]; then - verbose \ - "verify_openvpn - EASYRSA_OPENVPN='$EASYRSA_OPENVPN'" + verbose "verify_openvpn; Preset EASYRSA_OPENVPN='$EASYRSA_OPENVPN'" + return + fi + + # Try to find openvpn *nix + if which openvpn >/dev/null 2>&1; then + set_var EASYRSA_OPENVPN "$(which openvpn)" else - user_error "Cannot find an OpenVPN binary." + # Try to find openvpn.exe, specifically for Windows + # Assign temp-file for Windows path name + ovpn_path_tmp="" + easyrsa_mktemp ovpn_path_tmp + + if which openvpn.exe > "$ovpn_path_tmp"; then + # shellcheck disable=SC1003 # (info): Want to escape a single quote? + ovpn_path="$(sed s/'\\'/'\/'/ "$ovpn_path_tmp")" || \ + die "verify_openvpn - Failed to convert openvpn path." + set_var EASYRSA_OPENVPN "$ovpn_path" + else + user_error "\ +An 'openvpn' binary is not in your system PATH. +EasyRSA can not generate OpenVPN TLS keys." + fi fi + verbose "verify_openvpn; Set EASYRSA_OPENVPN='$EASYRSA_OPENVPN'" } # => verify_openvpn() # OpenVPN TLS Auth/Crypt Key diff --git a/wop-test.sh b/wop-test.sh index 39be8814a..99919088b 100644 --- a/wop-test.sh +++ b/wop-test.sh @@ -1,13 +1,109 @@ #!/bin/sh -# shellcheck disable=SC2161,SC1091 # 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 # project; use with other POSIX shells for Windows may require modification to # this wrapper script. +# SC2162 - read without -r will mangle backslashes +# SC1091 - Not following source file +# SC1003 - (info): Want to escape a single quote? +# shellcheck disable=SC2162,SC1091,SC1003 + +# intent confirmation helper func +# modified from easyrsa +confirm() { + # Unit test can bypass this confirm + [ "$EASYRSA_WIN_QUICK" ] && return + prompt="$1" + value="$2" + msg="$3" + input="" + print "\ +$msg + +Type the word '$value' to continue, or any other input to abort." + printf %s " $prompt" + # shellcheck disable=SC2162 # read without -r - confirm() + read input + printf '\n' + [ "$input" = "$value" ] && return + unset -v EASYRSA_SILENT + notice "Aborting without confirmation." + exit 1 +} # => confirm() + +# Access denied error +access_denied() { + echo "Cannot locate or use a User-Home directory." + echo "Press [Enter] to exit." + read + exit 1 +} # => access_denied() + +# Administrator access Required tests +admin_access() { + mkdir "$1" 2>/dev/null || return 1 + [ -d "$1" ] || return 1 + echo 1 >"$1"/1 2>/dev/null || return 1 + [ -f "$1"/1 ] || return 1 + rm -rf "$1" 2>/dev/null || return 1 + [ ! -d "$1" ] || return 1 +} # => admin_access() + +# Setup "$HOMEDRIVE\$HOMEPATH\OpenVPN\easy-rsa" directory +use_home_dir() { + if [ "$USERPROFILE" ]; then + # Use $USERPROFILE + user_home="$USERPROFILE" + elif [ "$HOMEDRIVE" ]; then + if [ "$HOMEPATH" ]; then + # Use $HOMEDRIVE and $HOMEPATH + user_home="${HOMEDRIVE}${HOMEPATH}" + else + user_home= + fi + else + user_home= + fi + + # If no $user_home was identified + [ "$user_home" ] || access_denied + + # Use $user_home/openvpn directory + cd "$user_home"/openvpn || access_denied + + # Create $user_home/openvpn/easy-rsa directory + if [ ! -d easy-rsa ]; then + mkdir easy-rsa 2>/dev/null || access_denied + # Required test + [ -d easy-rsa ] || access_denied + fi + + # Use $user_home/openvpn/easy-rsa directory + cd easy-rsa 2>/dev/null || access_denied + + export HOME="$PWD" + export PATH="$HOME;$PATH" + unset -v user_home +} # => use_home_dir() + +# set_var is defined as any vars file needs it. +# This is the same as in easyrsa, but we _don't_ export +set_var() { + var="$1" + shift + value="$*" + eval "$var=\"\${$var-$value}\"" +} #=> set_var() + +######################################## +# Invocation entry point: + cd easyrsa3 || { echo "ERROR: Cannot find easyrsa3 directory"; exit 1; } +echo "Starting Easy-RSA shell.." + setup_path="${EASYRSA:-$PWD}" export PATH="$setup_path;$setup_path/bin;$PATH" export HOME="$setup_path" @@ -16,32 +112,41 @@ export HOME="$setup_path" # A user who runs mksh for other purposes might have it export ENV="/disable-env" +# Check for broken administrator access +# https://github.com/OpenVPN/easy-rsa/issues/1072 +if admin_access "$HOME"/easyrsa-write-test; then + sec_lev='#' +else + echo " +To use Easy-RSA in a protected system directory, you must have +full administrator privileges via Windows User Access Control." + + confirm "Continue without administrator access ? " yes " +Easy-RSA will now try to use your User-Home directory." + + use_home_dir + sec_lev='$' + echo " +NOTICE: +Easy-RSA has been auto-configured to run in your User-Home directory." +fi + # Verify required externals are present -extern_list="which awk cat cp mkdir printf rm" +extern_list="which awk cat cp mkdir printf rm grep sed" for f in $extern_list; do if ! which "${f}.exe" >/dev/null 2>&1; then echo "" echo "FATAL: EasyRSA Shell init is missing a required external file:" echo " ${f}.exe" - echo " Your installation is incomplete and cannot function without the required" - echo " files." + echo " Your installation is incomplete and cannot function without" + echo " the required files." echo "" - echo " Press enter to exit." - #shellcheck disable=SC2162 + echo "Press Enter to exit." read exit 1 fi done -# set_var is defined as any vars file needs it. -# This is the same as in easyrsa, but we _don't_ export -set_var() { - var="$1" - shift - value="$*" - eval "$var=\"\${$var-$value}\"" -} #=> set_var() - # Check for a usable openssl bin, referencing vars if present [ -r "vars" ] && EASYRSA_CALLER=1 . "vars" 2>/dev/null if [ -z "$EASYRSA_OPENSSL" ] && ! which openssl.exe >/dev/null 2>&1; then @@ -52,18 +157,34 @@ fi [ -f "$setup_path/easyrsa" ] || { echo "Missing easyrsa script. Expected to find it at: $setup_path/easyrsa" - exit 2 + echo "Press Enter to exit." + read + exit 1 } +# Check for openvpn executable +if which openvpn.exe >/dev/null 2>&1; then + EASYRSA_OPENVPN="$(which openvpn.exe | sed s/'\\'/'\/'/g)" || { + echo "verify_openvpn - Failed to convert openvpn path." + echo "Press Enter to exit." + read + exit 1 + } + export EASYRSA_OPENVPN="$EASYRSA_OPENVPN" +else + echo "WARNING: openvpn.exe is not in your system PATH." + echo "EasyRSA will not be able to generate OpenVPN TLS keys." +fi + # Set prompt and welcome message -export PS1=' -EasyRSA Shell -# ' +export PS1=" +EasyRSA Shell: +$USERNAME@$COMPUTERNAME $HOME $sec_lev " echo "" 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 "Invoke 'easyrsa' to call the program. Without commands, help is displayed." cd ..