#!/bin/bash # # priority: 300 # # Generate SSL certificates # # Mark Huang # Copyright (C) 2006 The Trustees of Princeton University # # Source function library and configuration . /etc/plc.d/functions . /etc/planetlab/plc_config # Be verbose set -x # Print the CNAME of an SSL certificate ssl_cname () { openssl x509 -noout -in $1 -subject | \ sed -e 's|.*CN *= *\([-_a-zA-Z0-9.]*\).*|\1|' | \ lower } backup_file () { filepath=$1 filename=$(basename ${filepath}) dir=$(dirname ${filepath}) mv -f ${filepath} ${dir}/${filename}-`date +%Y-%m-%d-%H-%M-%S`.bak } # Verify a certificate. If invalid, generate a new self-signed # certificate. verify_or_generate_certificate() { crt=$1 key=$2 ca=$3 cname=$(lower $4) # If the CA certificate does not exist, assume that the # certificate is self-signed. if [ ! -f $ca ] ; then cp -a $crt $ca fi if [ -f $crt ] ; then # Check if certificate is valid # Backup if invalid or if the subject has changed if openssl verify -CAfile $ca $crt | grep -q "error" || \ [ "$(ssl_cname $crt)" != "$cname" ] ; then backup_file $crt backup_file $ca backup_file $key fi fi if [ ! -f $crt ] ; then # Set subject subj= if [ -n "$cname" ] ; then subj="$subj/CN=$cname" fi # Generate new self-signed certificate mkdir -p $(dirname $crt) openssl req -new -x509 -days 3650 -set_serial $RANDOM \ -batch -subj "$subj" \ -nodes -keyout $key -out $crt check # The certificate it self-signed, so it is its own CA cp -a $crt $ca fi # Fix permissions chmod 644 $crt $ca } case "$1" in start) # Generate HTTPS certificates if necessary. We generate a # certificate for each enabled server with a different # hostname. These self-signed certificates may be overridden # later. MESSAGE=$"Generating SSL certificates for" dialog "$MESSAGE" for server in WWW API BOOT MONITOR; do eval "a=\$PLC_${server}_ENABLED" echo $a if [ "$a" -ne 1 ] ; then echo "Skipping" continue fi dialog "$server" ssl_key=PLC_${server}_SSL_KEY ssl_crt=PLC_${server}_SSL_CRT ca_ssl_crt=PLC_${server}_CA_SSL_CRT hostname=PLC_${server}_HOST # Check if we have already generated a certificate for # the same hostname. for previous_server in WWW API BOOT MONITOR; do if [ "$server" = "$previous_server" ] ; then break fi previous_ssl_key=PLC_${previous_server}_SSL_KEY previous_ssl_crt=PLC_${previous_server}_SSL_CRT previous_ca_ssl_crt=PLC_${previous_server}_CA_SSL_CRT previous_hostname=PLC_${previous_server}_HOST if [ -f ${!previous_ssl_crt} ] && \ [ "$(ssl_cname ${!previous_ssl_crt})" = "${!hostname}" ] ; then cp -a ${!previous_ssl_key} ${!ssl_key} cp -a ${!previous_ssl_crt} ${!ssl_crt} cp -a ${!previous_ca_ssl_crt} ${!ca_ssl_crt} break fi done verify_or_generate_certificate \ ${!ssl_crt} ${!ssl_key} ${!ca_ssl_crt} \ ${!hostname} done # 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 MONITOR WWW; do enabled=PLC_${server}_ENABLED if [ "${!enabled}" != "1" ] ; then continue fi ssl_key=PLC_${server}_SSL_KEY ssl_crt=PLC_${server}_SSL_CRT ssl_ca_crt=PLC_${server}_CA_SSL_CRT symlink ${!ssl_crt} /etc/pki/tls/certs/localhost.crt symlink ${!ssl_key} /etc/pki/tls/private/localhost.key symlink ${!ssl_ca_crt} /etc/pki/tls/certs/server-chain.crt symlink ${!ssl_crt} /etc/httpd/conf/ssl.crt/server.crt symlink ${!ssl_key} /etc/httpd/conf/ssl.key/server.key done # Ensure that the server-chain gets used, as it is off by # default. sed -i -e 's/^#SSLCertificateChainFile /SSLCertificateChainFile /' \ /etc/httpd/conf.d/ssl.conf result "$MESSAGE" ;; esac exit $ERRORS