summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulius Goryavsky <julius.goryavsky@mariadb.com>2021-09-23 16:14:54 +0200
committerJulius Goryavsky <julius.goryavsky@mariadb.com>2021-09-24 11:31:27 +0200
commit77b11965220e249b8fe1dc178e0aff4a8a58db2a (patch)
tree626c757bcb5905ea4371f20b17ba183f07659ea1
parent467011bcac3b3f42ae6f21dde8d88e78708b21d1 (diff)
downloadmariadb-git-77b11965220e249b8fe1dc178e0aff4a8a58db2a.tar.gz
MDEV-26360: Using hostnames breaks certificate validationbb-10.2-MDEV-26360-galera
Fixed flaws with overly strict or, conversely, overly soft verification of certificates in some scenarios: 1. Removed the check that the 'commonname' (CN) in the certificate matches the 'localhost' value on the side of the joiner node, which was performed earlier, even if the address was received by the script only as an argument (out of the exchange via the Galera protocol) - since for the joining node this argument always contains its own local address, not the address of the remote host, so it is always treated as 'localhost', which is not necessarily true (outside of mtr testing); 2. Removed checking the domain name or IP-address of the peer node in the encrypt=2 mode; 3. Fixed checking of compliance of certificates when rsync SST is used; 4. Added the ability to specify CA not only as a file, but also as a path to the directory where the certificates are stored. To do this, the user just needs to specify the path to this directory as the value ssl-ca or tca parameter, ending with the '/' character.
-rw-r--r--scripts/wsrep_sst_common.sh16
-rw-r--r--scripts/wsrep_sst_mariabackup.sh55
-rw-r--r--scripts/wsrep_sst_rsync.sh63
-rw-r--r--scripts/wsrep_sst_xtrabackup-v2.sh61
4 files changed, 136 insertions, 59 deletions
diff --git a/scripts/wsrep_sst_common.sh b/scripts/wsrep_sst_common.sh
index 67244a7c622..a1293fcb749 100644
--- a/scripts/wsrep_sst_common.sh
+++ b/scripts/wsrep_sst_common.sh
@@ -1065,8 +1065,9 @@ check_for_dhparams()
#
verify_ca_matches_cert()
{
- local ca_path="$1"
- local cert_path="$2"
+ local ca="$1"
+ local cert="$2"
+ local path=${3:-0}
# If the openssl utility is not installed, then
# we will not do this certificate check:
@@ -1075,8 +1076,15 @@ verify_ca_matches_cert()
return
fi
- if ! "$OPENSSL_BINARY" verify -verbose -CAfile "$ca_path" "$cert_path" >/dev/null 2>&1
- then
+ local not_match=0
+
+ if [ $path -eq 0 ]; then
+ "$OPENSSL_BINARY" verify -verbose -CAfile "$ca" "$cert" >/dev/null 2>&1 || not_match=1
+ else
+ "$OPENSSL_BINARY" verify -verbose -CApath "$ca" "$cert" >/dev/null 2>&1 || not_match=1
+ fi
+
+ if [ $not_match -eq 1 ]; then
wsrep_log_error "******** FATAL ERROR ********************************************"
wsrep_log_error "* The certifcate and CA (certificate authority) do not match. *"
wsrep_log_error "* It does not appear that the certificate was issued by the CA. *"
diff --git a/scripts/wsrep_sst_mariabackup.sh b/scripts/wsrep_sst_mariabackup.sh
index 54632e5f79b..3fe3bf5c206 100644
--- a/scripts/wsrep_sst_mariabackup.sh
+++ b/scripts/wsrep_sst_mariabackup.sh
@@ -34,6 +34,7 @@ ssyslog=""
ssystag=""
BACKUP_PID=""
tcert=""
+tpath=0
tpem=""
tkey=""
tmode="DISABLED"
@@ -85,7 +86,6 @@ readonly SECRET_TAG="secret"
# Required for backup locks
# For backup locks it is 1 sent by joiner
-# 5.6.21 PXC and later can't donate to an older joiner
sst_ver=1
if [ -n "$(command -v pv)" ] && pv --help | grep -qw -- '-F'; then
@@ -339,64 +339,83 @@ get_transfer()
fi
fi
+ CN_option=",commonname=''"
+
if [ $encrypt -eq 2 ]; then
wsrep_log_info "Using openssl based encryption with socat: with crt and pem"
if [ -z "$tpem" -o -z "$tcert" ]; then
- wsrep_log_error "Both PEM and CRT files required"
+ wsrep_log_error \
+ "Both PEM file and CRT file (or path) are required"
exit 22
fi
if [ ! -r "$tpem" -o ! -r "$tcert" ]; then
- wsrep_log_error "Both PEM and CRT files must be readable"
+ wsrep_log_error \
+ "Both PEM file and CRT file (or path) must be readable"
exit 22
fi
- verify_ca_matches_cert "$tcert" "$tpem"
- tcmd="$tcmd,cert='$tpem',cafile='$tcert'$sockopt"
+ verify_ca_matches_cert "$tcert" "$tpem" $tpath
+ if [ $tpath -eq 0 ]; then
+ tcmd="$tcmd,cert='$tpem',cafile='$tcert'"
+ else
+ tcmd="$tcmd,cert='$tpem',capath='$tcert'"
+ fi
stagemsg="$stagemsg-OpenSSL-Encrypted-2"
- wsrep_log_info "$action with cert=$tpem, cafile=$tcert"
+ wsrep_log_info "$action with cert=$tpem, ca=$tcert"
elif [ $encrypt -eq 3 -o $encrypt -eq 4 ]; then
wsrep_log_info "Using openssl based encryption with socat: with key and crt"
if [ -z "$tpem" -o -z "$tkey" ]; then
- wsrep_log_error "Both certificate and key files required"
+ wsrep_log_error "Both certificate file (or path) " \
+ "and key file are required"
exit 22
fi
if [ ! -r "$tpem" -o ! -r "$tkey" ]; then
- wsrep_log_error "Both certificate and key files must be readable"
+ wsrep_log_error "Both certificate file (or path) " \
+ "and key file must be readable"
exit 22
fi
verify_cert_matches_key "$tpem" "$tkey"
stagemsg="$stagemsg-OpenSSL-Encrypted-3"
if [ -z "$tcert" ]; then
if [ $encrypt -eq 4 ]; then
- wsrep_log_error "Peer certificate required if encrypt=4"
+ wsrep_log_error \
+ "Peer certificate file (or path) required if encrypt=4"
exit 22
fi
# no verification
- tcmd="$tcmd,cert='$tpem',key='$tkey',verify=0$sockopt"
+ CN_option=""
+ tcmd="$tcmd,cert='$tpem',key='$tkey',verify=0"
wsrep_log_info "$action with cert=$tpem, key=$tkey, verify=0"
else
# CA verification
if [ ! -r "$tcert" ]; then
- wsrep_log_error "Certificate file must be readable"
+ wsrep_log_error "Certificate file or path must be readable"
exit 22
fi
- verify_ca_matches_cert "$tcert" "$tpem"
+ verify_ca_matches_cert "$tcert" "$tpem" $tpath
if [ -n "$WSREP_SST_OPT_REMOTE_USER" ]; then
CN_option=",commonname='$WSREP_SST_OPT_REMOTE_USER'"
- elif [ $encrypt -eq 4 ]; then
+ elif [ "$WSREP_SST_OPT_ROLE" = 'joiner' -o $encrypt -eq 4 ]
+ then
CN_option=",commonname=''"
elif is_local_ip "$WSREP_SST_OPT_HOST_UNESCAPED"; then
CN_option=',commonname=localhost'
else
CN_option=",commonname='$WSREP_SST_OPT_HOST_UNESCAPED'"
fi
- tcmd="$tcmd,cert='$tpem',key='$tkey',cafile='$tcert'$CN_option$sockopt"
- wsrep_log_info "$action with cert=$tpem, key=$tkey, cafile=$tcert"
+ if [ $tpath -eq 0 ]; then
+ tcmd="$tcmd,cert='$tpem',key='$tkey',cafile='$tcert'"
+ else
+ tcmd="$tcmd,cert='$tpem',key='$tkey',capath='$tcert'"
+ fi
+ wsrep_log_info "$action with cert=$tpem, key=$tkey, ca=$tcert"
fi
else
wsrep_log_info "Unknown encryption mode: encrypt=$encrypt"
exit 22
fi
+ tcmd="$tcmd$CN_option$sockopt"
+
if [ "$WSREP_SST_OPT_ROLE" = 'joiner' ]; then
tcmd="$tcmd stdio"
fi
@@ -473,6 +492,12 @@ check_server_ssl_config()
"of the tca, tcert and/or tkey in the [sst] section"
fi
fi
+ if [ -n "$tcert" ]; then
+ tcert=$(trim_string "$tcert")
+ if [ "${tcert%/}" != "$tcert" ]; then
+ tpath=1
+ fi
+ fi
}
read_cnf()
diff --git a/scripts/wsrep_sst_rsync.sh b/scripts/wsrep_sst_rsync.sh
index e16ed75cb16..ad9688011e1 100644
--- a/scripts/wsrep_sst_rsync.sh
+++ b/scripts/wsrep_sst_rsync.sh
@@ -236,11 +236,18 @@ check_server_ssl_config()
SSLMODE=$(parse_cnf "$SST_SECTIONS" 'ssl-mode' | tr [:lower:] [:upper:])
# no old-style SSL config in [sst], check for new one:
-if [ -z "$SSTKEY" -a -z "$SSTCERT" -a -z "$SSTCA" ]
-then
+if [ -z "$SSTKEY" -a -z "$SSTCERT" -a -z "$SSTCA" ]; then
check_server_ssl_config
fi
+SSTPATH=0
+if [ -n "$SSTCA" ]; then
+ SSTCA=$(trim_string "$SSTCA")
+ if [ "${SSTCA%/}" != "$SSTCA" ]; then
+ SSTPATH=1
+ fi
+fi
+
if [ -z "$SSLMODE" ]; then
# Implicit verification if CA is set and the SSL mode
# is not specified by user:
@@ -254,9 +261,19 @@ if [ -z "$SSLMODE" ]; then
fi
fi
-if [ -n "$SSTCA" ]
-then
- CAFILE_OPT="CAfile = $SSTCA"
+if [ -n "$SSTCERT" -a -n "$SSTKEY" ]; then
+ verify_cert_matches_key "$SSTCERT" "$SSTKEY"
+fi
+
+if [ -n "$SSTCA" ]; then
+ if [ $SSTPATH -eq 0 ]; then
+ CAFILE_OPT="CAfile = $SSTCA"
+ else
+ CAFILE_OPT="CApath = $SSTCA"
+ fi
+ if [ -n "$SSTCERT" ]; then
+ verify_ca_matches_cert "$SSTCA" "$SSTCERT" $SSTPATH
+ fi
else
CAFILE_OPT=""
fi
@@ -272,38 +289,38 @@ then
;;
'VERIFY_CA')
VERIFY_OPT='verifyChain = yes'
- if [ -n "$WSREP_SST_OPT_REMOTE_USER" ]; then
- CHECK_OPT="checkHost = $WSREP_SST_OPT_REMOTE_USER"
- else
- # check if the address is an ip-address (v4 or v6):
- if echo "$WSREP_SST_OPT_HOST_UNESCAPED" | \
- grep -q -E '^([0-9]+(\.[0-9]+){3}|[0-9a-fA-F]*(\:[0-9a-fA-F]*)+)$'
- then
- CHECK_OPT="checkIP = $WSREP_SST_OPT_HOST_UNESCAPED"
- else
- CHECK_OPT="checkHost = $WSREP_SST_OPT_HOST"
- fi
- if is_local_ip "$WSREP_SST_OPT_HOST_UNESCAPED"; then
- CHECK_OPT_LOCAL="checkHost = localhost"
- fi
- fi
;;
*)
wsrep_log_error "Unrecognized ssl-mode option: '$SSLMODE'"
exit 22 # EINVAL
;;
esac
- if [ -z "$CAFILE_OPT" ]; then
- wsrep_log_error "Can't have ssl-mode='$SSLMODE' without CA file"
+ if [ -z "$SSTCA" ]; then
+ wsrep_log_error "Can't have ssl-mode='$SSLMODE' without CA file or path"
exit 22 # EINVAL
fi
+ if [ -n "$WSREP_SST_OPT_REMOTE_USER" ]; then
+ CHECK_OPT="checkHost = $WSREP_SST_OPT_REMOTE_USER"
+ elif [ "$WSREP_SST_OPT_ROLE" = 'donor' ]; then
+ # check if the address is an ip-address (v4 or v6):
+ if echo "$WSREP_SST_OPT_HOST_UNESCAPED" | \
+ grep -q -E '^([0-9]+(\.[0-9]+){3}|[0-9a-fA-F]*(\:[0-9a-fA-F]*)+)$'
+ then
+ CHECK_OPT="checkIP = $WSREP_SST_OPT_HOST_UNESCAPED"
+ else
+ CHECK_OPT="checkHost = $WSREP_SST_OPT_HOST"
+ fi
+ if is_local_ip "$WSREP_SST_OPT_HOST_UNESCAPED"; then
+ CHECK_OPT_LOCAL="checkHost = localhost"
+ fi
+ fi
fi
STUNNEL=""
if [ -n "$SSLMODE" -a "$SSLMODE" != 'DISABLED' ]; then
STUNNEL_BIN="$(command -v stunnel)"
if [ -n "$STUNNEL_BIN" ]; then
- wsrep_log_info "Using stunnel for SSL encryption: CAfile: '$SSTCA', ssl-mode='$SSLMODE'"
+ wsrep_log_info "Using stunnel for SSL encryption: CA: '$SSTCA', ssl-mode='$SSLMODE'"
STUNNEL="$STUNNEL_BIN $STUNNEL_CONF"
fi
fi
diff --git a/scripts/wsrep_sst_xtrabackup-v2.sh b/scripts/wsrep_sst_xtrabackup-v2.sh
index 999c6c649ba..7cc05185ce3 100644
--- a/scripts/wsrep_sst_xtrabackup-v2.sh
+++ b/scripts/wsrep_sst_xtrabackup-v2.sh
@@ -34,6 +34,7 @@ ssyslog=""
ssystag=""
BACKUP_PID=""
tcert=""
+tpath=0
tpem=""
tkey=""
tmode="DISABLED"
@@ -201,9 +202,10 @@ get_keys()
if [ -z "$ekey" ]; then
ecmd="xbcrypt --encrypt-algo='$ealgo' --encrypt-key-file='$ekeyfile'"
else
- wsrep_log_warning "Using the 'encrypt-key' option causes the encryption key"
- wsrep_log_warning "to be set via the command-line and is considered insecure."
- wsrep_log_warning "It is recommended to use the 'encrypt-key-file' option instead."
+ wsrep_log_warning \
+ "Using the 'encrypt-key' option causes the encryption key " \
+ "to be set via the command-line and is considered insecure. " \
+ "It is recommended to use the 'encrypt-key-file' option instead."
ecmd="xbcrypt --encrypt-algo='$ealgo' --encrypt-key='$ekey'"
fi
if [ -n "$encrypt_threads" ]; then
@@ -341,64 +343,83 @@ get_transfer()
fi
fi
+ CN_option=",commonname=''"
+
if [ $encrypt -eq 2 ]; then
wsrep_log_info "Using openssl based encryption with socat: with crt and pem"
if [ -z "$tpem" -o -z "$tcert" ]; then
- wsrep_log_error "Both PEM and CRT files required"
+ wsrep_log_error \
+ "Both PEM file and CRT file (or path) are required"
exit 22
fi
if [ ! -r "$tpem" -o ! -r "$tcert" ]; then
- wsrep_log_error "Both PEM and CRT files must be readable"
+ wsrep_log_error \
+ "Both PEM file and CRT file (or path) must be readable"
exit 22
fi
- verify_ca_matches_cert "$tcert" "$tpem"
- tcmd="$tcmd,cert='$tpem',cafile='$tcert'$sockopt"
+ verify_ca_matches_cert "$tcert" "$tpem" $tpath
+ if [ $tpath -eq 0 ]; then
+ tcmd="$tcmd,cert='$tpem',cafile='$tcert'"
+ else
+ tcmd="$tcmd,cert='$tpem',capath='$tcert'"
+ fi
stagemsg="$stagemsg-OpenSSL-Encrypted-2"
- wsrep_log_info "$action with cert=$tpem, cafile=$tcert"
+ wsrep_log_info "$action with cert=$tpem, ca=$tcert"
elif [ $encrypt -eq 3 -o $encrypt -eq 4 ]; then
wsrep_log_info "Using openssl based encryption with socat: with key and crt"
if [ -z "$tpem" -o -z "$tkey" ]; then
- wsrep_log_error "Both certificate and key files required"
+ wsrep_log_error "Both certificate file (or path) " \
+ "and key file are required"
exit 22
fi
if [ ! -r "$tpem" -o ! -r "$tkey" ]; then
- wsrep_log_error "Both certificate and key files must be readable"
+ wsrep_log_error "Both certificate file (or path) " \
+ "and key file must be readable"
exit 22
fi
verify_cert_matches_key "$tpem" "$tkey"
stagemsg="$stagemsg-OpenSSL-Encrypted-3"
if [ -z "$tcert" ]; then
if [ $encrypt -eq 4 ]; then
- wsrep_log_error "Peer certificate required if encrypt=4"
+ wsrep_log_error \
+ "Peer certificate file (or path) required if encrypt=4"
exit 22
fi
# no verification
- tcmd="$tcmd,cert='$tpem',key='$tkey',verify=0$sockopt"
+ CN_option=""
+ tcmd="$tcmd,cert='$tpem',key='$tkey',verify=0"
wsrep_log_info "$action with cert=$tpem, key=$tkey, verify=0"
else
# CA verification
if [ ! -r "$tcert" ]; then
- wsrep_log_error "Certificate file must be readable"
+ wsrep_log_error "Certificate file or path must be readable"
exit 22
fi
- verify_ca_matches_cert "$tcert" "$tpem"
+ verify_ca_matches_cert "$tcert" "$tpem" $tpath
if [ -n "$WSREP_SST_OPT_REMOTE_USER" ]; then
CN_option=",commonname='$WSREP_SST_OPT_REMOTE_USER'"
- elif [ $encrypt -eq 4 ]; then
+ elif [ "$WSREP_SST_OPT_ROLE" = 'joiner' -o $encrypt -eq 4 ]
+ then
CN_option=",commonname=''"
elif is_local_ip "$WSREP_SST_OPT_HOST_UNESCAPED"; then
CN_option=',commonname=localhost'
else
CN_option=",commonname='$WSREP_SST_OPT_HOST_UNESCAPED'"
fi
- tcmd="$tcmd,cert='$tpem',key='$tkey',cafile='$tcert'$CN_option$sockopt"
- wsrep_log_info "$action with cert=$tpem, key=$tkey, cafile=$tcert"
+ if [ $tpath -eq 0 ]; then
+ tcmd="$tcmd,cert='$tpem',key='$tkey',cafile='$tcert'"
+ else
+ tcmd="$tcmd,cert='$tpem',key='$tkey',capath='$tcert'"
+ fi
+ wsrep_log_info "$action with cert=$tpem, key=$tkey, ca=$tcert"
fi
else
wsrep_log_info "Unknown encryption mode: encrypt=$encrypt"
exit 22
fi
+ tcmd="$tcmd$CN_option$sockopt"
+
if [ "$WSREP_SST_OPT_ROLE" = 'joiner' ]; then
tcmd="$tcmd stdio"
fi
@@ -475,6 +496,12 @@ check_server_ssl_config()
"of the tca, tcert and/or tkey in the [sst] section"
fi
fi
+ if [ -n "$tcert" ]; then
+ tcert=$(trim_string "$tcert")
+ if [ "${tcert%/}" != "$tcert" ]; then
+ tpath=1
+ fi
+ fi
}
read_cnf()