#!/bin/sh
#ident $Id: certutil,v 2.2 2001/05/27 12:16:31 lukeh Exp $
#
# certutil -- manage trusted X.509 certificates
# inspired by Netscape PKCS #11 toolkit
# contributed by Jarkko Turkulainen <jt@wapit.com>
#
#
# INTRODUCTION
#
# certutil can be used with various OpenSSL routines and tools
# that utilize OpenSSL. Example:
#
# $ openssl s_client -CApath certdir
#
# where certdir is a directory created by certutil. Other well known
# programs that use the same format are stunnel, sendmail and pam_ldap
#
#
#
# HOWTO
#
# 1. Initialize certificate database
#
# Simply by adding a new certificate. If the certificate directory
# doesn't exist, the script asks for creating a one. Example:
#
# $ certutil -a -n "First Cert" -i cert.pem -d /home/jt/mycerts
# ./certutil: cannot access /home/jt/mycerts, create? [y/N] y
#
#
# 2. Add new certificate
#
# $ certutil -a -n "My Cert" -i cert.pem [-d certdir]
#
# Note that nickname (-n) must exist. certdir is optional - if it's
# not given, $PWD is used. The directory must have a file named certs.dat.
# If that file doesn't exist, the script refuses to do anything. If your
# certs.dat file is corrupted, "rm -rf" the whole dir and start from
# the scratch. cert.pem is the actual sertificate.
#
# 3. Delete certificate
#
# $ certutil -r -n "My Cert" [-d certdir]
#
# This command removes the certificate named "My Cert". certdir is
# optional, see 2.
#
# 4. List sertificates
#
# $ certutil -l [-d certdir]
#
# And again, certdir is optional.
#
# 5. View certificate properties
#
# $ certutil -v -n "My Cert" [-d certdir]
#
#
# Print usage
usage() {
cat << EOF
Usage: $0 -l [-d dir]
-a -n name -i file [-d dir]
-r -n name [-d dir]
-v -n name [-d dir]
Commands:
-l -- List sertificates (requires a valid dir)
-a -- Add sertificate and create dir if necessary
-r -- Remove sertificate (requires a valid dir)
-v -- View sertificate (requires a valid dir)
Parameters:
dir -- Certificate directory, or \$PWD if not given
name -- Nickname of the certificate
file -- Certificate file in PEM format
EOF
exit 1
}
# Check path
check_path() {
# check the directory
if [ ! -d $CDIR -a $ADD -eq 1 ]; then
echo -n "$0: cannot access $CDIR, create? [y/N] "
read LINE
case $LINE in
y|Y)
mkdir $CDIR
chmod 700 $CDIR
touch $CDIR/certs.dat
chmod 600 $CDIR/certs.dat
;;
*)
exit 1
;;
esac
fi
# check certs.dat
if [ ! -e $CDIR/certs.dat ]; then
echo "$0: please specify a valid cert directory"
exit 1
fi
}
# Add certificates
add_cert() {
check_path
if [ ! -e $FILE ]; then
echo "$0: cannot find $FILE"
exit 1
fi
HASH=`openssl x509 -in $FILE -hash -noout 2>/dev/null`.0
if [ $? -ne 0 ]; then
echo "$0: unable to load certificate $FILE"
exit 1
fi
if grep "^$CNAME|" $CDIR/certs.dat 1>/dev/null 2>&1; then
echo "$0: nickname already in use"
exit 1
fi
if [ -e $CDIR/$HASH ]; then
echo "$0: certificate already in directory"
echo `openssl x509 -in $CDIR/$HASH -subject -noout`
exit 1
else
cp $FILE $CDIR/$HASH
chmod 600 $CDIR/$HASH
echo "$CNAME|$HASH" >> $CDIR/certs.dat
chmod 600 $CDIR/certs.dat
fi
}
# List certificates
#
# (this is too slow...)
#
list_cert() {
check_path
echo
echo "Certificates in directory $CDIR"
echo
printf "%-30s%s\n" nickname subject/issuer
echo "----------------------------------------------------------------------------"
cat $CDIR/certs.dat | while read LINE; do
NICK=`echo $LINE | cut -d "|" -f 1`
HASH=`echo $LINE | cut -d "|" -f 2`
SUBJECT=`openssl x509 -in $CDIR/$HASH -subject -noout`
ISSUER=`openssl x509 -in $CDIR/$HASH -issuer -noout`
printf "%-30s%s\n" "$NICK" "$SUBJECT"
printf "%-30s%s\n\n" "" "$ISSUER"
done
}
# Remove certificates
remove_cert() {
check_path
(
cat $CDIR/certs.dat | while read LINE; do
NICK=`echo $LINE | cut -d "|" -f 1`
HASH=`echo $LINE | cut -d "|" -f 2`
if [ "$CNAME" = "$NICK" ]; then
rm $CDIR/$HASH
else
echo $LINE
fi
done
) > /tmp/$$
mv /tmp/$$ $CDIR/certs.dat
chmod 600 $CDIR/certs.dat
}
# View certificate
view_cert() {
check_path
cat $CDIR/certs.dat | while read LINE; do
NICK=`echo $LINE | cut -d "|" -f 1`
HASH=`echo $LINE | cut -d "|" -f 2`
if [ "$CNAME" = "$NICK" ]; then
openssl x509 -in $CDIR/$HASH -text
return 1
fi
done
}
# Parse option string
ADD=0
REMOVE=0
LIST=0
VIEW=0
while getopts "arlvd:n:i:" OPT; do
case $OPT in
a)
ADD=1
;;
r)
REMOVE=1
;;
l)
LIST=1
;;
v)
VIEW=1
;;
d)
CDIR=$OPTARG
;;
n)
CNAME=$OPTARG
;;
i)
FILE=$OPTARG
;;
*)
usage
;;
esac
done
# Default options
CDIR=${CDIR:=.}
# Check command line options
if [ $ADD -eq 1 -a $REMOVE -eq 0 -a $LIST -eq 0 -a $VIEW -eq 0 ]; then
if [ -n "$CNAME" -a -n "$FILE" ]; then
add_cert
else
echo "$0: missing certificate name or file"
usage
fi
elif [ $REMOVE -eq 1 -a $ADD -eq 0 -a $LIST -eq 0 -a $VIEW -eq 0 ]; then
if [ -n "$CNAME" ]; then
remove_cert
else
echo "$0: missing certificate name"
usage
fi
elif [ $LIST -eq 1 -a $ADD -eq 0 -a $REMOVE -eq 0 -a $VIEW -eq 0 ]; then
list_cert
elif [ $VIEW -eq 1 -a $ADD -eq 0 -a $REMOVE -eq 0 -a $LIST -eq 0 ]; then
if [ -n "$CNAME" ]; then
if view_cert; then
echo "$0: cert named \"$CNAME\" not found"
exit 1
fi
else
echo "$0: missing certificate name"
usage
fi
else
usage
fi
syntax highlighted by Code2HTML, v. 0.9.1