#! /bin/bash # $Id: mkproxy,v 1.19 2008/02/29 13:41:55 janjust Exp $ # safeguard against bad apples LC_ALL=C export LC_ALL function debug() { if [ -n "${DEBUG:-}" ] then echo -e "$@" fi } function info() { if [ -z "${QUIET:-}" ] then echo -e "$@" fi } function run_cmd() { if [ -n "${DEBUG:-}" ] then echo -e "run_cmd: $@" fi if [ -n "${QUIET:-}" ] then cmd_output=`eval "$@" 2>&1` exitcode=$? if [ $exitcode -ne 0 ] then echo "$cmd_output" >&2 fi else eval "$@" exitcode=$? fi return $exitcode } VERSION="mkproxy version 1.50" USAGE="\ This script will generate a X509 grid proxy using a public/private key pair found on an attached Aladdin eToken PRO. Options [--help] Displays usage. [--version] Displays version. [--debug] Enables extra debug output. [--quiet] Quiet mode, minimal output. [--limited] Creates a limited globus proxy. [--old] Creates a legacy globus proxy (default). [--gt3] Creates a pre-RFC3820 compliant proxy. [--rfc] Creates a RFC3820 compliant proxy. [--days=N] Number of days the proxy is valid. [--valid=HH:MM] Proxy is valid for HH hours and MM minutes (default=12:00). [--path-length=N] Allow a chain of at most N proxies to be generated from this one (default=2). [--bits=N] Number of bits in key (512, 1024, 2048, default=512). [--out=proxyfile] Non-standard location of new proxy cert. [--slot=N] Slot number where eToken is located (default=0). [--label=string] (Part of) label of X509 certificate on eToken. [--id=string] (Part of) ID of X509 certificate on eToken. " LABEL= ID= DEBUG= QUIET= while [ $# -gt 0 ] do case "$1" in (--slot|-s) SLOT=$2 shift ;; (--slot=*) SLOT=${1##--slot=} ;; (--label|-l) LABEL=$2 shift ;; (--label=*) LABEL=${1##--label=} ;; (--id|-i) ID=$2 shift ;; (--id=*) ID=${1##--id=} ;; (--days|-d) DAYS=$2 VALID=`expr 24 \* $DAYS`:00 shift ;; (--days=*) DAYS=${1##--days=} VALID=`expr 24 \* $DAYS`:00 ;; (--valid) VALID=$2 shift ;; (--valid=*) VALID=${1##--valid=} ;; (--out|-o) X509_USERPROXY=$2 shift ;; (--out=*) X509_USERPROXY=${1##--out=} ;; (--pcpl) PROXY_PATHLENGTH=$2 shift ;; (--pcpl=*) PROXY_PATHLENGTH=${1##--pcpl=} ;; (--path-length) PROXY_PATHLENGTH=$2 shift ;; (--path-length=*) PROXY_PATHLENGTH=${1##--path-length=} ;; (--version|-v) echo "$VERSION" exit 0 ;; (--debug) DEBUG=1 QUIET= ;; (--quiet|-q) QUIET=1 DEBUG= ;; (--limited) PROXY_POLICY=limited_policy ;; (--old) PROXY_STYLE=legacy_proxy ;; (--gt3) PROXY_STYLE=globus_proxy ;; (--rfc) PROXY_STYLE=rfc3820_proxy ;; (--bits|-b) BITS=$2 shift ;; (--bits=*) BITS=${1##--bits=} ;; (*) echo "$VERSION" echo "$USAGE" exit 0 ;; esac shift done info "Starting Aladdin eToken PRO proxy generation" # Apply defaults SLOT=${SLOT:-0} VALID=${VALID:-12:00} PROXY_SUGGEST=/tmp/x509up_u`id -u` PROXY="${X509_USERPROXY:-$PROXY_SUGGEST}" # the next 3 variables are referenced from openssl.cnnf export PROXY_PATHLENGTH=${PROXY_PATHLENGTH:-2} export PROXY_POLICY=${PROXY_POLICY:-normal_policy} export PROXY_STYLE=${PROXY_STYLE:-legacy_proxy} BITS=${BITS:-512} DATE_CMD="date -d" debug "Output File: $PROXY" MYDIR=${0%/*} if [ "$MYDIR" = "${MYDIR#/}" ] then MYDIR=$PWD/$MYDIR fi MYDIR=${MYDIR%/*} export LD_LIBRARY_PATH="$MYDIR/lib:$LD_LIBRARY_PATH" export PKCS11_ENG="$MYDIR/lib/engine_pkcs11.so" export PKCS11_MOD="$MYDIR/lib/libetpkcs11.so" if [ ! -r "$PKCS11_MOD" ] then export PKCS11_MOD="/usr/local/lib/libetpkcs11.so" fi export OPENSSL="$MYDIR/bin/openssl" export OPENSSL_CONF="$MYDIR/etc/openssl.cnf" if [ `uname -s` = "Darwin" ] then export DYLD_LIBRARY_PATH="$MYDIR/lib" DATE_CMD="echo" elif [ `uname -o` = "Cygwin" ] then export PKCS11_ENG="$MYDIR/lib/engine_pkcs11.dll" export PKCS11_MOD="$WINDIR\system32\\\etpkcs11.dll" export PATH=$MYDIR/bin:$MYDIR/lib:$PATH fi if [ ! -r "${PKCS11_ENG}" ] then echo "Error: cannot find PKCS11 engine (engine_pkcs11) to use." >&2 exit 2 fi if [ ! -r "${PKCS11_MOD}" ] then echo "Error: cannot find PKCS11 module (etpkcs11) to use." >&2 exit 3 fi PKCS11TOOL="$MYDIR/bin/pkcs11-tool --slot $SLOT --module $PKCS11_MOD" if [ -n "$DEBUG" ] then PKCS11TOOL="$PKCS11TOOL -v -v -v" fi debug "running $PKCS11TOOL -O" ETOKEN_CONTENTS=`$PKCS11TOOL -O` #ETOKEN_CONTENTS=`cat tt` if [ $? -ne 0 ] then echo "Warning: cannot read eToken. Aborting." >&2 exit 4 fi # Look for a X.509 certificate object with an exact label LABEL=`echo $LABEL | sed -e 's/\//\\\\\\//g'` CERT_LABEL=`echo "$ETOKEN_CONTENTS" | \ sed -n "/Certificate Object, type = X.509 cert:/N;\ s/.*label: *\($LABEL\)/\1/p" | \ head -1` if [ -n "$LABEL" -a -z "$CERT_LABEL" ] then # Look for a X.509 certificate object with a specific label CERT_LABEL=`echo "$ETOKEN_CONTENTS" | \ sed -n "/Certificate Object, type = X.509 cert:/N;\ s/.*label: *\(.*$LABEL.*\)/\1/p" | \ head -1` fi if [ -n "$LABEL" -a -z "$CERT_LABEL" ] then echo "No certificates matching label='$LABEL' found on eToken in slot $SLOT" >&2 exit 5 fi if [ -z "$ID" ] then # No ID specified, look for the matching certificate ID from label LABEL=`echo $CERT_LABEL | sed -e 's/\//\\\\\\//g'` CERT_ID=`echo "$ETOKEN_CONTENTS" | \ sed -n "/Certificate Object, type = X.509 cert:/N;N;N;\ s/.*label: *$LABEL.*ID: *\(.*\)/\1/p" | \ head -1` else # Look for a X.509 certificate object with an exact ID ID=`echo $ID | sed -e 's/\//\\\\\\//g'` CERT_ID=`echo "$ETOKEN_CONTENTS" | \ sed -n "/Certificate Object, type = X.509 cert:/N;N;N;\ s/.*ID: *\($ID\)/\1/p" | \ head -1` if [ -z "$CERT_ID" ] then # Look for a X.509 certificate object with a specific ID CERT_ID=`echo "$ETOKEN_CONTENTS" | \ sed -n "/Certificate Object, type = X.509 cert:/N;N;N;\ s/.*ID: *\(.*$ID.*\)/\1/p" | \ head -1` fi fi if [ -n "$ID" -a -z "$CERT_ID" ] then echo "No certificates matching id='$ID' found on eToken in slot $SLOT" >&2 exit 6 fi info "Found X.509 certificate on eToken:" info " label: $CERT_LABEL" info " id: $CERT_ID" PROXYREQ=`mktemp proxyrequest.XXXXXX` PROXYKEY=`mktemp proxykey.XXXXXX` PROXYCERT=`mktemp proxykey.XXXXXX` PROXYUSERCERT=`mktemp proxyusercert.XXXXXX` PROXYUSERDER=`mktemp proxyuserder.XXXXXX` RND=`expr $RANDOM \* $RANDOM` # Using a pipe screws up under Cygwin!! debug "extracting public certificate from token" $PKCS11TOOL --type cert -r --id "$CERT_ID" -o $PROXYUSERDER run_cmd $OPENSSL x509 -in $PROXYUSERDER -inform der -out $PROXYUSERCERT debug "running 'openssl x509 -noout -in $PROXYUSERCERT -subject'" SUBJ=`$OPENSSL x509 -noout -in $PROXYUSERCERT -subject | sed -e s'/subject= //'` info "Your identity: $SUBJ" debug "running 'openssl x509 -noout -in $PROXYUSERCERT -serial'" SERIAL=`$OPENSSL x509 -noout -in $PROXYUSERCERT -serial | sed -e s'/serial=//'` info "Certificate serial number: $SERIAL" if [ "$PROXY_STYLE" = "legacy_proxy" ] then if [ "$PROXY_POLICY" = "normal_policy" ] then PROXY_SUBJ="proxy" else PROXY_SUBJ="limited proxy" fi PROXY_EXTENSIONS="" PROXY_SERIAL="0x$SERIAL" else # for non-legacy proxies the proxy policy (limited, normal) is implemented # using X509v3 extensions, which are loaded from the 'extfile' PROXY_SUBJ="$RND" PROXY_EXTENSIONS="-extfile $OPENSSL_CONF" PROXY_SERIAL="$RND" fi run_cmd $OPENSSL req -new -nodes -keyout $PROXYKEY -out $PROXYREQ \ -newkey rsa:$BITS -subj \"$SUBJ/CN=$PROXY_SUBJ\" run_cmd $OPENSSL x509 -req \ -engine pkcs11 -CAkeyform engine \ -in $PROXYREQ \ -CA $PROXYUSERCERT \ -CAkey ${SLOT:+$SLOT:}$CERT_ID \ -out $PROXYCERT \ -set_serial $PROXY_SERIAL -sha1 -valid $VALID \ $PROXY_EXTENSIONS exitcode=$? if [ $exitcode -eq 0 ] then cat $PROXYCERT $PROXYKEY $PROXYUSERCERT > "$PROXY" chmod 600 "$PROXY" # simple proxy validation end_date=`$OPENSSL x509 -noout -enddate -in "$PROXY" | sed 's/notAfter=//'` info "Your proxy is valid until: `$DATE_CMD \"$end_date\"`" fi rm $PROXYCERT $PROXYKEY $PROXYREQ $PROXYUSERCERT $PROXYUSERDER exit $exitcode