#!/bin/sh # # /usr/local/sbin/localmksslcerts # Copyright 2001-2004 Jonas Smedegaard # # $Id: localmksslcerts,v 1.12 2004-05-05 18:24:56 jonas Exp $ # # Generate certificates for mail (and other) servers # Based on uw-imapd-ssl post-install script # # TODO: Use getopts # TODO: Add symlink from CA certificate to cacert.pem if non-existing # TODO: Default CA certificate is cacert.pem if --cacert not set set -e prg=$(basename $0) copyright="(C) 2001-2004 Jonas Smedegaard " usage() { echo "$prg, $copyright Usage: $prg [--fqdn ] [...] --daemon [...] [--force] or: $prg [...] [-f] Options: --fqdn Fully Qualified Domain Name for this host. --cn Country Name (2 letter code) --state State or Province Name (full name) --loc Locality Name (eg, city) --org Organisation/company --ou Organisational unit/department --daemon Daemon(s) in need for a certificate (separate certificate is generated for each daemon) --issuer Email address of the person responsible for the certificate --cert Use certified host certificate --cacert CAcert used for creating missing host certificate --makeca Create CA certificate if missing -f, --force Force overwriting existing certificate(s) -h, --help This help text If issuer is not given, \"postmaster@\" is used." exit 1 } # Set some defaults CWD=`pwd` PATH=$PATH:/usr/bin/ssl DAYS2EXPIRE=365 fqdn='' cn='' state='' loc='' org='' ou='' daemon='' daemons='' issuer='' cert='' cacert='' makeca='' force='' args='' while [ $# -gt 0 ]; do doubleshift='' case $1 in --fqdn) fqdn="$2"; doubleshift=1;; --cn) cn="$2"; doubleshift=1;; --state) state="$2"; doubleshift=1;; --loc) loc="$2"; doubleshift=1;; --org) org="$2"; doubleshift=1;; --ou) ou="$2"; doubleshift=1;; --daemon) daemons="$daemons$2 "; doubleshift=1;; --issuer) issuer="$2"; doubleshift=1;; --cert) cert=1;; --cacert) cacert="$2"; doubleshift=1;; --makeca) makeca=1;; --force|-f) force=1;; -*) usage;; *) args="$args$1 ";; esac if [ -n "$doubleshift" ];then if [ $# -gt 1 ]; then shift else echo "ERROR: Parameter for option \"$1\" missing!" usage fi fi shift done set -- $args if [ -z "$issuer" ]; then DOMAINNAME="`hostname -d`" ISSUER="postmaster@$DOMAINNAME" fi if [ -z "$fqdn" ]; then if [ $# -gt 0 ]; then fqdn="`hostname -f`" else echo "Too few parameters!" usage fi fi for val in org ou; do if eval [ -z "\$$val" ]; then eval "$val=\"$fqdn\"" fi done for val in cn state loc; do if eval [ -z "\$$val" ]; then eval "$val=\".\"" fi done if [ -n "$cert" ]; then if [ ! -f /etc/ssl/certs/$fqdn.pem -o ! -f /etc/ssl/private/$fqdn.pem ]; then if [ -z "$cacert" ]; then echo "ERROR: Host certificate for \"$fqdn\" missing!" exit 1 fi if [ ! -r /etc/ssl/certs/$cacert.pem -o ! -r /etc/ssl/private/$cacert.pem ]; then if [ -n "$makeca" ]; then # Generate private key for CA certificate cd /etc/ssl/private #FIXME: Make strength configurable openssl genrsa -des3 -out $cacert.pem 1024 chown root:root $cacert.pem chmod 0400 $cacert.pem # Generate and pre-filled certification request cd /etc/ssl/certs #FIXME: Make validity configurable openssl req -new \ -key /etc/ssl/private/$cacert.pem \ -x509 -days 1095 \ -out $cacert.pem # Add hash to certified public certificate and cleanup ln -sf $cacert.pem `openssl x509 -noout -hash -in $cacert.pem`.0 else echo "ERROR: CAcert (certifying authority certificate) missing!" exit 1 fi fi echo "Generating host certificate for \"$fqdn\"..." for file in /etc/ssl/private/$fqdn.pem /etc/ssl/certs/$fqdn.csr /etc/ssl/certs/$fqdn.pem; do if [ -e $file ]; then if [ -n "$force" ]; then rm -f $file else echo "ERROR: File $file already exists!" exit 1 fi fi done # Generate private key for host certificate cd /etc/ssl/private openssl genrsa -out $fqdn.pem chown root:root $fqdn.pem chmod 0600 $fqdn.pem # Generate and pre-filled certification request cd /etc/ssl/certs openssl req -new \ -key /etc/ssl/private/$fqdn.pem \ -out $fqdn.csr > /dev/null 2>&1 <<+ $cn $state $loc $org $ou $fqdn $issuer . . + # Generate public ccertificate from certification request openssl x509 -req \ -days $DAYS2EXPIRE \ -CA /etc/ssl/certs/$cacert.pem \ -CAkey /etc/ssl/private/$cacert.pem \ -CAcreateserial -out $fqdn.pem -in $fqdn.csr # Add hash to certified public certificate and cleanup ln -sf $fqdn.pem `openssl x509 -noout -hash -in $fqdn.pem`.0 rm $fqdn.csr fi fi cd /etc/ssl/certs for daemon in $daemons $@; do if [ -f $daemon.pem ]; then if [ -n "$force" ]; then rm -f `openssl x509 -noout -hash < $daemon.pem`.0 rm -f $daemon.pem else echo "Ignoring certificate (/etc/ssl/certs/$daemon.pem already exists...)" continue fi fi if [ -n "$cert" ]; then echo "Attaching $daemon to certified certificate for $fqdn." ln -sf $fqdn.pem $daemon.pem ( cd /etc/ssl/private ln -sf $fqdn.pem $daemon.pem ) else echo -n "Generating self-certifying $daemon certificate..." openssl req -new -x509 -nodes \ -days $DAYS2EXPIRE \ -keyout $daemon.pem \ -out $daemon.pem > /dev/null 2>&1 <<+ $cn $state $loc $org $ou $fqdn $issuer + ln -sf $daemon.pem `openssl x509 -noout -hash -in $daemon.pem`.0 chown root:root $daemon.pem chmod 0640 $daemon.pem echo "Done!" fi done cd $CWD