libvirt/tools/virt-pki-validate.in
Daniel P. Berrangé ecf8619430 tools: relax x509 Subject regexes to allow numbers and more
The virt-pki-validate tool is extracting components in the x509
certificate Subject field. Unfortunately the regex it is is using is far
too strict, and so truncating valid data. It needs to consider ',' as a
field separator, and if that's not there take all data until the EOL.

With the broken regex:

$ echo "  Subject: O=Test,CN=guestHyp1ver"  | sed 's+.*CN=\(.[a-zA-Z \._-]*\).*+\1+'
guestHyp

And with the fixed regex

$ echo "Subject: O=Test,CN=guestHyp1ver"  | sed 's+.*CN=\([^,]*\).*+\1+'
guestHyp1ver

Reported-by: Kashyap Chamarthy <kchamart@redhat.com>
Reviewed-by: Kashyap Chamarthy <kchamart@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
2018-12-11 14:58:02 +00:00

323 lines
9.6 KiB
Bash
Executable File

#!/bin/sh
#
# This shell script checks the TLS certificates and options needed
# for the secure client/server support of libvirt as documented at
# https://libvirt.org/remote.html#Remote_certificates
#
# Copyright (C) 2009-2013 Red Hat, Inc.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library. If not, see
# <http://www.gnu.org/licenses/>.
#
# Daniel Veillard <veillard@redhat.com>
#
case $1 in
-h | --h | --he | --hel | --help)
cat <<EOF
Usage:
$0 [OPTION]
Options:
-h | --help Display program help
-V | --version Display program version
EOF
exit ;;
-V | --v | --ve | --ver | --vers | --versi | --versio | --version)
cat <<EOF
$0 (libvirt) @VERSION@
EOF
exit ;;
--) shift ;;
-) # Not an option but an argument; it gets rejected later
;;
-*)
echo "$0: unrecognized option '$1'" >&2
exit 1 ;;
esac
if test $# != 0; then
echo "$0: unrecognized argument '$1'" >&2
exit 1
fi
USER=`who am i | awk '{ print $1 }'`
SERVER=1
CLIENT=1
PORT=16514
#
# First get certtool
#
CERTOOL=`which certtool 2>/dev/null`
if [ ! -x "$CERTOOL" ]
then
echo "Could not locate the certtool program"
echo "make sure the gnutls-utils (or gnutls-bin) package is installed"
exit 1
fi
echo Found "$CERTOOL"
#
# Check the directory structure
#
SYSCONFDIR="@sysconfdir@"
PKI="$SYSCONFDIR/pki"
if [ ! -d "$PKI" ]
then
echo the $PKI directory is missing, it is usually
echo installed as part of the filesystem or openssl packages
exit 1
fi
if [ ! -r "$PKI" ]
then
echo the $PKI directory is not readable by $USER
echo "as root do: chmod a+rx $PKI"
exit 1
fi
if [ ! -x "$PKI" ]
then
echo the $PKI directory is not listable by $USER
echo "as root do: chmod a+rx $PKI"
exit 1
fi
CA="$PKI/CA"
if [ ! -d "$CA" ]
then
echo the $CA directory is missing, it is usually
echo installed as part of the or openssl package
exit 1
fi
if [ ! -r "$CA" ]
then
echo the $CA directory is not readable by $USER
echo "as root do: chmod a+rx $CA"
exit 1
fi
if [ ! -x "$CA" ]
then
echo the $CA directory is not listable by $USER
echo "as root do: chmod a+rx $CA"
exit 1
fi
LIBVIRT="$PKI/libvirt"
if [ ! -d "$LIBVIRT" ]
then
echo the $LIBVIRT directory is missing, it is usually
echo installed by the libvirt package
echo "as root do: mkdir -m 755 $LIBVIRT ; chown root:root $LIBVIRT"
exit 1
fi
if [ ! -r "$LIBVIRT" ]
then
echo the $LIBVIRT directory is not readable by $USER
echo "as root do: chown root:root $LIBVIRT ; chmod 755 $LIBVIRT"
exit 1
fi
if [ ! -x "$LIBVIRT" ]
then
echo the $LIBVIRT directory is not listable by $USER
echo "as root do: chown root:root $LIBVIRT ; chmod 755 $LIBVIRT"
exit 1
fi
LIBVIRTP="$LIBVIRT/private"
if [ ! -d "$LIBVIRTP" ]
then
echo the $LIBVIRTP directory is missing, it is usually
echo installed by the libvirt package
echo "as root do: mkdir -m 755 $LIBVIRTP ; chown root:root $LIBVIRTP"
exit 1
fi
if [ ! -r "$LIBVIRTP" ]
then
echo the $LIBVIRTP directory is not readable by $USER
echo "as root do: chown root:root $LIBVIRTP ; chmod 755 $LIBVIRTP"
exit 1
fi
if [ ! -x "$LIBVIRTP" ]
then
echo the $LIBVIRTP directory is not listable by $USER
echo "as root do: chown root:root $LIBVIRTP ; chmod 755 $LIBVIRTP"
exit 1
fi
#
# Now check the certificates
# First the CA certificate
#
if [ ! -f "$CA/cacert.pem" ]
then
echo the CA certificate $CA/cacert.pem is missing while it
echo should be installed on both client and servers
echo "see https://libvirt.org/remote.html#Remote_TLS_CA"
echo on how to install it
exit 1
fi
if [ ! -r "$CA/cacert.pem" ]
then
echo the CA certificate $CA/cacert.pem is not readable by $USER
echo "as root do: chmod 644 $CA/cacert.pem"
exit 1
fi
sed_get_org='/Issuer:/ {
s/.*Issuer:.*CN=//
s/,.*//
p
}'
ORG=`"$CERTOOL" -i --infile "$CA/cacert.pem" | sed -n "$sed_get_org"`
if [ "$ORG" = "" ]
then
echo the CA certificate $CA/cacert.pem does not define the organization
echo it should probably regenerated
echo "see https://libvirt.org/remote.html#Remote_TLS_CA"
echo on how to regenerate it
exit 1
fi
echo Found CA certificate $CA/cacert.pem for $ORG
# Second the client certificates
if [ -f "$LIBVIRT/clientcert.pem" ]
then
if [ ! -r "$LIBVIRT/clientcert.pem" ]
then
echo Client certificate $LIBVIRT/clientcert.pem should be world readable
echo "as root do: chown root:root $LIBVIRT/clientcert.pem ; chmod 644 $LIBVIRT/clientcert.pem"
else
S_ORG=`"$CERTOOL" -i --infile "$LIBVIRT/clientcert.pem" | grep Subject: | sed 's+.*O=\([^,]*\).*+\1+'`
if [ "$ORG" != "$S_ORG" ]
then
echo The CA certificate and the client certificate do not match
echo CA organization: $ORG
echo Client organization: $S_ORG
fi
CLIENT=`"$CERTOOL" -i --infile "$LIBVIRT/clientcert.pem" | grep Subject: | sed 's+.*CN=\(.[^,]*\).*+\1+'`
echo Found client certificate $LIBVIRT/clientcert.pem for $CLIENT
if [ ! -e "$LIBVIRTP/clientkey.pem" ]
then
echo Missing client private key $LIBVIRTP/clientkey.pem
else
echo Found client private key $LIBVIRTP/clientkey.pem
OWN=`ls -l "$LIBVIRTP/clientkey.pem" | awk '{ print $3 }'`
# The substr($1, 1, 10) gets rid of acl and xattr markers
MOD=`ls -l "$LIBVIRTP/clientkey.pem" | awk '{ print substr($1, 1, 10) }'`
if [ "$OWN" != "root" ]
then
echo The client private key should be owned by root
echo "as root do: chown root $LIBVIRTP/clientkey.pem"
fi
if [ "$MOD" != "-rw-r--r--" ]
then
echo The client private key need to be read by client tools
echo "as root do: chmod 644 $LIBVIRTP/clientkey.pem"
fi
fi
fi
else
echo Did not find "$LIBVIRT/clientcert.pem" client certificate
echo The machine cannot act as a client
echo "see https://libvirt.org/remote.html#Remote_TLS_client_certificates"
echo on how to regenerate it
CLIENT=0
fi
# Third the server certificates
if [ -f "$LIBVIRT/servercert.pem" ]
then
if [ ! -r "$LIBVIRT/servercert.pem" ]
then
echo Server certificate $LIBVIRT/servercert.pem should be world readable
echo "as root do: chown root:root $LIBVIRT/servercert.pem ; chmod 644 $LIBVIRT/servercert.pem"
else
S_ORG=`"$CERTOOL" -i --infile "$LIBVIRT/servercert.pem" | grep Subject: | sed 's+.*O=\([^,]*\).*+\1+'`
if [ "$ORG" != "$S_ORG" ]
then
echo The CA certificate and the server certificate do not match
echo CA organization: $ORG
echo Server organization: $S_ORG
fi
S_HOST=`"$CERTOOL" -i --infile "$LIBVIRT/servercert.pem" | grep Subject: | sed 's+.*CN=\([^,]*\).*+\1+'`
if test "$S_HOST" != "`hostname -s`" && test "$S_HOST" != "`hostname`"
then
echo The server certificate does not seem to match the host name
echo hostname: '"'`hostname`'"'
echo Server certificate CN: '"'$S_HOST'"'
fi
echo Found server certificate $LIBVIRT/servercert.pem for $S_HOST
if [ ! -e "$LIBVIRTP/serverkey.pem" ]
then
echo Missing server private key $LIBVIRTP/serverkey.pem
else
echo Found server private key $LIBVIRTP/serverkey.pem
OWN=`ls -l "$LIBVIRTP/serverkey.pem" | awk '{ print $3 }'`
# The substr($1, 1, 10) gets rid of acl and xattr markers
MOD=`ls -l "$LIBVIRTP/serverkey.pem" | awk '{ print substr($1, 1, 10) }'`
if [ "$OWN" != "root" ]
then
echo The server private key should be owned by root
echo "as root do: chown root $LIBVIRTP/serverkey.pem"
fi
if [ "$MOD" != "-rw-------" ]
then
echo The server private key need to be read only by root
echo "as root do: chmod 600 $LIBVIRTP/serverkey.pem"
fi
fi
fi
else
echo Did not find $LIBVIRT/servercert.pem server certificate
echo The machine cannot act as a server
echo "see https://libvirt.org/remote.html#Remote_TLS_server_certificates"
echo on how to regenerate it
SERVER=0
fi
if [ "$SERVER" = "1" ]
then
if [ -r "$SYSCONFDIR"/sysconfig/libvirtd ]
then
if grep "^LIBVIRTD_ARGS.*--listen" "$SYSCONFDIR"/sysconfig/libvirtd \
>/dev/null 2>&1
then
:
else
echo Make sure "$SYSCONFDIR"/sysconfig/libvirtd is setup to listen to
echo TCP/IP connections and restart the libvirtd service
fi
fi
if [ -r "$SYSCONFDIR"/sysconfig/iptables ]
then
if grep "$PORT" "$SYSCONFDIR"/sysconfig/iptables >/dev/null 2>&1
then
:
else
echo Make sure "$SYSCONFDIR"/sysconfig/iptables is setup to allow
echo incoming TCP/IP connections on port $PORT and
echo restart the iptables service
fi
fi
fi
exit 0