mmsssl.sh revision 257873cfc1dd3337766407f80397db60a56f2f5a
#!/bin/sh
#
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
# Common Development and Distribution License (the "License").
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
# See the License for the specific language governing permissions
# and limitations under the License.
#
# When distributing Covered Code, include this CDDL HEADER in each
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
# If applicable, add the following below this CDDL HEADER, with the
# fields enclosed by brackets "[]" replaced with your own identifying
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#
# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
#
#
# MMS SSL Self-Signed Certificate Authority
#
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/sadm/bin:$PATH
LD_LIBRARY_PATH=/lib:/usr/lib:$LD_LIBRARY_PATH
umask 066
PROG=`basename $0`
# Now setup directories
SSLDIR="/var/mms/ssl"
CADIR="$SSLDIR/ca"
PUBDIR="$SSLDIR/pub"
ROOT_CNF="$CADIR/mms_openssl.cnf"
CERTSDIR="$CADIR/certs"
DIR=
# DSA Parameters Prime Number Bit Length
PRIME_BITS=2048
# User
USER=""
MMS_USER="mms"
# Root files (CA)
SERIAL="$CADIR/serial"
INDEX="$CADIR/index.txt"
CRL="$PUBDIR/$MMS_USER""_crl.pem"
ROOT_CERT="$CADIR/$MMS_USER""_ca_cert.pem"
ROOT_KEY="$CADIR/$MMS_USER""_ca_key.pem"
PASSWD_FILE="$CADIR/$MMS_USER""_ca_pass"
ROOT_PEM="$CADIR/$MMS_USER""_ca.pem"
ROOT_CERT_PUB="$PUBDIR/$MMS_USER""_ca_cert.pem"
MMS_PEM="$PUBDIR/$MMS_USER.pem"
MMS_CERT="$PUBDIR/$MMS_USER""_cert.pem"
MMS_DH1024="$PUBDIR/$MMS_USER""_dh1024.pem"
root_user()
{
user=`/bin/id | grep root | wc -l`
if [ $user -eq 0 ]; then
echo "Error, you must be root to run this script."
exit 1
fi
}
gen_password()
{
pass_file="$1"
echo
echo "Generate private key password phrase"
/bin/dd if=/dev/random bs=1 count=15 2>/dev/null | \
openssl base64 > "$pass_file"
if [ ! -f "$pass_file" ]; then
exit 1
fi
}
# setup mms as ca (certificate authority)
initialize()
{
echo
echo "Initialize certificate authority"
# certificate serial number
echo "01" > "$SERIAL"
if [ ! -f "$SERIAL" ]; then
exit 1
fi
# certificate database
touch "$INDEX"
if [ ! -f "$INDEX" ]; then
exit 1
fi
# new certs dir
mkdir $CERTSDIR
if [ $? -ne 0 ]; then
exit 1
fi
chmod 0700 $CERTSDIR
if [ $? -ne 0 ]; then
exit 1
fi
# ca random password phrase
gen_password "$PASSWD_FILE"
}
# generate crl (certificate revocation list) file
update_crl()
{
echo
echo "Update CRL"
cmd="openssl ca -gencrl -out $CRL -config $ROOT_CNF"
cmd="$cmd -passin file:$PASSWD_FILE"
echo $cmd
$cmd
if [ $? -ne 0 ]; then
exit 1
fi
# publish the list, let everyone read the file
chmod 0640 $CRL
if [ $? -ne 0 ]; then
exit 1
fi
# tell mm to reload updated crl
svcadm refresh mms:mm > /dev/null 2>&1
}
# compute public shared prime number p and generator g
dh_pem()
{
echo
echo "Generate Diffie-Hellman parameters"
cmd="openssl dhparam -check -5 1024 -out $MMS_DH1024 -outform PEM"
echo $cmd
$cmd
if [ $? -ne 0 ]; then
exit 1
fi
chmod 0600 $MMS_DH1024
if [ $? -ne 0 ]; then
exit 1
fi
}
# rsa private key
rsa_key()
{
rsa_key_file="$1"
echo
echo "Create RSA certificate with SHA-1 signature"
cmd="openssl genrsa -out $rsa_key_file -des3"
cmd="$cmd -passout file:$PASSWD_FILE"
echo $cmd
$cmd
if [ $? -ne 0 ]; then
exit 1
fi
}
# generate self signed root certificate and private key
rsa_cert()
{
echo
echo "Generate self-signed certificate authority"
unset -v OPENSSL_CONF
# gen self signed ca certificate
cmd="openssl req -x509 -newkey rsa:$PRIME_BITS -out $ROOT_CERT"
cmd="$cmd -keyout $ROOT_KEY -sha1 -outform PEM"
cmd="$cmd -passout file:$PASSWD_FILE"
echo $cmd
$cmd
if [ $? -ne 0 ]; then
exit 1
fi
chmod 0600 "$ROOT_CERT"
if [ $? -ne 0 ]; then
exit 1
fi
# mms_ca.pem
cat $ROOT_CERT $ROOT_KEY > $ROOT_PEM
if [ ! -f $ROOT_PEM ]; then
exit 1
fi
# put ca certificate in public directory
cp $ROOT_CERT $ROOT_CERT_PUB
if [ $? -ne 0 ]; then
exit 1
fi
# let everyone read public ca certificate
chmod 0440 $ROOT_CERT_PUB
if [ $? -ne 0 ]; then
exit 1
fi
# view certificate info
openssl x509 -subject -issuer -noout -in $ROOT_CERT
# initialize cert revocation list
update_crl
}
certificate_request()
{
dir=$1
mess=$2
echo
echo "Generate certificate request ($USER,$dir)"
mkdir -p "$dir"
if [ $? -ne 0 ]; then
exit 1
fi
# user password phrase
pass_file="$dir/$USER""_pass"
gen_password "$pass_file"
# filenames
req="$dir/$USER""_req.pem"
key="$dir/$USER""_key.pem"
# use default openssl configuration for certificate request
unset -v OPENSSL_CONF
# generate certificate request
cmd="openssl req -newkey rsa:$PRIME_BITS -keyout $key -keyform PEM"
cmd="$cmd -out $req -outform PEM -sha1 -passout file:$pass_file"
echo $cmd
$cmd
if [ $? -ne 0 ]; then
exit 1
fi
if [ $mess -eq 1 ]; then
echo
echo
echo
echo "Certificate request: $req"
echo "Private key: $key"
echo "Private key password: $pass_file"
echo
echo "Email certificate request file to MMS CA for signing."
echo
fi
}
ca_sign()
{
echo
echo "Sign certificate request"
# filenames
req="$PUBDIR/$USER""_req.pem"
cert="$PUBDIR/$USER""_cert.pem"
key="$PUBDIR/$USER""_key.pem"
root_cert=`basename $ROOT_CERT`
# root signs client certificate request
cmd="openssl ca -in $req -out $cert -notext -cert $ROOT_CERT"
cmd="$cmd -config $ROOT_CNF -md sha1 -passin file:$PASSWD_FILE"
echo $cmd
$cmd
if [ $? -ne 0 ]; then
exit 1
fi
if [ -f $key ]; then
# combine certificate, private key and public root certificate
pem="$PUBDIR/$USER.pem"
cat $cert $key $ROOT_CERT_PUB > $pem
if [ $? -ne 0 ]; then
rm -f $pem
echo "Error, create $pem"
else
echo
echo "The combined certificate, private key and CA certificate file\n$pem"
echo
fi
else
user_cert=`basename $cert`
user_key=`basename $key`
# remote user without access to ssl public directory
echo
echo "Use the distinguished name email address to deliver"
echo "the following files to the user:"
echo "\t$cert"
echo "\t$ROOT_CERT_PUB"
echo
echo "Instruct the user to do the following:"
echo "\tcat $user_cert $user_key $root_cert > $USER.pem"
echo
fi
}
# revoke client's certificate
revoke_certificate()
{
echo "Revoke certificate"
# filename
cert="$PUBDIR/$USER""_cert.pem"
# revoke certificate
cmd="openssl ca -revoke $cert -config $ROOT_CNF"
cmd="$cmd -passin file:$PASSWD_FILE"
echo $cmd
$cmd
if [ $? -ne 0 ]; then
exit 1
fi
# add revoked cert to the list
update_crl
}
check_client()
{
if [ -z "$USER" ]; then
echo "Error, missing user name."
exit 1
fi
}
usage()
{
echo "usage: mmsssl.sh [ ca | req | crl ] [-v] [-n]"
echo
echo "mmsssl.sh ca -c configure mms ca"
echo "mmsssl.sh ca -s -u user_name sign certificate request"
echo "mmsssl.sh ca -r -u user_name revoke certificate"
echo "mmsssl.sh req -u user_name [-d path] certificate request"
echo "mmsssl.sh crl revoked certificate list"
echo
echo "Examples:"
echo "1. Create the MMS CA and MM RSA certificates:"
echo "\t% mmsssl.sh ca -c"
echo "\tRun the command only once on the host where the MM will execute."
echo "\tDiffie-Hellman (DH) parameters are generated."
echo "\tYou will enter a DN (Distinguished Name) once for the CA and"
echo "\tonce for the MM certificate. You will sign the MM certificate"
echo "\tand commit the request."
echo
echo "2. MMS user certificate request:"
echo "\t% mmsssl.sh req -u JohnQPublic"
echo "\tEmail the JohnQPublic_req.pem to the MMS CA for signing."
echo
echo "3. MMS CA signs user certificate request:"
echo "\t% cp JohnQPublic_req.pem \\"
echo "\t$PUBDIR/JohnQPublic_req.pem"
echo "\tCopy certificate request into the MMS CA for signing."
echo "\t% mmsssl.sh ca -s -u JohnQPublic"
echo "\tYou will sign the MM certificate and commit the request."
echo "\tEmail the JohnQPublic_cert.pem and mms_ca_cert.pem "\
"files to the user."
echo
echo "4. MMS user creates single PEM file for MMS:"
echo "\t% cat JohnQPublic_cert.pem JohnQPublic_key.pem \\"
echo "\tmms_ca_cert.pem > JohnQPublic.pem"
echo
echo "5. MMS CA revokes user certificate:"
echo "\t% mmsssl.sh ca -r -u JohnQPublic"
echo "\tThe revoked certificate is added to the file"
echo "\t$PUBDIR/mms_crl.pem"
echo
echo "6. MMS CA reviews CRL (Certificate Revocation List):"
echo "\t% mmsssl.sh crl"
echo "\tLists revoked certificate serial numbers."
echo
echo "Notes:"
echo "1. user_name is one word i.e. John Q. Public is JohnQPublic"
echo "2. one-way authentication is where only the server is configured"
echo " with a RSA certificate."
echo "3. two-way authentication is when the server and client both have"
echo " a RSA certificate."
echo "4. MMS supports both one-way and two-way authentication."
echo "5. The MMS CA can use a certificate request made by a tool"
echo " other than this script."
echo "6. The crl.pem file contains the CRL for this MMS CA."
echo "7. The MM, Watcher, LM (Library Manager) and DM (Drive Manager)"
echo " can use the same certificate."
echo
exit 2
}
#
# Main
#
if [ $# -eq 0 ]; then
usage
fi
choice=$1
oper=""
shift
found=0
while getopts "csru:d:" opt; do
found=0
case $opt in
c)
# setup mms ca
oper="configure"
found=1
;;
s)
# Create Signed Certificate on this host.
#
# On remote hosts its a two step process:
# 1. request certificate
# 2. CA sign's certificate
oper="sign"
found=1
;;
r)
# Revoke Certificate
#
# Update the MM CA CRL and put on all remote hosts
# especially if you have one MM CA for multiple MMs.
oper="revoke"
found=1
;;
u)
# User Name
USER="$OPTARG"
found=1
;;
d)
# User directory
DIR="$OPTARG"
found=1
;;
esac
if [ $found -eq 0 ]; then
usage
fi
done
case $choice in
ca)
# setup non-root MMS client in /etc
OPENSSL_CONF="$ROOT_CNF"
HOME="$CADIR"
root_user
case $oper in
configure)
# setup MMS CA
root_user
initialize
dh_pem
rsa_cert
# sign mms certificate request
USER=$MMS_USER
certificate_request "$PUBDIR" 0
ca_sign
echo "Done"
;;
sign)
# sign certificate request
check_client
ca_sign
echo "Done"
;;
revoke)
if [ -z "$USER" ]; then
echo "Error, missing client user name."
exit 1
fi
revoke_certificate
echo "Done"
;;
*) usage
;;
esac
;;
req)
# certificate request
check_client
if [ "$DIR" = "" ]; then
DIR="$HOME/mms"
fi
certificate_request "$DIR" 1
echo "Done"
;;
crl)
# show certificate revocation list
crl=$CRL
root_cert=$ROOT_CERT
openssl crl -in $crl -text -noout
openssl crl -in $crl -noout -CAfile $root_cert
echo "Done"
;;
*) usage
;;
esac
exit 0