#!/bin/sh
###########################################################################
#
#   $Id: upgrade2psd.sh,v 1.6.2.1 1998/05/28 08:00:10 cvsusr Exp $
#
#   Copyright (c) 1997 Dynamic Software AB
#   This is unpublished proprietary source code.
#
#   Description:    This scripts convert a BoKS 4.2.x private key and
#                   certificate to a BoKS 4.[34] PSD.
#
#   Author:         Magnus Nystrm
#
#   Created:        9709
#
#   Latest mod:     $Date: 1998/05/28 08:00:10 $
#
###########################################################################
###########################################################################
#
#   $Id: common_funcs.sh,v 1.4 1996/12/09 13:39:06 magnus Exp $
#
#   Description:    This is common code for create_ca_creds, create_user_creds,
#                   keyadm and ../../dscontainer/src/create_dscpkg
#                   Automatically included.

###########################################################################
debug_msg() {
#
#   Function:   Debug functionality. Turned on if environment variable
#               DSC_DEBUG is non-null.
#
#   Arguments:  $1 -    What to do
#               $2 -    What to do it with
#
#   ReturnValue:0 = OK, otherwise something went wrong
#
#   Environment:  
#
###########################################################################

    if [ ! -z "$DSC_DEBUG" ]; then
        case $1 in

        IN )
            echo DEBUG - Entering $2 >&2
            ;;
        OUT )
            echo DEBUG - Leaving $2 >&2
            ;;
        TRACE )
            set -x
            ;;
        TRACEOFF )
            set +x
            ;;
        * )
            echo DEBUG - "$*" >&2
            ;;
        esac
    fi
}
###########################################################################
error_msg() {
#
#   Function:   Writes an error message on stderr.
#
#   Arguments:  $1      Error message type
#               $2      Error message
#
#   ReturnValue:0 = OK, otherwise something went wrong
#
#   Environment:  
#
###########################################################################

    if [ -z "$silent" ]; then

        case $1 in

        ERR )
            echo "ERROR: $2" >&2
            ;;
        NOTIFY )
            echo "NOTE: $2" >&2
            ;;
        * )
            echo "$pgm:$1 $2" >&2
            ;;
        esac

    fi

    return 0
}
###########################################################################
quit_reply() {
#
#   Function:       Checks if given reply indicate that the user wants to
#                   quit
#
#   Arguments:      $1 - Given reply
#
#   ReturnValue:    0 = OK, otherwise something went wrong
#
#   Environment:  
#
###########################################################################

    debug_msg IN quit_reply

    if [ "$1" = "q" -o "$1" = "quit" -o "$1" = "Q" -o "$1" = "QUIT" ]; then
        ret_val=0
    else
        ret_val=1
    fi

    debug_msg OUT quit_reply

    return $ret_val
}
###########################################################################
get_pin() {
#
#   Function:   Asks user for someone's pin
#
#   Arguments:  $1 = Who's pin
#
#   ReturnValue:0 = OK, otherwise something went wrong
#
#   Environment:  
#
###########################################################################

    debug_msg IN get_pin

    pin_user=$1

    echo "#"
    echo "# $pin_user Password"
    echo "#\n"
    done=false
    stty -echo
    while [ "$done" = false ]; do
        echo "\t Enter $pin_user password or q[uit]:\c"
        read REPLY
        echo ""
        if [ -z "$REPLY" ]; then
            error_msg NOTIFY "Must give $pin_user password or 'q' - Try again!"
        elif [ "$REPLY" = "q" -o "$REPLY" = "Q" ]; then
            stty echo
            return 1
        else
            pin="$REPLY"
            echo "\t Re-enter $pin_user password or q[uit]:\c"
            read REPLY
            echo ""
            if [ -z "$REPLY" ]; then
                error_msg NOTIFY \
                    "Must give $pin_user password or 'q' - Try again!"
            elif quit_reply "$REPLY"; then
                stty echo
                return 1
            elif [ "$REPLY" != "$pin" ]; then
                error_msg NOTIFY "Different passwords given - Try again!"
            else
                done=true
            fi
        fi
    done
    stty echo

    debug_msg OUT get_pin

    return 0
}
###########################################################################
#
# End of common code
#
###########################################################################
###########################################################################
#
#   Function:       
#
#   Description:    
#
#   Arguments:      
#
#   ReturnValue:    
#
#   Environment:    This script shall be run in BoKS-shell.
#
###########################################################################
###########################################################################
usage_msg() {
#
#   Function:   Echoes a usage_msg message on stdout
#
#   Arguments:  -
#
#   ReturnValue:0 = OK, otherwise something went wrong
#
#   Environment:  
#
###########################################################################

    echo "Usage:"
    echo "$pgm -pre  [-d directory] [-h host]"
    echo "$pgm -post [-d directory] [-h host]"
}
###########################################################################
get_hostpin() {
###########################################################################
#
#   Function:       get_hostpin
#
#   Description:    Retrieves the host's nodekey from master's database
#
#   Arguments:      hostname
#
#   ReturnValue:    0 = OK, otherwise something went wrong
#
#   Environment:    Sets ENV variable DSC_USER_PASSWORD
#
###########################################################################

    host=$1
    DSC_USER_PASSWORD=`hostkey -g -h $host 2>/dev/null`
    export DSC_USER_PASSWORD
    [ "$DSC_USER_PASSWORD" != "" ]
}
###########################################################################
do_preupgrade() {
###########################################################################
#
#   Function:       do_preupgrade
#
#   Description:    Fetch host.crt and host.key from given host
#
#   Arguments:      host
#
#   ReturnValue:    0 = OK, otherwise something went wrong
#
#   Environment:    -
#
###########################################################################

    host=$1
    host_ip=`lh -i $host`
    if [ $? -ne 0 ]; then
	error_msg ERR "Could not get IP address for $host"
	return 1
    fi
    
    cadm -l -f keys/Certificate -h $host >${host}.${host_ip}.crt 2>/dev/null
    if [ $? -ne 0 ]; then
	rm -f ${host}.${host_ip}.crt
	error_msg ERR "Could not retrieve host certificate for $host"
	return 1
    fi

    cadm -l -f keys/PrivateKey -h $host >${host}.${host_ip}.key 2>/dev/null
    if [ $? -ne 0 ]; then
	rm -f ${host}.${host_ip}.crt ${host}.${host_ip}.key
	error_msg ERR "Could not retrieve host certificate for $host"
	return 1
    fi

    echo "Succesful pre-upgrade of host $host"
    
    return 0
}
###########################################################################
do_postupgrade() {	
###########################################################################
#
#   Function:       do_postupgrade
#
#   Description:    Do the actual upgrade of a host
#
#   Arguments:      hostname ipaddress
#
#   ReturnValue:    0 = OK, otherwise something went wrong
#
#   Environment:    -
#
###########################################################################

    host=$1
    host_ip=$2
    #
    # Convert PrivateKey (BoKS 4.2)
    #	    
    if [ ! -r ${host}.${host_ip}.key ]; then
	error_msg ERR "No private key file found for host $host"
	return 1
    fi
	
    ds2pkcs -i ${host}.${host_ip}.key -o .pkcs.$$ 2>/dev/null
    if [ $? -ne 0 ]; then
	error_msg ERR "Could not convert private key for $host"
	return 1
    fi
		
    #
    # Create key package with given private key
    #
    get_hostpin $host
    if [ $? -ne 0 ]; then
	error_msg ERR "Could not find nodekey for host $host"
	return 1
    fi

    #
    # Need distinguished name from old certificate
    #
    host_dname=`dumpcert ${host}.${host_ip}.crt |\
	awk '$1 ~ /Subject:/ { printf "%s",$2; exit 0 }'`
    if [ "$host_dname" = "" ]; then
	error_msg ERR "Could not parse ${host}'s certificate"
	return 1
    fi

    #
    # Create host PSD
    #
    keypkgadm -C -u $host -n "$host_dname" -k `cat .pkcs.$$` \
	-e ${host}.kpg -T HOST
    if [ $? -ne 0 ]; then
	error_msg ERR "Could not create PSD for $host"
	return 1
    fi

    rm -f .pkcs.$$
    #
    # Insert certificate into DSContainer
    #
    dscadm -C -e ${host}.kpg -c ${host}.${host_ip}.crt 2>/dev/null
    if [ $? -ne 0 ]; then
	error_msg ERR "Could not create PSD for $host"
	return 1
    fi

    #
    # Store key package in BoKS
    #
    keypkgadm -I -e ${host}.kpg -m BOKS -T HOST -o $host_ip 2>/dev/null
    if [ $? -ne 0 ]; then
        error_msg ERR "Could not store created host PSD in SSMI database"
        return 1
    fi

    #
    # Store certificate in BoKS
    #
    dscertadm -I -i ${host}.${host_ip}.crt -m BOKS -T HOST -o $host_ip \
	2>/dev/null
    if [ $? -ne 0 ]; then
        error_msg ERR "Could not store host certificate for $host in SSMI database"
        return 1
    fi

    #
    # Install PSD on host
    #
    cadm -w -S ${host}.kpg -f keys/host.kpg -h ${host} 2>/dev/null
    if [ $? -ne 0 ]; then
	error_msg ERR "Could not install PSD on $host"
	return 1
    else
	echo "Sucessful upgrade to PSD on host $host"
    fi

    #
    # Clean up
    #
    rm -f ${host}.${host_ip}.crt ${host}.${host_ip}.key ${host}.kpg

    
    return 0
}
############################################################
#
# Program name
#
pgm=`basename $0`
#
# Options & Variables
#
state="unknown"
directory=""
host=""

#
# 'Safe' umask
#
umask 077

#
#   Get command-line options
#
while getopts "p:d:h:?" opt;
do
    case $opt in
        p )
	    if expr $OPTARG : 're' 1>/dev/null ; then
		state=preupgrade
	    elif expr $OPTARG : 'ost' 1>/dev/null ; then
		state=postupgrade
	    else
		usage_msg
		exit 1
	    fi		
            ;;
        d )
            directory="$OPTARG"
            ;;
	h )
	    host="$OPTARG"
	    ;;
        ? | \? )
            usage_msg
            exit 1
            ;;
    esac
done

#
#  Checks
#
if [ "$state" = "unknown" ]; then
    usage_msg
    exit 1
fi

if [ "$directory" != "" ]; then
    if [ ! -d $directory -o ! -w $directory ]; then
	error_msg ERR "$d is not a writable directory for this process!"
	exit 1
    else
	cd $directory	
    fi
fi

if [ "$BOKS_etc" = "" ]; then
    error_msg ERR "Must be run in a SSMI admin shell!"
    exit 1
fi

case $state in

    preupgrade )

	if [ "$host" != "" ]; then
	    hostlist=$host
	else
	    hostlist=`lh -uh`
	fi

	for host in $hostlist
	do
	    do_preupgrade $host
	done
	
	;;

    postupgrade )

	if [ "$host" != "" ]; then
	    hostlist=${host}\.*\.crt
	else
	    hostlist=*.crt
	fi

	for host in $hostlist
	do
	    hostname=`expr $host : "\(.*\)\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.crt"`
	    host_ip=`expr $host : "$hostname\.\(.*\)\..*"`
	    do_postupgrade $hostname $host_ip
	done
	
	rm -f .pkcs.*

	;;

esac

#
# Alles klar
#
exit 0
