#!/bin/sh

if test -z "${GLOBUS_LOCATION}"; then
    echo ""
    echo "ERROR: Please set GLOBUS_LOCATION to the Globus installation directory before"
    echo "running this script"
    echo ""
    exit 1
fi

. ${GLOBUS_LOCATION}/libexec/globus-script-initializer
globus_source ${GLOBUS_LOCATION}/libexec/globus-sh-tools.sh

#
# renew a request using a Globus 1.0 or 1.1 installation
#

# hard-coded for now... Change defintion of ssl_exec_name to get this
# script to work with other SSL implementations, such as openSSL.
# we will replace this with openssl if we find openssl
ssl_exec_name=openssl

PROGRAM_NAME=`echo $0 | ${GLOBUS_SH_SED-sed} 's|.*/||g'`

PROGRAM_VERSION=`echo '$Revision: 1.7.2.1 $'| ${GLOBUS_SH_SED-sed} -e 's|\\$||g' -e 's|Revision: \(.*\)|\1|'`

VERSION="0.12"

PACKAGE="globus_gsi_cert_utils"

DIRT_TIMESTAMP="1055342205"
DIRT_BRANCH_ID="42"

short_usage="$PROGRAM_NAME [-help] [-nopassphrase] [...] <challenge text>"

long_usage()
{
    ${GLOBUS_SH_CAT-cat} >&2 <<EOF

${short_usage}

    This command creates a request for renewal of your Globus credentials.
    Optional arguments:
      -help, -usage        : displays this message
      -debug               : extra output (if problem occurs)
      -nopassphrase        : do not encrypt the new private key file 
      -sslexec    <path>   : location of SSL executable (${ssl_exec_name})
      -oldcert    <path>   : location of old certificate
      -oldkey     <path>   : location of old (private) key
      -newkey     <path>   : location of new (private) key
      -newcertreq <path>   : location of certificate renewal request
      -version             : prints the version 
    Required Argument:
      <challenge>          : challenge text, as per email instructions.

EOF
}

globus_source $libexecdir/globus-args-parser-header $@


MyWhich()
{
    command=$1
    if [ ${debug} = yes ]; then
	echo "DEBUG: looking for [${command}]"
    fi
    whichres=
    for dir in `echo $PATH | ${GLOBUS_SH_SED-sed} 's/:/ /g'` ; do
	if [ -x ${dir}/${command} -a -z "${whichres}" ]; then
	    whichres=${dir}/${command}
	fi
    done
    if [ ${debug} = yes ]; then
	echo "DEBUG: result: [${whichres}]"
    fi
}


bailout ()
{
    if [ -z "${beenhere}" ]; then
	beenhere=yes
	if [ ${debug} = yes ]; then
	    echo "DEBUG: in bailout()"
	fi
	echo ""
	echo "    The renewal request process was interrupted."
	echo "    Cleaning up..."
	${GLOBUS_SH_RM-rm} -f ${tmpproxy} ${tmpproxy}.digest ${newkey} ${newcertreq}
    fi
    exit 1
}
trap bailout 1 2 3 6 15

#########################################################################
# start

sslexec=${bindir}/${ssl_exec_name}
proxy_init=${bindir}/grid-proxy-init
proxy_destroy=${bindir}/grid-proxy-destroy
tmpproxy=/tmp/globus-cert-renewal-temp-proxy.$$
newcertreq=
newkey=
oldkey=
oldcert=
challenge=
globusdir=${GLOBUS_LOCATION}
debug=no
sslexec_rsa_opts=-des3

while [ -n "$1" ]; do
    case "$1" in
	-sslexec | -newkey | -newcertreq | \
	-oldkey | -oldcert)
	    if [ -z "$2" ]; then
		echo "Error: Additional argument needed to $1" 1>&2
		echo "-usage will display usage" 1>&2
		exit 1
	    fi
	    var=`echo "$1" | ${GLOBUS_SH_SED-sed} 's/^-//'`
	    eval ${var}=${2}
	    shift ; shift
	    ;;
	-nopassphrase)
	    sslexec_rsa_opts=
	    shift
	    ;;
	-debug)
	    debug=yes
	    shift
	    ;;
	-*)
            globus_args_unrecognized_option $1
	    ;;
	*)
	    challenge="$1"
	    shift
	    ;;
    esac
done

if [ -z "$HOME" -a \( -z "${newcertreq}" -o -z "${newkey}" -o -z "${oldkey}" -o -z "${oldcert}" \)  ]; then
    echo "Error: Environment variable \$HOME not set -- quitting" 1>&2
    exit 1
fi

tmpfile=/tmp/please-remove-this-file.$$
echo "blah" > ${tmpfile}

if [ ${debug} = yes ]; then
    ${GLOBUS_SH_CAT-cat} <<EOF
DEBUG: after initial checks:
    globusdir=${globusdir}
    sslexec=${sslexec}
    newkey=${newkey}
    newcertreq=${newcertreq}
    oldkey=${oldkey}
    oldcert=${oldcert}
    challenge=${challenge}
EOF
fi



if [ ! -x ${proxy_init} ]; then
    echo "Could not locate the executable for proxy initialization." 1>&2
    exit 1
fi

if [ ! -x ${proxy_destroy} ]; then
    echo "Could not locate the executable for proxy destruction." 1>&2
    exit 1
fi

if [ ${debug} = yes ]; then
    echo "DEBUG: trying to locate the SSL command (${ssl_exec_name})"
fi

if [ ! -x ${sslexec} ]; then
    echo "Error: Could not execute the command '${ssl_exec_name}'. Rerun this command" 1>&2
    echo "using the -sslexec option. -help will display usage" 1>&2
    exit 1
fi

if [ ! -x ${bindir}/grid-cert-info ]; then
    echo "Error: Couldn't execute: '${bindir}/grid-cert-info'" 1>&2
    exit 1
fi

if [ -n "${oldcert}" ]; then
    extra_arg="-f ${oldcert}"
fi

BASE_DN=`${bindir}/grid-cert-info -subject ${extra_arg} | sed -e "s|^\(\/[Oo]=[Gg][Rr][Ii][Dd]\/[Oo]=[Gg][Ll][Oo][Bb][Uu][Ss]\)\/.*|\1|" | sed -e "s|^\(\/[Cc]=[Uu][Ss]\/[Oo]=[Gg][Ll][Oo][Bb][Uu][Ss]\)\/.*|\1|"`


if [ "$BASE_DN" = "`${bindir}/grid-cert-info -subject ${extra_arg}`" ]; then
    echo "Error: grid-cert-renew can only be used for certificates"
    echo "       generated by the Globus CA.  (/O=Grid/O=Globus/* or"
    echo "       /C=US/O=Globus/*)"
    exit 1;
fi

${sslexec} version 1>/dev/null 2>/dev/null
xxx=$?
if [ ${xxx} -ne 0 ]; then
    echo "Error: Could not execute the command '${ssl_exec_name}'. Rerun this command" 1>&2
    echo "using the -sslexec option. -help will display usage" 1>&2
    exit 1
fi
if [ ${debug} = yes ]; then
    echo "DEBUG: got sslexec=[${sslexec}]"
fi

if [ -z "${newkey}" ]; then
    cd $HOME
    if [ -d .globus ]; then
	newkey=.globus/newkey.pem
    else
	echo "    Warning: could not find the subdirectory \$HOME/.globus" 1>&2
	echo "    Warning: Your new key will be placed in \$HOME" 1>&2
	newkey=newkey.pem
    fi
fi
if [ ${debug} = yes ]; then
    echo "DEBUG: got newkey=[${newkey}]"
fi

if [ -z "${newcertreq}" ] ; then
    cd $HOME
    if [ -d .globus ]; then
	newcertreq=.globus/renewalrequest.pem
    else
	echo "    Warning: Your renewal request will be placed in \$HOME" 1>&2
	newcertreq=renewalrequest.pem
    fi
fi
if [ ${debug} = yes ]; then
    echo "DEBUG: got newcertreq=[${newcertreq}]"
fi


# 1. generate a proxy, and keypair from current cert and key

${GLOBUS_SH_CAT-cat} <<EOF

    The certificate renewal process consists of four steps:

    1. Decrypting your current private key. The key is used to sign the
       renewal request, so that we know that you are you...

       Use your current passphrase when prompted.

EOF
proxy_opts="-valid 0:5 -bits 1024 -old -out ${tmpproxy}"
if [ -n "${oldkey}" ]; then
    proxy_opts="${proxy_opts} -key ${oldkey}"
fi
if [ -n "${oldcert}" ]; then
    proxy_opts="${proxy_opts} -cert ${oldcert}"
fi
if [ ${debug} = yes ] ; then
    echo "DEBUG: running ${proxy_init} ${proxy_opts}"
fi
${proxy_init} ${proxy_opts}
xxx=$?
if [ ${xxx} -ne 0 -a ${xxx} -ne 2 ] ; then
    if [ ${debug} = yes ] ; then
	echo "DEBUG: got return value ${xxx}"
    fi
    echo "ERROR: Running grid-proxy-init"
    echo "Use -debug for further information."
    exit 1
fi

# 2. extract the private key, encrypt it in new passphrase
#    and save it as new user key

if [ ${debug} = yes ] ; then
    echo "DEBUG: running ${GLOBUS_SH_RM-rm} -f ${newkey} ${newcertreq}"
fi
${GLOBUS_SH_RM-rm} -f ${newkey} ${newcertreq}

${GLOBUS_SH_CAT-cat} <<EOF

    2. Creating a new private key which will replace your old key that is
       about to expire.  When prompted (twice) enter a passphrase 
       for the new key.

EOF
if [ ${debug} = yes ] ; then
    echo "DEBUG: running ${sslexec} rsa ${sslexec_rsa_opts} -in ${tmpproxy} -out ${newkey}"
fi
${sslexec} rsa ${sslexec_rsa_opts} -in ${tmpproxy} -out ${newkey}
xxx=$?
if [ ${xxx} -ne 0 ]; then
    if [ ${debug} = yes ] ; then
	echo "DEBUG: got return value ${xxx}"
    fi
    echo "Something went wrong..." 1>&2
    ${proxy_destroy} ${tmpproxy}
    exit 1
fi
${GLOBUS_SH_CHMOD-chmod} 400 ${newkey}

#Save some info 
echo $HOME > ${newcertreq}
echo "newcertreq=${newcertreq}" >> ${newcertreq}
echo "newkey=${newkey}" >> ${newcertreq}

#copy proxy cert signed by user
if [ ${debug} = yes ] ; then
    echo "DEBUG: running ${sslexec} x509 -in ${tmpproxy} -text >> ${newcertreq}"
fi
${sslexec} x509 -in ${tmpproxy} >> ${newcertreq} 2>/dev/null
xxx=$?
if [ ${xxx} -ne 0 ]; then
    if [ ${debug} = yes ] ; then
	echo "DEBUG: got return value ${xxx}"
    fi
    echo "Something went wrong..." 1>&2
    ${GLOBUS_SH_RM-rm} -f ${newkey} ${newcertreq}
    ${proxy_destroy} ${tmpproxy}
    exit 1
fi

${GLOBUS_SH_CAT-cat} <<EOF

    3. Creating a certificate renewal request, based on your new key.
       With the certificate request we also add your challenge, encrypted
       with your old key.
EOF
# generate a digest which can not be copied 
if [ ${debug} = yes ] ; then
    echo "DEBUG: running ${sslexec} x509 -in ${tmpproxy} > ${tmpproxy}.digest"
fi
${sslexec} x509 -in ${tmpproxy} > ${tmpproxy}.digest
xxx=$?
if [ ${xxx} -ne 0 ]; then
    if [ ${debug} = yes ] ; then
	echo "DEBUG: got return value ${xxx}"
    fi
    echo "Something went wrong..." 1>&2
    ${GLOBUS_SH_RM-rm} -f ${newkey} ${newcertreq} ${tmpproxy}.digest
    ${proxy_destroy} ${tmpproxy}
    exit 1
fi
while [ -z "${challenge}" ] ; do
    ${GLOBUS_SH_CAT-cat} <<EOF

       You have not supplied the challenge text string that was included
       in the email message sent to you from the CA.

Please enter the challenge:
EOF
    read challenge
done
if [ ${debug} = yes ] ; then
    echo "DEBUG: got challenge = [${challenge}]"
fi
echo "${challenge}" >> ${tmpproxy}.digest
if [ ${debug} = yes ] ; then
    echo "DEBUG: running ${sslexec} dgst ${tmpproxy}.digest >> ${newcertreq}"
fi
${sslexec} dgst ${tmpproxy}.digest >> ${newcertreq}
xxx=$?
if [ ${xxx} -ne 0 ]; then
    if [ ${debug} = yes ] ; then
	echo "DEBUG: got return value ${xxx}"
    fi
    echo "Something went wrong..." 1>&2
    ${GLOBUS_SH_RM-rm} -f ${newkey} ${newcertreq} ${tmpproxy}.digest
    ${proxy_destroy} ${tmpproxy}
    exit 1
fi
${GLOBUS_SH_RM-rm} -f ${tmpproxy}.digest

#generate a cert req signed by the new key. 
${GLOBUS_SH_CAT-cat} <<EOF

       When prompted, enter the SAME passphrase as in step 2.

EOF
if [ ${debug} = yes ] ; then
    echo "DEBUG: running ${sslexec} x509 -in ${tmpproxy} -x509toreq -signkey ${newkey}  >> ${newcertreq}"
fi
${sslexec} x509 -in ${tmpproxy} -x509toreq -signkey ${newkey}  >> ${newcertreq}
xxx=$?
while [ ${xxx} -ne 0 ]; do
    if [ ${debug} = yes ] ; then
	echo "DEBUG: got return value ${xxx}"
    fi
    echo ""
    echo "    Try again..."
    echo ""
    ${sslexec} x509 -in ${tmpproxy} -x509toreq -signkey ${newkey}  >> ${newcertreq}
    xxx=$?
done

if [ ${debug} = yes ] ; then
    echo "DEBUG: running ${proxy_destroy} ${tmpproxy}"
fi
${proxy_destroy} ${tmpproxy}

${GLOBUS_SH_CAT-cat} <<EOF

    4. Completing the renewal request process:

       The new key is stored in ${newkey}
       The renewal request is stored in ${newcertreq}

       You now have to send the renewal request to the Globus CA.
       This is done by executing the following line:

          cat ${newcertreq} | mail ca@globus.org

       Within 2 working days, you will receieve an email containing the
       new certificate along with instructions on how to install it.

       IMPORTANT:
       a. This program does NOT email the certificate request: you
	  must do it manually
       b. Make sure you send the certificate request from an email
	  account that can receive email.

EOF

