summaryrefslogtreecommitdiff
path: root/localmksslcerts
blob: b9b30ca143814eed8ecb2ab5e1677cabe6c82342 (plain)
  1. #!/bin/sh
  2. #
  3. # /usr/local/sbin/localmksslcerts
  4. # Copyright 2001-2004 Jonas Smedegaard <dr@jones.dk>
  5. #
  6. # $Id: localmksslcerts,v 1.17 2005-07-01 11:33:18 jonas Exp $
  7. #
  8. # Generate certificates for mail (and other) servers
  9. # Based on uw-imapd-ssl post-install script
  10. #
  11. # TODO: Use getopts
  12. # TODO: Add symlink from CA certificate to cacert.pem if non-existing
  13. # TODO: Default CA certificate is cacert.pem if --cacert not set
  14. set -e
  15. prg=$(basename $0)
  16. copyright="(C) 2001-2004 Jonas Smedegaard <dr@jones.dk>"
  17. usage() {
  18. echo "$prg, $copyright
  19. Usage: $prg [--fqdn <FQDN>] [...] --daemon <daemon> [...] [--force]
  20. or: $prg <daemon> [<daemon>...] [-f]
  21. Options:
  22. --fqdn <FQDN> Fully Qualified Domain Name for this host.
  23. --cn <country> Country Name (2 letter code)
  24. --state <state> State or Province Name (full name)
  25. --loc <locality> Locality Name (eg, city)
  26. --org <organisation> Organisation/company
  27. --ou <department> Organisational unit/department
  28. --daemon <daemon> Daemon(s) in need for a certificate
  29. (certificate is generated for each daemon)
  30. --issuer <issuer> Email address of entity issuing certificate
  31. --cert Use certified host certificate
  32. --cacert <file> Where to store host certificate if missing
  33. --makeca Create CA certificate if missing
  34. -f, --force Force overwriting existing certificate(s)
  35. -h, --help This help text
  36. Examples:
  37. Create certs for UW imapd/popd, bound to default host cert if there:
  38. localmksslcerts imapd pop3d
  39. Create host cert for non-default hostname, overwriting stray files:
  40. localmksslcerts --fqdn mail.jones.dk --cert --force
  41. Create host cert for non-default hostname and bind to UW daemons:
  42. localmksslcerts --fqdn mail.jones.dk --cert --force imapd pop3d
  43. Create CA-signed host cert (and CA cert if not there):
  44. localmksslcerts --cert --cacert IT-guide_dr_Jones_CA
  45. If issuer is not given, \"postmaster@<localdomain>\" is used."
  46. exit 1
  47. }
  48. # Set some defaults
  49. CWD=`pwd`
  50. PATH=$PATH:/usr/bin/ssl
  51. DAYS2EXPIRE=365
  52. fqdn=''
  53. cn=''
  54. state=''
  55. loc=''
  56. org=''
  57. ou=''
  58. daemon=''
  59. daemons=''
  60. issuer=''
  61. cert=''
  62. cacert=''
  63. makeca=''
  64. force=''
  65. args=''
  66. while [ $# -gt 0 ]; do
  67. doubleshift=''
  68. case $1 in
  69. --fqdn) fqdn="$2"; doubleshift=1;;
  70. --cn) cn="$2"; doubleshift=1;;
  71. --state) state="$2"; doubleshift=1;;
  72. --loc) loc="$2"; doubleshift=1;;
  73. --org) org="$2"; doubleshift=1;;
  74. --ou) ou="$2"; doubleshift=1;;
  75. --daemon) daemons="$daemons$2 "; doubleshift=1;;
  76. --issuer) issuer="$2"; doubleshift=1;;
  77. --cert) cert=1;;
  78. --cacert) cacert="$2"; doubleshift=1;;
  79. --makeca) makeca=1;;
  80. --force|-f) force=1;;
  81. -*) usage;;
  82. *) args="$args$1 ";;
  83. esac
  84. if [ -n "$doubleshift" ];then
  85. if [ $# -gt 1 ]; then
  86. shift
  87. else
  88. echo "ERROR: Parameter for option \"$1\" missing!"
  89. usage
  90. fi
  91. fi
  92. shift
  93. done
  94. set -- $args
  95. if [ -z "$issuer" ]; then
  96. DOMAINNAME="`hostname -d`"
  97. ISSUER="postmaster@$DOMAINNAME"
  98. fi
  99. if [ -z "$fqdn" ]; then
  100. if [ $# -gt 0 ]; then
  101. fqdn="`hostname -f`"
  102. else
  103. echo "Too few parameters!"
  104. usage
  105. fi
  106. fi
  107. for val in org ou; do
  108. if eval [ -z "\$$val" ]; then
  109. eval "$val=\"$fqdn\""
  110. fi
  111. done
  112. for val in cn state loc; do
  113. if eval [ -z "\$$val" ]; then
  114. eval "$val=\".\""
  115. fi
  116. done
  117. if [ -n "$cert" ]; then
  118. if [ ! -s /etc/ssl/certs/$fqdn.pem ] || [ ! -s /etc/ssl/private/$fqdn.pem ]; then
  119. echo "WARNING: Host certificate for \"$fqdn\" missing..."
  120. if [ -z "$cacert" ]; then
  121. echo "ERROR: The \"--cacert\" option is required when making a host certificate!"
  122. exit 1
  123. fi
  124. # Cleaning up - if allowed
  125. for file in /etc/ssl/private/$fqdn.pem /etc/ssl/certs/$fqdn.csr /etc/ssl/certs/$fqdn.pem; do
  126. if [ -e $file ]; then
  127. if [ -n "$force" ]; then
  128. rm -f $file
  129. else
  130. echo "ERROR: File $file already exists!"
  131. exit 1
  132. fi
  133. fi
  134. done
  135. if [ ! -s /etc/ssl/certs/$cacert.pem ] || [ ! -s /etc/ssl/private/$cacert.pem ]; then
  136. echo "WARNING: CAcert (certifying authority certificate) missing..."
  137. if [ -z "$makeca" ]; then
  138. echo "ERROR: The \"--makeca\" option is required when making a CAcert!"
  139. exit 1
  140. fi
  141. # Generate private key for CA certificate
  142. echo "Generating CAcert \"$cacert\"..."
  143. cd /etc/ssl/private
  144. #FIXME: Make strength configurable
  145. openssl genrsa -des3 -out $cacert.pem 1024
  146. chown root:root $cacert.pem
  147. chmod 0400 $cacert.pem
  148. # Generate and pre-fill certification request
  149. cd /etc/ssl/certs
  150. #FIXME: Make validity configurable
  151. openssl req -new \
  152. -key /etc/ssl/private/$cacert.pem \
  153. -x509 -days 1095 \
  154. -out $cacert.pem
  155. # Add hash to certified public certificate and cleanup
  156. ln -sf $cacert.pem `openssl x509 -noout -hash -in $cacert.pem`.0
  157. fi
  158. echo "Generating host certificate for \"$fqdn\"..."
  159. # Generate private key for host certificate
  160. cd /etc/ssl/private
  161. openssl genrsa -out $fqdn.pem
  162. chown root:root $fqdn.pem
  163. chmod 0600 $fqdn.pem
  164. # Generate and pre-fill certification request
  165. cd /etc/ssl/certs
  166. openssl req -new \
  167. -key /etc/ssl/private/$fqdn.pem \
  168. -out $fqdn.csr > /dev/null 2>&1 <<+
  169. $cn
  170. $state
  171. $loc
  172. $org
  173. $ou
  174. $fqdn
  175. $issuer
  176. .
  177. .
  178. +
  179. # Generate public certificate from certification request
  180. openssl x509 -req \
  181. -days $DAYS2EXPIRE \
  182. -CA /etc/ssl/certs/$cacert.pem \
  183. -CAkey /etc/ssl/private/$cacert.pem \
  184. -CAcreateserial -out $fqdn.pem -in $fqdn.csr
  185. # Add hash to certified public certificate and cleanup
  186. ln -sf $fqdn.pem `openssl x509 -noout -hash -in $fqdn.pem`.0
  187. rm $fqdn.csr
  188. fi
  189. fi
  190. cd /etc/ssl/certs
  191. for daemon in $daemons $@; do
  192. if [ -f $daemon.pem ]; then
  193. if [ -n "$force" ]; then
  194. rm -f `openssl x509 -noout -hash < $daemon.pem`.0
  195. rm -f $daemon.pem
  196. else
  197. echo "Ignoring certificate (/etc/ssl/certs/$daemon.pem already exists...)"
  198. continue
  199. fi
  200. fi
  201. if [ -n "$cert" ]; then
  202. echo "Attaching $daemon to certified certificate for $fqdn."
  203. ln -sf $fqdn.pem $daemon.pem
  204. (
  205. cd /etc/ssl/private
  206. ln -sf $fqdn.pem $daemon.pem
  207. )
  208. else
  209. echo -n "Generating self-certifying $daemon certificate..."
  210. openssl req -new -x509 -nodes \
  211. -days $DAYS2EXPIRE \
  212. -keyout $daemon.pem \
  213. -out $daemon.pem > /dev/null 2>&1 <<+
  214. $cn
  215. $state
  216. $loc
  217. $org
  218. $ou
  219. $fqdn
  220. $issuer
  221. +
  222. ln -sf $daemon.pem `openssl x509 -noout -hash -in $daemon.pem`.0
  223. chown root:root $daemon.pem
  224. chmod 0640 $daemon.pem
  225. echo "Done!"
  226. fi
  227. done
  228. cd $CWD