#!/bin/sh
# $Id: verify-chain-for-ee-cert,v 1.1 2003/05/22 22:38:23 helm Exp $

usage_error() {
  echo "$0 [-help] [-v|-verbose] [-gsi|-all] just-one-certificate" 1>&2
}

VERBOSE=""
CERT=""
One=""
Two=""
OPENSSL=openssl
TCMODE="gsi"

go_help() {

usage_error 

cat <<NoMoreHelp

This script verifies the chain of CA signing certificates
for an end entity (EE) certificate using "openssl verify".

Only specify one certificate per invocation.  The first certificate
on the command line is the only one that will be checked.

Certificates only!  This script does not validate EE certificates
held in PKCS #12 (.p12) files, due to security issues.

Certificates which fail to verify will likely cause
globus or grid related operations to fail. 

This script is most useful for testing certificates of 
interesting grid services, such as gatekeeper, and should
be used to test all grid host or service certificates.

The verification searches for CA signing keys in the
GSI CA search path as described here:
http://www.globus.org/security/config.html

The "TRUSTED_CA" list described in the above URL is constructed:

\$X509_CERT_DIR (environment variable)
\$HOME/.globus/certificates/ [that is, $HOME/.globus/certificates/]
/etc/grid-security/certificates/ 
\$GLOBUS_LOCATION/share/certificates/

-gsi [default] causes the verification to use the first 
directory found in TRUSTED_CA as the location
of CA signing certificates.  The script will search no
further, even if needed certificates are missing.  This is
the way gsi behaves.

-all will validate the EE cert against each directory
in TRUSTED_CA.

Examples
verify-chain-for-ee-cert /etc/grid-security/hostcert.pem
   Verify a grid service (host) certificate, using the
   GSI algorithm

verify-chain-for-ee-cert -v -all /etc/grid-security/hostcert.pem
   verify a grid service (host) certificate, against all
   available TRUSTED_CA directories, with copious output

DOEGrids CA project recommends that you install CA support files
in /etc/grid-security/certificates, and remove all other possible
TRUSTED_CA directories.

NoMoreHelp

exit 0

}

Pcount=1

while [ "$Pcount" -le "$#" ] ; do
   MyArg="`eval echo \"\$"${Pcount}"\"`"
   case "${MyArg}" in
      -v | -verbose )
          VERBOSE="-verbose"
          [ $VERBOSE ] && echo "Setting VERBOSE mode" >&2
          Pcount=`expr $Pcount + 1`
          ;;
      -help )
          go_help
          exit 0
          ;;
      -gsi )
          TCMODE="gsi"
          [ $VERBOSE ] && echo "Setting GSI mode" >&2
          Pcount=`expr $Pcount + 1`
          ;;
      -all )
          TCMODE="tutti"
          [ $VERBOSE ] && echo "Setting ALL TRUSTED_CA mode" >&2
          Pcount=`expr $Pcount + 1`
          ;;
        *)
          CERT="${MyArg}"
          break
         ;;
   esac
done

[ -z "${CERT:-}" ] && { echo "No certificate" 1>&2 ; usage_error ; exit 1 ; }

[ -f "$CERT" ] || { echo "${CERT}: Certificate file not found" 1>&2 ; exit 2 ; }
[ -s "$CERT" ] || { echo "${CERT}: Certificate file zero length" 1>&2 ; exit 2 ; }

if [ "$VERBOSE" ] ; then
   echo "Verbose flag set" >&2
   echo "End Entity Certificate file: $CERT" >&2
fi

# This will blow up if openssl isn't around or isn't functional
# All versions of openssl will work, afaik.
OPV=`$OPENSSL version` || exit 1
[ $VERBOSE ] && echo "Using" $OPV >&2

# Build TRUSTED_CA array
# as per
# http://www.globus.org/security/config.html

# This is for a summary diagnostic
ISX509=unset
ISHOME=unset
ISGSIF=unset
ISGLOC=unset

TRUSTED_CA_ARRAY=""

[ $VERBOSE ] && echo "" >&2

if [ "${X509_CERT_DIR-unset}" = "unset" ]; then
 [ $VERBOSE ] && echo "[ok] \$X509_CERT_DIR is not defined" >&2
else
 [ $VERBOSE ] && echo "\$X509_CERT_DIR: $X509_CERT_DIR" >&2
 TRUSTED_CA_ARRAY="$TRUSTED_CA_ARRAY $X509_CERT_DIR"
fi

if [ "${HOME-unset}" = "unset" ]; then
 echo "\$HOME is not defined -- should not happen" >&2
else
 Temp="$HOME/.globus/certificates"
 if [ -d "$Temp" ] ; then
   [ $VERBOSE ] && echo "will search $Temp" >&2
   TRUSTED_CA_ARRAY="$TRUSTED_CA_ARRAY $Temp"
 else
   [ $VERBOSE ] && echo "[ok] $Temp does not exist" >&2
 fi
 Temp=""
fi

# We force this to exist.  Even if it doesn't.  The validator will complain.
 TRUSTED_CA_ARRAY="$TRUSTED_CA_ARRAY /etc/grid-security/certificates"

if [ "${GLOBUS_LOCATION-unset}" = "unset" ]; then
 [ $VERBOSE ] && echo "[ok] \$GLOBUS_LOCATION is not defined --" >&2
 [ $VERBOSE ] && echo "     will not be able to check \$GLOBUS_LOCATION/share/certificates" >&2
else
 Temp="$GLOBUS_LOCATION/share/certificates"
 [ $VERBOSE ] && echo "will search $Temp" >&2
 TRUSTED_CA_ARRAY="$TRUSTED_CA_ARRAY $Temp"
 Temp=""
fi

[ $VERBOSE ] && echo "" >&2

ExitStatus=0

[ $VERBOSE ] && echo "\$TRUSTED_CA: $TRUSTED_CA_ARRAY" >&2

for i in $TRUSTED_CA_ARRAY ; do
# It's maddening not to know which CApath is being used
#   if [ $VERBOSE ] ; then
      echo "" >&2
      echo "Checking CApath $i" >&2
#   fi
      if [ -d "$i" ] ; then
# This is the main event
        JunkFile=/tmp/openssl-validifier.$$
        $OPENSSL verify $VERBOSE -CApath "$i" "$CERT"  2>&1 | tee "$JunkFile" >&2
#        ExitStatus=$?
#        openssl doesn't return any error status sometimes, so we have to do something else
         [ "`grep -c -s rror "$JunkFile"`" -gt 0 ] && ExitStatus=2
         rm -f "$JunkFile"
         [ "$TCMODE" = "gsi" ] && break
      else
        echo "${i}: not a directory or doesn't exist" >&2
      fi   
done

exit $ExitStatus
# $Log: verify-chain-for-ee-cert,v $
# Revision 1.1  2003/05/22 22:38:23  helm
# *** empty log message ***
#
# Revision 1.3  2003/05/16 17:53:08  helm
# examples
#
# Revision 1.2  2003/05/16 17:39:11  helm
# messages + openssl out to stderr
#
# Revision 1.1  2003/05/16 17:01:38  helm
# Add sanity check scripts
#
