- The self-signed root CA keypair and cert should *not* be used to sign
[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.6 2006/06/28 20:44:17 alk 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 mkcert ()
21 {
22     CN=$1
23     KEY=$2
24     CRT=$3
25
26     # Generate a temporary CSR. We could save the CSR, but it's not
27     # worth the trouble.
28     csr=$(mktemp /tmp/csr.XXXXXX)
29
30     mkdir -p $(dirname $KEY)
31     openssl req -config /etc/planetlab/ssl/openssl.cnf \
32         -new -extensions v3_req -days 3650 -set_serial $RANDOM \
33         -batch -subj "/CN=$CN" \
34         -nodes -keyout $KEY -out $csr
35     check
36     chmod 600 $KEY
37
38     # Generate and sign certificate from CSR
39     serial=$(cat /etc/planetlab/ssl/serial)
40
41     openssl ca -config /etc/planetlab/ssl/openssl.cnf \
42         -keyfile $PLC_ROOT_CA_SSL_KEY \
43         -cert $PLC_ROOT_CA_SSL_CRT \
44         -batch -infiles $csr
45     check
46
47     mv /etc/planetlab/ssl/$serial.pem $CRT
48     chmod 644 $CRT
49
50     # Delete CSR
51     rm -f $csr
52 }
53
54 case "$1" in
55     start)
56         MESSAGE=$"Generating SSL certificates"
57         dialog "$MESSAGE"
58
59         # Check if root CA certificate is valid
60         if [ -f $PLC_ROOT_CA_SSL_CRT ] ; then
61             verify=$(openssl verify $PLC_ROOT_CA_SSL_CRT)
62             # If self signed, assume that we generated it
63             if grep -q "self signed certificate" <<<$verify ; then
64                 # Delete if expired or PLC name or e-mail address has changed
65                 if grep -q "expired" <<<$verify || \
66                     [ "$(ssl_cname $PLC_ROOT_CA_SSL_CRT)" != "$PLC_NAME Root CA" ] || \
67                     [ "$(ssl_email $PLC_ROOT_CA_SSL_CRT)" != "$PLC_MAIL_SUPPORT_ADDRESS" ] ; then
68                     rm -f $PLC_ROOT_CA_SSL_CRT
69                 fi
70             fi
71         fi
72
73         # Generate root CA key pair and certificate
74         if [ ! -f $PLC_ROOT_CA_SSL_CRT ] ; then
75             mkdir -p $(dirname $PLC_ROOT_CA_SSL_CRT)
76             openssl req -config /etc/planetlab/ssl/openssl.cnf \
77                 -new -x509 -extensions v3_ca -days 3650 -set_serial $RANDOM \
78                 -batch -subj "/CN=$PLC_NAME Root CA/emailAddress=$PLC_MAIL_SUPPORT_ADDRESS" \
79                 -nodes -keyout $PLC_ROOT_CA_SSL_KEY -out $PLC_ROOT_CA_SSL_CRT
80             check
81             chmod 600 $PLC_ROOT_CA_SSL_KEY
82             chmod 644 $PLC_ROOT_CA_SSL_CRT
83
84             # API certificate verification requires a public key
85             openssl rsa -pubout <$PLC_ROOT_CA_SSL_KEY >$PLC_ROOT_CA_SSL_KEY_PUB
86             check
87             chmod 644 $PLC_ROOT_CA_SSL_KEY_PUB
88
89             # Reset DB
90             >/etc/planetlab/ssl/index.txt
91             echo "01" >/etc/planetlab/ssl/serial
92         fi
93
94         # Check if MA/SA certificate is valid
95         if [ -f $PLC_MA_SA_SSL_CRT ] ; then
96             verify=$(openssl verify -CAfile $PLC_ROOT_CA_SSL_CRT $PLC_MA_SA_SSL_CRT)
97             # Delete if expired or not signed correctly
98             if grep -q "error" <<<$verify ; then
99                 rm -f $PLC_MA_SA_SSL_CRT
100             fi
101         fi
102
103         # Generate MA/SA key pair and certificate
104         if [ ! -f $PLC_MA_SA_SSL_CRT ] ; then
105             mkcert "$PLC_NAME Management and Slice Authority" \
106                 $PLC_MA_SA_SSL_KEY $PLC_MA_SA_SSL_CRT
107
108             # Make readable by apache so that the API can sign certificates
109             chown apache $PLC_MA_SA_SSL_KEY
110             chmod 600 $PLC_MA_SA_SSL_KEY
111
112             # API requires a public key for slice ticket verification
113             openssl rsa -pubout <$PLC_MA_SA_SSL_KEY >$PLC_MA_SA_SSL_KEY_PUB
114             check
115             chmod 644 $PLC_MA_SA_SSL_KEY_PUB
116         fi
117
118         # Generate self-signed HTTPS certificate(s). These nice
119         # commands come from the mod_ssl spec file for Fedora Core
120         # 2. We generate a certificate for each enabled server
121         # with a different hostname. These self-signed
122         # certificates may be overridden later.
123         for server in WWW API BOOT ; do
124             ssl_key=PLC_${server}_SSL_KEY
125             ssl_crt=PLC_${server}_SSL_CRT
126             hostname=PLC_${server}_HOST
127
128             # Check if we have already generated a certificate for
129             # the same hostname.
130             for previous_server in WWW API BOOT ; do
131                 if [ "$server" = "$previous_server" ] ; then
132                     break
133                 fi
134                 previous_ssl_key=PLC_${previous_server}_SSL_KEY
135                 previous_ssl_crt=PLC_${previous_server}_SSL_CRT
136                 previous_hostname=PLC_${previous_server}_HOST
137
138                 if [ -f ${!previous_ssl_crt} ] && \
139                     [ "$(ssl_cname ${!previous_ssl_crt})" = "${!hostname}" ] ; then
140                     cp -a ${!previous_ssl_key} ${!ssl_key}
141                     cp -a ${!previous_ssl_crt} ${!ssl_crt}
142                     break
143                 fi
144             done
145
146             # Check if self-signed certificate is valid
147             if [ -f ${!ssl_crt} ] ; then
148                 verify=$(openssl verify ${!ssl_crt})
149                 # If self-signed
150                 if grep -q "self signed certificate" <<<$verify ; then
151                     # Delete if expired or hostname changed
152                     if grep -q "expired" <<<$verify || \
153                         [ "$(ssl_cname ${!ssl_crt})" != "${!hostname}" ] ; then
154                         rm -f ${!ssl_crt}
155                     fi
156                 fi
157             fi
158
159             # Generate new self-signed certificate
160             if [ ! -f ${!ssl_crt} ] ; then
161                 mkdir -p $(dirname ${!ssl_crt})
162                 openssl req -new -x509 -days 3650 -set_serial $RANDOM \
163                     -batch -subj "/CN=${!hostname}" \
164                     -nodes -keyout ${!ssl_key} -out ${!ssl_crt}
165                 check
166                 chmod 644 ${!ssl_crt}
167             fi
168         done
169
170         # Install HTTPS certificates into both /etc/pki (Fedora Core
171         # 4) and /etc/httpd/conf (Fedora Core 2). If the API, boot,
172         # and web servers are all running on the same machine, the web
173         # server certificate takes precedence.
174         for server in API BOOT WWW ; do
175             enabled=PLC_${server}_ENABLED
176             if [ "${!enabled}" != "1" ] ; then
177                 continue
178             fi
179             ssl_key=PLC_${server}_SSL_KEY
180             ssl_crt=PLC_${server}_SSL_CRT
181
182             symlink ${!ssl_crt} /etc/pki/tls/certs/localhost.crt
183             symlink ${!ssl_key} /etc/pki/tls/private/localhost.key
184             symlink ${!ssl_crt} /etc/httpd/conf/ssl.crt/server.crt
185             symlink ${!ssl_key} /etc/httpd/conf/ssl.key/server.key
186         done
187
188         result "$MESSAGE"
189         ;;
190 esac
191
192 exit $ERRORS