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.
This commit is contained in:
parent
8b7abe21e0
commit
a3da3c8a0b
@ -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
|
||||
}
|
||||
|
@ -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)"
|
||||
|
@ -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 \
|
||||
|
@ -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)"
|
||||
|
Loading…
x
Reference in New Issue
Block a user