#!/bin/sh
#
# Copyright (c) 2001-2002 Packet Design, LLC.
# All rights reserved.
#
# Subject to the following obligations and disclaimer of warranty,
# use and redistribution of this software, in source or object code
# forms, with or without modifications are expressly permitted by
# Packet Design; provided, however, that:
#
# (i) Any and all reproductions of the source or object code
# must include the copyright notice above and the following
# disclaimer of warranties; and
# (ii) No rights are granted, in any manner or form, to use
# Packet Design trademarks, including the mark "PACKET DESIGN"
# on advertising, endorsements, or otherwise except as such
# appears in the above copyright notice or in the software.
#
# THIS SOFTWARE IS BEING PROVIDED BY PACKET DESIGN "AS IS", AND
# TO THE MAXIMUM EXTENT PERMITTED BY LAW, PACKET DESIGN MAKES NO
# REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING
# THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
# OR NON-INFRINGEMENT. PACKET DESIGN DOES NOT WARRANT, GUARANTEE,
# OR MAKE ANY REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS
# OF THE USE OF THIS SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY,
# RELIABILITY OR OTHERWISE. IN NO EVENT SHALL PACKET DESIGN BE
# LIABLE FOR ANY DAMAGES RESULTING FROM OR ARISING OUT OF ANY USE
# OF THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY DIRECT,
# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE, OR CONSEQUENTIAL
# DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, LOSS OF
# USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
# THE USE OF THIS SOFTWARE, EVEN IF PACKET DESIGN IS ADVISED OF
# THE POSSIBILITY OF SUCH DAMAGE.
#
# Author: Archie Cobbs <archie@freebsd.org>
#
# $Id: rc.sslkey,v 1.1.1.1 2012/02/21 23:25:53 misho Exp $
#
# This script is used to verify/create keys and certificates for SSL.
#
# Our OpenSSL config file
CONFIG_FILE="cert.cfg"
# Our CA key and self-signed cert
CA_DIR="ca"
CA_KEY="${CA_DIR}/ca.key"
CA_CRT="${CA_DIR}/ca.crt"
#
# Create a new certificate authority if needed
#
check_ca()
{
HOSTNAME=`hostname`
check_cert "${CA_KEY}" "${CA_CRT}" "${HOSTNAME} Certificate Authority"
}
#
# This verifies that we have a valid RSA key pair and creates one if not.
#
# Args:
# $1 Key file
#
check_key()
{
if [ ! -r "${1}" ]; then
rm -f "${1}"
elif ! openssl rsa -check -in "${1}" -noout >/dev/null 2>&1; then
echo rc.sslkey: RSA key is invalid
rm -f "${1}"
fi
if [ ! -r "${1}" ]; then
echo rc.sslkey: Generating new RSA key pair for "${1}"
openssl genrsa -out "${1}" 1024 \
>/dev/null 2>&1
fi
}
#
# Sign a public key using our semi-bogus certificate authority
#
# Args:
# $1 Key file
# $2 Certificate file
# $3 CN (Common Name, e.g., web site hostname)
#
sign_key()
{
CSR="/tmp/csr.$$"
# Make sure we have a valid certificate authority
check_ca
# Generate a certificate signing request
printf '\n\n\n%s\n\n' "${3}" | openssl req -config "${CONFIG_FILE}" \
-new -key "${1}" -out "${CSR}" >/dev/null 2>&1
# Zero out index in case we need to regenerate a cert
cat /dev/null > ${CA_DIR}/index
# Now sign the key using built-in CA
printf 'y\ny\n' | openssl ca -config "${CONFIG_FILE}" \
-extensions x509v3 -in "${CSR}" -out "${2}" >/dev/null 2>&1
# Done
rm -f "${CSR}"
}
#
# This verifies that we have a valid certificate and creates one if not.
#
# Args:
# $1 Key file
# $2 Cert file
# $3 CN (Common Name, e.g., web site hostname)
#
check_cert()
{
# Check private key
#
check_key $1
# Verify certificate and delete it if it's not valid
#
if [ -r "${2}" ]; then
DIG1=`openssl rsa -noout -modulus -in "${1}" \
2>/dev/null | openssl md5`
DIG2=`openssl x509 -noout -modulus -in "${2}" \
2>/dev/null | openssl md5`
if [ "${DIG1}" != "${DIG2}" ]; then \
echo rc.sslkey: certificate "${2}" \
does not match key "${1}"
rm -f "${2}"
elif ! openssl x509 -noout -in "${2}" \
-checkend 43200 >/dev/null 2>&1; then
echo rc.sslkey: certificate "${2}" has expired
rm -f "${2}"
else
CCN=`openssl x509 -noout -in "${2}" -subject \
| sed -e 's,^.*CN=,,g' -e 's,/.*$,,g' 2>&1`
if [ "${CCN}" != "${3}" ]; then
echo rc.sslkey: certificate "${2}" incorrect \
CN: \""${CCN}"\" instead of \""${3}"\"
rm -f "${2}"
fi
fi
else
rm -f "${2}"
fi
# Create new certificate if none. Handle special case of
# self-signing our own cert (to avoid infinite recursion).
#
if [ ! -r "${2}" -a "${2}" = "${CA_CRT}" -a "${1}" = "${CA_KEY}" ]; then
echo rc.sslkey: creating new CA certificate
find "${CA_DIR}/certs" -type f -print | xargs rm -f
cat /dev/null > "${CA_DIR}/index"
echo 01 > "${CA_DIR}/serial"
printf '\n\n\n%s\n\n' "${3}" | openssl req -new -x509 \
-config "${CONFIG_FILE}" -key "${1}" -out "${2}" \
> /dev/null 2>&1
elif [ ! -r "${2}" ]; then
echo rc.sslkey: creating new certificate for "${3}"
sign_key "${1}" "${2}" "${3}"
fi
}
#
# Main entry point
#
# Usage:
# rc.sslkey keyfile [ certfile CN ]
#
# If this script is called with one argument, it just verifies the
# CA and SSL RSA keys. Otherwise, there must be three arguments:
#
# $1 RSA key file
# $2 SSL certificate file
# $3 CN (Common Name, e.g., web site hostname)
#
# and the $2 certificate file is also verified/created.
#
if [ $# -eq 1 ]; then
check_key "${CA_KEY}"
check_key "${1}"
exit 0
fi
if [ $# -ne 3 ]; then
echo Usage: rc.sslkey keyfile \[ certfile common-name \]
exit 1
fi
check_cert "${1}" "${2}" "${3}"
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>