2007-07-12 19:47:19 +04:00
#!/bin/sh
#
# This shell script checks the TLS certificates and options needed
# for the secure client/server support of libvirt as documented at
# http://libvirt.org/remote.html#Remote_certificates
#
2013-05-15 03:42:12 +04:00
# 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/>.
#
2007-07-12 19:47:19 +04:00
# Daniel Veillard <veillard@redhat.com>
#
2013-08-20 02:38:57 +04:00
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
2007-07-12 19:47:19 +04:00
USER=`who am i | awk '{ print $1 }'`
SERVER=1
CLIENT=1
PORT=16514
#
# First get certtool
#
CERTOOL=`which certtool 2>/dev/null`
2011-02-20 23:29:25 +03:00
if [ ! -x "$CERTOOL" ]
2007-07-12 19:47:19 +04:00
then
2010-04-22 01:52:10 +04:00
echo "Could not locate the certtool program"
echo "make sure the gnutls-utils (or gnutls-bin) package is installed"
2007-07-12 19:47:19 +04:00
exit 1
fi
2011-02-20 23:29:26 +03:00
echo Found "$CERTOOL"
2007-07-12 19:47:19 +04:00
#
# Check the directory structure
#
build: use common .in replacement mechanism
We had several different styles of .in conversion in our Makefiles:
ALLCAPS, @ALLCAPS@, @lower@, ::lower::
Canonicalize on one form, to make it easier to copy and paste
between .in files.
Also, we were using some non-portable sed constructs: \@ is an
undefined escape sequence (it happens to be @ itself in GNU sed,
but POSIX allows it to mean something else), as well as risky
behavior (failure to consistently quote things means a space
in $(sysconfdir) could throw things off; also, Autoconf recommends
using | rather than , or ! in the s||| operator, because | has to
be quoted in shell and is therefore less likely to appear in file
names than , or !).
Fix all of these uses to follow the same syntax.
* daemon/libvirtd.8.in: Switch to @var@.
* tools/virt-xml-validate.in: Likewise.
* tools/virt-pki-validate.in: Likewise.
* src/locking/virtlockd.init.in: Likewise.
* daemon/Makefile.am: Prefer | over ! in sed.
(libvirtd.8): Prefer consistent substitution.
(libvirtd.init, libvirtd.service): Avoid non-portable sed.
* tools/Makefile.am (libvirt-guests.sh, libvirt-guests.init)
(libvirt-guests.service): Likewise.
(virt-xml-validate, virt-pki-validate, virt-sanlock-cleanup):
Prefer consistent capitalization.
* src/Makefile.am (virtlockd.init, virtlockd.service)
(virtlockd.socket): Prefer consistent substitution.
2013-01-05 00:35:04 +04:00
SYSCONFDIR="@sysconfdir@"
2010-04-22 01:52:10 +04:00
PKI="$SYSCONFDIR/pki"
2011-02-20 23:29:26 +03:00
if [ ! -d "$PKI" ]
2007-07-12 19:47:19 +04:00
then
echo the $PKI directory is missing, it is usually
echo installed as part of the filesystem or openssl packages
exit 1
fi
2011-02-20 23:29:26 +03:00
if [ ! -r "$PKI" ]
2007-07-12 19:47:19 +04:00
then
echo the $PKI directory is not readable by $USER
echo "as root do: chmod a+rx $PKI"
exit 1
fi
2011-02-20 23:29:26 +03:00
if [ ! -x "$PKI" ]
2007-07-12 19:47:19 +04:00
then
echo the $PKI directory is not listable by $USER
echo "as root do: chmod a+rx $PKI"
exit 1
fi
CA="$PKI/CA"
2011-02-20 23:29:26 +03:00
if [ ! -d "$CA" ]
2007-07-12 19:47:19 +04:00
then
echo the $CA directory is missing, it is usually
echo installed as part of the or openssl package
exit 1
fi
2011-02-20 23:29:26 +03:00
if [ ! -r "$CA" ]
2007-07-12 19:47:19 +04:00
then
echo the $CA directory is not readable by $USER
echo "as root do: chmod a+rx $CA"
exit 1
fi
2011-02-20 23:29:26 +03:00
if [ ! -x "$CA" ]
2007-07-12 19:47:19 +04:00
then
echo the $CA directory is not listable by $USER
echo "as root do: chmod a+rx $CA"
exit 1
fi
LIBVIRT="$PKI/libvirt"
2011-02-20 23:29:26 +03:00
if [ ! -d "$LIBVIRT" ]
2007-07-12 19:47:19 +04:00
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
2011-02-20 23:29:26 +03:00
if [ ! -r "$LIBVIRT" ]
2007-07-12 19:47:19 +04:00
then
echo the $LIBVIRT directory is not readable by $USER
echo "as root do: chown root:root $LIBVIRT ; chmod 755 $LIBVIRT"
exit 1
fi
2011-02-20 23:29:26 +03:00
if [ ! -x "$LIBVIRT" ]
2007-07-12 19:47:19 +04:00
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"
2011-02-20 23:29:26 +03:00
if [ ! -d "$LIBVIRTP" ]
2007-07-12 19:47:19 +04:00
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
2011-02-20 23:29:26 +03:00
if [ ! -r "$LIBVIRTP" ]
2007-07-12 19:47:19 +04:00
then
echo the $LIBVIRTP directory is not readable by $USER
echo "as root do: chown root:root $LIBVIRTP ; chmod 755 $LIBVIRTP"
exit 1
fi
2011-02-20 23:29:26 +03:00
if [ ! -x "$LIBVIRTP" ]
2007-07-12 19:47:19 +04:00
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
#
2011-02-20 23:29:26 +03:00
if [ ! -f "$CA/cacert.pem" ]
2007-07-12 19:47:19 +04:00
then
echo the CA certificate $CA/cacert.pem is missing while it
echo should be installed on both client and servers
echo "see http://libvirt.org/remote.html#Remote_TLS_CA"
echo on how to install it
exit 1
fi
2011-02-20 23:29:26 +03:00
if [ ! -r "$CA/cacert.pem" ]
2007-07-12 19:47:19 +04:00
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
2010-04-30 01:20:50 +04:00
sed_get_org='/Issuer:/ {
s/.*Issuer:.*CN=//
s/,.*//
p
}'
2011-02-20 23:29:26 +03:00
ORG=`"$CERTOOL" -i --infile "$CA/cacert.pem" | sed -n "$sed_get_org"`
2010-04-22 01:52:10 +04:00
if [ "$ORG" = "" ]
2007-07-12 19:47:19 +04:00
then
echo the CA certificate $CA/cacert.pem does not define the organization
echo it should probably regenerated
echo "see http://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
2011-02-20 23:29:26 +03:00
if [ -f "$LIBVIRT/clientcert.pem" ]
2007-07-12 19:47:19 +04:00
then
2011-02-20 23:29:26 +03:00
if [ ! -r "$LIBVIRT/clientcert.pem" ]
2007-07-12 19:47:19 +04:00
then
echo Client certificate $LIBVIRT/clientcert.pem should be world readable
2010-04-22 03:21:06 +04:00
echo "as root do: chown root:root $LIBVIRT/clientcert.pem ; chmod 644 $LIBVIRT/clientcert.pem"
2007-07-12 19:47:19 +04:00
else
2011-02-20 23:29:26 +03:00
S_ORG=`"$CERTOOL" -i --infile "$LIBVIRT/clientcert.pem" | grep Subject: | sed 's+.*O=\([a-zA-Z \._-]*\).*+\1+'`
2010-04-22 03:21:06 +04:00
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
2011-02-20 23:29:26 +03:00
CLIENT=`"$CERTOOL" -i --infile "$LIBVIRT/clientcert.pem" | grep Subject: | sed 's+.*CN=\(.[a-zA-Z \._-]*\).*+\1+'`
2010-04-22 03:21:06 +04:00
echo Found client certificate $LIBVIRT/clientcert.pem for $CLIENT
2011-02-20 23:29:26 +03:00
if [ ! -e "$LIBVIRTP/clientkey.pem" ]
2010-04-22 03:21:06 +04:00
then
echo Missing client private key $LIBVIRTP/clientkey.pem
else
echo Found client private key $LIBVIRTP/clientkey.pem
2011-02-20 23:29:26 +03:00
OWN=`ls -l "$LIBVIRTP/clientkey.pem" | awk '{ print $3 }'`
2012-05-31 13:00:06 +04:00
# The substr($1, 1, 10) gets rid of acl and xattr markers
MOD=`ls -l "$LIBVIRTP/clientkey.pem" | awk '{ print substr($1, 1, 10) }'`
2010-04-22 03:21:06 +04:00
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
2007-07-12 19:47:19 +04:00
fi
else
2011-02-20 23:29:26 +03:00
echo Did not find "$LIBVIRT/clientcert.pem" client certificate
2007-07-12 19:47:19 +04:00
echo The machine cannot act as a client
echo "see http://libvirt.org/remote.html#Remote_TLS_client_certificates"
echo on how to regenerate it
CLIENT=0
fi
# Third the server certificates
2011-02-20 23:29:26 +03:00
if [ -f "$LIBVIRT/servercert.pem" ]
2007-07-12 19:47:19 +04:00
then
2011-02-20 23:29:26 +03:00
if [ ! -r "$LIBVIRT/servercert.pem" ]
2007-07-12 19:47:19 +04:00
then
echo Server certificate $LIBVIRT/servercert.pem should be world readable
2010-04-22 03:21:06 +04:00
echo "as root do: chown root:root $LIBVIRT/servercert.pem ; chmod 644 $LIBVIRT/servercert.pem"
2007-07-12 19:47:19 +04:00
else
2011-02-20 23:29:26 +03:00
S_ORG=`"$CERTOOL" -i --infile "$LIBVIRT/servercert.pem" | grep Subject: | sed 's+.*O=\([a-zA-Z\. _-]*\).*+\1+'`
2010-04-22 03:21:06 +04:00
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
2011-02-20 23:29:26 +03:00
S_HOST=`"$CERTOOL" -i --infile "$LIBVIRT/servercert.pem" | grep Subject: | sed 's+.*CN=\([a-zA-Z\. _-]*\)+\1+'`
2010-04-22 03:21:06 +04:00
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
2011-02-20 23:29:26 +03:00
if [ ! -e "$LIBVIRTP/serverkey.pem" ]
2010-04-22 03:21:06 +04:00
then
echo Missing server private key $LIBVIRTP/serverkey.pem
else
echo Found server private key $LIBVIRTP/serverkey.pem
2011-02-20 23:29:26 +03:00
OWN=`ls -l "$LIBVIRTP/serverkey.pem" | awk '{ print $3 }'`
2012-05-31 13:00:06 +04:00
# The substr($1, 1, 10) gets rid of acl and xattr markers
MOD=`ls -l "$LIBVIRTP/serverkey.pem" | awk '{ print substr($1, 1, 10) }'`
2010-04-22 03:21:06 +04:00
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
2007-07-12 19:47:19 +04:00
fi
else
2011-02-20 23:29:26 +03:00
echo Did not find $LIBVIRT/servercert.pem server certificate
2007-07-12 19:47:19 +04:00
echo The machine cannot act as a server
echo "see http://libvirt.org/remote.html#Remote_TLS_server_certificates"
echo on how to regenerate it
SERVER=0
fi
if [ "$SERVER" = "1" ]
then
2010-04-22 01:52:10 +04:00
if [ -r "$SYSCONFDIR"/sysconfig/libvirtd ]
2007-07-12 19:47:19 +04:00
then
2010-04-22 01:52:10 +04:00
if grep "^LIBVIRTD_ARGS.*--listen" "$SYSCONFDIR"/sysconfig/libvirtd \
>/dev/null 2>&1
2010-04-22 03:21:06 +04:00
then
2010-04-22 01:52:10 +04:00
:
else
echo Make sure "$SYSCONFDIR"/sysconfig/libvirtd is setup to listen to
2010-04-22 03:21:06 +04:00
echo TCP/IP connections and restart the libvirtd service
fi
2007-07-12 19:47:19 +04:00
fi
2010-04-22 01:52:10 +04:00
if [ -r "$SYSCONFDIR"/sysconfig/iptables ]
2007-07-12 19:47:19 +04:00
then
2011-02-20 23:29:26 +03:00
if grep "$PORT" "$SYSCONFDIR"/sysconfig/iptables >/dev/null 2>&1
2010-04-22 03:21:06 +04:00
then
2010-04-22 01:52:10 +04:00
:
else
echo Make sure "$SYSCONFDIR"/sysconfig/iptables is setup to allow
2010-04-22 03:21:06 +04:00
echo incoming TCP/IP connections on port $PORT and
echo restart the iptables service
fi
2007-07-12 19:47:19 +04:00
fi
fi
2009-09-16 17:42:57 +04:00
exit 0
: <<=cut
=pod
=head1 NAME
virt-pki-validate - validate libvirt PKI files are configured correctly
=head1 SYNOPSIS
2013-08-20 02:38:57 +04:00
virt-pki-validate [OPTION]
2009-09-16 17:42:57 +04:00
=head1 DESCRIPTION
2009-09-22 13:42:06 +04:00
This tool validates that the necessary PKI files are configured for
2009-09-16 17:42:57 +04:00
a secure libvirt server or client using the TLS encryption protocol.
It will report any missing certificate or key files on the host. It
2009-09-22 13:42:06 +04:00
should be run as root to ensure it can read all the necessary files
2009-09-16 17:42:57 +04:00
2013-08-20 02:38:57 +04:00
=head1 OPTIONS
=over
=item B<-h, --help>
Display command line help usage then exit.
=item B<-V, --version>
Display version information then exit.
=back
2009-09-16 17:42:57 +04:00
=head1 EXIT STATUS
Upon successful validation, an exit status of 0 will be set. Upon
failure a non-zero status will be set.
=head1 AUTHOR
Richard Jones
=head1 BUGS
Report any bugs discovered to the libvirt community via the
mailing list C<http://libvirt.org/contact.html> or bug tracker C<http://libvirt.org/bugs.html>.
Alternatively report bugs to your software distributor / vendor.
=head1 COPYRIGHT
2012-07-24 21:41:03 +04:00
Copyright (C) 2006-2012 by Red Hat, Inc.
2009-09-16 17:42:57 +04:00
=head1 LICENSE
virt-pki-validate is distributed under the terms of the GNU GPL v2+.
This is free software; see the source for copying conditions. There
is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE
=head1 SEE ALSO
C<virsh(1)>, online PKI setup instructions C<http://libvirt.org/remote.html>
=cut