#!/bin/sh 

# 
# Copyright 1999-2006 University of Chicago
# 
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# 
# http://www.apache.org/licenses/LICENSE-2.0
# 
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# 


my_seq_lines() {
    start=$1
    end=$2

    while test $start -lt $end; do
        echo $start
        start=`expr $start + 1`
    done
}

my_seq() {

    echo `my_seq_lines $@ | xargs`
}


if test "`echo -n \"testecho\"`" = "testecho"; then
    ECHOOPTION=" -n "
    ECHOTAIL=""
else
    ECHOOPTION=""
    ECHOTAIL=' \c'
fi

recho() {

    echo $ECHOOPTION $@ $ECHOTAIL
}

find_ca_dir() {
    cahash=$1
    shift

    for x in "$@"; do
        if test -f "$x/$cahash.0"; then
            echo "${x}"
            return 0
        fi
    done
}

get_security_dir() {
    cadir=$1

    if test ! -z "${GRID_SECURITY_DIR}" ; then
        echo "${GRID_SECURITY_DIR}"
    elif test "$cadir" = "/etc/grid-security/certificates"; then
        echo "/etc/grid-security"
    else
        echo "${GLOBUS_LOCATION}/etc"
    fi
}

get_hashes() {
    cadir=$1
    ${GLOBUS_SH_LS-ls} ${cadir}/*.0 2> /dev/null | xargs
}

show_default() {

    DEFAULTCAHASH="NONE"
    gsconf=""
    if test -f "${GRID_SECURITY_DIR}/grid-security.conf"; then
        gsconf=${GRID_SECURITY_DIR}/grid-security.conf
    elif test -f "/etc/grid-security/grid-security.conf"; then
        gsconf="/etc/grid-security/grid-security.conf"
    elif test -f "${GLOBUS_LOCATION}/etc/grid-security.conf"; then
        gsconf="${GLOBUS_LOCATION}/etc/grid-security.conf"
    fi

    DEFAULTCACONFFILE=`${GLOBUS_SH_LS-ls} -l "$gsconf" 2>/dev/null | ${GLOBUS_SH_SED-sed} -e "s|.*-> \(.*\)|\1|"`
    DEFAULTCAHASH=`echo "$DEFAULTCACONFFILE" | ${GLOBUS_SH_SED-sed} -e "s|.*\.\(.*\)$|\1|"`

    for x in "$@"; do
        if test -f "${x}/$DEFAULTCAHASH.0"; then
            DEFAULT_SUBJECT=`${SSL_EXEC} x509 -in ${x}/$DEFAULTCAHASH.0 -noout -subject | ${GLOBUS_SH_SED-sed} -e "s|subject= ||"`
            echo
            echo "The default CA is: $DEFAULT_SUBJECT"
            echo "         Location: ${x}/$DEFAULTCAHASH.0"
            echo
	    break
	fi
    done
}

ca_list() {


    echo "The available CA configurations installed on this host are:"
    echo
    
    index=1

    for x in "$@"; do
	cert_hashes=`get_hashes ${x}`
        if test -n "${cert_hashes}"; then
 
        echo "Directory: ${x}"
        echo

        for cert in ${cert_hashes}; do
            if test -r "${cert}" ; then 
                eval "CA${index}=${cert}"
                TEMP_SUBJECT=`${SSL_EXEC} x509 -in ${cert} -noout -subject`
                eval "CA_SUBJECT${index}=\"`echo ${TEMP_SUBJECT} | ${GLOBUS_SH_SED-sed} -e \"s|subject= ||\"`\""
                TEMP_HASH=`echo ${cert} | ${GLOBUS_SH_SED-sed} -e  "s|.*/\([^/]*\)\.0|\1|"`
                eval "CA_HASH${index}=$TEMP_HASH"
                eval "echo \"$index) \${CA_HASH${index}} -  \${CA_SUBJECT${index}}\""
                index=`expr $index + 1`
            fi
        done

        echo

        fi 
    done

    show_default "$@"
}

interactive() {
    
    ca_list "$@"

    CA_CHOSEN_INDEX=""

    while [ -z "$CA_CHOSEN_INDEX" ]
    do
        echo
        recho "Enter the index number of the CA to set as the default [q to quit]: "
        read CA_CHOSEN_INDEX

        if [ "${CA_CHOSEN_INDEX}" = "" ] || \
           [ "${CA_CHOSEN_INDEX}" = "q" ]; then
           exit 1;
        fi
        # Check for number
        if test ${CA_CHOSEN_INDEX} -eq ${CA_CHOSEN_INDEX} 2>/dev/null ; then
            if [ 1 -gt ${CA_CHOSEN_INDEX} ] || [ $index -le ${CA_CHOSEN_INDEX} ]; then
                echo "${CA_CHOSEN_INDEX} is not a valid index!"
                CA_CHOSEN_INDEX=""
            fi
        else
            echo "${CA_CHOSEN_INDEX} is not a valid index!"
            CA_CHOSEN_INDEX=""
        fi
    done
    
    eval "CA_SUBJECT=\${CA_SUBJECT${CA_CHOSEN_INDEX}}"
    eval "CA_CERT=\${CA${CA_CHOSEN_INDEX}}"
    CA_CERT_DIR=`echo $CA_CERT | ${GLOBUS_SH_SED-sed} -e "s|/[^\/]*$||"`
}

readCommandLine () {
    # Expects $* from the shell invocation

    while [ "X$1" != "X" ]
    do
        case $1 in
            -\?|-h|-help|usage)
                long_usage
                exit 0
                ;;
                
            -list)
                JUSTLIST=1
                shift 
                ;;
            -ca)
                ca_to_use="$2"
                shift ; shift
                ;;
            -dir)
                X509_CERT_DIR="$2"
                shift; shift;
                ;;
            *)
                globus_args_unrecognized_option "$1"
                ;;
         esac
    done

}

error() {

    eval "missing_file=\$$1"

    echo
    echo "The file: ${missing_file} does not exist"
    echo "The CA: ${CA_SUBJECT}"
    echo "has not been setup correctly."
    echo
    exit 1
}

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

${short_usage}

    Options:
      -help            : Display this message
      -list            : List the available CAs to use and the current
                         default
      -ca <ca hash>    : Set the default CA non-interactively

    Deprecated Options:

      -dir <dir_name>  : Set GRID_SECURITY_DIR and X509_CERT_DIR instead

EOF

}


############################################################
# main code section
############################################################

if test -f ${GLOBUS_LOCATION:-/usr}/share/globus/globus-script-initializer; then
    . ${GLOBUS_LOCATION:-/usr}/share/globus/globus-script-initializer
elif test -f ${GLOBUS_LOCATION:-/usr}/libexec/globus-script-initializer; then
    . ${GLOBUS_LOCATION:-/usr}/libexec/globus-script-initializer
else
    echo "ERROR: Please set GLOBUS_LOCATION to the Globus installation directory before" 1>&2
    echo "running this script" 1>&2
    exit 1
fi
globus_source ${libexecdir}/globus-sh-tools.sh

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

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

VERSION="6.5"

PACKAGE="globus_gsi_cert_utils"

DIRT_TIMESTAMP="1269265678"
DIRT_BRANCH_ID="80"

short_usage="$PROGRAM_NAME [-help] [ options ...]"

. $libexecdir/globus-args-parser-header

if test -n "${GLOBUS_LOCATION}" -a -x ${bindir}/openssl; then
    SSL_EXEC=${bindir}/openssl
else
    SSL_EXEC="openssl"
fi

if ! ${SSL_EXEC} version > /dev/null 2> /dev/null; then
    echo "Unable to locate openssl binary in $bindir or PATH" 1>&2
    exit 1
fi

readCommandLine "$@"

# reset positional parameters
for x in "$@"; do
    shift
done

# look for trusted certs directories
if test -n "${X509_CERT_DIR}" ; then
    set -- "${X509_CERT_DIR}"
    if test -n "${GRID_SECURITY_DIR}"; then
        set -- "$@" "${GRID_SECURITY_DIR}"
    fi
fi

if test -d "/etc/grid-security/certificates/." ; then
    set -- "$@" "/etc/grid-security/certificates" 
fi
if test -d "${GLOBUS_LOCATION:-/usr}/share/certificates/."; then
    set -- "$@" "${GLOBUS_LOCATION:-/usr}/share/certificates"
fi

found_ca=0
for x in "$@"; do
    if test -n "`get_hashes ${x}`"; then
        found_ca=1
    fi
done

if test $found_ca -eq 0; then
    echo 
    echo "There does not appear to be a valid CA"
    echo "located in any of the following directories:"
    echo ""
    for x in "$@"; do
        echo "    ${x}"
    done
    echo ""
    echo "To specify a different location where the grid security"
    echo "configuration files were installed, set the X509_CERT_DIR"
    echo "set the GRID_SECURITY_DIR environment variables."
    echo ""
    exit 1
fi

if [ -n "$JUSTLIST" ]; then
    ca_list "$@"
    exit
fi

if [ -z "$ca_to_use" ]; then
    interactive "$@"
else
    CA_CERT_DIR=`find_ca_dir $ca_to_use "$@"`
    CA_CERT="$CA_CERT_DIR/$ca_to_use.0"
    if test ! -r "${CA_CERT}" ; then
        echo
        echo "Cannot find a CA with hash ${ca_to_use}."
        echo "Use grid-default-ca -list to see a list of CA hashes "
        echo "available on this machine."
        echo 
        exit 1
    fi
    TMP_SUBJECT=`${SSL_EXEC} x509 -in ${CA_CERT} -noout -subject`
    CA_SUBJECT=`echo ${TMP_SUBJECT} | ${GLOBUS_SH_SED-sed} -e "s|subject= ||"`
fi

secconfdir=`get_security_dir ${CA_CERT_DIR}`

if [ ! -w "${secconfdir}" ]; then
    echo
    echo "You do not have permission to set the default CA configuration at"
    echo 
    echo $secconfdir
    echo
    exit 1
fi

echo
echo "setting the default CA to: ${CA_SUBJECT}"
echo

NEW_DEFAULT_CA_HASH=`${SSL_EXEC} x509 -in ${CA_CERT} -noout -hash`

GRID_SECURITY_FILE=${CA_CERT_DIR}/grid-security.conf.${NEW_DEFAULT_CA_HASH}
CA_SSL_HOST_CONFIG_FILE=${CA_CERT_DIR}/globus-host-ssl.conf.${NEW_DEFAULT_CA_HASH}
CA_SSL_USER_CONFIG_FILE=${CA_CERT_DIR}/globus-user-ssl.conf.${NEW_DEFAULT_CA_HASH}
DIRECTIONS_FILE=${CA_CERT_DIR}/directions.${NEW_DEFAULT_CA_HASH}

if [ -w ${GRID_SECURITY_FILE} ]; then
    
    echo "linking ${GRID_SECURITY_FILE} to"
    echo "        ${secconfdir}/grid-security.conf"
    echo
    ${GLOBUS_SH_RM-rm} -f ${secconfdir}/grid-security.conf
    ${GLOBUS_SH_LN-ln} -s ${GRID_SECURITY_FILE} \
			  ${secconfdir}/grid-security.conf 
else
    error GRID_SECURITY_FILE
fi

if [ -w ${CA_SSL_HOST_CONFIG_FILE} ]; then

    echo "linking ${CA_SSL_HOST_CONFIG_FILE} to"
    echo "        ${secconfdir}/globus-host-ssl.conf"
    echo
    ${GLOBUS_SH_RM-rm} -f ${secconfdir}/globus-host-ssl.conf
    ${GLOBUS_SH_LN-ln} -s ${CA_SSL_HOST_CONFIG_FILE} \
		          ${secconfdir}/globus-host-ssl.conf
else
    error CA_SSL_HOST_CONFIG_FILE
fi

if [ -w ${CA_SSL_USER_CONFIG_FILE} ]; then

    echo "linking ${CA_SSL_USER_CONFIG_FILE} to"
    echo "        ${secconfdir}/globus-user-ssl.conf"
    echo
    ${GLOBUS_SH_RM-rm} -f ${secconfdir}/globus-user-ssl.conf
    ${GLOBUS_SH_LN-ln} -s ${CA_SSL_USER_CONFIG_FILE} \
	    	          ${secconfdir}/globus-user-ssl.conf
else
    error CA_SSL_USER_CONFIG_FILE
fi

if [ -w ${DIRECTIONS_FILE} ]; then

    echo "linking ${DIRECTIONS_FILE} to"
    echo "        ${secconfdir}/directions"
    echo
    ${GLOBUS_SH_RM-rm} -f ${secconfdir}/directions
    ${GLOBUS_SH_LN-ln} -s ${DIRECTIONS_FILE} \
	    	          ${secconfdir}/directions
else
    if test -r ${secconfdir}/directions ; then
        echo "removing link ${secconfdir}/directions"
        echo
        ${GLOBUS_SH_RM-rm} -f ${secconfdir}/directions
    fi
fi

echo 
echo "...done."
echo
exit 0
