- just compare cnames (CN field), not emails (emailAddress field)
[myplc.git] / plc.d / ssl
1 #!/bin/bash
2 #
3 # priority: 400
4 #
5 # Generate SSL certificates
6 #
7 # Mark Huang <mlhuang@cs.princeton.edu>
8 # Copyright (C) 2006 The Trustees of Princeton University
9 #
10 # $Id: ssl,v 1.11 2007/01/18 18:44:18 mlhuang Exp $
11 #
12
13 # Source function library and configuration
14 . /etc/plc.d/functions
15 . /etc/planetlab/plc_config
16
17 # Be verbose
18 set -x
19
20 # Print the CNAME of an SSL certificate
21 ssl_cname ()
22 {
23     openssl x509 -noout -in $1 -subject | \
24         sed -n -e 's@.*/CN=\([^/]*\).*@\1@p' | \
25         lower
26 }
27
28 # Verify a certificate. If invalid, generate a new self-signed
29 # certificate.
30 verify_or_generate_certificate() {
31     crt=$1
32     key=$2
33     ca=$3
34     cname=$(lower $4)
35
36     # If the CA certificate does not exist, assume that the
37     # certificate is self-signed.
38     if [ ! -f $ca ] ; then
39         cp -a $crt $ca
40     fi
41
42     if [ -f $crt ] ; then
43         # Check if certificate is valid
44         verify=$(openssl verify -CAfile $ca $crt)
45         # Delete if invalid or if the subject has changed
46         if grep -q "error" <<<$verify || \
47             [ "$(ssl_cname $crt)" != "$cname" ] ; then
48             rm -f $crt $ca
49         fi
50     fi
51
52     if [ ! -f $crt ] ; then
53         # Set subject
54         subj=
55         if [ -n "$cname" ] ; then
56             subj="$subj/CN=$cname"
57         fi
58
59         # Generate new self-signed certificate
60         mkdir -p $(dirname $crt)
61         openssl req -new -x509 -days 3650 -set_serial $RANDOM \
62             -batch -subj "$subj" \
63             -nodes -keyout $key -out $crt
64         check
65
66         # The certificate it self-signed, so it is its own CA
67         cp -a $crt $ca
68     fi
69
70     # Fix permissions
71     chmod 644 $crt $ca
72 }
73
74 case "$1" in
75     start)
76         MESSAGE=$"Generating SSL certificates"
77         dialog "$MESSAGE"
78
79         # Generate HTTPS certificates if necessary. We generate a
80         # certificate for each enabled server with a different
81         # hostname. These self-signed certificates may be overridden
82         # later.
83         for server in WWW API BOOT ; do
84             ssl_key=PLC_${server}_SSL_KEY
85             ssl_crt=PLC_${server}_SSL_CRT
86             ca_ssl_crt=PLC_${server}_CA_SSL_CRT
87             hostname=PLC_${server}_HOST
88
89             # Check if we have already generated a certificate for
90             # the same hostname.
91             for previous_server in WWW API BOOT ; do
92                 if [ "$server" = "$previous_server" ] ; then
93                     break
94                 fi
95                 previous_ssl_key=PLC_${previous_server}_SSL_KEY
96                 previous_ssl_crt=PLC_${previous_server}_SSL_CRT
97                 previous_ca_ssl_crt=PLC_${previous_server}_CA_SSL_CRT
98                 previous_hostname=PLC_${previous_server}_HOST
99
100                 if [ -f ${!previous_ssl_crt} ] && \
101                     [ "$(ssl_cname ${!previous_ssl_crt})" = "${!hostname}" ] ; then
102                     cp -a ${!previous_ssl_key} ${!ssl_key}
103                     cp -a ${!previous_ssl_crt} ${!ssl_crt}
104                     cp -a ${!previous_ca_ssl_crt} ${!ca_ssl_crt}
105                     break
106                 fi
107             done
108
109             verify_or_generate_certificate \
110                 ${!ssl_crt} ${!ssl_key} ${!ca_ssl_crt} \
111                 ${!hostname}
112         done
113
114         # Install HTTPS certificates into both /etc/pki (Fedora Core
115         # 4) and /etc/httpd/conf (Fedora Core 2). If the API, boot,
116         # and web servers are all running on the same machine, the web
117         # server certificate takes precedence.
118         for server in API BOOT WWW ; do
119             enabled=PLC_${server}_ENABLED
120             if [ "${!enabled}" != "1" ] ; then
121                 continue
122             fi
123             ssl_key=PLC_${server}_SSL_KEY
124             ssl_crt=PLC_${server}_SSL_CRT
125
126             symlink ${!ssl_crt} /etc/pki/tls/certs/localhost.crt
127             symlink ${!ssl_key} /etc/pki/tls/private/localhost.key
128             symlink ${!ssl_crt} /etc/httpd/conf/ssl.crt/server.crt
129             symlink ${!ssl_key} /etc/httpd/conf/ssl.key/server.key
130         done
131
132         result "$MESSAGE"
133         ;;
134 esac
135
136 exit $ERRORS