| # Copyright 1999-2004 Gentoo Foundation |
| # Distributed under the terms of the GNU General Public License v2 |
| # $Header: /var/cvsroot/gentoo-x86/eclass/ssl-cert.eclass,v 1.18 2010/02/16 14:23:39 pva Exp $ |
| # |
| # @ECLASS: ssl-cert.eclass |
| # @MAINTAINER: |
| # Author: Max Kalika <max@gentoo.org> |
| # @BLURB: Eclass for SSL certificates |
| # @DESCRIPTION: |
| # This eclass implements a standard installation procedure for installing |
| # self-signed SSL certificates. |
| # @EXAMPLE: |
| # "install_cert /foo/bar" installs ${ROOT}/foo/bar.{key,csr,crt,pem} |
| |
| # Conditionally depend on OpenSSL: allows inheretence |
| # without pulling extra packages if not needed |
| DEPEND="ssl? ( dev-libs/openssl )" |
| IUSE="ssl" |
| |
| # @FUNCTION: gen_cnf |
| # @USAGE: |
| # @DESCRIPTION: |
| # Initializes variables and generates the needed |
| # OpenSSL configuration file and a CA serial file |
| # |
| # Access: private |
| gen_cnf() { |
| # Location of the config file |
| SSL_CONF="${T}/${$}ssl.cnf" |
| # Location of the CA serial file |
| SSL_SERIAL="${T}/${$}ca.ser" |
| # Location of some random files OpenSSL can use: don't use |
| # /dev/u?random here -- doesn't work properly on all platforms |
| SSL_RANDOM="${T}/environment:${T}/eclass-debug.log:/etc/resolv.conf" |
| |
| # These can be overridden in the ebuild |
| SSL_DAYS="${SSL_DAYS:-730}" |
| SSL_BITS="${SSL_BITS:-1024}" |
| SSL_COUNTRY="${SSL_COUNTRY:-US}" |
| SSL_STATE="${SSL_STATE:-California}" |
| SSL_LOCALITY="${SSL_LOCALITY:-Santa Barbara}" |
| SSL_ORGANIZATION="${SSL_ORGANIZATION:-SSL Server}" |
| SSL_UNIT="${SSL_UNIT:-For Testing Purposes Only}" |
| SSL_COMMONNAME="${SSL_COMMONNAME:-localhost}" |
| SSL_EMAIL="${SSL_EMAIL:-root@localhost}" |
| |
| # Create the CA serial file |
| echo "01" > "${SSL_SERIAL}" |
| |
| # Create the config file |
| ebegin "Generating OpenSSL configuration${1:+ for CA}" |
| cat <<-EOF > "${SSL_CONF}" |
| [ req ] |
| prompt = no |
| default_bits = ${SSL_BITS} |
| distinguished_name = req_dn |
| [ req_dn ] |
| C = ${SSL_COUNTRY} |
| ST = ${SSL_STATE} |
| L = ${SSL_LOCALITY} |
| O = ${SSL_ORGANIZATION} |
| OU = ${SSL_UNIT} |
| CN = ${SSL_COMMONNAME}${1:+ CA} |
| emailAddress = ${SSL_EMAIL} |
| EOF |
| eend $? |
| |
| return $? |
| } |
| |
| # @FUNCTION: get_base |
| # @USAGE: [if_ca] |
| # @RETURN: <base path> |
| # @DESCRIPTION: |
| # Simple function to determine whether we're creating |
| # a CA (which should only be done once) or final part |
| # |
| # Access: private |
| get_base() { |
| if [ "${1}" ] ; then |
| echo "${T}/${$}ca" |
| else |
| echo "${T}/${$}server" |
| fi |
| } |
| |
| # @FUNCTION: gen_key |
| # @USAGE: <base path> |
| # @DESCRIPTION: |
| # Generates an RSA key |
| # |
| # Access: private |
| gen_key() { |
| local base=`get_base $1` |
| ebegin "Generating ${SSL_BITS} bit RSA key${1:+ for CA}" |
| /usr/bin/openssl genrsa -rand "${SSL_RANDOM}" \ |
| -out "${base}.key" "${SSL_BITS}" &> /dev/null |
| eend $? |
| |
| return $? |
| } |
| |
| # @FUNCTION: gen_csr |
| # @USAGE: <base path> |
| # @DESCRIPTION: |
| # Generates a certificate signing request using |
| # the key made by gen_key() |
| # |
| # Access: private |
| gen_csr() { |
| local base=`get_base $1` |
| ebegin "Generating Certificate Signing Request${1:+ for CA}" |
| /usr/bin/openssl req -config "${SSL_CONF}" -new \ |
| -key "${base}.key" -out "${base}.csr" &>/dev/null |
| eend $? |
| |
| return $? |
| } |
| |
| # @FUNCTION: gen_crt |
| # @USAGE: <base path> |
| # @DESCRIPTION: |
| # Generates either a self-signed CA certificate using |
| # the csr and key made by gen_csr() and gen_key() or |
| # a signed server certificate using the CA cert previously |
| # created by gen_crt() |
| # |
| # Access: private |
| gen_crt() { |
| local base=`get_base $1` |
| if [ "${1}" ] ; then |
| ebegin "Generating self-signed X.509 Certificate for CA" |
| /usr/bin/openssl x509 -extfile "${SSL_CONF}" \ |
| -days ${SSL_DAYS} -req -signkey "${base}.key" \ |
| -in "${base}.csr" -out "${base}.crt" &>/dev/null |
| else |
| local ca=`get_base 1` |
| ebegin "Generating authority-signed X.509 Certificate" |
| /usr/bin/openssl x509 -extfile "${SSL_CONF}" \ |
| -days ${SSL_DAYS} -req -CAserial "${SSL_SERIAL}" \ |
| -CAkey "${ca}.key" -CA "${ca}.crt" \ |
| -in "${base}.csr" -out "${base}.crt" &>/dev/null |
| fi |
| eend $? |
| |
| return $? |
| } |
| |
| # @FUNCTION: gen_pem |
| # @USAGE: <base path> |
| # @DESCRIPTION: |
| # Generates a PEM file by concatinating the key |
| # and cert file created by gen_key() and gen_cert() |
| # |
| # Access: private |
| gen_pem() { |
| local base=`get_base $1` |
| ebegin "Generating PEM Certificate" |
| (cat "${base}.key"; echo; cat "${base}.crt") > "${base}.pem" |
| eend $? |
| |
| return $? |
| } |
| |
| # Removed due to bug 174759 |
| docert() { |
| eerror "Function \"docert\" has been removed for security reasons." |
| eerror "\"install_cert\" should be used instead. See bug 174759." |
| die |
| } |
| |
| # @FUNCTION: install_cert |
| # @USAGE: <certificates> |
| # @DESCRIPTION: |
| # Uses all the private functions above to generate and install the |
| # requested certificates. |
| # <certificates> are full pathnames relative to ROOT, without extension. |
| # |
| # Example: "install_cert /foo/bar" installs ${ROOT}/foo/bar.{key,csr,crt,pem} |
| # |
| # Access: public |
| install_cert() { |
| if [ $# -lt 1 ] ; then |
| eerror "At least one argument needed" |
| return 1; |
| fi |
| |
| case ${EBUILD_PHASE} in |
| unpack|compile|test|install) |
| eerror "install_cert cannot be called in ${EBUILD_PHASE}" |
| return 1 ;; |
| esac |
| |
| # Generate a CA environment #164601 |
| gen_cnf 1 || return 1 |
| gen_key 1 || return 1 |
| gen_csr 1 || return 1 |
| gen_crt 1 || return 1 |
| echo |
| |
| gen_cnf || return 1 |
| echo |
| |
| local count=0 |
| for cert in "$@" ; do |
| # Check the requested certificate |
| if [ -z "${cert##*/}" ] ; then |
| ewarn "Invalid certification requested, skipping" |
| continue |
| fi |
| |
| # Check for previous existence of generated files |
| for type in key csr crt pem ; do |
| if [ -e "${ROOT}${cert}.${type}" ] ; then |
| ewarn "${ROOT}${cert}.${type}: exists, skipping" |
| continue 2 |
| fi |
| done |
| |
| # Generate the requested files |
| gen_key || continue |
| gen_csr || continue |
| gen_crt || continue |
| gen_pem || continue |
| echo |
| |
| # Install the generated files and set sane permissions |
| local base=$(get_base) |
| install -d "${ROOT}${cert%/*}" |
| install -m0400 "${base}.key" "${ROOT}${cert}.key" |
| install -m0444 "${base}.csr" "${ROOT}${cert}.csr" |
| install -m0444 "${base}.crt" "${ROOT}${cert}.crt" |
| install -m0400 "${base}.pem" "${ROOT}${cert}.pem" |
| count=$((${count}+1)) |
| done |
| |
| # Resulting status |
| if [ ${count} = 0 ] ; then |
| eerror "No certificates were generated" |
| return 1 |
| elif [ ${count} != ${#} ] ; then |
| ewarn "Some requested certificates were not generated" |
| fi |
| } |