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