ssl-cert.eclass 6.8 KB

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