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