a4afb7f24935ea7bc718db145dffbc82efae7f4f
[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.7 2006/06/28 21:34: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 }
26
27 # Print the emailAddress of an SSL certificate
28 ssl_email ()
29 {
30     openssl x509 -noout -in $1 -subject | \
31         sed -n -e 's@.*/emailAddress=\([^/]*\).*@\1@p'
32 }
33
34 # Verify a certificate. If invalid, generate a new self-signed
35 # certificate.
36 verify_or_generate_certificate() {
37     crt=$1
38     key=$2
39     ca=$3
40     cname=$4
41     email=$5
42
43     if [ -f $crt ] ; then
44         # Check if certificate is valid
45         verify=$(openssl verify -CAfile $ca $crt)
46         # Delete if invalid or if the subject has changed
47         if grep -q "error" <<<$verify || \
48             [ "$(ssl_cname $crt)" != "$cname" ] || \
49             [ "$(ssl_email $crt)" != "$email" ] ; then
50             rm -f $crt $ca
51         fi
52     fi
53
54     if [ ! -f $crt ] ; then
55         # Set subject
56         subj=
57         if [ -n "$cname" ] ; then
58             subj="$subj/CN=$cname"
59         fi
60         if [ -n "$email" ] ; then
61             subj="$subj/emailAddress=$email"
62         fi
63
64         # Generate new self-signed certificate
65         mkdir -p $(dirname $crt)
66         openssl req -new -x509 -days 3650 -set_serial $RANDOM \
67             -batch -subj "$subj" \
68             -nodes -keyout $key -out $crt
69         check
70         chmod 644 $crt
71     fi
72
73     if [ ! -f $ca ] ; then
74         # The certificate it self-signed, so it is its own CA
75         cp -a $crt $ca
76     fi
77 }
78
79 case "$1" in
80     start)
81         MESSAGE=$"Generating SSL certificates"
82         dialog "$MESSAGE"
83
84         # Verify or generate MA/SA certificate if necessary. This
85         # self-signed certificate may be overridden later.
86         verify_or_generate_certificate \
87             $PLC_MA_SA_SSL_CRT $PLC_MA_SA_SSL_KEY $PLC_MA_SA_CA_SSL_CRT \
88             "$PLC_NAME Management and Slice Authority" \
89             $PLC_MAIL_SUPPORT_ADDRESS
90
91         # Make MA/SA key readable by apache so that the API can sign
92         # certificates
93         chown apache $PLC_MA_SA_SSL_KEY
94         chmod 600 $PLC_MA_SA_SSL_KEY
95
96         # Extract the public key of the root CA (if any) that signed
97         # the MA/SA certificate.
98         openssl x509 -in $PLC_MA_SA_CA_SSL_CRT -noout -pubkey >$PLC_MA_SA_CA_SSL_KEY_PUB
99         check
100         chmod 644 $PLC_MA_SA_CA_SSL_KEY_PUB
101
102         # Generate HTTPS certificates if necessary. We generate a
103         # certificate for each enabled server with a different
104         # hostname. These self-signed certificates may be overridden
105         # later.
106         for server in WWW API BOOT ; do
107             ssl_key=PLC_${server}_SSL_KEY
108             ssl_crt=PLC_${server}_SSL_CRT
109             ca_ssl_crt=PLC_${server}_CA_SSL_CRT
110             hostname=PLC_${server}_HOST
111
112             # Check if we have already generated a certificate for
113             # the same hostname.
114             for previous_server in WWW API BOOT ; do
115                 if [ "$server" = "$previous_server" ] ; then
116                     break
117                 fi
118                 previous_ssl_key=PLC_${previous_server}_SSL_KEY
119                 previous_ssl_crt=PLC_${previous_server}_SSL_CRT
120                 previous_ca_ssl_crt=PLC_${previous_server}_CA_SSL_CRT
121                 previous_hostname=PLC_${previous_server}_HOST
122
123                 if [ -f ${!previous_ssl_crt} ] && \
124                     [ "$(ssl_cname ${!previous_ssl_crt})" = "${!hostname}" ] ; then
125                     cp -a ${!previous_ssl_key} ${!ssl_key}
126                     cp -a ${!previous_ssl_crt} ${!ssl_crt}
127                     cp -a ${!previous_ca_ssl_crt} ${!ca_ssl_crt}
128                     break
129                 fi
130             done
131
132             verify_or_generate_certificate \
133                 ${!ssl_crt} ${!ssl_key} ${!ca_ssl_crt} \
134                 ${!hostname} $PLC_MAIL_SUPPORT_ADDRESS
135
136         done
137
138         # Install HTTPS certificates into both /etc/pki (Fedora Core
139         # 4) and /etc/httpd/conf (Fedora Core 2). If the API, boot,
140         # and web servers are all running on the same machine, the web
141         # server certificate takes precedence.
142         for server in API BOOT WWW ; do
143             enabled=PLC_${server}_ENABLED
144             if [ "${!enabled}" != "1" ] ; then
145                 continue
146             fi
147             ssl_key=PLC_${server}_SSL_KEY
148             ssl_crt=PLC_${server}_SSL_CRT
149
150             symlink ${!ssl_crt} /etc/pki/tls/certs/localhost.crt
151             symlink ${!ssl_key} /etc/pki/tls/private/localhost.key
152             symlink ${!ssl_crt} /etc/httpd/conf/ssl.crt/server.crt
153             symlink ${!ssl_key} /etc/httpd/conf/ssl.key/server.key
154         done
155
156         result "$MESSAGE"
157         ;;
158 esac
159
160 exit $ERRORS