Merge github#758: media-sound/mpd: fix the systemd user service
[gentoo.git] / eclass / ssl-cert.eclass
1 # Copyright 1999-2014 Gentoo Foundation
2 # Distributed under the terms of the GNU General Public License v2
3 # $Id$
4
5 # @ECLASS: ssl-cert.eclass
6 # @MAINTAINER:
7 # @AUTHOR:
8 # Max Kalika <max@gentoo.org>
9 # @BLURB: Eclass for SSL certificates
10 # @DESCRIPTION:
11 # This eclass implements a standard installation procedure for installing
12 # self-signed SSL certificates.
13 # @EXAMPLE:
14 # "install_cert /foo/bar" installs ${ROOT}/foo/bar.{key,csr,crt,pem}
15
16 # @ECLASS-VARIABLE: SSL_CERT_MANDATORY
17 # @DESCRIPTION:
18 # Set to non zero if ssl-cert is mandatory for ebuild.
19 : ${SSL_CERT_MANDATORY:=0}
20
21 # @ECLASS-VARIABLE: SSL_CERT_USE
22 # @DESCRIPTION:
23 # Use flag to append dependency to.
24 : ${SSL_CERT_USE:=ssl}
25
26 # @ECLASS-VARIABLE: SSL_DEPS_SKIP
27 # @DESCRIPTION:
28 # Set to non zero to skip adding to DEPEND and IUSE.
29 : ${SSL_DEPS_SKIP:=0}
30
31 if [[ "${SSL_DEPS_SKIP}" == "0" ]]; then
32         if [[ "${SSL_CERT_MANDATORY}" == "0" ]]; then
33                 DEPEND="${SSL_CERT_USE}? ( dev-libs/openssl )"
34                 IUSE="${SSL_CERT_USE}"
35         else
36                 DEPEND="dev-libs/openssl"
37         fi
38 fi
39
40 # @FUNCTION: gen_cnf
41 # @USAGE:
42 # @DESCRIPTION:
43 # Initializes variables and generates the needed
44 # OpenSSL configuration file and a CA serial file
45 #
46 # Access: private
47 gen_cnf() {
48         # Location of the config file
49         SSL_CONF="${T}/${$}ssl.cnf"
50         # Location of the CA serial file
51         SSL_SERIAL="${T}/${$}ca.ser"
52         # Location of some random files OpenSSL can use: don't use
53         # /dev/u?random here -- doesn't work properly on all platforms
54         SSL_RANDOM="${T}/environment:${T}/eclass-debug.log:/etc/resolv.conf"
55
56         # These can be overridden in the ebuild
57         SSL_DAYS="${SSL_DAYS:-730}"
58         SSL_BITS="${SSL_BITS:-1024}"
59         SSL_COUNTRY="${SSL_COUNTRY:-US}"
60         SSL_STATE="${SSL_STATE:-California}"
61         SSL_LOCALITY="${SSL_LOCALITY:-Santa Barbara}"
62         SSL_ORGANIZATION="${SSL_ORGANIZATION:-SSL Server}"
63         SSL_UNIT="${SSL_UNIT:-For Testing Purposes Only}"
64         SSL_COMMONNAME="${SSL_COMMONNAME:-localhost}"
65         SSL_EMAIL="${SSL_EMAIL:-root@localhost}"
66
67         # Create the CA serial file
68         echo "01" > "${SSL_SERIAL}"
69
70         # Create the config file
71         ebegin "Generating OpenSSL configuration${1:+ for CA}"
72         cat <<-EOF > "${SSL_CONF}"
73                 [ req ]
74                 prompt             = no
75                 default_bits       = ${SSL_BITS}
76                 distinguished_name = req_dn
77                 [ req_dn ]
78                 C                  = ${SSL_COUNTRY}
79                 ST                 = ${SSL_STATE}
80                 L                  = ${SSL_LOCALITY}
81                 O                  = ${SSL_ORGANIZATION}
82                 OU                 = ${SSL_UNIT}
83                 CN                 = ${SSL_COMMONNAME}${1:+ CA}
84                 emailAddress       = ${SSL_EMAIL}
85         EOF
86         eend $?
87
88         return $?
89 }
90
91 # @FUNCTION: get_base
92 # @USAGE: [if_ca]
93 # @RETURN: <base path>
94 # @DESCRIPTION:
95 # Simple function to determine whether we're creating
96 # a CA (which should only be done once) or final part
97 #
98 # Access: private
99 get_base() {
100         if [ "${1}" ] ; then
101                 echo "${T}/${$}ca"
102         else
103                 echo "${T}/${$}server"
104         fi
105 }
106
107 # @FUNCTION: gen_key
108 # @USAGE: <base path>
109 # @DESCRIPTION:
110 # Generates an RSA key
111 #
112 # Access: private
113 gen_key() {
114         local base=$(get_base "$1")
115         ebegin "Generating ${SSL_BITS} bit RSA key${1:+ for CA}"
116         openssl genrsa -rand "${SSL_RANDOM}" \
117                 -out "${base}.key" "${SSL_BITS}" &> /dev/null
118         eend $?
119
120         return $?
121 }
122
123 # @FUNCTION: gen_csr
124 # @USAGE: <base path>
125 # @DESCRIPTION:
126 # Generates a certificate signing request using
127 # the key made by gen_key()
128 #
129 # Access: private
130 gen_csr() {
131         local base=$(get_base "$1")
132         ebegin "Generating Certificate Signing Request${1:+ for CA}"
133         openssl req -config "${SSL_CONF}" -new \
134                 -key "${base}.key" -out "${base}.csr" &>/dev/null
135         eend $?
136
137         return $?
138 }
139
140 # @FUNCTION: gen_crt
141 # @USAGE: <base path>
142 # @DESCRIPTION:
143 # Generates either a self-signed CA certificate using
144 # the csr and key made by gen_csr() and gen_key() or
145 # a signed server certificate using the CA cert previously
146 # created by gen_crt()
147 #
148 # Access: private
149 gen_crt() {
150         local base=$(get_base "$1")
151         if [ "${1}" ] ; then
152                 ebegin "Generating self-signed X.509 Certificate for CA"
153                 openssl x509 -extfile "${SSL_CONF}" \
154                         -days ${SSL_DAYS} -req -signkey "${base}.key" \
155                         -in "${base}.csr" -out "${base}.crt" &>/dev/null
156         else
157                 local ca=$(get_base 1)
158                 ebegin "Generating authority-signed X.509 Certificate"
159                 openssl x509 -extfile "${SSL_CONF}" \
160                         -days ${SSL_DAYS} -req -CAserial "${SSL_SERIAL}" \
161                         -CAkey "${ca}.key" -CA "${ca}.crt" \
162                         -in "${base}.csr" -out "${base}.crt" &>/dev/null
163         fi
164         eend $?
165
166         return $?
167 }
168
169 # @FUNCTION: gen_pem
170 # @USAGE: <base path>
171 # @DESCRIPTION:
172 # Generates a PEM file by concatinating the key
173 # and cert file created by gen_key() and gen_cert()
174 #
175 # Access: private
176 gen_pem() {
177         local base=$(get_base "$1")
178         ebegin "Generating PEM Certificate"
179         (cat "${base}.key"; echo; cat "${base}.crt") > "${base}.pem"
180         eend $?
181
182         return $?
183 }
184
185 # @FUNCTION: install_cert
186 # @USAGE: <certificates>
187 # @DESCRIPTION:
188 # Uses all the private functions above to generate and install the
189 # requested certificates.
190 # <certificates> are full pathnames relative to ROOT, without extension.
191 #
192 # Example: "install_cert /foo/bar" installs ${ROOT}/foo/bar.{key,csr,crt,pem}
193 #
194 # Access: public
195 install_cert() {
196         if [ $# -lt 1 ] ; then
197                 eerror "At least one argument needed"
198                 return 1;
199         fi
200
201         case ${EBUILD_PHASE} in
202         unpack|prepare|configure|compile|test|install)
203                 die "install_cert cannot be called in ${EBUILD_PHASE}"
204                 ;;
205         esac
206
207         # Generate a CA environment #164601
208         gen_cnf 1 || return 1
209         gen_key 1 || return 1
210         gen_csr 1 || return 1
211         gen_crt 1 || return 1
212         echo
213
214         gen_cnf || return 1
215         echo
216
217         local count=0
218         for cert in "$@" ; do
219                 # Check the requested certificate
220                 if [ -z "${cert##*/}" ] ; then
221                         ewarn "Invalid certification requested, skipping"
222                         continue
223                 fi
224
225                 # Check for previous existence of generated files
226                 for type in key csr crt pem ; do
227                         if [ -e "${ROOT}${cert}.${type}" ] ; then
228                                 ewarn "${ROOT}${cert}.${type}: exists, skipping"
229                                 continue 2
230                         fi
231                 done
232
233                 # Generate the requested files
234                 gen_key || continue
235                 gen_csr || continue
236                 gen_crt || continue
237                 gen_pem || continue
238                 echo
239
240                 # Install the generated files and set sane permissions
241                 local base=$(get_base)
242                 install -d "${ROOT}${cert%/*}"
243                 install -m0400 "${base}.key" "${ROOT}${cert}.key"
244                 install -m0444 "${base}.csr" "${ROOT}${cert}.csr"
245                 install -m0444 "${base}.crt" "${ROOT}${cert}.crt"
246                 install -m0400 "${base}.pem" "${ROOT}${cert}.pem"
247                 : $(( ++count ))
248         done
249
250         # Resulting status
251         if [ ${count} = 0 ] ; then
252                 eerror "No certificates were generated"
253                 return 1
254         elif [ ${count} != ${#} ] ; then
255                 ewarn "Some requested certificates were not generated"
256         fi
257 }