#!/bin/sh
#
# Grid Engine CA framework script
#
# (c) 2004 Sun Microsystems, Inc. Use is subject to license terms.  
#
# set -x

# Reset PATH to a safe value  
#
PATH=/bin:/usr/bin:/usr/sbin:/usr/ucb

# Easy way to prevent clearing of screen
#
CLEAR=clear
#CLEAR=:


#-------------------------------------------------------------------------
# USEFUL LOCAL SHELL PROCEDURES

#-------------------------------------------------------------------------
# ErrUsage: print usage string, exit
#
ErrUsage()
{
   myname=`basename $0`
   $INFOTEXT -e \
   "\nUsage: %s <command>\n" \
   "   -init            initialize CA infrastructure\n" \
   "   -req             generate a certificate request and private key\n" \
   "   -sign            sign a certificate request\n" \
   "   -copy            install user certificate and private key\n" \
   "   -verify <cert>   verify a <cert>\n" \
   "   -print <cert>    print a <cert>\n" \
   "   -printkey <key>  print a <key>\n" \
   "   -renew <user>    extend the certificate of <user>\n" \
   "   -renew_ca        extend the CA certificate\n" \
   "   -renew_sys       extend the daemon certificate\n" \
   "   -days <days>     days of validity of the certificate\n" \
   "   -sha1            use sha-1 instead of md5 as message digest\n" \
   "   -encryptkey      use des to encrypt the generated key with a passphrase\n" \
   "   -outdir <dir>    write to directory <dir>\n" \
   "   -cadir <dir>     overwrite CALOCALTOP and CATOP settings\n" \
   "   -pkcs12 <file>   generate pkcs12 format files for the users in <file>\n" \
   "   -usercert <file> generate certificates and keys for the users in <file>\n" \
   "   -user <u:g:e>    generate certificates and keys for <u:g:e>\n" \
   "                    with u=Unix User, g=Common Name, e=email\n" \
   $myname

   exit 1
}

#--------------------------------------------------------------------------
# InitCA Init CA directories and get DN info
#
InitCA()
{
   $CLEAR
   $INFOTEXT -u "\nInitializing Certificate Authority (CA) for OpenSSL security framework"

   if [ -d $CATOP -a -d $CALOCALTOP ]; then
      $INFOTEXT -e "\nThere are already directories of the CA infrastructure in\n   %s\n   or\n   %s\n" "$CATOP" "$CALOCALTOP"
      $INFOTEXT -auto $AUTO -ask "y" "n" -def "y" -n \
         "Do you want to recreate your SGE CA infrastructure (y/n) [y] >> "
      if [ $? != 0 ]; then
         $INFOTEXT "We will not reinitialize your SGE CA infrastructure."
         exit 0
      fi
   fi

   MakeCADirs

   MakeCAcert

 
   MakeCert daemon $ME "SGE Daemon" none
   MakeCert user $ME "SGE install user" none

   if [ "$ADMINUSER" != default ]; then
      MakeCert user $ADMINUSER "SGE admin user" none
   fi
}

#---------------------------------------------------------------------------
# CheckIfQmasterHost
#    If our hostname given in $1 is the same as in the "act_qmaster" file
#    echo "true" else echo "false"
#
# $1 = hostname
#
CheckIfQmasterHost()
{
   host=$1

   if [ "$host" = "`cat $SGE_ROOT/$SGE_CELL/common/act_qmaster`" ]; then
      echo true
   else
      echo false
   fi
}

#--------------------------------------------------------------------------
# InstallKey
#
# $1 = user | daemon
# $2 = $ME ( username )
#
InstallKey()
{
   HOST=`$V5UTILBIN/gethostname -aname`
   result=`CheckIfQmasterHost $HOST`
   if [ "$result" != "true" ]; then 
      $INFOTEXT "You can install your private key and certificate only on the master host."
      return 1
   fi 

   if [ -d /var/sgeCA/$CA_PORT/$SGE_CELL/userkeys ]; then
      userkeydir=/var/sgeCA/$CA_PORT/$SGE_CELL/userkeys
   else
      $INFOTEXT "Cant find local userkey directory."
      return 1
   fi   

   if [ $1 = daemon ]; then
      keyfile=$CALOCALTOP/private/key.pem
      certfile=$CATOP/certs/cert.pem
      randfile=$CALOCALTOP/private/rand.seed
      HOMEDIR=`env LC_ALL=C grep '^root:' /etc/passwd | cut -f6 -d:`
   else
      keyfile=$userkeydir/$ME/key.pem
      certfile=$userkeydir/$ME/cert.pem
      randfile=$userkeydir/$ME/rand.seed
      HOMEDIR=$HOME
   fi

   basedir=$HOMEDIR/.sge/$CA_PORT/$SGE_CELL
   if [ ! -d $basedir ]; then
      $V5UTILBIN/adminrun $2 $MKDIR -p $basedir
   fi

   if [ ! -d $basedir/certs ]; then
      $V5UTILBIN/adminrun $2 $MKDIR $basedir/certs
   fi

   if [ ! -d $basedir/private ]; then
      $V5UTILBIN/adminrun $2 $MKDIR $basedir/private
   fi

   if [ -f $basedir/private/key.pem ]; then
      $V5UTILBIN/adminrun $2 rm -f $basedir/private/key.pem
   fi

   if [ -f $basedir/private/rand.seed ]; then
      $V5UTILBIN/adminrun $2 rm -f $basedir/private/rand.seed
   fi

   if [ -f $basedir/certs/cert.pem ]; then
      $V5UTILBIN/adminrun $2 rm -f $basedir/certs/cert.pem
   fi

   $V5UTILBIN/adminrun $2 $CP $keyfile $basedir/private
   $V5UTILBIN/adminrun $2 $CP $randfile $basedir/private
   $V5UTILBIN/adminrun $2 $CHMOD 700 $basedir/private
   $V5UTILBIN/adminrun $2 $CHMOD 400 $basedir/private/*

   $V5UTILBIN/adminrun $2 $CP $certfile $basedir/certs
   $V5UTILBIN/adminrun $2 $CHMOD 755 $basedir/certs
   $V5UTILBIN/adminrun $2 $CHMOD 444 $basedir/certs/*

   $INFOTEXT "Certificate and private key for user %s have been installed" $ME

   return 0
}


#--------------------------------------------------------------------------
# MakeCAcert create CA certificate and private key
#
#
MakeCAcert()
{
   $INFOTEXT -u "\nCreating CA certificate and private key"
   $INFOTEXT -e "Please give some basic parameters to create the distinguished name (DN)\n" \
   "for the certificates.\n\n" \
   "We will ask for\n" \
   "   - the two letter country code\n" \
   "   - the state\n" \
   "   - the location, e.g city or your buildingcode\n" \
   "   - the organization (e.g. your company name)\n" \
   "   - the organizational unit, e.g. your department\n" \
   "   - the email address of the CA administrator (you!)\n"

   $INFOTEXT -wait -auto $AUTO -n "\nHit <RETURN> to continue >> "
   # $CLEAR

   done=false
   while [ $done = false ]; do

      if [ "$AUTO" = "true" ]; then
            CA_C=`echo $CSP_COUNTRY_CODE | env LC_ALL=C tr "[a-z]" "[A-Z]"`
            CA_ST="$CSP_STATE"
            CA_L="$CSP_LOCATION"
            CA_O="$CSP_ORGA"
            CA_OU="$CSP_ORGA_UNIT"
            CA_EMAIL="$CSP_MAIL_ADDRESS"
      else
         dndone=false
         while [ $dndone = false ]; do
            $INFOTEXT -n "Please enter your two letter country code, e.g. 'US' >> "
            INP=`Enter ""`
            if [ "$INP != " -a `echo $INP | wc -c` = 3 ]; then
               CA_C=`echo $INP | env LC_ALL=C tr "[a-z]" "[A-Z]"`
               dndone=true
            fi
         done

         dndone=false
         while [ $dndone = false ]; do
            $INFOTEXT -n "Please enter your state >> "
            INP=`Enter ""`
            CA_ST="$INP"
            if [ "$INP" != "" ]; then
               CA_ST="$INP"
               dndone=true
            fi
         done

         dndone=false
         while [ $dndone = false ]; do
            $INFOTEXT -n "Please enter your location, e.g city or buildingcode >> "
            INP=`Enter ""`
            CA_L="$INP"
            if [ "$INP" != "" ]; then
               CA_L="$INP"
               dndone=true
            fi
         done

         dndone=false
         while [ $dndone = false ]; do
            $INFOTEXT -n "Please enter the name of your organization >> "
            INP=`Enter ""`   
            if [ "$INP" != "" ]; then
               CA_O="$INP"
               dndone=true
            fi
         done

         dndone=false
         while [ $dndone = false ]; do
            $INFOTEXT -n "Please enter your organizational unit, e.g. your department >> "
            INP=`Enter ""`    
            CA_OU="$INP"
            if [ "$INP" != "" ]; then
               CA_OU="$INP"
               dndone=true
            fi
         done

         dndone=false
         while [ $dndone = false ]; do
            $INFOTEXT -n "Please enter the email address of the CA administrator >> "
            INP=`Enter ""`   
            if [ "$INP" != "" ]; then
               CA_EMAIL="$INP"
               dndone=true
            fi
         done
      fi


      $CLEAR
      $INFOTEXT -e "\nYou selected the following basic data for the distinguished name of\n" \
      "your certificates:\n\n" \
      "Country code:         %s=%s\n" \
      "State:                %s=%s\n" \
      "Location:             %s=%s\n" \
      "Organization:         %s=%s\n" \
      "Organizational unit:  %s=%s\n" \
      "CA email address:     %s=%s\n" \
      C "$CA_C" ST "$CA_ST" L "$CA_L" O "$CA_O" OU "$CA_OU" emailAddress "$CA_EMAIL"
      $INFOTEXT -auto $AUTO -ask "y" "n" -def "y" -n \
         "Do you want to use these data (y/n) [y] >> "
      if [ $? = 0 ]; then
         done=true
 
         TMPFILE=/tmp/sge_ca$$.tmp
         TMPFILE1=/tmp/sge_ca1$$.tmp
         $RM -f $TMPFILE $TMPFILE1
         $TOUCH $TMPFILE $TMPFILE1
         echo C="$CA_C" >> $TMPFILE
         echo ST="$CA_ST" >> $TMPFILE
         echo L="$CA_L" >> $TMPFILE
         echo O="$CA_O" >> $TMPFILE
         echo OU="$CA_OU" >> $TMPFILE
         ExecuteAsAdmin $CP $TMPFILE $CATOP/dn.info
         echo CN="SGE Certificate Authority" >> $TMPFILE
         echo userId=CA >> $TMPFILE
         echo emailAddress=$CA_EMAIL >> $TMPFILE

         export CATOP
         Execute cat $CONFIG_DIR/sge_ssl_template.cnf $TMPFILE > $TMPFILE1

         if [ $ADMINUSER != default -a $rootinstalls = true ]; then
            # echo +++ $ADMINUSER
            MakeRandFile $CALOCALTOP/private/rand.seed $ADMINUSER
         else
            # echo +++ $ME
            MakeRandFile $CALOCALTOP/private/rand.seed $ME
         fi
         RANDFILE=$CALOCALTOP/private/rand.seed; export RANDFILE

         umask 077
         $INFOTEXT "Creating CA certificate and private key"
         ExecuteAsAdmin $REQ -config $TMPFILE1 -new -x509 \
              -keyout ${CALOCALTOP}/private/$CAKEY -out ${CATOP}/$CACERT $DAYS
         status=$?
         umask 022

         ExecuteAsAdmin $CHMOD 444 ${CATOP}/$CACERT

         rm -f $TMPFILE $TMPFILE1

         if [ $status != 0 ]; then
            $INFOTEXT "Failed to create CA certificate and private key. Exit"
            exit 1
         fi

      else
         $CLEAR
      fi
   done

   $INFOTEXT -wait -auto $AUTO -n "\nHit <RETURN> to continue >> "
   $CLEAR
}

#--------------------------------------------------------------------------
# MakeRandFile create a random data file
#  
# $1 = <randfilename>
# $2 = <owner>
#
MakeRandFile()
{

   # OpenSSL uses /dev/urandom by default so if it's there, don't
   # polute the PRNG with predictable data.
   rfile="/dev/urandom"
   if [ ! -r /dev/urandom ]; then
      if [ -r /dev/random ]; then 
         rfile=/dev/random
      # elif [ -r /kernel/genunix ]; then
      #   rfile=/kernel/genunix
      elif [ -r /bin/vi ]; then
         rfile=/bin/vi
      fi
   fi
   $INFOTEXT "Creating RANDFILE from '%s' in '%s'" $rfile $1

   $V5UTILBIN/adminrun $2 dd if=$rfile of=/tmp/.rand count=2048
   RANDFILE=/tmp/.rand; export RANDFILE;
   $V5UTILBIN/adminrun $2 $OPENSSL rand -rand /tmp/.rand -out $1 2048
   $V5UTILBIN/adminrun $2 $RM /tmp/.rand
   $V5UTILBIN/adminrun $2 $CHMOD 644 $1
   # echo "--------------"
   # ls -l $rfile $1
   # echo "--------------"

}


#--------------------------------------------------------------------------
# MakeUserCert create user certificates and keys for Windows Admin user
#
# $1 = <user:gecos:email>
#
MakeUserCert()
{
   line="$1"

   unixuser=`echo $line|cut -d: -f1`
   gecos=`echo $line|cut -d: -f2`
   email=`echo $line|cut -d: -f3`

   # echo $unixuser:$gecos:$email
   if [ "$unixuser" = "" ]; then
      $INFOTEXT "no Unix user specified. Exit."
      exit 1
   fi   

   if [ "$gecos" = "" ]; then
      gecos=$unixuser
   fi   
   if [ "$email" = "" ]; then
      email=$unixuser
   fi   

   entries=`$V5UTILBIN/adminrun $ADMINUSER grep "CN=$gecos" $CATOP/index.txt|grep '^V'|wc -l`
   if [ $entries = 0 ]; then
      $INFOTEXT "Generating certificate and key for '%s' ('%s','%s')." \
         "$unixuser" "$gecos" "$email"
      MakeCert user "$unixuser" "$gecos" "$email"
   else   
      $INFOTEXT "Please renew certificate for '%s' ('%s','%s') instead." \
         "$unixuser" "$gecos" "$email"
      # RenewCert user $unixuser
   fi
}

#--------------------------------------------------------------------------
# MakeUserCerts create user certificates and keys from userfile
# userfile contains a list of entries of the following format per user.
#
# <unix username>:<gecos field>:<user's email address>
#
# $1 = <userfile>
#
MakeUserCerts()
{
   if [ ! -f "$1" ]; then
      $INFOTEXT "no valid userfile '%s'. Exit." $1
      exit 1
   fi

   userfile=$1

   cat $userfile | while read line; do
      MakeUserCert "$line"
   done   
}

#--------------------------------------------------------------------------
# MakePKCS12 create pkcs12 file of user certificate and keys from userfile
# userfile contains a list of entries of the following format per user.
#
# <unix username>:<gecos field>:<user's email address>
#
# $1 = <userfile>
#
MakePKCS12()
{
   if [ ! -f "$1" ]; then
      $INFOTEXT "no valid userfile '%s'. Exit." $1
      exit 1
   fi

   cat $1 | while read line; do
      unixuser=`echo $line|cut -d: -f1`
      $INFOTEXT "Generating %s.p12." \
         "$unixuser"
      $P12 -export -inkey $CALOCALTOP/userkeys/$unixuser/key.pem -out $CALOCALTOP/userkeys/$unixuser/$unixuser.p12 -in $CALOCALTOP/userkeys/$unixuser/cert.pem -certfile $CALOCALTOP/cacert.pem -caname "SGE CA"
   done   
}

#--------------------------------------------------------------------------
# DumpUsers dump user info 
#
DumpUsers()
{
   CERTDIR=$CALOCALTOP/userkeys
   RSFILE=/tmp/rand

   # create rand.seed file
   MakeRandFile $RSFILE $USER

   RANDFILE=$RSFILE; export RANDFILE

   $INFOTEXT "Dumping users to $outdir/dumped_users.txt"
   for i in `ls $CERTDIR`; do
      $X509 -in $CERTDIR/$i/cert.pem -subject -noout|$AWK -F '/' '{print $8 ":" $7 ":" $9}' | sed -e 's/UID=//' -e 's/CN=//' -e 's/emailAddress=//' >> $outdir/dumped_users.txt
   done
}

#--------------------------------------------------------------------------
# MakeCert create certificate and private key for daemon
#
# $1 = "daemon" or "user"
# $2 = userId   (Unix user name)
# $3 = commonname         (e.g. passwd gecos field)
# $4 = email address
#
MakeCert()
{
   $INFOTEXT -u "\nCreating '%s' certificate and key" "$3"

   TMPFILE=/tmp/sge_ca$$.tmp
   TMPFILE1=/tmp/sge_ca1$$.tmp
   $RM -f $TMPFILE $TMPFILE1
   Execute cp $CATOP/dn.info $TMPFILE
   echo userId=$2 >> $TMPFILE
   echo CN=$3 >> $TMPFILE
   echo emailAddress=$4 >> $TMPFILE
   Execute cat $CONFIG_DIR/sge_ssl_template.cnf $TMPFILE > $TMPFILE1


   if [ $1 = daemon ]; then
      KEYDIR=$CALOCALTOP/private
      KEYFILE=$CALOCALTOP/private/key.pem
      REQFILE=$CALOCALTOP/private/req.pem
      CERTFILE=$CATOP/certs/cert.pem
      RSFILE=$CALOCALTOP/private/rand.seed
   else
      KEYDIR=$CALOCALTOP/userkeys/$2
      KEYFILE=$KEYDIR/key.pem
      REQFILE=$KEYDIR/req.pem
      CERTFILE=$KEYDIR/cert.pem
      RSFILE=$KEYDIR/rand.seed
      Execute $RM -rf $KEYDIR
      ExecuteAsAdmin $MKDIR $KEYDIR
   fi

   # create rand.seed file
   MakeRandFile $RSFILE $ADMINUSER

   RANDFILE=$RSFILE; export RANDFILE

   if [ $rootinstalls = true ]; then
      umask 077
   fi

   # create a certificate request
   ExecuteAsAdmin $REQ -config $TMPFILE1 -new -keyout $KEYFILE -out $REQFILE $DAYS
   if [ $? != 0 ]; then
      $INFOTEXT "Can't create %s or %s. Exit." $KEYFILE $REQFILE
      exit 1
   fi  

   # sign certificate request
   ExecuteAsAdmin $CA -config $TMPFILE1 -policy policy_anything -batch $DAYS \
                      -out $CERTFILE -infiles $REQFILE
   if [ $? != 0 ]; then
      $INFOTEXT "Can't sign certificate request %s. Exit." $REQFILE 
      exit 1
   fi
   ExecuteAsAdmin $CHMOD 444 $CERTFILE

   $RM -f $TMPFILE $TMPFILE1 

   if [ $1 = daemon ]; then
      Execute $CHMOD 500 $KEYDIR
      Execute $CHMOD 400 $KEYDIR/*
      Execute $CHMOD 600 $KEYDIR/rand.seed
      $INFOTEXT "created and signed certificate for SGE daemons" 
   else
      if [ $rootinstalls = true ]; then
         Execute $CHMOD 500 $KEYDIR
         Execute $CHMOD 400 $KEYDIR/*
         # check if user exists and chown if yes
         id $2  > /dev/null 2>&1
         if [ $? = 0 ]; then
            Execute $CHOWN -R $2 $KEYDIR
         fi   
      fi

      $INFOTEXT "created and signed certificate for user '%s' in '%s'" $2 $KEYDIR
   fi

   umask 022
}

#--------------------------------------------------------------------------
# RenewCA renew a selfsigned CA certificate
#
RenewCA()
{
   $INFOTEXT -u "\nRenewing CA certificate"

   CAKEYDIR=$CALOCALTOP/private
   CAKEYFILE=$CALOCALTOP/private/cakey.pem
   CACERTFILE=$CATOP/cacert.pem
   RSFILE=$CALOCALTOP/private/rand.seed
   NEWCACERTFILE=$CATOP/cacert.pem.new
   OLDCACERTFILE=$CATOP/cacert.pem.`date | tr " " "_"`
   RANDFILE=$RSFILE; export RANDFILE

   ExecuteAsAdmin $X509 -in $CACERTFILE -signkey $CAKEYFILE $DAYS -out $NEWCACERTFILE

   ExecuteAsAdmin $CP $CACERTFILE $OLDCACERTFILE
   ExecuteAsAdmin $CHMOD 644 $CACERTFILE
   ExecuteAsAdmin $MV $NEWCACERTFILE $CACERTFILE
   ExecuteAsAdmin $CHMOD 444 $CACERTFILE

}


#--------------------------------------------------------------------------
# RenewCert renew a certificate
#
# $1 = "daemon" or "user"
# $2 = userId   (Unix user name)
#
RenewCert()
{
   if [ $1 = daemon ]; then
      $INFOTEXT -u "\nRenewing daemon certificate"
   else
      $INFOTEXT -u "\nRenewing  '%s' user certificate" "$2"
   fi

   TMPFILE=/tmp/sge_ca$$.tmp
   TMPFILE1=/tmp/sge_ca1$$.tmp
   $RM -f $TMPFILE $TMPFILE1
   Execute cp $CATOP/dn.info $TMPFILE
   echo userId=$2 >> $TMPFILE
   echo CN="dummy" >> $TMPFILE
   echo emailAddress="dummy" >> $TMPFILE
   Execute cat $CONFIG_DIR/sge_ssl_template.cnf $TMPFILE > $TMPFILE1


   if [ $1 = daemon ]; then
      KEYDIR=$CALOCALTOP/private
      KEYFILE=$CALOCALTOP/private/key.pem
      REQFILE=$CALOCALTOP/private/req.pem
      CERTFILE=$CATOP/certs/cert.pem
      NEWCERTFILE=$CATOP/certs/cert.pem.new
      OLDCERTFILE=$CATOP/certs/cert.pem.old
      RSFILE=$CALOCALTOP/private/rand.seed
      CRLFILE=$CATOP/ca-crl.pem
   else
      KEYDIR=$CALOCALTOP/userkeys/$2
      KEYFILE=$KEYDIR/key.pem
      REQFILE=$KEYDIR/req.pem
      CERTFILE=$KEYDIR/cert.pem
      NEWCERTFILE=$KEYDIR/cert.pem.new
      OLDCERTFILE=$KEYDIR/cert.pem.old
      RSFILE=$KEYDIR/rand.seed
      CRLFILE=$CATOP/ca-crl.pem
   fi

   # create rand.seed file
   # rand.seed already exists, therefore no MakeRandFile $RSFILE $2
   RANDFILE=$RSFILE; export RANDFILE

   if [ $rootinstalls = true ]; then
      umask 077
   fi

   # revoke the old certificate and create the certificate revocation list
   Execute $CHMOD 511 $KEYDIR
   if [ $1 = daemon ]; then
      ExecuteAsAdmin $CHMOD 644 $CERTFILE
      ExecuteAsAdmin $CHMOD 666 $RSFILE
   else
      Execute $CHMOD 644 $CERTFILE
      Execute $CHMOD 666 $RSFILE
   fi
   ExecuteAsAdmin $CA -config $TMPFILE1 -policy policy_anything \
                      -batch $DAYS \
                      -revoke $CERTFILE 

   if [ $? != 0 ]; then
      $INFOTEXT "Can't revoke %s. Exit." $CERTFILE
      exit 1
   fi  

   # create the certificate revocation list
   ExecuteAsAdmin $CA -config $TMPFILE1 -policy policy_anything \
                      -batch $DAYS \
                      -gencrl -out $CRLFILE

   if [ $? != 0 ]; then
      $INFOTEXT "Can't generate revocation list %s. Exit." $CRLFILE
      exit 1
   fi  

   # create request from certificate
   # Execute $X509 -x509toreq -in $CERTFILE -out $REQFILE -signkey $KEYFILE 

   # extend the request
   #Execute $X509 -req $DAYS -in $REQFILE \
   #                -signkey $CALOCALTOP/private/$CAKEY \
   #                -out $NEWCERTFILE

   # allow admin user access to user's dir
   if [ $ADMINUSER != default -a $rootinstalls = true ]; then
      Execute $CHOWN -R $ADMINUSER $KEYDIR
      Execute $CHMOD 700 $KEYDIR
   fi

   # sign certificate request
   ExecuteAsAdmin $CA -config $TMPFILE1 \
                      -policy policy_anything -batch $DAYS \
                      -out $NEWCERTFILE -infiles $REQFILE

   if [ $? != 0 ]; then
      $INFOTEXT "Can't renew %s. Exit." $CERTFILE
      exit 1
   fi  

   if [ $1 = daemon ]; then
      if [ -f $OLDCERTFILE ]; then
	 ExecuteAsAdmin $RM -f $OLDCERTFILE
      fi
      ExecuteAsAdmin $CP $CERTFILE $OLDCERTFILE
      ExecuteAsAdmin $MV $NEWCERTFILE $CERTFILE
      ExecuteAsAdmin $CHMOD 444 $CERTFILE
   else
      Execute $CP $CERTFILE $OLDCERTFILE
      Execute $MV $NEWCERTFILE $CERTFILE
   fi

   $RM -f $TMPFILE $TMPFILE1 

   if [ $1 = daemon ]; then
      $INFOTEXT "renewed certificate for SGE daemons" 
   else
      if [ $rootinstalls = true ]; then
         Execute $CHMOD 500 $KEYDIR
         Execute $CHMOD 400 $KEYDIR/*
         Execute $CHOWN -R $2 $KEYDIR
      fi

      $INFOTEXT "renewed certificate for user '%s' in '%s'" $2 $KEYDIR
   fi

   umask 022
}


#--------------------------------------------------------------------------
# MakeCADirs
#    create all directories for CA infrastructure
#
# 
MakeCADirs()
{


   if [ -f $CATOP -o -f $CALOCALTOP ]; then
      $INFOTEXT "The CA directories\n   %s or %s\n seem to be regular files" \
            $CATOP $CALOCALTOP
      $INFOTEXT "CA initialization failed. Exit."
      exit 1
   fi

   Execute $RM -rf $CALOCALTOP > /dev/null 2>&1
   ExecuteAsAdmin $RM -rf $CATOP > /dev/null 2>&1

   if [ -f $CATOP -o -d $CATOP -o -f $CALOCALTOP -o -d $CALOCALTOP ]; then
      $INFOTEXT "Can't delete the CA directories\n   %s or %s" \
            $CATOP $CALOCALTOP
      $INFOTEXT "CA initialization failed. Exit."
      exit 1
   fi

   $INFOTEXT "Creating %s" $CATOP
   ExecuteAsAdmin $MKDIR $CATOP

   $INFOTEXT "Creating %s" $CALOCALTOP
   Execute $MKDIR -p $CALOCALTOP

   if [ $ADMINUSER != default -a $rootinstalls = true ]; then
      Execute $CHOWN $ADMINUSER $CALOCALTOP
   fi

   $INFOTEXT "Creating %s" ${CATOP}/certs
   ExecuteAsAdmin $MKDIR ${CATOP}/certs

   $INFOTEXT "Creating %s" ${CATOP}/crl
   $INFOTEXT -log "Creating %s" ${CATOP}/crl
   ExecuteAsAdmin $MKDIR ${CATOP}/crl

   $INFOTEXT "Creating %s" ${CATOP}/newcerts
   $INFOTEXT -log "Creating %s" ${CATOP}/newcerts
   ExecuteAsAdmin $MKDIR ${CATOP}/newcerts

   $INFOTEXT "Creating %s" ${CATOP}/serial
   $INFOTEXT -log "Creating %s" ${CATOP}/serial
   TruncCreateAndMakeWriteable ${CATOP}/serial
   echo "01" > ${CATOP}/serial
   ExecuteAsAdmin $CHMOD 644 ${CATOP}/serial

   $INFOTEXT "Creating %s" ${CATOP}/index.txt
   $INFOTEXT -log "Creating %s" ${CATOP}/index.txt
   ExecuteAsAdmin $TOUCH ${CATOP}/index.txt   

   $INFOTEXT "Creating %s" ${CALOCALTOP}/userkeys
   $INFOTEXT -log "Creating %s" ${CALOCALTOP}/userkeys
   ExecuteAsAdmin $MKDIR ${CALOCALTOP}/userkeys   

   umask 077
   $INFOTEXT "Creating %s" ${CALOCALTOP}/private
   $INFOTEXT -log "Creating %s" ${CALOCALTOP}/private
   ExecuteAsAdmin $MKDIR ${CALOCALTOP}/private
   umask 022

   $INFOTEXT -wait -auto $AUTO -n "\nHit <RETURN> to continue >> "
   $CLEAR

}

#--------------------------------------------------------------------------
# THE MAIN PROCEDURE
#--------------------------------------------------------------------------

umask 022

if [ -z "$SGE_ROOT" -o ! -d "$SGE_ROOT" ]; then
   echo
   echo ERROR: Please set your \$SGE_ROOT environment variable
   echo and start this script again.
   echo Exit
   echo
   exit 1
fi

if [ ! -f "$SGE_ROOT/util/arch" ]; then
   echo
   echo ERROR: The shell script \"$SGE_ROOT/util/arch\" does not exist.
   echo Please verify your distribution and restart this script. Exit.
   echo
   exit 1
fi

if [ ! -f $SGE_ROOT/util/arch_variables ]; then
   echo
   echo ERROR: Missing shell script \"$SGE_ROOT/util/arch_variables\".
   echo Please verify your distribution and restart this script. Exit.
   echo
   exit 1
fi

. $SGE_ROOT/util/arch_variables

if [ "$SGE_CELL" = "" ]; then
   SGE_CELL=default
   export SGE_CELL
fi

if [ "$SGE_QMASTER_PORT" != "" ]; then
   CA_PORT=port$SGE_QMASTER_PORT
   export CA_PORT
else
   CA_PORT=sge_qmaster
   export CA_PORT
fi


#---------------------------------------
# setup INFOTEXT begin
#---------------------------------------

V5BIN=$SGE_ROOT/bin/$ARCH
V5UTILBIN=$SGE_ROOT/utilbin/$ARCH
# INFOTXT_DUMMY is needed by message parsing script
# which is looking for $INFOTEXT and would report
# errors in the next command. Please use INFOTXT_DUMMY
# instead of using $INFOTEXT

INFOTXT_DUMMY=$V5UTILBIN/infotext
INFOTEXT=$INFOTXT_DUMMY
if [ ! -x $INFOTXT_DUMMY ]; then
   echo "can't find binary \"$INFOTXT_DUMMY\""
   echo "Installation failed."
   exit 1
fi
SGE_INFOTEXT_MAX_COLUMN=5000; export SGE_INFOTEXT_MAX_COLUMN

#---------------------------------------
# setup INFOTEXT end
#---------------------------------------

SetAdminUser

CATOP=$SGE_ROOT/$SGE_CELL/common/sgeCA
export CATOP

euid=`$V5UTILBIN/uidgid -euid`
if [ $euid = 0 ]; then
   CALOCALTOP=/var/sgeCA/$CA_PORT/$SGE_CELL
   rootinstalls=true
else
   CALOCALTOP=/tmp/sgeCA/$CA_PORT/$SGE_CELL
   rootinstalls=false
fi

ME=`whoami`
if [ "$ME" = "" ]; then
   $INFOTEXT "Can't determine your username with \"%s\" command. Exit" whoami
   $INFOTEXT -log "Can't determine your username with \"%s\" command. Exit" whoami
   MoveLog
   exit 1
fi

CAKEY=cakey.pem
CACERT=cacert.pem

CONFIG_DIR=$SGE_ROOT/util/sgeCA
OPENSSL=$V5UTILBIN/openssl

AUTO="false"
#-----------------------------
# CommandLine Argument Parsing
#
WHICH="undef"
newreq=newreq.pem
newcert=newcert.pem
user=""
outdir=.
indir=.
userfile=""
md="-md5"
nodes="-nodes"

ARGC=$#
while [ $ARGC != 0 ]; do
   case $1 in
   -auto)
      AUTO="true"
      . $2
      shift
      ARGC=`expr $ARGC - 1`
      ;;
   -init)
      WHICH="init"
      ;;
   -req)
      WHICH="req"
      ;;
   -sign)
      WHICH="sign"
      ;;
   -copy)
      WHICH="copy"
      ;;
   -verify)
      if [ $ARGC -lt 2 ]; then
         $INFOTEXT "Error: -verify needs argument"
         ErrUsage
      fi
      WHICH="verify"
      newcert=$2
      shift
      ARGC=`expr $ARGC - 1`
      ;;
   -print)
      if [ $ARGC -lt 2 ]; then
         $INFOTEXT "Error: -print needs argument"
         ErrUsage
      fi
      WHICH="print"
      newcert=$2
      shift
      ARGC=`expr $ARGC - 1`
      ;;
   -printkey)
      if [ $ARGC -lt 2 ]; then
         $INFOTEXT "Error: -printkey needs argument"
         ErrUsage
      fi
      WHICH="printkey"
      newcert=$2
      shift
      ARGC=`expr $ARGC - 1`
      ;;
   -days)
      if [ $ARGC -lt 2 ]; then
         $INFOTEXT "Error: -days needs argument"
         ErrUsage
      fi
      DAYS="-days $2"
      shift
      ARGC=`expr $ARGC - 1`
      ;;
   -outdir)
      if [ $ARGC -lt 2 ]; then
         $INFOTEXT "Error: -outdir needs argument"
         ErrUsage
      fi
      outdir="$2"
      shift
      ARGC=`expr $ARGC - 1`
      ;;
   -cadir)
      if [ $ARGC -lt 2 ]; then
         $INFOTEXT "Error: -cadir needs argument"
         ErrUsage
      fi
      CATOP="$2"
      CALOCALTOP="$2"
      shift
      ARGC=`expr $ARGC - 1`
      ;;
   -pkcs12)
      WHICH="pkcs12"
      if [ $ARGC -lt 2 ]; then
         $INFOTEXT "Error: -pkcs12 needs argument"
         ErrUsage
      fi
      userfile="$2"
      shift
      ARGC=`expr $ARGC - 1`
      ;;
   -sha1)
      md="-sha1"
      ;;
   -encryptkey)
      nodes=""
      ;;
   -usercert)
      WHICH="usercert"
      if [ $ARGC -lt 2 ]; then
         $INFOTEXT "Error: -usercert needs argument"
         ErrUsage
      fi
      userfile=$2
      shift
      ARGC=`expr $ARGC - 1`
      ;;
   -user)
      WHICH="oneuser"
      if [ $ARGC -lt 2 ]; then
         $INFOTEXT "Error: -user needs argument"
         ErrUsage
      fi
      user=$2
      shift
      ARGC=`expr $ARGC - 1`
      ;;
   -renew)
      if [ $ARGC -lt 2 ]; then
         $INFOTEXT "Error: -renew needs argument"
         ErrUsage
      fi
      WHICH="renew"
      user=$2
      shift
      ARGC=`expr $ARGC - 1`
      ;;
   -renew_sys)
      WHICH="renew_sys"
      ;;
   -renew_ca)
      WHICH="renew_ca"
      ;;
   -version)
      WHICH="version"
      ;;
   -dumpusers)
      WHICH="dumpusers"
      ;;
   *)
      $INFOTEXT "Error: Unknown option %s" "$1"
      ErrUsage
      ;;
   esac
   shift
   ARGC=`expr $ARGC - 1`
done

if [ "$WHICH" = "undef" ]; then
   ErrUsage
fi


REQ="$OPENSSL req $md $nodes"

CA="$OPENSSL ca -keyfile $CALOCALTOP/private/$CAKEY -cert $CATOP/$CACERT \
             -outdir $CATOP/newcerts"

VERIFY="$OPENSSL verify"

X509="$OPENSSL x509"
X509KEY="$OPENSSL rsa"

P12="$OPENSSL pkcs12"

case $WHICH in
init)
   InitCA  
   ;;
req)
    # create a certificate request
    $REQ -new -keyout $outdir/$newreq -out $outdir/$newreq $DAYS
    RET=$?
    if [ $RET = 0 ]; then
      $INFOTEXT "Request (and private key) is in %s" $outdir/$newreq
    else
      $INFOTEXT "No success"
    fi  
   ;;
sign) 
    $CA -policy policy_anything $DAYS $BATCHMODE -out $outdir/$newcert -infiles $indir/$newreq
    RET=$?
    if [ $RET = 0 ]; then
      $INFOTEXT "Signed certificate is in %s" $outdir/$newcert
    fi
    ;;
copy) 
    InstallKey user $ME
    ;;
usercert) 
    MakeUserCerts $userfile
    ;;
oneuser)
    MakeUserCert "$user"
    ;;
verify) 
    $VERIFY -CAfile $CATOP/$CACERT $newcert
    RET=$?
    ;;
print) 
    $X509 -in $newcert -text
    RET=$?
    ;;
printkey) 
    $X509KEY -in $newcert -text
    RET=$?
    ;;
renew) 
    RenewCert user $user
    RET=$?
    ;;
renew_sys) 
    RenewCert daemon $ADMINUSER
    RET=$?
    ;;
renew_ca) 
    RenewCA
    RET=$?
    ;;
pkcs12) 
    MakePKCS12 $userfile

    RET=$?
    ;;
version)
    echo "sge_ca 6.0u7"
    ;;
dumpusers)
    DumpUsers
    RET=$?
    ;;
help)
    ErrUsage
    ;;
esac

exit 0
