summaryrefslogtreecommitdiff
blob: 8a8c0acbff078928659e2e15078b30e5c5f2eb18 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
# Copyright 1999-2003 Gentoo Technologies, Inc.
# Distributed under the terms of the GNU General Public License v2
# $Header: /var/cvsroot/gentoo-x86/eclass/ssl-cert.eclass,v 1.4 2004/05/06 14:37:09 max Exp $
#
# Author: Max Kalika <max@gentoo.org>
#
# This eclass implements standard installation procedure for installing
# self-signed SSL certificates.

ECLASS=ssl-cert
INHERITED="$INHERITED $ECLASS"

# Conditionally depend on OpenSSL: allows inheretence
# without pulling extra packages if not needed
DEPEND="ssl? ( dev-libs/openssl )"

# 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_BITS:-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"
	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}
		emailAddress       = ${SSL_EMAIL}
	EOF
	eend $?
	
	return $?
}

# 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
}

# 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 $?
}

# 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 $?
}

# 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 $?
}

# 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 $?
}

# Uses all the private functions above to generate
# and install the requested certificates
#
# Access: public
docert() {
	if [ $# -lt 1 ] ; then
		eerror "At least one argument needed"
		return 1;
	fi

	# Initialize configuration
	gen_cnf || return 1
	echo

	# Generate a CA environment
	gen_key 1 || return 1
	gen_csr 1 || return 1
	gen_crt 1 || return 1
	echo

	local count=0
	for cert in "$@" ; do
		# Sanitize and check the requested certificate
		cert="`/usr/bin/basename "${cert}"`"
		if [ -z "${cert}" ] ; then
			ewarn "Invalid certification requested, skipping"
			continue
		fi

		# Check for previous existence of generated files
		for type in key crt pem ; do
			if [ -e "${D}${INSDESTTREE}/${cert}.${type}" ] ; then
				ewarn "${D}${INSDESTTREE}/${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`
		newins "${base}.key" "${cert}.key"
		fperms 0400 "${INSDESTTREE}/${cert}.key"
		newins "${base}.csr" "${cert}.csr"
		fperms 0444 "${INSDESTTREE}/${cert}.csr"
		newins "${base}.crt" "${cert}.crt"
		fperms 0444 "${INSDESTTREE}/${cert}.crt"
		newins "${base}.pem" "${cert}.pem"
		fperms 0400 "${INSDESTTREE}/${cert}.pem"
		count=$((${count}+1))
	done

	# Resulting status
	if [ ! ${count} ] ; then
		eerror "No certificates were generated"
		return 1
	elif [ ${count} != ${#} ] ; then
		ewarn "Some requested certificates were not generated"
	fi
}