#!/bin/ksh -p
#
# ident "@(#)utconfig.ksh	1.191 09/08/20 SMI"
#
# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
# Use is subject to license terms.
#

#
# Solaris 10 Trusted Extension guard
#
ORIGIN=`/usr/bin/dirname $0`
UTIL_LIB=${ORIGIN:-/opt/SUNWut/lib}/../lib/support_lib/util_lib
. $UTIL_LIB
FailExecInLocalZoneOnTx 
#
# Solaris 10 Trusted Extension guard 
#

unset JAVA_HOME
unset CLASSPATH
PATH="/usr/sbin:/usr/bin:/sbin:/bin"
PROGRAM_ID=$(basename $0)
THIS_HOST=$(uname -n)

if [[ -d /var/adm/log ]] ; then
  LOG_DIR="/var/adm/log"
elif [[ -d /var/log/SUNWut ]] ; then
  LOG_DIR="/var/log/SUNWut"
else
  LOG_DIR="/var/log"
fi

LOGFILE="${LOG_DIR}/${PROGRAM_ID}.$(date '+%Y_%m_%d_%H:%M:%S').log"

# For Debug output uncomment the next 2 lines 
#PS4='[$LINENO]+ '
#set -x

# 
# See if G_MEDIA_DIR is already defined.
#
# Must be named G_MEDIA_DIR to match the install framework
# because sras_config depends on it and is also invoked
# from the M20SRAS install module.
#
if [[ -z $G_MEDIA_DIR ]] ; then

  # get the full pathname of the command
  typeset THIS_COMMAND=$(whence $0)

  # location of this package (ex. /opt/SUNWut, cdrom)
  typeset PRODUCT_DIR=${THIS_COMMAND%/*}
  PRODUCT_DIR=${PRODUCT_DIR:-`pwd`}/..


  # pathname of the install library directory
  G_MEDIA_DIR=${PRODUCT_DIR}/lib

fi # -z $G_MEDIA_DIR

ETC_OPT_UT="/etc/opt/SUNWut"
VAR_OPT_UT="/var/opt/SUNWut"
UT_SRDS_ETC="$ETC_OPT_UT/srds"
UT_SRWA_CONFIG="/opt/SUNWut/lib/support_lib/srwa_config"

PW_PID=
SUBST_PID=

TMP_DIR_PATH="${VAR_OPT_UT}/tmp"
TMP_PROGID=${TMP_DIR_PATH}/$PROGRAM_ID.$$
 
trap "rm -rf ${TMP_PROGID}.*; stty echo </dev/tty; CleanupPipeProcs ; exit 1" \
    HUP INT QUIT TERM

TMP_FILE="${TMP_PROGID}.tmp"
TMP_CONF_FILE="${TMP_PROGID}.conf"
TMP_INSERT_FILE="${TMP_PROGID}.insert"
TMP_REP_FILE="${TMP_PROGID}.rep"
TMP_PWPIPE="${TMP_PROGID}.pipe"
TMP_SUBST="${TMP_PROGID}.subst"

BEFORE="before.$PROGRAM_ID"
SMARTCARD_FILES_PATH="${ETC_OPT_UT}/smartcard"
AUTHPROPS="${ETC_OPT_UT}/auth.props"
UTADMIN_GROUP="utadmin"
ADMINGID=""


Usage() {
  print -u2 "Usage: $PROGRAM_ID $PROGRAM_OPTS"
  exit 1
}

CheckUidIsZero() {
  case "$(id)" in
    'uid=0('*) return 0;;  # uid is zero
    *)         Fatal "must be run as UID 0 (root)";;
  esac
}

CleanupAndExit() {
  rm -rf ${TMP_PROGID}.*
  exit $1
}

Fatal() {
  print -u2 "$PROGRAM_ID: fatal, $1"
  exit 1
}

Note() {
  print -u2 "$PROGRAM_ID: note, $1"
  return 0
}

#
# Helpers for FIFOs used to get sensitive content out of command lines
#

CleanupPipeProcs() {
  [ -n "$PW_PID" ] && kill "$PW_PID" 2> /dev/null
  [ -n "$SUBST_PID" ] && kill "$SUBST_PID" 2> /dev/null
}

CreatePipe() {
  mkfifo -m 600 "$1"
}

CreateSecureFile() {
	touch "$1"
	chmod 600 "$1"
}

DestroyPipe() {
  rm -f "$1"

  [ -n "$2" ] && kill $2 2>/dev/null
}

DestroySecureFile() {
	rm -f "$1"
}

CreatePWPipe_SunOS() {
  CreatePipe $TMP_PWPIPE || return 1
  
  # Must use $ROOTPW here instead of $(utpw -p),
  # as we temporarily change $ROOTPW during upgrade
  print -- "$ROOTPW" > $TMP_PWPIPE &
  PW_PID=$!
}

DestroyPWPipe_SunOS() {
  DestroyPipe "$TMP_PWPIPE" "$PW_PID"

  PW_PID=
}

CreatePWPipe_Linux() {
	CreateSecureFile "$TMP_PWPIPE" || return 1
	print -n -- "$ROOTPW" > "$TMP_PWPIPE"
}

DestroyPWPipe_Linux() {
	DestroySecureFile "$TMP_PWPIPE"
}

CreatePWPipe() {

    case "$OS" in # {
    SunOS)
      CreatePWPipe_SunOS
    ;;

    Linux)
      CreatePWPipe_Linux
    ;;

    *)
      Fatal "unknown OS name $OS"
    ;;

    esac # }
}

DestroyPWPipe() {

    case "$OS" in # {
    SunOS)
      DestroyPWPipe_SunOS
    ;;

    Linux)
      DestroyPWPipe_Linux
    ;;

    *)
      Fatal "unknown OS name $OS"
    ;;

    esac # }
}

#
# Platform dependencies set here
#
SetPlatformDependencies () {
  UT_BASEDIR="$(cd ${ETC_OPT_UT}/basedir; /bin/pwd)"
  #
  # !!!!!! Note: must use '/bin/pwd' in above, shell built-n does not
  # report the "real" directory path.

  # Define the command to start and stop the SRDS daemon
  #
  UTDSD_CMD=/etc/init.d/utds

  case "$OS" in # {
  SunOS)
    # Define Solaris specific LDAP variables
    #
    LCL_PACKAGE="SUNWlldap"

    # Define Linux versions of LDAP client commands
    #
    # XXX NOTE: Need to address Solaris beyond 9	<===
    #
    LDAPADD="/usr/bin/ldapadd"
    LDAPSEARCH="/usr/bin/ldapsearch -L"
    LDAPMODIFY="/usr/bin/ldapmodify"
    LDAP_PWOPT="-j"

    # Define Solaris specific filenames
    #
    ETCSERVICES="/etc/inet/services"
    DHCPCONFIG="/var/dhcp/dhcptab"
	;;

  Linux)
    # Define Linux specific LDAP variables
    # Determine which LDAP client package is installed
    #
    LCL_PACKAGE="$(rpm -qf /usr/bin/ldapadd 2>/dev/null)"

    # Define Linux versions of LDAP client commands
    #
    # openldap-clients default to SASL authentication but SRDS does not
    # support it.  Need to use -x to use the older simple authentication.
    #
    LDAPADD="/usr/bin/ldapadd -h ${THIS_HOST} -x"
    LDAPSEARCH="/usr/bin/ldapsearch -h ${THIS_HOST} -x -LLL"
    LDAPMODIFY="/usr/bin/ldapmodify -h ${THIS_HOST} -x"
    LDAP_PWOPT="-y"

    # Define Linux specific filenames
    #
    ETCSERVICES="/etc/services"
    DHCPCONFIG="/etc/dhcpd.conf"
    ;;

  *)
    Fatal "unknown OS name $OS"
    ;;
  esac # }
}

UTInstalled() {
  ${G_MEDIA_DIR}/utprodinfo -t installed SUNWuta
  return $?
}

LdapClientInstalled() {
  ${G_MEDIA_DIR}/utprodinfo -t installed $LCL_PACKAGE 2> /dev/null
  return $?
}

LdapClientInstallPartial() {
  ${G_MEDIA_DIR}/utprodinfo -t partial $LCL_PACKAGE
  return $?  
}

SRDSInstalled() {
  ${G_MEDIA_DIR}/utprodinfo -t installed $SRDS_PACKAGE
  return $?
}

SRDSInstallPartial() {
  ${G_MEDIA_DIR}/utprodinfo -t partial $SRDS_PACKAGE
  return $?  
}

SRDSVersion() {
  INSTALLED_VERSION="$(${G_MEDIA_DIR}/utprodinfo -p $SRDS_PACKAGE PRODVERS)"
  #
  # above var is global, used in calling func error msg

  case "$INSTALLED_VERSION" in
    $1) return 0;;
    *)  return 1;;
  esac
}

KioskInstalled() {
  ${G_MEDIA_DIR}/utprodinfo -t installed $UT_KIOSK_PACKAGE
  return $?
}

UTPasswordExists() {
   [[ -r ${ETC_OPT_UT}/utadmin.pw ]] && return 0 || return 1
}


SetUTFilePerms() {
  if [[ -z $1 ]]; then
    Fatal "configuration file parameter not specified"
  elif [[ ! -f $1 ]]; then
    Fatal "$1 is not a file"
  fi
  chmod 660 $1
  chgrp utadmin $1
}


PreviousUTDataStore() {

   if [[ -d ${VAR_OPT_LDAP_DBM_UT}/id2entry.dbb ||
		-f ${UT_SRDS_ETC}/current/utdsd.run ]]; then
       return 0	    
   else
       return 1
   fi
}

EncryptPasswd() {
  typeset STATUS=0

  if [[ $# != 1 ]] ; then
    print -u2 "EncryptPasswd() invoked without a password"
    return 1
  fi
  print -- "$1" | ${SRDS_BASEDIR}/srds/lib/utencode
  return $STATUS
}

PleaseTryAgain() {
  print -u2 "\nError: $1, please try again."
  return $?
}


SetPASSWD() {
  typeset STATUS=0
  typeset ERROR_CODE=0
  typeset ENTRY REPLY1 REPLY2

  while true; do
    case $ERROR_CODE in
      1) PleaseTryAgain "entries must be at least 5 characters in length";;
      2) PleaseTryAgain "entry contains invalid characters";;
      3) PleaseTryAgain "entries were not the same";;
    esac

    for ENTRY in "Enter" "Re-enter"; do
      print -n -- "$ENTRY $1 password: "
      stty -echo
      read -r
      stty echo
      print ""
      case "$ENTRY" in
        Enter) REPLY1="$REPLY";;
        *)     REPLY2="$REPLY";;
      esac
    done

    # use "utpw -V" to validate length and char set of entry
    #
    print -- "$REPLY1" |$UTA_BASEDIR/sbin/utpw -V
    case $? in
      0) ;; 
      1) ERROR_CODE=1; continue;;
      2) ERROR_CODE=2; continue;;
      *) print -n "Password validation, utpw failed with unknown exit status $?"; continue;;
    esac
    if [[ "$REPLY1" != "$REPLY2" ]]; then
      ERROR_CODE=3
      continue
    fi

    PASSWD="$REPLY1"
    break
  done

  return $STATUS
}

PromptForParameters() {
  typeset STATUS=0

  if $FORCE; then
    if [[ -z "$PASSWD" ]]; then
      Fatal "PASSWD file does not exist"
    elif [[ $(expr "$PASSWD" : '.*') -lt 5 ]]; then
      Fatal "PASSWD must be at least 5 characters in length"
    fi
  else
    fmt <<-!

	This script automates the configuration of the $UT_PROD_NAME
	and related software products.  Before proceeding, you
	should have read the $UT_PROD_NAME $UT_VERSION Installation
	Guide and filled out the Configuration Worksheet.  This script
	will prompt you for the values you filled out on the Worksheet.
	For your convenience, default values (where applicable) are
	shown in brackets. 
	!
    if [ -z "$utconfig_warning" ] ; then
      if ! ReplyIsYes "\nContinue"; then
        CleanupAndExit 0
      fi
    else
      print "\n$utconfig_warning"
      if ReplyIsNo "\nContinue"; then
        CleanupAndExit 0
      fi
    fi
  fi

  ROOTNAME="${ROOTENTRY#o=}"
  ROOTNAME="${ROOTNAME%%,*}"

  SKIP_SRDS=false

  if ! $FORCE ; then
     if PreviousUTDataStore; then
              SKIP_SRDS=true
     else
        SetPASSWD "Sun Ray admin"
     fi
  else
        SKIP_SRDS=true
  fi

  case "$PASSWD" in
    *\\*) UTPASSWD="$(print -- "$PASSWD" |sed 's:\\:\\\\:g')";; # escape backslashs
    *)    UTPASSWD="$PASSWD";;
  esac

  ROOTDN="cn=admin,$ROOTENTRY"

  ROOTPW="$PASSWD"
  CRYPTD_ROOTPW="$(EncryptPasswd "$ROOTPW")"

  if [[ $? != 0 ]]; then
    Fatal "internal error, could not encrypt password '$ROOTPW'"
  fi
  case "$CRYPTD_ROOTPW" in
    "") Fatal "internal error, encrypted password is empty";;
  esac

  if ! $FORCE; then
      # Possible return values from srwc_config:
      # 0 - Configure Tomcat
      # 1 - Do not configure Tomcat
      ${UT_SRWA_CONFIG} prompt -l "$LOGFILE"
      CONFIG_TOMCAT=$?
  fi
  
  if $DO_KIOSK_CONFIG ; then
    InitKioskVars

    if ! $FORCE; then
      if PromptForKioskConfig no ; then
	UT_KIOSK=yes
        PromptForKioskParameters
      elif KioskConfigured ; then
	UT_KIOSK=yes
      fi	  
    fi
  fi	# $DO_KIOSK_CONFIG

  return $STATUS
}

SubstituteMacros() {
  typeset PW
  typeset ret
  case $UTPASSWD in
    *\&*) # escape ampersands only for updating the datastore
	  PW="$(print -- "$UTPASSWD" |sed 's:\&:\\\&:g')";;
    *) PW="$UTPASSWD";;
  esac

  CreatePipe $TMP_SUBST || return 1

  # Must use print "..$SHELL_VAR..." (rather than utpw -p) to send 
  # passwords to FIFO, which is used to keep password off the command 
  # line, as this may be called before utadmin.pw exists and to handle 
  # CRYPTD_ROOTPW properly.
  print "
    s
@(ROOTENTRY)
$ROOTENTRY
g
    s
@(ROOTNAME)
$ROOTNAME
g
    s
@(HOSTNAME)
$HOSTNAME
g
    s
@(THIS_HOST)
$THIS_HOST
g
    s
@(LDAP_PORT)
$LDAP_PORT
g
    s
@(UTPASSWD)
$PW
g
    s
@(VERSIONENTRY)
$VERSIONENTRY
g
    s
,o=v[1-9][^,]*,
,o=v$VERSIONENTRY,
g
    s
@(ROOTDN)
$ROOTDN
g
    s
{sunds}NOTSET
$CRYPTD_ROOTPW
g
    s
@(HTTPCFGFILE)
$HTTPCFGFILE
g
    s
@(HTTPPORT)
$UT_PORT
g
    s
@(SSLENABLE)
$SSLENABLE
g
  " > $TMP_SUBST &
  SUBST_PID=$!

  sed -f $TMP_SUBST "$1"

  ret=$?

  DestroyPipe $TMP_SUBST $SUBST_PID
  SUBST_PID=

  return $ret
}

InsertFile(){
    grep '^# SUNWutrep begin' $1 >/dev/null 2>&1
    if [[ $? -eq 0 ]]; then
	# Replication block exists, insert before SUNWutrep block
	ed - $1 <<-EOE 2>/dev/null 1>&2
	/^# SUNWutrep begin/
	-
	.r $2
	w
	q
	EOE
    else
	# Replication block not defined, append at the end of the file
	cat $2 >> $1
    fi
}

#
#  Restores SRDS configuration files from the default directory:
#	/etc/opt/SUNWut/srds/default
#
RestoreSRDSConf() {
    for confile in utdsd.acl.conf utdsd.at.conf utdsd.conf utdsd.oc.conf utdsd.ini
    do
	if [[ ! -f ${SRDS_LDAP_CURRENT}/${confile} ]]; then
    	    cp ${SRDS_LDAP_DEFAULT}/${confile} ${SRDS_LDAP_CURRENT}/${confile}
	fi
    done
    LDAP_PORT=$(get_ldap_port)
}

#
#  Sync up the SRDS port number in the /etc/inet/services file
#
SyncEtcServices() {
    grep "^utdsd[ 	][ 	]*${LDAP_PORT}/" ${ETCSERVICES} >/dev/null 2>&1
    if [[ $? -ne 0 ]]; then
    	TMP_SERVICES_FILE="${TMP_DIR_PATH}/services.SUNWut.prototype"
	# need to update the SRDS port number
	sed -e "s/^\(utdsd[	 ][	 ]*\)[0-9][0-9]*\(\/.*\)$/\1${LDAP_PORT}\2/" \
		${UTO_BASEDIR}/lib/prototype/services.SUNWut.prototype \
		> $TMP_SERVICES_FILE
	${UTO_BASEDIR}/lib/utrepair -a -d ${TMP_DIR_PATH} ${ETCSERVICES}
	rm $TMP_SERVICES_FILE 2> /dev/null
    fi
}

AppendAndCopySchema() {
  typeset STATUS=0
  typeset CONF_FILE="$SRDS_LDAP_CURRENT/$1"

  CreateBeforeFile $CONF_FILE

  DeleteUTEntry $CONF_FILE >$TMP_CONF_FILE

  # append Sun Ray entry on tmp file
  #
  cat $UT_TEMPLATE_LDAP/$1 >>$TMP_CONF_FILE

  ReplaceFile $CONF_FILE $TMP_CONF_FILE

  cp $UT_TEMPLATE_LDAP/$2 $SRDS_LDAP_CURRENT/$2
  
  return $STATUS
}

UnappendAndRmSchema() {
  typeset STATUS=0
  typeset CONF_FILE="$SRDS_LDAP_CURRENT/$1"

  DeleteUTEntry $CONF_FILE >$TMP_CONF_FILE

  ReplaceFile $CONF_FILE $TMP_CONF_FILE

  rm -f $SRDS_LDAP_CURRENT/$2

  DestroyBeforeFile $CONF_FILE
  
  return $STATUS
}

UpdateSchema() {
  typeset STATUS=0

  print "\nUpdating $SRDS_PN schema ..."

  AppendAndCopySchema utdsd.oc.conf utdsd.oc.ut.conf
  AppendAndCopySchema utdsd.at.conf utdsd.at.ut.conf

  return $STATUS
}

DowndateSchema() {
  typeset STATUS=0

  print "\nRemoving Sun Ray related portions of $SRDS_PN schema ..."

  UnappendAndRmSchema utdsd.oc.conf utdsd.oc.ut.conf
  UnappendAndRmSchema utdsd.at.conf utdsd.at.ut.conf

  return $STATUS
}

UpdateAcls() {
  typeset STATUS=0
  typeset CONF_FILE="$SRDS_LDAP_CURRENT/utdsd.acl.conf"

  print "\nUpdating $SRDS_PN ACL's ..."

  CreateBeforeFile $CONF_FILE

  DeleteUTEntry $CONF_FILE >$TMP_CONF_FILE

  sed '/^access /,$d' $TMP_CONF_FILE >$TMP_INSERT_FILE
  #
  # delete from the first "access" line to the last line

  SubstituteMacros $UT_TEMPLATE_LDAP/utdsd.acl.conf >>$TMP_INSERT_FILE

  sed -n '/^access /,$p' $TMP_CONF_FILE >>$TMP_INSERT_FILE
  #
  # only print from the first "access" line to the last line

  ReplaceFile $CONF_FILE $TMP_INSERT_FILE
  
  return $STATUS
}

DowndateAcls() {
  typeset STATUS=0
  typeset CONF_FILE="$SRDS_LDAP_CURRENT/utdsd.acl.conf"

  if ! $FORCE ; then
     print "\nRemoving Sun Ray related portions of $SRDS_PN ACL's ..."
  fi

  DeleteUTEntry $CONF_FILE >$TMP_CONF_FILE
  ReplaceFile $CONF_FILE $TMP_CONF_FILE
  DestroyBeforeFile $CONF_FILE
  
  return $STATUS
}

CreateDatastoreConfig() {
  typeset STATUS=0

  print "\nCreating $SRDS_PN ..."

  CreateBeforeFile $DS_CONF_FILE

  DeleteUTEntry $DS_CONF_FILE >$TMP_CONF_FILE
  SubstituteMacros $UT_TEMPLATE_LDAP/utdsd.conf >${TMP_CONF_FILE}_1

  InsertFile $TMP_CONF_FILE ${TMP_CONF_FILE}_1
  /bin/rm -f ${TMP_CONF_FILE}_1 2>/dev/null 1>&2
  ReplaceFile $DS_CONF_FILE $TMP_CONF_FILE
  SetUTFilePerms $DS_CONF_FILE

  mkdir -p $VAR_OPT_LDAP_DBM_UT

#
# when configuring SRDS during the upgrade, make sure that replog file
# are more recent than the configuration file (utdsd.conf). Otherwise,
# this file will be deleted when restarting SundDS services.
  if [[ $SRDS_UPGRADE_FLAG = "YES" && \
        -s ${VAR_OPT_LDAP_REPLOG}/utpushd.replog ]]; then
     touch ${VAR_OPT_LDAP_REPLOG}/utpushd.replog
  fi
  
  return $STATUS
}

DestroyDatastoreConfig() {
  typeset STATUS=0

  if ! $FORCE ; then
     print "\nRemoving $SRDS_PN ..."
  fi

  DeleteUTEntry $DS_CONF_FILE >$TMP_CONF_FILE

  ReplaceFile $DS_CONF_FILE $TMP_CONF_FILE
  chmod 660 $DS_CONF_FILE

  DestroyBeforeFile $DS_CONF_FILE
  
  return $STATUS
}

RestartSRDS() {
  typeset STATUS=0

  print "\nRestarting $SRDS_PN ..."

  ${UTDSD_CMD} stop
  ${UTDSD_CMD} start
  
  return $STATUS
}


# remove "Corona" name from the utmodel attribute
CoronaNameChange()
{
	SUBTREE="utname=desktops,utname=${HOSTNAME},o=v1,${ROOTENTRY}"
	${LDAPSEARCH} -p $LDAP_PORT -b "$SUBTREE" "utmodel=corona*" dn | grep -i '^dn:' | while read dn
	do
		if [ -z $dn ]
		then
			continue
		fi

		CreatePWPipe || 
			Fatal "Cannot create pipe $TMP_PWPIPE for required LDAP modifications"

		${LDAPMODIFY} -p $LDAP_PORT -D "$ROOTDN" \
				$LDAP_PWOPT $TMP_PWPIPE <<-! 2>/dev/null 1>&2
		dn: $dn
		changetype: modify
		delete: utmodel

		!

		DestroyPWPipe
	done
}

CheckPolicyString()
{

	POLICYSTR=$($UTGLPOLICY \
	    | sed -n 's,^${UTO_BASEDIR}/sbin/utpolicy,,p' \
	    2>/dev/null)
	if [ ! -z $POLICYSTR ]
	then
		$UTGLPOLICY $POLICYSTR > /dev/null 2>&1
	fi
}

FixKioskPolicy()
{
  if $KIOSK_INSTALLED && KioskConfigured ; then
    # Nothing to do
    return 0
  fi
    
  # Determine current auth policy settings
  typeset curr_policy=$(${UTO_BASEDIR}/sbin/utpolicy 2>/dev/null | 
      			awk '/^#/ {next} {print}')

  # Determine if kiosk is enabled.
  if [[ -z "$(echo x $curr_policy | grep ' -k')" ]] ; then
    # Nothing to do
    return 0
  fi

  # Found kiosk unconfigured, but kiosk policy active
  print "\nDisabling previous kiosk policy"
  typeset target_policy=$(echo $curr_policy | sed 's/ *-k *[^ ]*//g' )

  eval "${UTO_BASEDIR}/sbin/utpolicy $target_policy >/dev/null 2>&1"
}

LoadDatastore()
{

  typeset STATUS=0
  typeset -i newLdapEntries=0
  typeset S="${LDAPADD} -p $LDAP_PORT -D $ROOTDN"

  TMP_MODS_FILE="${VAR_OPT_UT}/tmp/ldap.mods.tmp"

  # Break up ldap.mods into chunks and search before adding
  # each defined LDAP base entry.

  if ! $FORCE ; then
     print "\nLoading $SRDS_PN ..."
     print "\nExecuting '$S' ..."
  fi

  while read ldifLine
  do
     ENTRY_EXISTS=""
     if [[ -z $ldifLine && -f $TMP_MODS_FILE ]]
     then
	 # Pull out the DN value for each base entry

         DN_VALUE=$(SubstituteMacros $TMP_MODS_FILE |\
         awk ' $1 ~ /dn:/ { print $2}' | sed -e 's/ 	//g' )

	 if [[ -z $DN_VALUE ]]; then
	    rm -f $TMP_MODS_FILE
	    continue
         fi

	 # Search for existing base entry
         ENTRY_EXISTS=$(${LDAPSEARCH} -p $LDAP_PORT \
                         -b $DN_VALUE -s base 'objectclass=*' 2>/dev/null) 

	 if [[ -z $ENTRY_EXISTS ]]; then
            SubstituteMacros $TMP_MODS_FILE |
            { 
	    	CreatePWPipe &&
		    ${LDAPADD} -p $LDAP_PORT -D "$ROOTDN" $LDAP_PWOPT $TMP_PWPIPE 
		DestroyPWPipe
	    }
            (( newLdapEntries +=1 ))
	 else
	     rm -f $TMP_MODS_FILE
	     continue
	 fi

	 rm -f $TMP_MODS_FILE
     else
         echo $ldifLine >> $TMP_MODS_FILE
     fi

  done < $MODS_FILE

  if [[ $newLdapEntries -gt 0 ]]; then
    print "\nAdded $newLdapEntries new LDAP entries." 
  fi

  return $STATUS
}


UnloadDatastore() {
  typeset STATUS=0

  print "\nUnloading $SRDS_PN ..."

  rm -rf $VAR_OPT_LDAP_DBM_UT
  
  return $STATUS
}


ConfigUtadmin() {
  typeset STATUS=0
  typeset CONF_FILE="utadmin.conf"
  typeset PW_FILE="utadmin.pw"
  typeset FILE MODE

  print "\nCreating $UT_PROD_NAME Configuration ..."

  for FILE in $CONF_FILE $PW_FILE; do
    case "$FILE" in
      $PW_FILE) 
		if ! $SKIP_SRDS ; then
		   print -- "$UTPASSWD" | $UTA_BASEDIR/sbin/utpw -f >/dev/null 2>&1
		fi  ;;
      *)        SubstituteMacros $ETC_OPT_UT/$FILE.template >$ETC_OPT_UT/$FILE;;
    esac

    case "$FILE" in
      $PW_FILE) chown root:$UTADMIN_GROUP $ETC_OPT_UT/$FILE;;
      *) chown root:sys $ETC_OPT_UT/$FILE;;
    esac

    case "$FILE" in
      $PW_FILE) MODE="660";;
      *)        MODE="644";;
    esac
    chmod $MODE $ETC_OPT_UT/$FILE
  done

  return $STATUS
}

UnconfigUtadmin() {
  typeset STATUS=0
  typeset CONF_FILE="utadmin.conf"
  typeset PW_FILE="utadmin.pw"

  if [[ -f $ETC_OPT_UT/$CONF_FILE || -f $ETC_OPT_UT/$PW_FILE ]]; then
     UNCONFIG_DONE=true
     print "\nRemoving $UT_PROD_NAME Configuration files ..."
  fi

  # remove anyway
  rm -f $ETC_OPT_UT/$CONF_FILE $ETC_OPT_UT/$PW_FILE

  return $STATUS
}

ConfigSRDS() {
  typeset STATUS=0

  RestoreSRDSConf
  UpdateSchema
  UpdateAcls

  CreateDatastoreConfig
  touch ${UT_SRDS_ETC}/current/utdsd.run
  SyncEtcServices

  RestartSRDS

  LoadDatastore

  return $STATUS
}


UnconfigSRDSConf() {

  DestroyDatastoreConfig
  DowndateAcls
  DowndateSchema
}


UnconfigSRDS() {
  typeset STATUS=0

  ${UTDSD_CMD} stop

  UnloadDatastore
  UnconfigSRDSConf
  /bin/rm ${UT_SRDS_ETC}/current/utdsd.run 2> /dev/null

  ${UTDSD_CMD} start

  return $STATUS
}

# Import XConfig preferences from flat-file legacy config files into LDAP 

ImportUTPrefs() {

   UT_PREF_DIR=${VAR_OPT_UT}/preferences
   typeset STATUS=0
   if [[ ! -d $UT_PREF_DIR ]]; then
	return
   fi

   PREF=$(find $UT_PREF_DIR ! -name "DEFAULT" -a -type f -print)

   # For each preference file build up the utxconfig command
   # invocation to import the preferences into LDAP

   print "Importing XConfig settings into LDAP"

   for cfg in $PREF
   do
      tokenID=$(basename $cfg)
      dirpath=$(dirname $cfg)
      tokenType=$(basename $dirpath)
      importPrefCmd="${UTO_BASEDIR}/bin/utxconfig -t \
	${tokenType}.${tokenID} -c ${cfg}"

      eval $importPrefCmd

      if [[ $? -ne 0 ]]; then
         STATUS=1 
      fi
   done

   # Handle the special case, DEFAULT file

   if [[ -f ${UT_PREF_DIR}/DEFAULT ]]; then
      ${UTO_BASEDIR}/bin/utxconfig -a -c ${UT_PREF_DIR}/DEFAULT
      if [[ $? -ne 0 ]]; then
         STATUS=1 
      fi
   fi

   # Summary report on any utxconfig failures encountered.
   if [[ $STATUS -ne 0 ]]; then
      print "Some problems encountered while attempting to add utxconfig preferences into LDAP"
   fi
}

RemoveOldBackupFiles() {

  # Remove backup files generated during running of utconfig.

  GMSIGFILEPATH=`eval get_current_gmSignaturefile`

  [[ -f ${GMSIGFILEPATH}.bak ]] && rm -f ${GMSIGFILEPATH}.bak
  [[ -f "$AUTHPROPS.bak" ]] && rm -f $AUTHPROPS.bak
}

ConfigDbm() {
	$UTDBINIT -c `$UTADMINGID`
}

ConfigLog() {

  # Configure admin log. New with Sun Ray 1.1 

  typeset TMPFILE_LOG=${TMP_FILE}.log

  ${SUNWUTLIB}/utlog -a \
	-s all -f local1.info -d ${VAR_OPT_UT}/log/admin_log -z;

  if [[ $? -ne 0 ]]; then
	print "Problem encountered while attempting to enable admin syslog."
	return 1
  fi

  # Update log rotation task.
  case "$OS" in
    SunOS)      # Update Solaris cron entries

		(
		   crontab -l root 2>/dev/null 
		   print "33 3 * * * $SUNWUTLIB/utlog -c -d ${VAR_OPT_UT}/log/admin_log 2>/dev/null 1>/dev/null";
		) > $TMPFILE_LOG

		crontab $TMPFILE_LOG
		rm -f $TMPFILE_LOG 2>/dev/null;
		;;      # end case SunOS

   Linux)	# Add Linux cron file in /etc/cron.d
		typeset CRONFILE_LOG="/etc/cron.d/SUNWut.cron"
		(
		   grep -v admin_log ${CRONFILE_LOG} 2>/dev/null
		   print "33 3 * * * root $SUNWUTLIB/utlog -c -d ${VAR_OPT_UT}/log/admin_log 2>/dev/null 1>/dev/null"
		) > $TMPFILE_LOG

		rm $CRONFILE_LOG 2>/dev/null
		cp $TMPFILE_LOG $CRONFILE_LOG
		rm -f $TMPFILE_LOG 2>/dev/null;

		;;      # end case Linux

    *)          # Unknown OS
		Note "unknown OS name $OS, cron for utlog not added"
  esac

}

UnconfigGroup() {
  GMSIGFILEPATH=`eval get_current_gmSignaturefile`

  if [[ -s $GMSIGFILEPATH ]]; then
	UNCONFIG_DONE=true
	print "\nRemoving the group signature ..."
  fi

  # reset anyway
  rm -f $GMSIGFILEPATH
  touch $GMSIGFILEPATH
  chmod 600 $GMSIGFILEPATH

} 

UnconfigDbm() {
	$UTDBINIT -d
}

ConfigSmartCard() {

  if [[ -d $SMARTCARD_FILES_PATH ]]; then
      chgrp $UTADMIN_GROUP $SMARTCARD_FILES_PATH
  else
      Note "Smartcard config file directory doesn't exist"
  fi

  if [[ -f $SMARTCARD_FILES_PATH/probe_order.conf ]]; then
     chgrp $UTADMIN_GROUP $SMARTCARD_FILES_PATH/probe_order.conf
     chmod g+w $SMARTCARD_FILES_PATH/probe_order.conf
  else
      Note "Smartcard config probe order configuration file doesn't exist"
  fi
}

ConfigGroup() {
  if [[ "$UT_GROUP" == "yes" ]]; then
	# all group members must have the same signature 
        groupsig_MSG
        $UTO_BASEDIR/sbin/utgroupsig
  else
	# group of one needs a unique signature
	generate_groupsig
  fi  
}

# setPerms <logfile-basename> <perms> <gid>
#
setPerms () {

  if [[ -f $1 ]]; then
      chgrp $3 $1
      chmod $2 $1
      if ls $1.? >/dev/null 2>/dev/null ; then
          chgrp $3 $1.?
          chmod $2 $1.?
      fi
  fi
}

# Set permissions/group for all log files
chgPermsLogFiles () {

  # If syslog-ng is present on this platform then force a reconfiguration 
  # in order to make the syslog-ng daemon aware of the new logfile ownership.
  #
  if [ -x $UTO_BASEDIR/lib/utctl.d/features/utsyslog-ngctl ] ; then
    $UTO_BASEDIR/lib/utctl disable syslog-ng
    sleep 4 # give the daemon a chance to recover from being HUP'ed
    $UTO_BASEDIR/lib/utctl enable syslog-ng
  fi

  ADMINGID=`$UTADMINGID`

  setPerms ${VAR_OPT_UT}/log/admin_log $1 $ADMINGID
	
  setPerms ${VAR_OPT_UT}/log/messages $1 $ADMINGID

  setPerms ${VAR_OPT_UT}/log/auth_log $1 $ADMINGID

  setPerms ${VAR_OPT_UT}/log/utmountd.log $1 $ADMINGID

  setPerms ${VAR_OPT_UT}/log/utstoraged.log $1 $ADMINGID

}
# XXX REview the SWS bits that might be necessary for 
# non-upgrade auto configure.
DoAutoConfig() {
  FORCE=true

  # Extract password
  UTPasswordExists && PASSWD="$($UTA_BASEDIR/sbin/utpw -p)"

  CreateUTTempDir

  PromptForParameters 

  # Normally done as part of SRAS config.
  # However it may be needed in SunDs silent config.
  ConfigUtadmin

  if [[ ! -f "${VAR_OPT_UT}/log/admin_log" && -f ${DHCPCONFIG} ]]; then
       ConfigLog
  fi
 
  # This section of code applies to administration upgrade.
  # Preserve existing password before unlocking datastore with temporary pw

  # Set upgrade flag
  SRDS_UPGRADE_FLAG="YES"

  SAVED_CRYPTDPW=$(awk '/^# SUNWut begin/ {found=1}\
     found==1 && $1=="rootpw" {print $2}' $DS_CONF_FILE)
  
  # A temporary password is required to gain privilege to
  # unlock datastore during upgrade.
  ROOTPW="UpgradePW"
  CRYPTD_ROOTPW="$(EncryptPasswd "$ROOTPW")"


  # Strip away 'ut' specific SRDS configuration
  UnconfigSRDSConf 
  # Configure the schema + LDAP base entries
  ConfigSRDS
  ConfigDbm
  # check for utpolicy string in the LDAP policystring attribute.
  # This is added to fix a 1.1 bug which is carried forward during
  # the upgrade.
  CheckPolicyString
  CoronaNameChange

  # shutdown SRDS for the remaining operations
  ${UTDSD_CMD} stop

  # Re-index the utgroupid and utgrouptype attributes.
  # This is needed because these 2 attributes were mis-indexed in 1.x.
  # We only re-index if the database files for both utgroupid and
  # utgrouptype do not exist.
  if [ ! -f ${VAR_OPT_LDAP_DBM_UT}/utgroupid.dbb -o \
	! -f ${VAR_OPT_LDAP_DBM_UT}/utgrouptype.dbb ]; then
     ${SRDS_BASEDIR}/srds/lib/utidxgen -a utGroupId utGroupType
  fi

  # To revert to orginal rootPW we need to reconfigure utdsd.conf

  CRYPTD_ROOTPW="$SAVED_CRYPTDPW"
  DestroyDatastoreConfig

  CreateDatastoreConfig

  ConfigSmartCard

  if [[ ! -s "${ETC_OPT_UT}/gmSignature" ]]; then
    UT_GROUP=no
    ConfigGroup
  fi

  ${UTDSD_CMD} start

  ImportUTPrefs

  # For now, we only configure the PAM to use DS authentication.  We need
  # to add Sun Ray administrator "admin" user for backward compatibility.
  # We first check if authorized user list exists.  If it exists, this means
  # we are ugprading from a server already supporting the authorized list and
  # no need to update the list.  Otherwise, we add the Sun Ray administrator
  # "admin" to the authroized user list.
  ADMIN_LIST=`${UTO_BASEDIR}/sbin/utadminuser`
  if [ -z "$ADMIN_LIST" ]; then
     ${UTO_BASEDIR}/sbin/utadminuser -a admin
  fi

  if [[ ! -f "${VAR_OPT_UT}/log/messages" ]]; then
	touch ${VAR_OPT_UT}/log/messages
  fi

  if [[ ! -f "${VAR_OPT_UT}/log/admin_log" ]]; then
	touch ${VAR_OPT_UT}/log/admin_log
  fi

  # Set permission to 640 and group to utadmin
  chgPermsLogFiles 640

  # end of the upgrade, reset the flag.
  SRDS_UPGRADE_FLAG="NO"

  return 0
}

DoKioskConfig() {
  if $KIOSK_INSTALLED ; then
    if [[ -f $UTCONF_FILE ]]; then
      print "\nConfiguration of Sun Ray Kiosk Mode Software"
      InitKioskVars

      if  $FORCE; then
	ForceKioskDefaults

      elif PromptForKioskConfig yes ; then
	PromptForKioskParameters
    
	print "About to configure Sun Ray Kiosk Mode:"
	ShowNewKioskConfig			       

	if ! ReplyIsYes_ "\nContinue"; then
	  CleanupAndExit 0
	fi
      fi

      ConfigKiosk
      FixKioskPolicy

      print "\nConfiguration of Sun Ray Kiosk Mode has completed."
      print "Please check the log file $LOGFILE for errors."
    else	# -f $UTCONF_FILE
      print "\nSun Ray Kiosk Mode Software requires a configured SRSS."
      print "Run '$PROGRAM_ID' once before you run '$PROGRAM_ID -k'."
    fi	# -f $UTCONF_FILE
  else	# $KIOSK_INSTALLED
    print "\nSun Ray Kiosk Mode Software is not installed."  
  fi	# $KIOSK_INSTALLED
}

DoWebConfig() {
  if [[ -f $UTCONF_FILE ]]; then
    ${UT_SRWA_CONFIG} prompt -l "$LOGFILE"
    CONFIG_TOMCAT=$?
    if [[ $CONFIG_TOMCAT -eq 0 ]]; then
      print ""
      ${UT_SRWA_CONFIG} info 
      ${UT_SRWA_CONFIG} display
      ${UT_SRWA_CONFIG} update
      print "\nConfiguration of the Sun Ray Web Administration component has completed."
      print "Please check the log file $LOGFILE for errors."
    fi
  else
    print "The web administration requires a configured SRSS."
    print "Run 'utconfig' once before you run 'utconfig -w'."
  fi
}

DoConfig() {
  typeset STATUS=0
  UT_KIOSK=no

  if grep '^pu.._replica' $DS_CONF_FILE >/dev/null 2>&1 || [ -f $UTCONF_FILE ]
  then
    utconfig_warning="WARNING: Sun Ray Datastore is enabled. This script may clobber the current configuration.\n"
  fi

  print "\nConfiguration of $UT_PROD_NAME"

  CreateUTTempDir

  PromptForParameters

  if ReplyIsNo "\nConfigure this server for a failover group?"; then
    UT_GROUP=no
  else
    UT_GROUP=yes
  fi

  print "\nAbout to configure the following software products:"

  cat <<-!

	$SRDS_PN $SRDS_RN
	    Hostname: $THIS_HOST
	    $UT_ROOT_S entry: $ROOTENTRY
	    $UT_ROOT_S name: $ROOTNAME
	    Sun Ray $ROOTNAME admin password: (not shown)
	    $SRDS_ROOTDN_S: $ROOTDN
	!
  
  if ! $FORCE; then
    if [[ $CONFIG_TOMCAT -eq 0 ]]; then
      print ""
      ${UT_SRWA_CONFIG} info 
      ${UT_SRWA_CONFIG} display
    fi
  fi
  
  print "\n$UT_PROD_NAME $UT_VERSION"
  print "    Failover group: $UT_GROUP"
  if $DO_KIOSK_CONFIG ; then
    print -- "    Sun Ray Kiosk Mode: $UT_KIOSK"

    ShowNewKioskConfig			       
  fi	# $DO_KIOSK_CONFIG

  if ! $FORCE && ! ReplyIsYes "\nContinue"; then
    CleanupAndExit 0
  fi

  if ! $SKIP_SRDS ; then
     RestoreSRDSConf
     ConfigSRDS
  fi

  ConfigUtadmin

  ADD_AUTHUSER=false
  if ! $FORCE; then
    
    # mark it so that we will add the admin user after starting the SRDS
    ADD_AUTHUSER=true

  fi

  if ! $FORCE; then
    if [[ $CONFIG_TOMCAT -eq 0 ]]; then
	  ${UT_SRWA_CONFIG} update
    fi
  fi
  
  ConfigDbm
  ConfigSmartCard

  ConfigGroup

  RestartSRDS
  if ${ADDAUTHUSER}; then
     # For now, we only configure the PAM to use DS authentication.  We need
     # to add Sun Ray administrator "admin" user for backward compatibility.
     ${UTO_BASEDIR}/sbin/utadminuser -a admin
  fi

  if [[ $SSL_ENABLE_S == Enabled ]]; then
    ssl_enabled_MSG
  fi

  if $DO_KIOSK_CONFIG ; then
    ConfigKiosk
  fi	# $DO_KIOSK_CONFIG
  FixKioskPolicy  

  # Determine current auth policy settings
  CURR_POLICY=$(${UTO_BASEDIR}/sbin/utpolicy | awk '/^#/ {next} {print}')
 
  # Determine if failover group enabled.
  GROUP_POLICY_SET=$(echo $CURR_POLICY | grep "\-g")

  if [[ "$UT_GROUP" == "yes" && -z $GROUP_POLICY_SET ]] ;then
    eval "${UTO_BASEDIR}/sbin/utpolicy $CURR_POLICY -g >/dev/null 2>&1"
  else 
    eval "${UTO_BASEDIR}/sbin/utpolicy $CURR_POLICY >/dev/null 2>&1"
  fi

  POLICY=$(${UTO_BASEDIR}/sbin/utpolicy | awk '/^#/ {next} {print}')

  ${UTO_BASEDIR}/lib/utgenpolicy $POLICY >/dev/null 2>&1

  # Set permissionto 640 and group to utadmin
  chgPermsLogFiles 640

  utpolicy_MSG

  print "\nConfiguration of $UT_PROD_NAME has completed.  Please check"
  print "the log file, $LOGFILE, for errors."
  
  return $STATUS
}

DoKioskUnconfig() {
  if $KIOSK_INSTALLED ; then
    if ! $FORCE ; then
      print "\nAbout to unconfigure Sun Ray Kiosk Mode."

      if ! ReplyIsYes_ "\nContinue"; then
	CleanupAndExit 0
      fi 		  
    fi 		  
    UNCONFIG_DONE=false
    UnconfigKiosk
    FixKioskPolicy
    if $UNCONFIG_DONE ; then
      print "\nUnconfiguration of Sun Ray Kiosk Mode has completed."
      print "Please check the log file $LOGFILE for errors."
    else
      print "\nSun Ray Kiosk Mode is already unconfigured."
    fi
  else
    print "\nSun Ray Kiosk Mode Software is not installed."  
  fi    
}

DoWebUnconfig() {
  ${UT_SRWA_CONFIG} unconfig
  print "\nUnconfiguration of the Sun Ray Web Administration component has completed."
  print "Please check the log file $LOGFILE for errors."
}

DoUnconfig() {
  typeset STATUS=0

  UNCONFIG_DONE=false

  print "\nUnconfiguration of $UT_PROD_NAME"

  if grep '^pu.._replica' $DS_CONF_FILE >/dev/null 2>&1
  then      
    Fatal "Sun Ray Datastore is enabled. You must firstly disable using utreplica -u"
  fi

  print "\nAbout to unconfigure the Sun Ray server."

  if ! $FORCE && ! ReplyIsYes "Continue"; then
    CleanupAndExit 0
  fi

  print "\nChecking $UT_PROD_NAME configuration ..."

  UnconfigGroup

  $UTO_BASEDIR/lib/utgenpolicy -a -g -z both -t clear > /dev/null 2>&1 

  UnconfigDbm
  UnconfigUtadmin

  ${UT_SRWA_CONFIG} unconfig

  ${UTO_BASEDIR}/sbin/utadminuser -r >/dev/null 2>&1

  # check to see if we need to unconfigure the datastore
  if PreviousUTDataStore; then
      UNCONFIG_DONE=true
      UnconfigSRDS
  fi

  RemoveOldBackupFiles

  if $DO_KIOSK_CONFIG ; then
    UnconfigKiosk
  fi

  # Set permissionto 600 and group to other
  chgPermsLogFiles 600

  if $UNCONFIG_DONE; then
     utpolicy_MSG
     print "\nUnconfiguration of $UT_PROD_NAME has completed."
  else
     print "\nThe server is already unconfigured."
  fi
  print "Please check the log file, $LOGFILE, for errors."
  
  return $STATUS
}


get_current_gmSignaturefile(){
	typeset gmSignatureFile=""
	gmSignatureFile=$(sed -n '
		s/^[ 	]*//
		s/[ 	]*$//
		s/#.*$//
		s/[ 	][ 	]*=[ 	][ 	]*/=/
		s/^gmSignatureFile=\(.*\)$/\1/p
		' $AUTHPROPS)
	# a reasonable default just in case	
	print -- ${gmSignatureFile:-"$ETC_OPT_UT/gmSignature"}
}


function generate_groupsig {
	typeset GMSIGFILEPATH=""
	typeset UMASK_ORIG=$(umask)
	# set umask to create with correct permissions
	umask $UMASK_ROOT

	GMSIGFILEPATH=`eval get_current_gmSignaturefile`
	
	# We're going to create a unique new gmSignature
	# save it if there is one there already
	if [[ -s ${GMSIGFILEPATH:-} ]]; then
	   mv $GMSIGFILEPATH $GMSIGFILEPATH.bak
	   print "\nSaving $GMSIGFILEPATH to $GMSIGFILEPATH.bak"
	fi
	
	# Give the signature a unique human-readable preamble.  Note that
	# because the preamble's format is well-known, this string can't be
	# the entirety of the signature.  It would be easily guessable.  The
	# time of creation can be seen from the signature file's metadata and
	# would be easy to infer from other files even if we protected the
	# signature file itself from being stat'ed.  We rely on the random
	# data appended below to make the signature robust against guessers.
	#
	DATESTAMP=$(date -u +'%Y''%m''%d'T'%H''%M''%S'Z)
	print -n "autogenerated $DATESTAMP $THIS_HOST $(hostid) " > $GMSIGFILEPATH 

	# make doubly sure that ownership and perms are correct.  Note that our
	# umask is already safe, so nobody can squeeze in before the 'chmod'.
	#
	chown root:root $GMSIGFILEPATH
	chmod 400 $GMSIGFILEPATH

	# use random data to generate a truly hard-to-guess signature 
	RANDSOURCE=""
	for RANDOMDEV in /dev/random /dev/urandom ; do
	    if [[ -c "$RANDOMDEV" ]] || [[ -s $RANDOMDEV ]]; then
		RANDSOURCE="$RANDOMDEV"
		break
	    fi
	done

	if [[ -n "$RANDSOURCE" ]] ; then
	    dd if="$RANDSOURCE" bs=1k count=1 >> $GMSIGFILEPATH 2> /dev/null
	else
	    # we didn't find a device that produces randomness, so rely on
	    # ksh's built-in generator.
	    
	    # Seed the generator with a value derived from a bunch of transient
	    # data, to make it hard for anyone to try to replicate the generated
	    # values.  (A 'read' would have been a more natural way to capture
	    # the two-item result of the 'cksum', but 'read' from a piped stdin
	    # seems to be broken in 'pdksh' so instead we capture the result into
	    # an array.  This means that no change is required if we decide to
	    # backport to a Linux release that needs pdksh.)
	    #
	    typeset cko
	    set -A cko $( (date ; ps -efa ; netstat -an ; netstat -in ; vmstat ; iostat) | cksum )
	    RANDOM=${cko[0]}

	    typeset lowers='a b c d e f g h i j k l m n o p q r s t u v w x y z'
	    typeset uppers='A B C D E F G H I J K L M N O P Q R S T U V W X Y Z'
	    typeset nums='0 1 2 3 4 5 6 7 8 9'
	    typeset puncs='! @ # $ % ^ & ( ) _ + | ~ - = { } [ ] , . /'
	    typeset symbols
	    set -A symbols $lowers $uppers $nums $puncs
	    typeset -i symlen=${#symbols[@]}

	    typeset -i LOOP=0
	    while [[ $LOOP -lt 1024 ]] ; do
		typeset -i ix=$(( ( $RANDOM + $(date '+%S') ) % $symlen ))
		print -n -- "${symbols[$ix]}"
		LOOP=$(( $LOOP + 1 ))
	    done >> $GMSIGFILEPATH
	fi
	print >> $GMSIGFILEPATH

	umask $UMASK_ORIG
	print "\nUnique \"$GMSIGFILEPATH\" has been generated."
}


# function used by utpolicy to change an auth.props entry takes 
# "key=value" argument -- modified to make the change in place
editAuthProps() {
	typeset kv=${1}
	typeset key=${kv%=*}
	if [[ ! -w $(dirname $AUTHPROPS) ]]
	then
		print -u2 Cannot update $AUTHPROPS
		return 1
	fi
	[[ -f "$AUTHPROPS.bak" ]] && rm -f $AUTHPROPS.bak
	[[ -f "$AUTHPROPS" ]] && cp -p $AUTHPROPS $AUTHPROPS.bak
	chmod 644 $AUTHPROPS
	# the "-" after ed tells ed that this is not interactive
	ed - $AUTHPROPS <<-! 2>/dev/null 1>&2
	g/^$key.*/s//$kv/
	.
	w
	q
	!
	return $?
}


#
# function to get the LDAP port number from the utdsd.ini file
#
get_ldap_port() {
	if [[ -f ${SRDS_LDAP_CURRENT}/utdsd.ini ]]; then
		sed -n -e 's/^LdapPort=//p' ${SRDS_LDAP_CURRENT}/utdsd.ini
	else
		# utdsd.init does not exist under /etc/opt/SUNWut/srds/current
		# directory.  This can only happen when the system is being
		# configured the first time.  We get the default port from
		# the default directory.
		sed -n -e 's/^LdapPort=//p' ${SRDS_LDAP_DEFAULT}/utdsd.ini
	fi
}

#
# Messages
#
groupsig_MSG(){
cat <<-!

You have chosen to configure this server for a failover group.

All servers in a failover group must share a unique signature, 
which is a string of 8 or more characters where at least two 
characters are letters and at least one is not.
 
!
}

utpolicy_MSG(){
cat <<-!

***********************************************************
The current policy has been modified.  You must restart the 
authentication manager to activate the changes. 
***********************************************************

!
}


#
# main {
#

# UMASKS
UMASK_ROOT=066
UMASK_WORLD=022

umask $UMASK_WORLD

OPTSTR=":ufkws:"
PROGRAM_OPTS="[-u] [-k] [-w]"

MODE="configure"
FORCE=false
OS=`/bin/uname -s`
SELECT_FULL_CONFIG=true
SELECT_KIOSK=false
SELECT_WEBADMIN=false

while getopts $OPTSTR OPT; do
  case "$OPT" in
    u) MODE="unconfigure" ;;
    k) SELECT_FULL_CONFIG=false; SELECT_KIOSK=true ;;
    w) SELECT_FULL_CONFIG=false; SELECT_WEBADMIN=true ;;
    s) if [ "$OPTARG" == "silent" ]; then
         MODE="autoconfigure"
       fi;;
    f) FORCE=true;;
   \?) Usage;;
  esac
done
shift $(($OPTIND - 1))

if (( $# != 0 )); then
  Usage
fi

CheckUidIsZero

#
# Set platform dependencies
#
SetPlatformDependencies

if $SELECT_FULL_CONFIG; then
# Source the old Web Server library.
. ${G_MEDIA_DIR}/support_lib/sras_config
fi
UT_PROD_NAME="Sun Ray Server Software"
UT_VERSION="4.2"

if ! UTInstalled; then
  Fatal "$UT_PROD_NAME is not installed on this host"
fi

UTA_BASEDIR="$(${G_MEDIA_DIR}/utprodinfo -r SUNWuta)/SUNWut"
UTO_BASEDIR="$(${G_MEDIA_DIR}/utprodinfo -r SUNWuto)/SUNWut"

# autoconfigure doesn't affect kiosk
if $SELECT_FULL_CONFIG && [[ $MODE != "autoconfigure" ]] || $SELECT_KIOSK 
then
  DO_KIOSK_CONFIG=true
# Source the utility library (currently only used by kiosk-related config)
. ${UTO_BASEDIR}/lib/support_lib/config_lib
# Source the kiosk library.
. ${UTO_BASEDIR}/lib/support_lib/kiosk_config
else
  DO_KIOSK_CONFIG=false
fi


SUNWUTLIB="$UTA_BASEDIR/lib"
UTGLPOLICY="$SUNWUTLIB/utglpolicy"
UT_TEMPLATE_LDAP="$UTA_BASEDIR/etc/template/ldap"

UTDBINIT="${SUNWUTLIB}/utdbinit"
UTADMINGID="${SUNWUTLIB}/utadmingid"


SRDS_PN="Sun Ray Data Store"
SRDS_RN="3.2"
SRDS_PACKAGE="SUNWutdso"

if ! SRDSInstalled; then
  Fatal "$SRDS_PN is not installed on this host"
elif ! SRDSVersion $SRDS_RN; then
  Fatal "$SRDS_PN $SRDS_RN is not installed on this host"
elif SRDSInstallPartial; then
  Fatal "$SRDS_PN $SRDS_RN is only partially installed"
fi

SRDS_BASEDIR="$(${G_MEDIA_DIR}/utprodinfo -r $SRDS_PACKAGE)/SUNWut"

LCL_PROD_NAME="LDAP Client Libraries"

if ! LdapClientInstalled; then
  Fatal "$LCL_PROD_NAME is not installed on this host"
elif LdapClientInstallPartial; then
  Fatal "$LCL_PROD_NAME is only partially installed"
fi

UT_ROOT_S="Sun Ray root"
DEFAULT_ROOTENTRY="o=utdata"

ROOTENTRY=""
ROOTNAME=""
ROOTPW=""
CRYPTD_ROOTPW=""
SRDS_ROOTDN_S="SRDS 'rootdn'"
DEFAULT_ROOTDN=""   # gets assigned later, constructed with $ROOTENTRY
ROOTDN=""
UTPASSWD=""
VERSIONENTRY="1"


UTCONF_FILE=${ETC_OPT_UT}/"utadmin.conf"
MODS_FILE="$UT_TEMPLATE_LDAP/ldap.mods"
VAR_OPT_LDAP_DBM_UT="${VAR_OPT_UT}/srds/dbm.ut"
VAR_OPT_LDAP_REPLOG="${VAR_OPT_UT}/srds/replog"
SRDS_UPGRADE_FLAG="NO"

SRDS_LDAP_DEFAULT="${ETC_OPT_UT}/srds/default"
SRDS_LDAP_CURRENT="${ETC_OPT_UT}/srds/current"
DS_CONF_FILE="$SRDS_LDAP_CURRENT/utdsd.conf"

LDAP_PORT=$(get_ldap_port)

#
# XXX	Note: the doc packages are not relocatable at present	<===
#
EN_DOC_DIR="${UT_BASEDIR}/doc/en/html"
JA_DOC_DIR="${UT_BASEDIR}/doc/ja/html"

LOCAL_EN_DOC_DIR="lib/locale/en_US/docdir"
LOCAL_FR_DOC_DIR="lib/locale/fr/docdir"
LOCAL_JA_DOC_DIR="lib/locale/ja/docdir"
LOCAL_ZH_DOC_DIR="lib/locale/zh/docdir"

UT_KIOSK_PACKAGE="SUNWkio"
KIOSK_INSTALLED=true
if ! KioskInstalled; then
  KIOSK_INSTALLED=false
  DO_KIOSK_CONFIG=false
fi

if [[ $MODE != "autoconfigure" ]]; then
  print "# Script: $PROGRAM_ID	Version: 4.2_77,REV=2009.10.19.17.01\n" > $LOGFILE
fi

# When upgrading an existing directory the hostname
# used to re-build the relavent SRDS files should
# be derived from the original hostname embedded in
# the LDAP directory and *not* obtained from uname

if [[ -f $UTCONF_FILE ]]; then
  DSHOST=$(awk -F= '$1~/admin.subtree/ {print $3}' $UTCONF_FILE|\
    awk -F, '{print $1}')
  if [[ -n $DSHOST ]]; then
    HOSTNAME="$DSHOST"
  fi
else
  HOSTNAME=$(uname -n)
fi

#  When upgrade from 1.1, should preserve the suffix, which could be
#  customized during 1.1 utconfig.

if [[ -f $DS_CONF_FILE ]]; then
  ROOTENTRY=$(awk '/^# SUNWut begin/ {found=1}\
    found==1 && $1=="suffix" {print $2}' $DS_CONF_FILE | sed 's/\"//g')
fi

if [[ -z $ROOTENTRY ]]; then
  ROOTENTRY="$DEFAULT_ROOTENTRY"
fi

if $SELECT_FULL_CONFIG; then
  case "$MODE" in
    autoconfigure)   DoAutoConfig ;; # No explicit logfile in silent mode.
    configure) 	     DoConfig      2>&1 |tee -a $LOGFILE;;
    unconfigure)     DoUnconfig    2>&1 |tee -a $LOGFILE;;
  esac
else
  case "$MODE" in  
    configure)      
      $SELECT_WEBADMIN && DoWebConfig      2>&1 |tee -a $LOGFILE
      $SELECT_KIOSK    && DoKioskConfig    2>&1 |tee -a $LOGFILE
      ;;
    unconfigure)    
      $SELECT_WEBADMIN && DoWebUnconfig    2>&1 |tee -a $LOGFILE
      $SELECT_KIOSK    && DoKioskUnconfig  2>&1 |tee -a $LOGFILE
       ;;
    *) 
      typeset sel=""
      if $SELECT_WEBADMIN; then
	sel="Web Administration "
      fi	    
      if $SELECT_KIOSK; then
        sel="Kiosk ${sel:+and }$sel"
      fi	    
      print -u2 "Unknown mode \"$MODE\" for configuring $sel software." 
      CleanupAndExit 1
      ;;
  esac
fi  

CleanupAndExit 0

# }
