1#!/bin/sh 2#ident $Id: certutil,v 1.2 2002/04/14 14:16:16 lukeh Exp $ 3# 4# certutil -- manage trusted X.509 certificates 5# inspired by Netscape PKCS #11 toolkit 6# contributed by Jarkko Turkulainen <jt@wapit.com> 7# 8# 9# INTRODUCTION 10# 11# certutil can be used with various OpenSSL routines and tools 12# that utilize OpenSSL. Example: 13# 14# $ openssl s_client -CApath certdir 15# 16# where certdir is a directory created by certutil. Other well known 17# programs that use the same format are stunnel, sendmail and pam_ldap 18# 19# 20# 21# HOWTO 22# 23# 1. Initialize certificate database 24# 25# Simply by adding a new certificate. If the certificate directory 26# doesn't exist, the script asks for creating a one. Example: 27# 28# $ certutil -a -n "First Cert" -i cert.pem -d /home/jt/mycerts 29# ./certutil: cannot access /home/jt/mycerts, create? [y/N] y 30# 31# 32# 2. Add new certificate 33# 34# $ certutil -a -n "My Cert" -i cert.pem [-d certdir] 35# 36# Note that nickname (-n) must exist. certdir is optional - if it's 37# not given, $PWD is used. The directory must have a file named certs.dat. 38# If that file doesn't exist, the script refuses to do anything. If your 39# certs.dat file is corrupted, "rm -rf" the whole dir and start from 40# the scratch. cert.pem is the actual certificate. 41# 42# 3. Delete certificate 43# 44# $ certutil -r -n "My Cert" [-d certdir] 45# 46# This command removes the certificate named "My Cert". certdir is 47# optional, see 2. 48# 49# 4. List certificates 50# 51# $ certutil -l [-d certdir] 52# 53# And again, certdir is optional. 54# 55# 5. View certificate properties 56# 57# $ certutil -v -n "My Cert" [-d certdir] 58# 59# 60 61 62# Print usage 63usage() { 64 cat << EOF 65 66Usage: $0 -l [-d dir] 67 -a -n name -i file [-d dir] 68 -r -n name [-d dir] 69 -v -n name [-d dir] 70 71 Commands: 72 -l -- List certificates (requires a valid dir) 73 -a -- Add certificate and create dir if necessary 74 -r -- Remove certificate (requires a valid dir) 75 -v -- View certificate (requires a valid dir) 76 77 Parameters: 78 dir -- Certificate directory, or \$PWD if not given 79 name -- Nickname of the certificate 80 file -- Certificate file in PEM format 81 82EOF 83 exit 1 84} 85 86# Check path 87check_path() { 88 89 # check the directory 90 if [ ! -d $CDIR -a $ADD -eq 1 ]; then 91 echo -n "$0: cannot access $CDIR, create? [y/N] " 92 read LINE 93 case $LINE in 94 y|Y) 95 mkdir $CDIR 96 chmod 700 $CDIR 97 touch $CDIR/certs.dat 98 chmod 600 $CDIR/certs.dat 99 ;; 100 *) 101 exit 1 102 ;; 103 esac 104 fi 105 106 # check certs.dat 107 if [ ! -e $CDIR/certs.dat ]; then 108 echo "$0: please specify a valid cert directory" 109 exit 1 110 fi 111} 112 113# Add certificates 114add_cert() { 115 check_path 116 if [ ! -e $FILE ]; then 117 echo "$0: cannot find $FILE" 118 exit 1 119 fi 120 HASH=`openssl x509 -in $FILE -hash -noout 2>/dev/null`.0 121 if [ $? -ne 0 ]; then 122 echo "$0: unable to load certificate $FILE" 123 exit 1 124 fi 125 126 if grep "^$CNAME|" $CDIR/certs.dat 1>/dev/null 2>&1; then 127 echo "$0: nickname already in use" 128 exit 1 129 fi 130 131 if [ -e $CDIR/$HASH ]; then 132 echo "$0: certificate already in directory" 133 echo `openssl x509 -in $CDIR/$HASH -subject -noout` 134 exit 1 135 else 136 cp $FILE $CDIR/$HASH 137 chmod 600 $CDIR/$HASH 138 echo "$CNAME|$HASH" >> $CDIR/certs.dat 139 chmod 600 $CDIR/certs.dat 140 fi 141 142} 143 144# List certificates 145# 146# (this is too slow...) 147# 148list_cert() { 149 check_path 150 echo 151 echo "Certificates in directory $CDIR" 152 echo 153 printf "%-30s%s\n" nickname subject/issuer 154 echo "----------------------------------------------------------------------------" 155 cat $CDIR/certs.dat | while read LINE; do 156 NICK=`echo $LINE | cut -d "|" -f 1` 157 HASH=`echo $LINE | cut -d "|" -f 2` 158 SUBJECT=`openssl x509 -in $CDIR/$HASH -subject -noout` 159 ISSUER=`openssl x509 -in $CDIR/$HASH -issuer -noout` 160 printf "%-30s%s\n" "$NICK" "$SUBJECT" 161 printf "%-30s%s\n\n" "" "$ISSUER" 162 163 done 164} 165 166# Remove certificates 167remove_cert() { 168 check_path 169 ( 170 cat $CDIR/certs.dat | while read LINE; do 171 NICK=`echo $LINE | cut -d "|" -f 1` 172 HASH=`echo $LINE | cut -d "|" -f 2` 173 if [ "$CNAME" = "$NICK" ]; then 174 rm $CDIR/$HASH 175 else 176 echo $LINE 177 fi 178 done 179 ) > /tmp/$$ 180 mv /tmp/$$ $CDIR/certs.dat 181 chmod 600 $CDIR/certs.dat 182} 183 184# View certificate 185view_cert() { 186 check_path 187 cat $CDIR/certs.dat | while read LINE; do 188 NICK=`echo $LINE | cut -d "|" -f 1` 189 HASH=`echo $LINE | cut -d "|" -f 2` 190 if [ "$CNAME" = "$NICK" ]; then 191 openssl x509 -in $CDIR/$HASH -text 192 return 1 193 fi 194 done 195} 196 197# Parse option string 198ADD=0 199REMOVE=0 200LIST=0 201VIEW=0 202while getopts "arlvd:n:i:" OPT; do 203 case $OPT in 204 a) 205 ADD=1 206 ;; 207 r) 208 REMOVE=1 209 ;; 210 l) 211 LIST=1 212 ;; 213 v) 214 VIEW=1 215 ;; 216 d) 217 CDIR=$OPTARG 218 ;; 219 n) 220 CNAME=$OPTARG 221 ;; 222 i) 223 FILE=$OPTARG 224 ;; 225 *) 226 usage 227 ;; 228 esac 229done 230 231# Default options 232CDIR=${CDIR:=.} 233 234# Check command line options 235if [ $ADD -eq 1 -a $REMOVE -eq 0 -a $LIST -eq 0 -a $VIEW -eq 0 ]; then 236 if [ -n "$CNAME" -a -n "$FILE" ]; then 237 add_cert 238 else 239 echo "$0: missing certificate name or file" 240 usage 241 fi 242elif [ $REMOVE -eq 1 -a $ADD -eq 0 -a $LIST -eq 0 -a $VIEW -eq 0 ]; then 243 if [ -n "$CNAME" ]; then 244 remove_cert 245 else 246 echo "$0: missing certificate name" 247 usage 248 fi 249elif [ $LIST -eq 1 -a $ADD -eq 0 -a $REMOVE -eq 0 -a $VIEW -eq 0 ]; then 250 list_cert 251elif [ $VIEW -eq 1 -a $ADD -eq 0 -a $REMOVE -eq 0 -a $LIST -eq 0 ]; then 252 if [ -n "$CNAME" ]; then 253 if view_cert; then 254 echo "$0: cert named \"$CNAME\" not found" 255 exit 1 256 fi 257 else 258 echo "$0: missing certificate name" 259 usage 260 fi 261else 262 usage 263fi 264