1 # Copyright 1999-2017 Gentoo Foundation
2 # Distributed under the terms of the GNU General Public License v2
4 # @ECLASS: ssl-cert.eclass
7 # Max Kalika <max@gentoo.org>
8 # @SUPPORTED_EAPIS: 1 2 3 4 5 6 7
9 # @BLURB: Eclass for SSL certificates
11 # This eclass implements a standard installation procedure for installing
12 # self-signed SSL certificates.
14 # "install_cert /foo/bar" installs ${ROOT}/foo/bar.{key,csr,crt,pem}
16 # Guard against unsupported EAPIs. We need EAPI >= 1 for slot dependencies.
19 die "${ECLASS}.eclass: EAPI=0 is not supported. Please upgrade to EAPI >= 1."
24 die "${ECLASS}.eclass: EAPI=${EAPI} is not supported yet."
28 # @ECLASS-VARIABLE: SSL_CERT_MANDATORY
30 # Set to non zero if ssl-cert is mandatory for ebuild.
31 : ${SSL_CERT_MANDATORY:=0}
33 # @ECLASS-VARIABLE: SSL_CERT_USE
35 # Use flag to append dependency to.
36 : ${SSL_CERT_USE:=ssl}
38 # @ECLASS-VARIABLE: SSL_DEPS_SKIP
40 # Set to non zero to skip adding to DEPEND and IUSE.
43 if [[ "${SSL_DEPS_SKIP}" == "0" ]]; then
44 if [[ "${SSL_CERT_MANDATORY}" == "0" ]]; then
45 SSL_DEPEND="${SSL_CERT_USE}? ( || ( dev-libs/openssl:0 dev-libs/libressl:0 ) )"
46 IUSE="${SSL_CERT_USE}"
48 SSL_DEPEND="|| ( dev-libs/openssl:0 dev-libs/libressl:0 )"
53 DEPEND="${SSL_DEPEND}"
56 BDEPEND="${SSL_DEPEND}"
66 # Initializes variables and generates the needed
67 # OpenSSL configuration file and a CA serial file
71 # Location of the config file
72 SSL_CONF="${T}/${$}ssl.cnf"
73 # Location of the CA serial file
74 SSL_SERIAL="${T}/${$}ca.ser"
75 # Location of some random files OpenSSL can use: don't use
76 # /dev/u?random here -- doesn't work properly on all platforms
77 SSL_RANDOM="${T}/environment:${T}/eclass-debug.log:/etc/resolv.conf"
79 # These can be overridden in the ebuild
80 SSL_DAYS="${SSL_DAYS:-730}"
81 SSL_BITS="${SSL_BITS:-4096}"
82 SSL_MD="${SSL_MD:-sha256}"
83 SSL_COUNTRY="${SSL_COUNTRY:-US}"
84 SSL_STATE="${SSL_STATE:-California}"
85 SSL_LOCALITY="${SSL_LOCALITY:-Santa Barbara}"
86 SSL_ORGANIZATION="${SSL_ORGANIZATION:-SSL Server}"
87 SSL_UNIT="${SSL_UNIT:-For Testing Purposes Only}"
88 SSL_COMMONNAME="${SSL_COMMONNAME:-localhost}"
89 SSL_EMAIL="${SSL_EMAIL:-root@localhost}"
91 # Create the CA serial file
92 echo "01" > "${SSL_SERIAL}"
94 # Create the config file
95 ebegin "Generating OpenSSL configuration${1:+ for CA}"
96 cat <<-EOF > "${SSL_CONF}"
99 default_bits = ${SSL_BITS}
100 distinguished_name = req_dn
105 O = ${SSL_ORGANIZATION}
107 CN = ${SSL_COMMONNAME}${1:+ CA}
108 emailAddress = ${SSL_EMAIL}
115 # @FUNCTION: get_base
117 # @RETURN: <base path>
119 # Simple function to determine whether we're creating
120 # a CA (which should only be done once) or final part
127 echo "${T}/${$}server"
132 # @USAGE: <base path>
134 # Generates an RSA key
138 local base=$(get_base "$1")
139 ebegin "Generating ${SSL_BITS} bit RSA key${1:+ for CA}"
140 if openssl version | grep -i libressl > /dev/null; then
141 openssl genrsa -out "${base}.key" "${SSL_BITS}" &> /dev/null
143 openssl genrsa -rand "${SSL_RANDOM}" \
144 -out "${base}.key" "${SSL_BITS}" &> /dev/null
152 # @USAGE: <base path>
154 # Generates a certificate signing request using
155 # the key made by gen_key()
159 local base=$(get_base "$1")
160 ebegin "Generating Certificate Signing Request${1:+ for CA}"
161 openssl req -config "${SSL_CONF}" -new \
162 -key "${base}.key" -out "${base}.csr" &>/dev/null
169 # @USAGE: <base path>
171 # Generates either a self-signed CA certificate using
172 # the csr and key made by gen_csr() and gen_key() or
173 # a signed server certificate using the CA cert previously
174 # created by gen_crt()
178 local base=$(get_base "$1")
180 ebegin "Generating self-signed X.509 Certificate for CA"
181 openssl x509 -extfile "${SSL_CONF}" \
183 -days ${SSL_DAYS} -req -signkey "${base}.key" \
184 -in "${base}.csr" -out "${base}.crt" &>/dev/null
186 local ca=$(get_base 1)
187 ebegin "Generating authority-signed X.509 Certificate"
188 openssl x509 -extfile "${SSL_CONF}" \
189 -days ${SSL_DAYS} -req -CAserial "${SSL_SERIAL}" \
190 -CAkey "${ca}.key" -CA "${ca}.crt" -${SSL_MD} \
191 -in "${base}.csr" -out "${base}.crt" &>/dev/null
199 # @USAGE: <base path>
201 # Generates a PEM file by concatinating the key
202 # and cert file created by gen_key() and gen_cert()
206 local base=$(get_base "$1")
207 ebegin "Generating PEM Certificate"
208 (cat "${base}.key"; echo; cat "${base}.crt") > "${base}.pem"
214 # @FUNCTION: install_cert
215 # @USAGE: <certificates>
217 # Uses all the private functions above to generate and install the
218 # requested certificates.
219 # <certificates> are full pathnames relative to ROOT, without extension.
221 # Example: "install_cert /foo/bar" installs ${ROOT}/foo/bar.{key,csr,crt,pem}
225 if [ $# -lt 1 ] ; then
226 eerror "At least one argument needed"
230 case ${EBUILD_PHASE} in
231 unpack|prepare|configure|compile|test|install)
232 die "install_cert cannot be called in ${EBUILD_PHASE}"
236 # Generate a CA environment #164601
237 gen_cnf 1 || return 1
238 gen_key 1 || return 1
239 gen_csr 1 || return 1
240 gen_crt 1 || return 1
247 for cert in "$@" ; do
248 # Check the requested certificate
249 if [ -z "${cert##*/}" ] ; then
250 ewarn "Invalid certification requested, skipping"
254 # Check for previous existence of generated files
255 for type in key csr crt pem ; do
256 if [ -e "${ROOT}${cert}.${type}" ] ; then
257 ewarn "${ROOT}${cert}.${type}: exists, skipping"
262 # Generate the requested files
269 # Install the generated files and set sane permissions
270 local base=$(get_base)
271 install -d "${ROOT}${cert%/*}"
272 install -m0400 "${base}.key" "${ROOT}${cert}.key"
273 install -m0444 "${base}.csr" "${ROOT}${cert}.csr"
274 install -m0444 "${base}.crt" "${ROOT}${cert}.crt"
275 install -m0400 "${base}.pem" "${ROOT}${cert}.pem"
280 if [ ${count} = 0 ] ; then
281 eerror "No certificates were generated"
283 elif [ ${count} != ${#} ] ; then
284 ewarn "Some requested certificates were not generated"