#!/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.
# 


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 "${sysconfdir}"
    fi
}

get_hashes() {
    cadir=$1
    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 "${sysconfdir}/grid-security.conf"; then
        gsconf="${sysconfdir}/grid-security.conf"
    fi

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

    for x in "$@"; do
        if test -f "${x}/$DEFAULTCAHASH.0"; then
            DEFAULT_SUBJECT=`openssl x509 -in ${x}/$DEFAULTCAHASH.0 -noout -subject | 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=`openssl x509 -in ${cert} -noout -subject`
                eval "CA_SUBJECT${index}=\"`echo ${TEMP_SUBJECT} | sed -e \"s|subject= ||\"`\""
                TEMP_HASH=`echo ${cert} | 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
        printf "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 | sed -e "s|/[^\/]*$||"`
}

globus_args_short_usage()
{
    cat 1>&2 <<EOF

Syntax : ${short_usage}

Use -help to display full usage.

EOF
}

globus_args_option_error()
{
    cat 1>&2 <<EOF

ERROR: option $1 : $2
EOF
    globus_args_short_usage
    exit 1
}

globus_args_unrecognized_option()
{
    globus_args_option_error $1 "unrecognized option"
    exit 1
}

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

    while [ "X$1" != "X" ]
    do
        case "$1" in
            -\?|-h|-help|usage|--help|-usage|--usage)
                long_usage
                exit 0
                ;;
            -version|--version)
                if [ "X${PROGRAM_NAME}" != "X" -a \
                     "X${PROGRAM_VERSION}" != "X" ]; then
                    echo "${PROGRAM_NAME}: ${PROGRAM_VERSION}"
                elif [ "X${PACKAGE}" != "X" -a \
                    "X${VERSION}" != "X" ]; then
                    echo "${PACKAGE}: ${VERSION}"
                else
                    echo "No version information available."
                fi
                exit 0
                ;;
            -versions|--versions)
                __AT=@
                if [ -n "${PACKAGE}" -a -n "${VERSION}" -a \
                     -n "${DIRT_TIMESTAMP}" -a -n "${DIRT_BRANCH_ID}" -a \
                     "X${DIRT_TIMESTAMP}" != "X${__AT}DIRT_TIMESTAMP${__AT}" -a \
                     "X${DIRT_BRANCH_ID}" != "X${__AT}DIRT_BRANCH_ID${__AT}" ];
                then
                    echo "${PACKAGE}: ${VERSION} (${DIRT_TIMESTAMP}-${DIRT_BRANCH_ID})"
                else
                    echo "No DiRT information available."
                fi
                exit 0;
                ;;
            -list|--list)
                JUSTLIST=1
                shift 
                ;;
            -ca|--ca)
                ca_to_use="$2"
                shift ; shift
                ;;
            -dir|--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 () {
    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
############################################################

prefix="${GLOBUS_LOCATION-@prefix@}"
exec_prefix="@exec_prefix@"
bindir="@bindir@"
sbindir="@sbindir@"
datarootdir="@datarootdir@"
datadir="@datadir@"
sysconfdir="@sysconfdir@"

PATH=${bindir}:${sbindir}:${PATH}

PROGRAM_NAME=`echo $0 | sed 's|.*/||g'`

PROGRAM_VERSION="@VERSION@"

VERSION="@VERSION@"

PACKAGE="@PACKAGE@"

DIRT_TIMESTAMP="@DIRT_TIMESTAMP@"
DIRT_BRANCH_ID="@DIRT_BRANCH_ID@"

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

if ! openssl 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 "${datadir}/certificates/."; then
    set -- "$@" "${datadir}/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=`openssl x509 -in ${CA_CERT} -noout -subject`
    CA_SUBJECT=`echo ${TMP_SUBJECT} | 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=`openssl 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
    rm -f ${secconfdir}/grid-security.conf
    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
    rm -f ${secconfdir}/globus-host-ssl.conf
    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
    rm -f ${secconfdir}/globus-user-ssl.conf
    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
    rm -f ${secconfdir}/directions
    ln -s ${DIRECTIONS_FILE} ${secconfdir}/directions
else
    if test -r ${secconfdir}/directions ; then
        echo "removing link ${secconfdir}/directions"
        echo
        rm -f ${secconfdir}/directions
    fi
fi

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