diff options
author | Julius Goryavsky <julius.goryavsky@mariadb.com> | 2022-02-22 12:34:58 +0100 |
---|---|---|
committer | Julius Goryavsky <julius.goryavsky@mariadb.com> | 2022-02-23 13:03:31 +0100 |
commit | a3da3c8a0b1113d941f837cce0615673b95fb9f2 (patch) | |
tree | b20429167ccff6d9b647945a61451570140ab852 /scripts | |
parent | 8b7abe21e041d616ddb5a68652bc96e97b3eed44 (diff) | |
download | mariadb-git-a3da3c8a0b1113d941f837cce0615673b95fb9f2.tar.gz |
MDEV-26377: Stricter validation of ssl-mode values
This commit adds validation of the values of the ssl-mode parameter
in SSL scripts, since now only a basic check for the presence of the
"VERIFY_" prefix is performed there to detect "VERIFY_IDENTITY" and
"VERIFY_CA", but all other values are not checked at all.
In addition, this commit removes leading and trailing spaces from
parameter values that SST scripts read from configuration files or
from the command line so that they do not interfere with parameter
checks and substitutions. Parameter substitution has been made more
robust against characters in strings that the shell might erroneously
interpret as regexp.
Diffstat (limited to 'scripts')
-rw-r--r-- | scripts/wsrep_sst_common.sh | 91 | ||||
-rw-r--r-- | scripts/wsrep_sst_mariabackup.sh | 26 | ||||
-rw-r--r-- | scripts/wsrep_sst_rsync.sh | 30 | ||||
-rw-r--r-- | scripts/wsrep_sst_xtrabackup-v2.sh | 26 |
4 files changed, 87 insertions, 86 deletions
diff --git a/scripts/wsrep_sst_common.sh b/scripts/wsrep_sst_common.sh index 6d4def74b86..d4d9a58897d 100644 --- a/scripts/wsrep_sst_common.sh +++ b/scripts/wsrep_sst_common.sh @@ -99,7 +99,6 @@ WSREP_SST_OPT_ADDR="" WSREP_SST_OPT_ADDR_PORT="" WSREP_SST_OPT_HOST="" WSREP_SST_OPT_HOST_UNESCAPED="" -WSREP_SST_OPT_HOST_ESCAPED="" INNODB_DATA_HOME_DIR=$(trim_dir "${INNODB_DATA_HOME_DIR:-}") INNODB_LOG_GROUP_HOME=$(trim_dir "${INNODB_LOG_GROUP_HOME:-}") INNODB_UNDO_DIR=$(trim_dir "${INNODB_UNDO_DIR:-}") @@ -122,20 +121,22 @@ case "$1" in # without square brackets: readonly WSREP_SST_OPT_HOST_UNESCAPED="${addr_no_bracket%%\]*}" # Square brackets are needed in most cases: - readonly WSREP_SST_OPT_HOST="[${WSREP_SST_OPT_HOST_UNESCAPED}]" - readonly WSREP_SST_OPT_HOST_ESCAPED="\\[${WSREP_SST_OPT_HOST_UNESCAPED}\\]" + readonly WSREP_SST_OPT_HOST="[$WSREP_SST_OPT_HOST_UNESCAPED]" # Mark this address as IPv6: readonly WSREP_SST_OPT_HOST_IPv6=1 + # Let's remove the leading part that contains the host address: + remain="${WSREP_SST_OPT_ADDR#*\]}" ;; *) readonly WSREP_SST_OPT_HOST="${WSREP_SST_OPT_ADDR%%[:/]*}" readonly WSREP_SST_OPT_HOST_UNESCAPED="$WSREP_SST_OPT_HOST" - readonly WSREP_SST_OPT_HOST_ESCAPED="$WSREP_SST_OPT_HOST" readonly WSREP_SST_OPT_HOST_IPv6=0 + # Let's remove the leading part that contains the host address: + remain="${WSREP_SST_OPT_ADDR#*[:/]}" ;; esac - # Let's remove the leading part that contains the host address: - remain="${WSREP_SST_OPT_ADDR#$WSREP_SST_OPT_HOST_ESCAPED}" + # If there is nothing but the address, then the remainder is empty: + [ "$remain" = "$WSREP_SST_OPT_ADDR" ] && remain="" # Let's remove the ":" character that separates the port number # from the hostname: remain="${remain#:}" @@ -143,39 +144,32 @@ case "$1" in # up to "/" (if present): WSREP_SST_OPT_ADDR_PORT="${remain%%/*}" # If the "/" character is present, then the path is not empty: - if [ "${remain#*/}" != "$remain" ]; then + if [ "$WSREP_SST_OPT_ADDR_PORT" != "$remain" ]; then # This operation removes everything up to the "/" character, # effectively removing the port number from the string: readonly WSREP_SST_OPT_PATH="${remain#*/}" else readonly WSREP_SST_OPT_PATH="" fi - # The rest of the string is the same as the path (for now): - remain="$WSREP_SST_OPT_PATH" - # If there is one more "/" in the string, then everything before - # it will be the module name, otherwise the module name is empty: - if [ "${remain%%/*}" != "$remain" ]; then - # This operation removes the tail after the very first - # occurrence of the "/" character (inclusively): - readonly WSREP_SST_OPT_MODULE="${remain%%/*}" - else - readonly WSREP_SST_OPT_MODULE="" - fi # Remove the module name part from the string, which ends with "/": remain="${WSREP_SST_OPT_PATH#*/}" - # If the rest of the string does not match the original, then there - # was something else besides the module name: + # This operation removes the tail after the very first occurrence + # of the "/" character, inclusively: + readonly WSREP_SST_OPT_MODULE="${WSREP_SST_OPT_PATH%%/*}" + # If there is one more "/" in the string, then everything before + # it will be the LSN, otherwise the LSN is empty: if [ "$remain" != "$WSREP_SST_OPT_PATH" ]; then # Extract the part that matches the LSN by removing all # characters starting from the very first "/": readonly WSREP_SST_OPT_LSN="${remain%%/*}" # Exctract everything after the first occurrence of # the "/" character in the string: + source="$remain" remain="${remain#*/}" # If the remainder does not match the original string, # then there is something else (the version number in # our case): - if [ "$remain" != "$WSREP_SST_OPT_LSN" ]; then + if [ "$remain" != "$source" ]; then # Let's extract the version number by removing the tail # after the very first occurence of the "/" character # (inclusively): @@ -238,14 +232,12 @@ case "$1" in readonly WSREP_SST_OPT_HOST_UNESCAPED="${addr_no_bracket%%\]*}" # Square brackets are needed in most cases: readonly WSREP_SST_OPT_HOST="[${WSREP_SST_OPT_HOST_UNESCAPED}]" - readonly WSREP_SST_OPT_HOST_ESCAPED="\\[${WSREP_SST_OPT_HOST_UNESCAPED}\\]" # Mark this address as IPv6: readonly WSREP_SST_OPT_HOST_IPv6=1 ;; *) readonly WSREP_SST_OPT_HOST="$2" readonly WSREP_SST_OPT_HOST_UNESCAPED="$2" - readonly WSREP_SST_OPT_HOST_ESCAPED="$2" readonly WSREP_SST_OPT_HOST_IPv6=0 ;; esac @@ -475,25 +467,25 @@ case "$1" in ;; '--innodb-force-recovery') if [ -n "$value" -a "$value" != "0" ]; then - INNODB_FORCE_RECOVERY="$value" + INNODB_FORCE_RECOVERY=$(trim_string "$value") fi skip_mysqld_arg=1 ;; '--log-bin') if [ -z "$WSREP_SST_OPT_BINLOG" ]; then - MYSQLD_OPT_LOG_BIN="$value" + MYSQLD_OPT_LOG_BIN=$(trim_string "$value") fi skip_mysqld_arg=1 ;; '--log-bin-index') if [ -z "$WSREP_SST_OPT_BINLOG_INDEX" ]; then - MYSQLD_OPT_LOG_BIN_INDEX="$value" + MYSQLD_OPT_LOG_BIN_INDEX=$(trim_string "$value") fi skip_mysqld_arg=1 ;; '--log-basename') if [ -z "$WSREP_SST_OPT_LOG_BASENAME" ]; then - MYSQLD_OPT_LOG_BASENAME="$value" + MYSQLD_OPT_LOG_BASENAME=$(trim_string "$value") fi skip_mysqld_arg=1 ;; @@ -678,27 +670,18 @@ if [ -n "$WSREP_SST_OPT_ADDR_PORT" ]; then # the corresponding variable: readonly WSREP_SST_OPT_PORT="$WSREP_SST_OPT_ADDR_PORT" fi -elif [ -n "$WSREP_SST_OPT_ADDR" ]; then +else # If the port is missing, take the default port: if [ -z "$WSREP_SST_OPT_PORT" ]; then readonly WSREP_SST_OPT_PORT=4444 fi WSREP_SST_OPT_ADDR_PORT="$WSREP_SST_OPT_PORT" - # Let's remove the leading part that contains the host address: - remain="${WSREP_SST_OPT_ADDR#$WSREP_SST_OPT_HOST_ESCAPED}" - # Let's remove the ":" character that separates the port number - # from the hostname: - remain="${remain#:}" - # Let's remove all characters upto first "/" character that - # separates the hostname with port number from the path: - remain="${remain#/}" - # Let's construct a new value for the address with the port: - WSREP_SST_OPT_ADDR="$WSREP_SST_OPT_HOST:$WSREP_SST_OPT_PORT" - if [ -n "$remain" ]; then - WSREP_SST_OPT_ADDR="$WSREP_SST_OPT_ADDR/$remain" - fi fi +# Let's construct a new value for the address with the port: +sst_path="${WSREP_SST_OPT_PATH:+/}$WSREP_SST_OPT_PATH" +WSREP_SST_OPT_ADDR="$WSREP_SST_OPT_HOST:$WSREP_SST_OPT_PORT$sst_path" + readonly WSREP_SST_OPT_ADDR readonly WSREP_SST_OPT_ADDR_PORT @@ -809,8 +792,11 @@ parse_cnf() local group="${groups%%\|*}" # Remove the remainder (the group name) from the rest # of the groups list (as if it were a prefix): - groups="${groups#$group}" - groups="${groups#\|}" + if [ "$group" != "$groups" ]; then + groups="${groups#*\|}" + else + groups="" + fi # If the group name is the same as the "mysqld" without "--" prefix, # then try to use it together with the group suffix: if [ "$group" = 'mysqld' -a -n "$WSREP_SST_OPT_SUFFIX_VALUE" ]; then @@ -835,9 +821,11 @@ parse_cnf() done # Use default if we haven't found a value: - if [ -z "$reval" ]; then - [ -n "${3:-}" ] && reval="$3" - fi + [ -z "$reval" ] && reval="${3:-}" + + # Truncate spaces: + [ -n "$reval" ] && reval=$(trim_string "$reval") + if [ -n "$BASH_VERSION" ]; then printf '%s' "$reval" else @@ -868,8 +856,11 @@ in_config() local group="${groups%%\|*}" # Remove the remainder (the group name) from the rest # of the groups list (as if it were a prefix): - groups="${groups#$group}" - groups="${groups#\|}" + if [ "$group" != "$groups" ]; then + groups="${groups#*\|}" + else + groups="" + fi # If the group name is the same as the "mysqld" without "--" prefix, # then try to use it together with the group suffix: if [ "$group" = 'mysqld' -a -n "$WSREP_SST_OPT_SUFFIX_VALUE" ]; then @@ -1455,13 +1446,9 @@ check_server_ssl_config() fi fi if [ -n "$tcert" ]; then - tcert=$(trim_string "$tcert") if [ "${tcert%/}" != "$tcert" -o -d "$tcert" ]; then tcap="$tcert" tcert="" fi fi - if [ -n "$tcap" ]; then - tcap=$(trim_string "$tcap") - fi } diff --git a/scripts/wsrep_sst_mariabackup.sh b/scripts/wsrep_sst_mariabackup.sh index a15a3f7b7a5..ce4001fdc56 100644 --- a/scripts/wsrep_sst_mariabackup.sh +++ b/scripts/wsrep_sst_mariabackup.sh @@ -40,7 +40,7 @@ tcert="" tcap="" tpem="" tkey="" -tmode='DISABLED' +tmode="" sockopt="" progress="" ttime=0 @@ -474,6 +474,15 @@ read_cnf() tmode=$(parse_cnf "$encgroups" 'ssl-mode' 'DISABLED' | \ tr [:lower:] [:upper:]) + case "$tmode" in + 'VERIFY_IDENTITY'|'VERIFY_CA'|'REQUIRED'|'DISABLED') + ;; + *) + wsrep_log_error "Unrecognized ssl-mode option: '$tmode'" + exit 22 # EINVAL + ;; + esac + if [ $encrypt -eq 0 -o $encrypt -ge 2 ]; then if [ "$tmode" != 'DISABLED' -o $encrypt -ge 2 ]; then check_server_ssl_config @@ -667,16 +676,13 @@ setup_ports() # wait_for_listen() { - local PORT="$1" - local ADDR="$2" - local MODULE="$3" for i in {1..150}; do - if check_port "" "$PORT" 'socat|nc'; then + if check_port "" "$SST_PORT" 'socat|nc'; then break fi sleep 0.2 done - echo "ready $ADDR/$MODULE//$sst_ver" + echo "ready $ADDR:$SST_PORT/$MODULE/$lsn/$sst_ver" } check_extra() @@ -733,7 +739,7 @@ recv_joiner() set +e if [ $wait -ne 0 ]; then - wait_for_listen "$SST_PORT" "$ADDR" "$MODULE" & + wait_for_listen & fi timeit "$msg" "$ltcmd | $strmcmd; RC=( "\${PIPESTATUS[@]}" )" @@ -1179,7 +1185,7 @@ then stagemsg='Joiner-Recv' - MODULE='xtrabackup_sst' + MODULE="${WSREP_SST_OPT_MODULE:-xtrabackup_sst}" [ -f "$DATA/$IST_FILE" ] && rm -f "$DATA/$IST_FILE" @@ -1187,7 +1193,7 @@ then [ -f "$DATA/xtrabackup_binary" ] && rm -f "$DATA/xtrabackup_binary" [ -f "$DATA/xtrabackup_galera_info" ] && rm -f "$DATA/xtrabackup_galera_info" - ADDR="$WSREP_SST_OPT_ADDR" + ADDR="$WSREP_SST_OPT_HOST" if [ "${tmode#VERIFY}" != "$tmode" ]; then # backward-incompatible behavior: @@ -1201,7 +1207,7 @@ then exit 42 fi CN=$("$OPENSSL_BINARY" x509 -noout -subject -in "$tpem" | \ - tr ',' '\n' | grep -F 'CN =' | cut -d= -f2 | sed s/^\ // | \ + tr ',' '\n' | grep -F 'CN =' | cut -d '=' -f2 | sed s/^\ // | \ sed s/\ %//) fi MY_SECRET="$(wsrep_gen_secret)" diff --git a/scripts/wsrep_sst_rsync.sh b/scripts/wsrep_sst_rsync.sh index 54160fd19a2..67a7afc638f 100644 --- a/scripts/wsrep_sst_rsync.sh +++ b/scripts/wsrep_sst_rsync.sh @@ -238,6 +238,15 @@ if [ -z "$SSLMODE" ]; then elif [ -n "$SSTKEY" -a -n "$SSTCERT" ]; then SSLMODE='REQUIRED' fi +else + case "$SSLMODE" in + 'VERIFY_IDENTITY'|'VERIFY_CA'|'REQUIRED'|'DISABLED') + ;; + *) + wsrep_log_error "Unrecognized ssl-mode option: '$SSLMODE'" + exit 22 # EINVAL + ;; + esac fi if [ -n "$SSTKEY" -a -n "$SSTCERT" ]; then @@ -262,18 +271,11 @@ VERIFY_OPT="" CHECK_OPT="" CHECK_OPT_LOCAL="" if [ "${SSLMODE#VERIFY}" != "$SSLMODE" ]; then - case "$SSLMODE" in - 'VERIFY_IDENTITY') + if [ "$SSLMODE" = 'VERIFY_IDENTITY' ]; then VERIFY_OPT='verifyPeer = yes' - ;; - 'VERIFY_CA') + else VERIFY_OPT='verifyChain = yes' - ;; - *) - wsrep_log_error "Unrecognized ssl-mode option: '$SSLMODE'" - exit 22 # EINVAL - ;; - esac + fi if [ -z "$SSTCA$SSTCAP" ]; then wsrep_log_error "Can't have ssl-mode='$SSLMODE' without CA file or path" exit 22 # EINVAL @@ -338,7 +340,8 @@ while check_pid "$STUNNEL_PID" 1 "$STUNNEL_CONF"; do sleep 1 done -MODULE='rsync_sst' +MODULE="${WSREP_SST_OPT_MODULE:-rsync_sst}" + RSYNC_PID="$WSREP_SST_OPT_DATA/$MODULE.pid" RSYNC_CONF="$WSREP_SST_OPT_DATA/$MODULE.conf" @@ -650,7 +653,7 @@ elif [ "$WSREP_SST_OPT_ROLE" = 'joiner' ] then check_sockets_utils - ADDR="$WSREP_SST_OPT_ADDR" + ADDR="$WSREP_SST_OPT_HOST" RSYNC_PORT="$WSREP_SST_OPT_PORT" RSYNC_ADDR="$WSREP_SST_OPT_HOST" RSYNC_ADDR_UNESCAPED="$WSREP_SST_OPT_HOST_UNESCAPED" @@ -751,7 +754,7 @@ EOF fi if [ "${SSLMODE#VERIFY}" != "$SSLMODE" ]; then - # backward-incompatible behavior + # backward-incompatible behavior: CN="" if [ -n "$SSTCERT" ]; then # find out my Common Name @@ -770,7 +773,6 @@ EOF ADDR="$CN:$MY_SECRET@$WSREP_SST_OPT_HOST" else MY_SECRET="" # for check down in recv_joiner() - ADDR="$WSREP_SST_OPT_HOST" fi until check_pid_and_port "$TRANSFER_PID" $TRANSFER_REAL_PID \ diff --git a/scripts/wsrep_sst_xtrabackup-v2.sh b/scripts/wsrep_sst_xtrabackup-v2.sh index e7cd77396fe..747378aced8 100644 --- a/scripts/wsrep_sst_xtrabackup-v2.sh +++ b/scripts/wsrep_sst_xtrabackup-v2.sh @@ -41,7 +41,7 @@ tcert="" tcap="" tpem="" tkey="" -tmode='DISABLED' +tmode="" sockopt="" progress="" ttime=0 @@ -479,6 +479,15 @@ read_cnf() tmode=$(parse_cnf "$encgroups" 'ssl-mode' 'DISABLED' | \ tr [:lower:] [:upper:]) + case "$tmode" in + 'VERIFY_IDENTITY'|'VERIFY_CA'|'REQUIRED'|'DISABLED') + ;; + *) + wsrep_log_error "Unrecognized ssl-mode option: '$tmode'" + exit 22 # EINVAL + ;; + esac + if [ $encrypt -eq 0 -o $encrypt -ge 2 ]; then if [ "$tmode" != 'DISABLED' -o $encrypt -ge 2 ]; then check_server_ssl_config @@ -679,16 +688,13 @@ setup_ports() # wait_for_listen() { - local PORT="$1" - local ADDR="$2" - local MODULE="$3" for i in {1..150}; do - if check_port "" "$PORT" 'socat|nc'; then + if check_port "" "$SST_PORT" 'socat|nc'; then break fi sleep 0.2 done - echo "ready $ADDR/$MODULE//$sst_ver" + echo "ready $ADDR:$SST_PORT/$MODULE/$lsn/$sst_ver" } check_extra() @@ -745,7 +751,7 @@ recv_joiner() set +e if [ $wait -ne 0 ]; then - wait_for_listen "$SST_PORT" "$ADDR" "$MODULE" & + wait_for_listen & fi timeit "$msg" "$ltcmd | $strmcmd; RC=( "\${PIPESTATUS[@]}" )" @@ -1206,7 +1212,7 @@ then stagemsg='Joiner-Recv' - MODULE='xtrabackup_sst' + MODULE="${WSREP_SST_OPT_MODULE:-xtrabackup_sst}" [ -f "$DATA/$IST_FILE" ] && rm -f "$DATA/$IST_FILE" @@ -1214,7 +1220,7 @@ then [ -f "$DATA/xtrabackup_binary" ] && rm -f "$DATA/xtrabackup_binary" [ -f "$DATA/xtrabackup_galera_info" ] && rm -f "$DATA/xtrabackup_galera_info" - ADDR="$WSREP_SST_OPT_ADDR" + ADDR="$WSREP_SST_OPT_HOST" if [ "${tmode#VERIFY}" != "$tmode" ]; then # backward-incompatible behavior: @@ -1228,7 +1234,7 @@ then exit 42 fi CN=$("$OPENSSL_BINARY" x509 -noout -subject -in "$tpem" | \ - tr ',' '\n' | grep -F 'CN =' | cut -d= -f2 | sed s/^\ // | \ + tr ',' '\n' | grep -F 'CN =' | cut -d '=' -f2 | sed s/^\ // | \ sed s/\ %//) fi MY_SECRET="$(wsrep_gen_secret)" |