0615d75d586587009ef7a1b060fc0ebff356e502
[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.4 2006/04/25 21:18:19 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 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 365 -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             # API requires a public key for slice ticket verification
109             openssl rsa -pubout <$PLC_MA_SA_SSL_KEY >$PLC_MA_SA_SSL_KEY_PUB
110             check
111             chmod 644 $PLC_MA_SA_SSL_KEY_PUB
112         fi
113
114         # Generate HTTPS certificate(s). We generate a certificate for
115         # each enabled server with a different hostname.
116         for server in WWW API BOOT ; do
117             ssl_key=PLC_${server}_SSL_KEY
118             ssl_crt=PLC_${server}_SSL_CRT
119             hostname=PLC_${server}_HOST
120
121             # Check if we have already generated a certificate for
122             # the same hostname.
123             for previous_server in WWW API BOOT ; do
124                 if [ "$server" = "$previous_server" ] ; then
125                     break
126                 fi
127                 previous_ssl_key=PLC_${previous_server}_SSL_KEY
128                 previous_ssl_crt=PLC_${previous_server}_SSL_CRT
129                 previous_hostname=PLC_${previous_server}_HOST
130
131                 if [ -f ${!previous_ssl_crt} ] && \
132                     [ "$(ssl_cname ${!previous_ssl_crt})" = "${!hostname}" ] ; then
133                     cp -a ${!previous_ssl_key} ${!ssl_key}
134                     cp -a ${!previous_ssl_crt} ${!ssl_crt}
135                     break
136                 fi
137             done
138
139             # Check if certificate is valid
140             if [ -f ${!ssl_crt} ] ; then
141                 verify=$(openssl verify -CAfile $PLC_ROOT_CA_SSL_CRT ${!ssl_crt})
142                 # Delete if expired or hostname changed. These
143                 # certificates do not necessarily have to be signed by
144                 # the root CA; they may be signed by a third party,
145                 # e.g., Entrust or Verisign.
146                 if grep -q "expired" <<<$verify || \
147                     [ "$(ssl_cname ${!ssl_crt})" != "${!hostname}" ] ; then
148                     rm -f ${!ssl_crt}
149                 fi
150             fi
151
152             # Generate and sign certificate
153             if [ ! -f ${!ssl_crt} ] ; then
154                 mkcert ${!hostname} ${!ssl_key} ${!ssl_crt}
155             fi
156         done
157
158         # Install HTTPS certificates into both /etc/pki (Fedora Core
159         # 4) and /etc/httpd/conf (Fedora Core 2). If the API, boot,
160         # and web servers are all running on the same machine, the web
161         # server certificate takes precedence.
162         for server in API BOOT WWW ; do
163             enabled=PLC_${server}_ENABLED
164             if [ "${!enabled}" != "1" ] ; then
165                 continue
166             fi
167             ssl_key=PLC_${server}_SSL_KEY
168             ssl_crt=PLC_${server}_SSL_CRT
169
170             symlink ${!ssl_crt} /etc/pki/tls/certs/localhost.crt
171             symlink ${!ssl_key} /etc/pki/tls/private/localhost.key
172             symlink ${!ssl_crt} /etc/httpd/conf/ssl.crt/server.crt
173             symlink ${!ssl_key} /etc/httpd/conf/ssl.key/server.key
174         done
175
176         result "$MESSAGE"
177         ;;
178 esac
179
180 exit $ERRORS