e2c8c027f207b56759eb8a4f9d753afc85a0a042
[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.10 2006/07/24 19:30:45 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 the CA certificate does not exist, assume that the
44     # certificate is self-signed.
45     if [ ! -f $ca ] ; then
46         cp -a $crt $ca
47     fi
48
49     if [ -f $crt ] ; then
50         # Check if certificate is valid
51         verify=$(openssl verify -CAfile $ca $crt)
52         # Delete if invalid or if the subject has changed
53         if grep -q "error" <<<$verify || \
54             [ "$(ssl_cname $crt)" != "$cname" ] || \
55             [ "$(ssl_email $crt)" != "$email" ] ; then
56             rm -f $crt $ca
57         fi
58     fi
59
60     if [ ! -f $crt ] ; then
61         # Set subject
62         subj=
63         if [ -n "$cname" ] ; then
64             subj="$subj/CN=$cname"
65         fi
66         if [ -n "$email" ] ; then
67             subj="$subj/emailAddress=$email"
68         fi
69
70         # Generate new self-signed certificate
71         mkdir -p $(dirname $crt)
72         openssl req -new -x509 -days 3650 -set_serial $RANDOM \
73             -batch -subj "$subj" \
74             -nodes -keyout $key -out $crt
75         check
76         chmod 644 $crt
77
78         # The certificate it self-signed, so it is its own CA
79         cp -a $crt $ca
80     fi
81 }
82
83 case "$1" in
84     start)
85         MESSAGE=$"Generating SSL certificates"
86         dialog "$MESSAGE"
87
88         # Generate HTTPS certificates if necessary. We generate a
89         # certificate for each enabled server with a different
90         # hostname. These self-signed certificates may be overridden
91         # later.
92         for server in WWW API BOOT ; do
93             ssl_key=PLC_${server}_SSL_KEY
94             ssl_crt=PLC_${server}_SSL_CRT
95             ca_ssl_crt=PLC_${server}_CA_SSL_CRT
96             hostname=PLC_${server}_HOST
97
98             # Check if we have already generated a certificate for
99             # the same hostname.
100             for previous_server in WWW API BOOT ; do
101                 if [ "$server" = "$previous_server" ] ; then
102                     break
103                 fi
104                 previous_ssl_key=PLC_${previous_server}_SSL_KEY
105                 previous_ssl_crt=PLC_${previous_server}_SSL_CRT
106                 previous_ca_ssl_crt=PLC_${previous_server}_CA_SSL_CRT
107                 previous_hostname=PLC_${previous_server}_HOST
108
109                 if [ -f ${!previous_ssl_crt} ] && \
110                     [ "$(ssl_cname ${!previous_ssl_crt})" = "${!hostname}" ] ; then
111                     cp -a ${!previous_ssl_key} ${!ssl_key}
112                     cp -a ${!previous_ssl_crt} ${!ssl_crt}
113                     cp -a ${!previous_ca_ssl_crt} ${!ca_ssl_crt}
114                     break
115                 fi
116             done
117
118             verify_or_generate_certificate \
119                 ${!ssl_crt} ${!ssl_key} ${!ca_ssl_crt} \
120                 ${!hostname}
121         done
122
123         # Install HTTPS certificates into both /etc/pki (Fedora Core
124         # 4) and /etc/httpd/conf (Fedora Core 2). If the API, boot,
125         # and web servers are all running on the same machine, the web
126         # server certificate takes precedence.
127         for server in API BOOT WWW ; do
128             enabled=PLC_${server}_ENABLED
129             if [ "${!enabled}" != "1" ] ; then
130                 continue
131             fi
132             ssl_key=PLC_${server}_SSL_KEY
133             ssl_crt=PLC_${server}_SSL_CRT
134
135             symlink ${!ssl_crt} /etc/pki/tls/certs/localhost.crt
136             symlink ${!ssl_key} /etc/pki/tls/private/localhost.key
137             symlink ${!ssl_crt} /etc/httpd/conf/ssl.crt/server.crt
138             symlink ${!ssl_key} /etc/httpd/conf/ssl.key/server.key
139         done
140
141         result "$MESSAGE"
142         ;;
143 esac
144
145 exit $ERRORS