Skip to content

Commit a3da3c8

Browse files
committed
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.
1 parent 8b7abe2 commit a3da3c8

File tree

4 files changed

+87
-86
lines changed

4 files changed

+87
-86
lines changed

scripts/wsrep_sst_common.sh

Lines changed: 39 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,6 @@ WSREP_SST_OPT_ADDR=""
9999
WSREP_SST_OPT_ADDR_PORT=""
100100
WSREP_SST_OPT_HOST=""
101101
WSREP_SST_OPT_HOST_UNESCAPED=""
102-
WSREP_SST_OPT_HOST_ESCAPED=""
103102
INNODB_DATA_HOME_DIR=$(trim_dir "${INNODB_DATA_HOME_DIR:-}")
104103
INNODB_LOG_GROUP_HOME=$(trim_dir "${INNODB_LOG_GROUP_HOME:-}")
105104
INNODB_UNDO_DIR=$(trim_dir "${INNODB_UNDO_DIR:-}")
@@ -122,60 +121,55 @@ case "$1" in
122121
# without square brackets:
123122
readonly WSREP_SST_OPT_HOST_UNESCAPED="${addr_no_bracket%%\]*}"
124123
# Square brackets are needed in most cases:
125-
readonly WSREP_SST_OPT_HOST="[${WSREP_SST_OPT_HOST_UNESCAPED}]"
126-
readonly WSREP_SST_OPT_HOST_ESCAPED="\\[${WSREP_SST_OPT_HOST_UNESCAPED}\\]"
124+
readonly WSREP_SST_OPT_HOST="[$WSREP_SST_OPT_HOST_UNESCAPED]"
127125
# Mark this address as IPv6:
128126
readonly WSREP_SST_OPT_HOST_IPv6=1
127+
# Let's remove the leading part that contains the host address:
128+
remain="${WSREP_SST_OPT_ADDR#*\]}"
129129
;;
130130
*)
131131
readonly WSREP_SST_OPT_HOST="${WSREP_SST_OPT_ADDR%%[:/]*}"
132132
readonly WSREP_SST_OPT_HOST_UNESCAPED="$WSREP_SST_OPT_HOST"
133-
readonly WSREP_SST_OPT_HOST_ESCAPED="$WSREP_SST_OPT_HOST"
134133
readonly WSREP_SST_OPT_HOST_IPv6=0
134+
# Let's remove the leading part that contains the host address:
135+
remain="${WSREP_SST_OPT_ADDR#*[:/]}"
135136
;;
136137
esac
137-
# Let's remove the leading part that contains the host address:
138-
remain="${WSREP_SST_OPT_ADDR#$WSREP_SST_OPT_HOST_ESCAPED}"
138+
# If there is nothing but the address, then the remainder is empty:
139+
[ "$remain" = "$WSREP_SST_OPT_ADDR" ] && remain=""
139140
# Let's remove the ":" character that separates the port number
140141
# from the hostname:
141142
remain="${remain#:}"
142143
# Extract the port number from the address - all characters
143144
# up to "/" (if present):
144145
WSREP_SST_OPT_ADDR_PORT="${remain%%/*}"
145146
# If the "/" character is present, then the path is not empty:
146-
if [ "${remain#*/}" != "$remain" ]; then
147+
if [ "$WSREP_SST_OPT_ADDR_PORT" != "$remain" ]; then
147148
# This operation removes everything up to the "/" character,
148149
# effectively removing the port number from the string:
149150
readonly WSREP_SST_OPT_PATH="${remain#*/}"
150151
else
151152
readonly WSREP_SST_OPT_PATH=""
152153
fi
153-
# The rest of the string is the same as the path (for now):
154-
remain="$WSREP_SST_OPT_PATH"
155-
# If there is one more "/" in the string, then everything before
156-
# it will be the module name, otherwise the module name is empty:
157-
if [ "${remain%%/*}" != "$remain" ]; then
158-
# This operation removes the tail after the very first
159-
# occurrence of the "/" character (inclusively):
160-
readonly WSREP_SST_OPT_MODULE="${remain%%/*}"
161-
else
162-
readonly WSREP_SST_OPT_MODULE=""
163-
fi
164154
# Remove the module name part from the string, which ends with "/":
165155
remain="${WSREP_SST_OPT_PATH#*/}"
166-
# If the rest of the string does not match the original, then there
167-
# was something else besides the module name:
156+
# This operation removes the tail after the very first occurrence
157+
# of the "/" character, inclusively:
158+
readonly WSREP_SST_OPT_MODULE="${WSREP_SST_OPT_PATH%%/*}"
159+
# If there is one more "/" in the string, then everything before
160+
# it will be the LSN, otherwise the LSN is empty:
168161
if [ "$remain" != "$WSREP_SST_OPT_PATH" ]; then
169162
# Extract the part that matches the LSN by removing all
170163
# characters starting from the very first "/":
171164
readonly WSREP_SST_OPT_LSN="${remain%%/*}"
172165
# Exctract everything after the first occurrence of
173166
# the "/" character in the string:
167+
source="$remain"
174168
remain="${remain#*/}"
175169
# If the remainder does not match the original string,
176170
# then there is something else (the version number in
177171
# our case):
178-
if [ "$remain" != "$WSREP_SST_OPT_LSN" ]; then
172+
if [ "$remain" != "$source" ]; then
179173
# Let's extract the version number by removing the tail
180174
# after the very first occurence of the "/" character
181175
# (inclusively):
@@ -238,14 +232,12 @@ case "$1" in
238232
readonly WSREP_SST_OPT_HOST_UNESCAPED="${addr_no_bracket%%\]*}"
239233
# Square brackets are needed in most cases:
240234
readonly WSREP_SST_OPT_HOST="[${WSREP_SST_OPT_HOST_UNESCAPED}]"
241-
readonly WSREP_SST_OPT_HOST_ESCAPED="\\[${WSREP_SST_OPT_HOST_UNESCAPED}\\]"
242235
# Mark this address as IPv6:
243236
readonly WSREP_SST_OPT_HOST_IPv6=1
244237
;;
245238
*)
246239
readonly WSREP_SST_OPT_HOST="$2"
247240
readonly WSREP_SST_OPT_HOST_UNESCAPED="$2"
248-
readonly WSREP_SST_OPT_HOST_ESCAPED="$2"
249241
readonly WSREP_SST_OPT_HOST_IPv6=0
250242
;;
251243
esac
@@ -475,25 +467,25 @@ case "$1" in
475467
;;
476468
'--innodb-force-recovery')
477469
if [ -n "$value" -a "$value" != "0" ]; then
478-
INNODB_FORCE_RECOVERY="$value"
470+
INNODB_FORCE_RECOVERY=$(trim_string "$value")
479471
fi
480472
skip_mysqld_arg=1
481473
;;
482474
'--log-bin')
483475
if [ -z "$WSREP_SST_OPT_BINLOG" ]; then
484-
MYSQLD_OPT_LOG_BIN="$value"
476+
MYSQLD_OPT_LOG_BIN=$(trim_string "$value")
485477
fi
486478
skip_mysqld_arg=1
487479
;;
488480
'--log-bin-index')
489481
if [ -z "$WSREP_SST_OPT_BINLOG_INDEX" ]; then
490-
MYSQLD_OPT_LOG_BIN_INDEX="$value"
482+
MYSQLD_OPT_LOG_BIN_INDEX=$(trim_string "$value")
491483
fi
492484
skip_mysqld_arg=1
493485
;;
494486
'--log-basename')
495487
if [ -z "$WSREP_SST_OPT_LOG_BASENAME" ]; then
496-
MYSQLD_OPT_LOG_BASENAME="$value"
488+
MYSQLD_OPT_LOG_BASENAME=$(trim_string "$value")
497489
fi
498490
skip_mysqld_arg=1
499491
;;
@@ -678,27 +670,18 @@ if [ -n "$WSREP_SST_OPT_ADDR_PORT" ]; then
678670
# the corresponding variable:
679671
readonly WSREP_SST_OPT_PORT="$WSREP_SST_OPT_ADDR_PORT"
680672
fi
681-
elif [ -n "$WSREP_SST_OPT_ADDR" ]; then
673+
else
682674
# If the port is missing, take the default port:
683675
if [ -z "$WSREP_SST_OPT_PORT" ]; then
684676
readonly WSREP_SST_OPT_PORT=4444
685677
fi
686678
WSREP_SST_OPT_ADDR_PORT="$WSREP_SST_OPT_PORT"
687-
# Let's remove the leading part that contains the host address:
688-
remain="${WSREP_SST_OPT_ADDR#$WSREP_SST_OPT_HOST_ESCAPED}"
689-
# Let's remove the ":" character that separates the port number
690-
# from the hostname:
691-
remain="${remain#:}"
692-
# Let's remove all characters upto first "/" character that
693-
# separates the hostname with port number from the path:
694-
remain="${remain#/}"
695-
# Let's construct a new value for the address with the port:
696-
WSREP_SST_OPT_ADDR="$WSREP_SST_OPT_HOST:$WSREP_SST_OPT_PORT"
697-
if [ -n "$remain" ]; then
698-
WSREP_SST_OPT_ADDR="$WSREP_SST_OPT_ADDR/$remain"
699-
fi
700679
fi
701680

681+
# Let's construct a new value for the address with the port:
682+
sst_path="${WSREP_SST_OPT_PATH:+/}$WSREP_SST_OPT_PATH"
683+
WSREP_SST_OPT_ADDR="$WSREP_SST_OPT_HOST:$WSREP_SST_OPT_PORT$sst_path"
684+
702685
readonly WSREP_SST_OPT_ADDR
703686
readonly WSREP_SST_OPT_ADDR_PORT
704687

@@ -809,8 +792,11 @@ parse_cnf()
809792
local group="${groups%%\|*}"
810793
# Remove the remainder (the group name) from the rest
811794
# of the groups list (as if it were a prefix):
812-
groups="${groups#$group}"
813-
groups="${groups#\|}"
795+
if [ "$group" != "$groups" ]; then
796+
groups="${groups#*\|}"
797+
else
798+
groups=""
799+
fi
814800
# If the group name is the same as the "mysqld" without "--" prefix,
815801
# then try to use it together with the group suffix:
816802
if [ "$group" = 'mysqld' -a -n "$WSREP_SST_OPT_SUFFIX_VALUE" ]; then
@@ -835,9 +821,11 @@ parse_cnf()
835821
done
836822

837823
# Use default if we haven't found a value:
838-
if [ -z "$reval" ]; then
839-
[ -n "${3:-}" ] && reval="$3"
840-
fi
824+
[ -z "$reval" ] && reval="${3:-}"
825+
826+
# Truncate spaces:
827+
[ -n "$reval" ] && reval=$(trim_string "$reval")
828+
841829
if [ -n "$BASH_VERSION" ]; then
842830
printf '%s' "$reval"
843831
else
@@ -868,8 +856,11 @@ in_config()
868856
local group="${groups%%\|*}"
869857
# Remove the remainder (the group name) from the rest
870858
# of the groups list (as if it were a prefix):
871-
groups="${groups#$group}"
872-
groups="${groups#\|}"
859+
if [ "$group" != "$groups" ]; then
860+
groups="${groups#*\|}"
861+
else
862+
groups=""
863+
fi
873864
# If the group name is the same as the "mysqld" without "--" prefix,
874865
# then try to use it together with the group suffix:
875866
if [ "$group" = 'mysqld' -a -n "$WSREP_SST_OPT_SUFFIX_VALUE" ]; then
@@ -1455,13 +1446,9 @@ check_server_ssl_config()
14551446
fi
14561447
fi
14571448
if [ -n "$tcert" ]; then
1458-
tcert=$(trim_string "$tcert")
14591449
if [ "${tcert%/}" != "$tcert" -o -d "$tcert" ]; then
14601450
tcap="$tcert"
14611451
tcert=""
14621452
fi
14631453
fi
1464-
if [ -n "$tcap" ]; then
1465-
tcap=$(trim_string "$tcap")
1466-
fi
14671454
}

scripts/wsrep_sst_mariabackup.sh

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ tcert=""
4040
tcap=""
4141
tpem=""
4242
tkey=""
43-
tmode='DISABLED'
43+
tmode=""
4444
sockopt=""
4545
progress=""
4646
ttime=0
@@ -474,6 +474,15 @@ read_cnf()
474474
tmode=$(parse_cnf "$encgroups" 'ssl-mode' 'DISABLED' | \
475475
tr [:lower:] [:upper:])
476476

477+
case "$tmode" in
478+
'VERIFY_IDENTITY'|'VERIFY_CA'|'REQUIRED'|'DISABLED')
479+
;;
480+
*)
481+
wsrep_log_error "Unrecognized ssl-mode option: '$tmode'"
482+
exit 22 # EINVAL
483+
;;
484+
esac
485+
477486
if [ $encrypt -eq 0 -o $encrypt -ge 2 ]; then
478487
if [ "$tmode" != 'DISABLED' -o $encrypt -ge 2 ]; then
479488
check_server_ssl_config
@@ -667,16 +676,13 @@ setup_ports()
667676
#
668677
wait_for_listen()
669678
{
670-
local PORT="$1"
671-
local ADDR="$2"
672-
local MODULE="$3"
673679
for i in {1..150}; do
674-
if check_port "" "$PORT" 'socat|nc'; then
680+
if check_port "" "$SST_PORT" 'socat|nc'; then
675681
break
676682
fi
677683
sleep 0.2
678684
done
679-
echo "ready $ADDR/$MODULE//$sst_ver"
685+
echo "ready $ADDR:$SST_PORT/$MODULE/$lsn/$sst_ver"
680686
}
681687

682688
check_extra()
@@ -733,7 +739,7 @@ recv_joiner()
733739
set +e
734740

735741
if [ $wait -ne 0 ]; then
736-
wait_for_listen "$SST_PORT" "$ADDR" "$MODULE" &
742+
wait_for_listen &
737743
fi
738744

739745
timeit "$msg" "$ltcmd | $strmcmd; RC=( "\${PIPESTATUS[@]}" )"
@@ -1179,15 +1185,15 @@ then
11791185

11801186
stagemsg='Joiner-Recv'
11811187

1182-
MODULE='xtrabackup_sst'
1188+
MODULE="${WSREP_SST_OPT_MODULE:-xtrabackup_sst}"
11831189

11841190
[ -f "$DATA/$IST_FILE" ] && rm -f "$DATA/$IST_FILE"
11851191

11861192
# May need xtrabackup_checkpoints later on
11871193
[ -f "$DATA/xtrabackup_binary" ] && rm -f "$DATA/xtrabackup_binary"
11881194
[ -f "$DATA/xtrabackup_galera_info" ] && rm -f "$DATA/xtrabackup_galera_info"
11891195

1190-
ADDR="$WSREP_SST_OPT_ADDR"
1196+
ADDR="$WSREP_SST_OPT_HOST"
11911197

11921198
if [ "${tmode#VERIFY}" != "$tmode" ]; then
11931199
# backward-incompatible behavior:
@@ -1201,7 +1207,7 @@ then
12011207
exit 42
12021208
fi
12031209
CN=$("$OPENSSL_BINARY" x509 -noout -subject -in "$tpem" | \
1204-
tr ',' '\n' | grep -F 'CN =' | cut -d= -f2 | sed s/^\ // | \
1210+
tr ',' '\n' | grep -F 'CN =' | cut -d '=' -f2 | sed s/^\ // | \
12051211
sed s/\ %//)
12061212
fi
12071213
MY_SECRET="$(wsrep_gen_secret)"

scripts/wsrep_sst_rsync.sh

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,15 @@ if [ -z "$SSLMODE" ]; then
238238
elif [ -n "$SSTKEY" -a -n "$SSTCERT" ]; then
239239
SSLMODE='REQUIRED'
240240
fi
241+
else
242+
case "$SSLMODE" in
243+
'VERIFY_IDENTITY'|'VERIFY_CA'|'REQUIRED'|'DISABLED')
244+
;;
245+
*)
246+
wsrep_log_error "Unrecognized ssl-mode option: '$SSLMODE'"
247+
exit 22 # EINVAL
248+
;;
249+
esac
241250
fi
242251

243252
if [ -n "$SSTKEY" -a -n "$SSTCERT" ]; then
@@ -262,18 +271,11 @@ VERIFY_OPT=""
262271
CHECK_OPT=""
263272
CHECK_OPT_LOCAL=""
264273
if [ "${SSLMODE#VERIFY}" != "$SSLMODE" ]; then
265-
case "$SSLMODE" in
266-
'VERIFY_IDENTITY')
274+
if [ "$SSLMODE" = 'VERIFY_IDENTITY' ]; then
267275
VERIFY_OPT='verifyPeer = yes'
268-
;;
269-
'VERIFY_CA')
276+
else
270277
VERIFY_OPT='verifyChain = yes'
271-
;;
272-
*)
273-
wsrep_log_error "Unrecognized ssl-mode option: '$SSLMODE'"
274-
exit 22 # EINVAL
275-
;;
276-
esac
278+
fi
277279
if [ -z "$SSTCA$SSTCAP" ]; then
278280
wsrep_log_error "Can't have ssl-mode='$SSLMODE' without CA file or path"
279281
exit 22 # EINVAL
@@ -338,7 +340,8 @@ while check_pid "$STUNNEL_PID" 1 "$STUNNEL_CONF"; do
338340
sleep 1
339341
done
340342

341-
MODULE='rsync_sst'
343+
MODULE="${WSREP_SST_OPT_MODULE:-rsync_sst}"
344+
342345
RSYNC_PID="$WSREP_SST_OPT_DATA/$MODULE.pid"
343346
RSYNC_CONF="$WSREP_SST_OPT_DATA/$MODULE.conf"
344347

@@ -650,7 +653,7 @@ elif [ "$WSREP_SST_OPT_ROLE" = 'joiner' ]
650653
then
651654
check_sockets_utils
652655

653-
ADDR="$WSREP_SST_OPT_ADDR"
656+
ADDR="$WSREP_SST_OPT_HOST"
654657
RSYNC_PORT="$WSREP_SST_OPT_PORT"
655658
RSYNC_ADDR="$WSREP_SST_OPT_HOST"
656659
RSYNC_ADDR_UNESCAPED="$WSREP_SST_OPT_HOST_UNESCAPED"
@@ -751,7 +754,7 @@ EOF
751754
fi
752755

753756
if [ "${SSLMODE#VERIFY}" != "$SSLMODE" ]; then
754-
# backward-incompatible behavior
757+
# backward-incompatible behavior:
755758
CN=""
756759
if [ -n "$SSTCERT" ]; then
757760
# find out my Common Name
@@ -770,7 +773,6 @@ EOF
770773
ADDR="$CN:$MY_SECRET@$WSREP_SST_OPT_HOST"
771774
else
772775
MY_SECRET="" # for check down in recv_joiner()
773-
ADDR="$WSREP_SST_OPT_HOST"
774776
fi
775777

776778
until check_pid_and_port "$TRANSFER_PID" $TRANSFER_REAL_PID \

0 commit comments

Comments
 (0)