From acafa75f495e5beb8641cc4c984779978aa7dc57 Mon Sep 17 00:00:00 2001 From: Mark Huang Date: Fri, 23 Jun 2006 21:47:18 +0000 Subject: [PATCH] - generate up to 5 sets of SSL certs: a root CA keypair/cert used to sign the other 4 certs, an MA/SA keypair/cert used for signing slice tickets and other docs, and www/boot/api keypairs/certs - /etc/planetlab/ssl is used to store the OpenSSL state; probably need to think of a better long-term solution --- plc.d/ssl | 142 +++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 109 insertions(+), 33 deletions(-) diff --git a/plc.d/ssl b/plc.d/ssl index fc3fa74..0615d75 100755 --- a/plc.d/ssl +++ b/plc.d/ssl @@ -7,23 +7,112 @@ # Mark Huang # Copyright (C) 2006 The Trustees of Princeton University # -# $Id: ssl,v 1.3 2006/04/07 04:28:16 mlhuang Exp $ +# $Id: ssl,v 1.4 2006/04/25 21:18:19 mlhuang Exp $ # # Source function library and configuration . /etc/plc.d/functions . /etc/planetlab/plc_config +# Be verbose +set -x + +mkcert () +{ + CN=$1 + KEY=$2 + CRT=$3 + + # Generate a temporary CSR. We could save the CSR, but it's not + # worth the trouble. + csr=$(mktemp /tmp/csr.XXXXXX) + + mkdir -p $(dirname $KEY) + openssl req -config /etc/planetlab/ssl/openssl.cnf \ + -new -extensions v3_req -days 365 -set_serial $RANDOM \ + -batch -subj "/CN=$CN" \ + -nodes -keyout $KEY -out $csr + check + chmod 600 $KEY + + # Generate and sign certificate from CSR + serial=$(cat /etc/planetlab/ssl/serial) + + openssl ca -config /etc/planetlab/ssl/openssl.cnf \ + -keyfile $PLC_ROOT_CA_SSL_KEY \ + -cert $PLC_ROOT_CA_SSL_CRT \ + -batch -infiles $csr + check + + mv /etc/planetlab/ssl/$serial.pem $CRT + chmod 644 $CRT + + # Delete CSR + rm -f $csr +} + case "$1" in start) MESSAGE=$"Generating SSL certificates" dialog "$MESSAGE" - # Generate self-signed SSL certificate(s). These nice - # commands come from the mod_ssl spec file for Fedora Core - # 2. We generate a certificate for each enabled server - # with a different hostname. These self-signed - # certificates may be overridden later. + # Check if root CA certificate is valid + if [ -f $PLC_ROOT_CA_SSL_CRT ] ; then + verify=$(openssl verify $PLC_ROOT_CA_SSL_CRT) + # If self signed, assume that we generated it + if grep -q "self signed certificate" <<<$verify ; then + # Delete if expired or PLC name or e-mail address has changed + if grep -q "expired" <<<$verify || \ + [ "$(ssl_cname $PLC_ROOT_CA_SSL_CRT)" != "$PLC_NAME Root CA" ] || \ + [ "$(ssl_email $PLC_ROOT_CA_SSL_CRT)" != "$PLC_MAIL_SUPPORT_ADDRESS" ] ; then + rm -f $PLC_ROOT_CA_SSL_CRT + fi + fi + fi + + # Generate root CA key pair and certificate + if [ ! -f $PLC_ROOT_CA_SSL_CRT ] ; then + mkdir -p $(dirname $PLC_ROOT_CA_SSL_CRT) + openssl req -config /etc/planetlab/ssl/openssl.cnf \ + -new -x509 -extensions v3_ca -days 3650 -set_serial $RANDOM \ + -batch -subj "/CN=$PLC_NAME Root CA/emailAddress=$PLC_MAIL_SUPPORT_ADDRESS" \ + -nodes -keyout $PLC_ROOT_CA_SSL_KEY -out $PLC_ROOT_CA_SSL_CRT + check + chmod 600 $PLC_ROOT_CA_SSL_KEY + chmod 644 $PLC_ROOT_CA_SSL_CRT + + # API certificate verification requires a public key + openssl rsa -pubout <$PLC_ROOT_CA_SSL_KEY >$PLC_ROOT_CA_SSL_KEY_PUB + check + chmod 644 $PLC_ROOT_CA_SSL_KEY_PUB + + # Reset DB + >/etc/planetlab/ssl/index.txt + echo "01" >/etc/planetlab/ssl/serial + fi + + # Check if MA/SA certificate is valid + if [ -f $PLC_MA_SA_SSL_CRT ] ; then + verify=$(openssl verify -CAfile $PLC_ROOT_CA_SSL_CRT $PLC_MA_SA_SSL_CRT) + # Delete if expired or not signed correctly + if grep -q "error" <<<$verify ; then + rm -f $PLC_MA_SA_SSL_CRT + fi + fi + + # Generate MA/SA key pair and certificate + if [ ! -f $PLC_MA_SA_SSL_CRT ] ; then + mkcert "$PLC_NAME Management and Slice Authority" \ + $PLC_MA_SA_SSL_KEY $PLC_MA_SA_SSL_CRT + + # API requires a public key for slice ticket verification + openssl rsa -pubout <$PLC_MA_SA_SSL_KEY >$PLC_MA_SA_SSL_KEY_PUB + check + chmod 644 $PLC_MA_SA_SSL_KEY_PUB + fi + + # Generate HTTPS certificate(s). We generate a certificate for + # each enabled server with a different hostname. for server in WWW API BOOT ; do ssl_key=PLC_${server}_SSL_KEY ssl_crt=PLC_${server}_SSL_CRT @@ -47,41 +136,28 @@ case "$1" in fi done - # Check if self signed certificate is valid + # Check if certificate is valid if [ -f ${!ssl_crt} ] ; then - verify=$(openssl verify ${!ssl_crt}) - # If self signed - if grep -q "self signed certificate" <<<$verify ; then - # Delete if expired or hostname changed - if grep -q "expired" <<<$verify || \ - [ "$(ssl_cname ${!ssl_crt})" != "${!hostname}" ] ; then - rm -f ${!ssl_crt} - fi - else - echo "$verify" >&2 + verify=$(openssl verify -CAfile $PLC_ROOT_CA_SSL_CRT ${!ssl_crt}) + # Delete if expired or hostname changed. These + # certificates do not necessarily have to be signed by + # the root CA; they may be signed by a third party, + # e.g., Entrust or Verisign. + if grep -q "expired" <<<$verify || \ + [ "$(ssl_cname ${!ssl_crt})" != "${!hostname}" ] ; then + rm -f ${!ssl_crt} fi fi - # Generate new self signed certificate + # Generate and sign certificate if [ ! -f ${!ssl_crt} ] ; then - mkdir -p $(dirname ${!ssl_crt}) - openssl req -new -x509 -days 365 -set_serial $RANDOM \ - -batch -subj "/CN=${!hostname}" \ - -nodes -keyout ${!ssl_key} -out ${!ssl_crt} - check - chmod 644 ${!ssl_crt} + mkcert ${!hostname} ${!ssl_key} ${!ssl_crt} fi done - # API requires a public key for slice ticket verification - if [ ! -f $PLC_API_SSL_KEY_PUB ] ; then - openssl rsa -pubout <$PLC_API_SSL_KEY >$PLC_API_SSL_KEY_PUB - check - fi - - # Install into both /etc/pki (Fedora Core 4) and - # /etc/httpd/conf (Fedora Core 2). If the API, boot, and - # web servers are all running on the same machine, the web + # Install HTTPS certificates into both /etc/pki (Fedora Core + # 4) and /etc/httpd/conf (Fedora Core 2). If the API, boot, + # and web servers are all running on the same machine, the web # server certificate takes precedence. for server in API BOOT WWW ; do enabled=PLC_${server}_ENABLED -- 2.45.2