From 7db20c9d166248e5f14fd724eb9c2cf15506b119 Mon Sep 17 00:00:00 2001 From: Christoph Anton Mitterer Date: Mon, 21 Nov 2022 22:12:13 +0100 Subject: [PATCH] ssh_filter_btrbk.sh: minor improvements MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit • Set shell options in one command. • Homogeneously use local variables for function positional parameters in all places. • In redirections, omit `1` for standard output. • Homogeneously use `if`-compount-commands instead of `[ … ] && …` in all places. • Homogeneously use curly brackets with parameter expansion. Signed-off-by: Christoph Anton Mitterer --- ssh_filter_btrbk.sh | 58 +++++++++++++++++++++++++++------------------ 1 file changed, 35 insertions(+), 23 deletions(-) diff --git a/ssh_filter_btrbk.sh b/ssh_filter_btrbk.sh index 3356559..18c1b3f 100755 --- a/ssh_filter_btrbk.sh +++ b/ssh_filter_btrbk.sh @@ -1,7 +1,6 @@ #!/bin/sh -set -e -set -u +set -e -u export PATH='/usr/bin:/bin' @@ -16,44 +15,53 @@ compress_list='gzip|pigz|bzip2|pbzip2|bzip3|xz|lzop|lz4|zstd' # note that the backslash is NOT a metacharacter in a POSIX bracket expression! option_match='-[a-zA-Z0-9=-]+' # matches short as well as long options -file_match_sane='/[0-9a-zA-Z_@+./-]*' # matches file path (equal to $file_match in btrbk < 0.32.0) +file_match_sane='/[0-9a-zA-Z_@+./-]*' # matches file path (equal to ${file_match} in btrbk < 0.32.0) file_match="/[^']*" # btrbk >= 0.32.0 quotes file arguments: match all but single quote file_arg_match="('${file_match}'|${file_match_sane})" # support btrbk < 0.32.0 log_cmd() { - if [ -n "$enable_log" ]; then - logger -p "$1" -t ssh_filter_btrbk.sh "$2 (Name: ${LOGNAME:-}; Connection: ${SSH_CONNECTION:-})${3:+: $3}: $SSH_ORIGINAL_COMMAND" + local priority="$1" + local authorisation_decision="$2" + local reason="${3-}" + + if [ -n "${enable_log}" ]; then + logger -p "${priority}" -t ssh_filter_btrbk.sh "${authorisation_decision} (Name: ${LOGNAME:-}; Connection: ${SSH_CONNECTION:-})${reason:+: ${reason}}: ${SSH_ORIGINAL_COMMAND}" fi } allow_cmd() { - allow_list="${allow_list}|$1" + local cmd="$1" + + allow_list="${allow_list}|${cmd}" } allow_exact_cmd() { - allow_exact_list="${allow_exact_list}|$1" + local cmd="$1" + + allow_exact_list="${allow_exact_list}|${cmd}" } reject_and_die() { local reason="$1" - log_cmd 'auth.err' 'btrbk REJECT' "$reason" - printf 'ERROR: ssh_filter_btrbk.sh: ssh command rejected: %s: %s\n' "$reason" "$SSH_ORIGINAL_COMMAND" 1>&2 + + log_cmd 'auth.err' 'btrbk REJECT' "${reason}" + printf 'ERROR: ssh_filter_btrbk.sh: ssh command rejected: %s: %s\n' "${reason}" "${SSH_ORIGINAL_COMMAND}" >&2 exit 1 } run_cmd() { log_cmd 'auth.info' 'btrbk ACCEPT' - eval " $SSH_ORIGINAL_COMMAND" + eval " ${SSH_ORIGINAL_COMMAND}" } reject_filtered_cmd() { - if [ -n "$restrict_path_list" ]; then + if [ -n "${restrict_path_list}" ]; then # match any of restrict_path_list, # or any file/directory (matching file_match) below restrict_path path_match="'(${restrict_path_list})(${file_match})?'" @@ -66,7 +74,7 @@ reject_filtered_cmd() # btrbk >= 0.32.0 quotes files, allow both (legacy) path_match="(${path_match}|${path_match_legacy})" - if [ -n "$allow_compress" ]; then + if [ -n "${allow_compress}" ]; then decompress_match="(${compress_list}) -d -c( -[pT][0-9]+)?" compress_match="(${compress_list}) -c( -[0-9])?( -[pT][0-9]+)?" else @@ -76,7 +84,7 @@ reject_filtered_cmd() # rate_limit_remote and stream_buffer_remote use combined # "mbuffer" as of btrbk-0.29.0 - if [ -n "$allow_stream_buffer" ] || [ -n "$allow_rate_limit" ]; then + if [ -n "${allow_stream_buffer}" ] || [ -n "${allow_rate_limit}" ]; then mbuffer_match='mbuffer -v 1 -q( -s [0-9]+[kmgKMG]?)?( -m [0-9]+[kmgKMG]?)?( -[rR] [0-9]+[kmgtKMGT]?)?' else mbuffer_match= @@ -91,31 +99,35 @@ reject_filtered_cmd() # when an error occurred. allow_stream_match="^${stream_in_match}${allow_cmd_match}${stream_out_match}" - if printf '%s' "$SSH_ORIGINAL_COMMAND" | grep -E "$allow_stream_match" >/dev/null 2>/dev/null; then + if printf '%s' "${SSH_ORIGINAL_COMMAND}" | grep -E "${allow_stream_match}" >/dev/null 2>/dev/null; then return 0 fi exact_cmd_match="^(${allow_exact_list})$"; - if printf '%s' "$SSH_ORIGINAL_COMMAND" | grep -E "$exact_cmd_match" >/dev/null 2>/dev/null; then + if printf '%s' "${SSH_ORIGINAL_COMMAND}" | grep -E "${exact_cmd_match}" >/dev/null 2>/dev/null; then return 0 fi - local formatted_restrict_path_list="$(printf '%s' "$restrict_path_list" | sed 's/|/", "/g')" - reject_and_die "disallowed command${restrict_path_list:+ (restrict-path: \"$formatted_restrict_path_list\")}" + local formatted_restrict_path_list="$(printf '%s' "${restrict_path_list}" | sed 's/|/", "/g')" + reject_and_die "disallowed command${restrict_path_list:+ (restrict-path: \"${formatted_restrict_path_list}\")}" } # check for "--sudo" option before processing other options sudo_prefix= for key in "$@"; do - [ "$key" = '--sudo' ] && sudo_prefix='sudo -n ' - [ "$key" = '--doas' ] && sudo_prefix='doas -n ' + if [ "${key}" = '--sudo' ]; then + sudo_prefix='sudo -n ' + fi + if [ "${key}" = '--doas' ]; then + sudo_prefix='doas -n ' + fi done while [ "$#" -ge 1 ]; do key="$1" - case "$key" in + case "${key}" in -l|--log) enable_log=1 ;; @@ -165,7 +177,7 @@ while [ "$#" -ge 1 ]; do ;; *) - printf 'ERROR: ssh_filter_btrbk.sh: failed to parse command line option: %s\n' "$key" 1>&2 + printf 'ERROR: ssh_filter_btrbk.sh: failed to parse command line option: %s\n' "${key}" >&2 exit 2 ;; esac @@ -185,7 +197,7 @@ allow_list="${allow_list#\|}" allow_exact_list="${allow_exact_list#\|}" restrict_path_list="${restrict_path_list#\|}" -case "$SSH_ORIGINAL_COMMAND" in +case "${SSH_ORIGINAL_COMMAND}" in *\.\./*) reject_and_die 'directory traversal' ;; *\$*) reject_and_die 'unsafe character "$"' ;; *\&*) reject_and_die 'unsafe character "&"' ;; @@ -195,7 +207,7 @@ case "$SSH_ORIGINAL_COMMAND" in *\<*) reject_and_die 'unsafe character "<"' ;; *\>*) reject_and_die 'unsafe character ">"' ;; *\`*) reject_and_die 'unsafe character "`"' ;; - *\|*) [ -n "$allow_compress" ] || [ -n "$allow_rate_limit" ] || [ -n "$allow_stream_buffer" ] || reject_and_die 'unsafe character "|"' ;; + *\|*) [ -n "${allow_compress}" ] || [ -n "${allow_rate_limit}" ] || [ -n "${allow_stream_buffer}" ] || reject_and_die 'unsafe character "|"' ;; esac reject_filtered_cmd