#!/bin/sh
#
# ident "@(#)postinstall	1.3 03/02/10 SMI"
#
# Copyright 2002 Sun Microsystems, Inc.  All rights reserved.
#

# This script creates the backout package for a patch package
#
# directory format options.
#
#

# Description:
#       Set the TYPE parameter for the remote file
#
# Parameters:
#       none
#
# Globals set:
#	TYPE

set_TYPE_parameter () {
	if [ ${PATCH_UNDO_ARCHIVE:?????} = "/dev" ]; then
		# handle device specific stuff
		TYPE="removable"
	else
		TYPE="filesystem"
	fi
}

#
# Description:
#       Build the remote file that points to the backout data
#
# Parameters:
#       $1:	the un/compressed undo archive
#
# Globals set:
#	UNDO, STATE

build_remote_file () {
	remote_path=$PKGSAV/$SUNW_PATCHID/remote
	set_TYPE_parameter
	STATE="active"

	if [ $1 = "undo" ]; then
		UNDO="undo"
	else
		UNDO="undo.Z"
	fi

	cat > $remote_path << EOF
# Backout data stored remotely
TYPE=$TYPE
FIND_AT=$ARCHIVE_DIR/$UNDO
STATE=$STATE
EOF
}

PATH=/usr/sadm/bin:$PATH

if [ "$PKG_INSTALL_ROOT" = "/" ]; then
	PKG_INSTALL_ROOT=""
fi

if [ -n "$PATCH_BUILD_DIR" -a -d "$PATCH_BUILD_DIR" ]; then
	BUILD_DIR="$PATCH_BUILD_DIR/$SUNW_PATCHID.$PKGINST"
else
	BUILD_DIR="$PKG_INSTALL_ROOT/var/tmp/$SUNW_PATCHID.$PKGINST"
fi

if [ ! -n "$PATCH_UNDO_ARCHIVE" ]; then
	PATCH_UNDO_ARCHIVE="none"
fi

FILE_DIR=$BUILD_DIR/files
RELOC_DIR=$FILE_DIR/reloc
ROOT_DIR=$FILE_DIR/root
BO_Deletes=$FILE_DIR/deletes
THIS_DIR=`dirname $0`
PROTO_FILE=$BUILD_DIR/prototype
TEMP_REMOTE=$PKGSAV/$SUNW_PATCHID/temp

if [ "$PATCH_PROGRESSIVE" = "true" ]; then
        # remove the scripts that are left behind
        install_scripts=`dirname $0`
        rm $install_scripts/checkinstall $install_scripts/patch_checkinstall $install_scripts/patch_postinstall

	# If this is being used in an old-style patch, insert
	# the old-style script commands here.

	#XXXOld_CommandsXXX#

	exit 0
fi

#
# At this point we either have a deletes file or we don't. If we do,
# we create a prototype entry.
#
if [ -f $BO_Deletes ]; then
	echo "i deletes=$BO_Deletes" >> $BUILD_DIR/prototype
fi

#
# Now delete everything in the deletes list after transferring
# the file to the backout package and the entry to the prototype
# file. Remember that the pkgmap will get the CLIENT_BASEDIR path
# but we have to actually get at it using the BASEDIR path. Also
# remember that removef will import our PKG_INSTALL_ROOT
#
Our_Deletes=$THIS_DIR/deletes
if [ -f $Our_Deletes ]; then
	cd $BASEDIR

	cat $Our_Deletes | while read path; do
		Reg_File=0

		if valpath -l $path; then
			Client_Path="$CLIENT_BASEDIR/$path"
			Build_Path="$RELOC_DIR/$path"
			Proto_Path=$BASEDIR/$path
		else	# It's an absolute path
			Client_Path=$path
			Build_Path="$ROOT_DIR$path"
			Proto_Path=$PKG_INSTALL_ROOT$path
		fi

		# If BASEDIR/CLIENTBASEDIR = "/", then the previous prepends
		# an extra / i.e. //. The sed command later can't find a
		# Proto_Path with // and therefore will not substitute the
		# correct build_Path resulting in the backout pkg not being
		# created.

		if [ "$CLIENT_BASEDIR" = "/" ]; then
			Client_Path=`echo $Client_Path | sed 's|^\/\/|\/|'`
			Proto_Path=`echo $Proto_Path | sed 's|^\/\/|\/|'`
		fi
			
		# Note: If the file isn't really there, pkgproto
		# doesn't write anything but displays an error
		# so check for the file before processing.

		if [ -f "$Proto_Path" ]; then
			LINE=`pkgproto $Proto_Path=$path`
		else
			continue
		fi

		ftype=`echo $LINE | nawk '{ print $1 }'`
		if [ "$ftype" = "f" ]; then
			Reg_File=1
		fi

		if [ $Reg_File = 1 ]; then
			# Add source file to the prototype entry
			if [ "$Proto_Path" = "$path" ]; then
				LINE=`echo $LINE | sed -e "s|$Proto_Path|$Build_Path|2"`
			else
				LINE=`echo $LINE | sed -e "s|$Proto_Path|$Build_Path|"`
			fi

			DirName=`dirname $Build_Path`
			# make room in the build tree
			mkdir -p $DirName
			cp -p $Proto_Path $Build_Path
		fi

		# Insert it into the prototype file
		echo $LINE 1>>$PROTO_FILE 2>/dev/null

		# Remove the file only if it's OK'd by removef
		rm `removef $PKGINST $Client_Path` 1>/dev/null 2>&1
	done
	removef -f $PKGINST

	rm $Our_Deletes
fi

#
# Unless specifically denied, make the backout package.
#
if [ "$PATCH_NO_UNDO" != "true" ]; then
	cd $BUILD_DIR	# We have to build from here.

	if [ "$PATCH_UNDO_ARCHIVE" != "none" ]; then
		STAGE_DIR="$PATCH_UNDO_ARCHIVE"
		ARCHIVE_DIR="$PATCH_UNDO_ARCHIVE/$SUNW_PATCHID/$PKGINST"
		mkdir -p $ARCHIVE_DIR
		mkdir -p $PKGSAV/$SUNW_PATCHID
	else
		if [ -d $PKGSAV/$SUNW_PATCHID ]; then
			rm -r $PKGSAV/$SUNW_PATCHID
		fi
		STAGE_DIR=$PKGSAV
		ARCHIVE_DIR=$PKGSAV/$SUNW_PATCHID
		mkdir $ARCHIVE_DIR
	fi

	pkgmk -o -d $STAGE_DIR 1>/dev/null 2>&1
	pkgtrans -s $STAGE_DIR $ARCHIVE_DIR/undo $PKG 1>/dev/null 2>&1
	compress $ARCHIVE_DIR/undo
	retcode=$?
	if [ "$retcode" != 0 ]; then
		echo "compress(1) returned error code $retcode"
		echo "The $PKGINST backout package will not be compressed."
		echo "Continuing to process backout package."
	fi
	if [ "$PATCH_UNDO_ARCHIVE" != "none" ]; then
		if [ $retcode != 0 ]; then
			build_remote_file "undo"
		else
			build_remote_file "undo.Z"
		fi
	fi
	rm -r $STAGE_DIR/$PKG

	cd ..
	rm -r $BUILD_DIR
	# remove the scripts that are left behind
	install_scripts=`dirname $0`
	rm $install_scripts/checkinstall $install_scripts/patch_checkinstall $install_scripts/patch_postinstall
fi

#
# Since this apparently worked, we'll mark as obsoleted the prior
# versions of this patch - installpatch deals with explicit obsoletions.
#
cd ${PKG_INSTALL_ROOT:-/}
cd var/sadm/pkg

active_base=`echo $SUNW_PATCHID | nawk '
	{ print substr($0, 1, match($0, "-")-1) } '`

List=`ls -d $PKGINST/save/${active_base}* 2>/dev/null`
if [ $? -ne 0 ]; then
	List=""
fi

for savedir in $List; do
        patch=`basename $savedir` 
        if [ $patch = $SUNW_PATCHID ]; then
		break
	fi

        # If we get here then the previous patch gets deleted
	if [ -f $savedir/undo ]; then
		mv $savedir/undo $savedir/obsolete
		echo $SUNW_PATCHID >> $savedir/obsoleted_by
	elif [ -f $savedir/undo.Z ]; then
		mv $savedir/undo.Z $savedir/obsolete.Z
		echo $SUNW_PATCHID >> $savedir/obsoleted_by
        elif  [ -f $savedir/remote ]; then
                `grep . $PKGSAV/$patch/remote | sed 's|STATE=.*|STATE=obsolete|' > $TEMP_REMOTE` 
                rm -f $PKGSAV/$patch/remote 
                mv $TEMP_REMOTE $PKGSAV/$patch/remote  
                rm -f $TEMP_REMOTE 
                echo $SUNW_PATCHID >> $savedir/obsoleted_by
	elif  [ -f $savedir/obsolete -o -f $savedir/obsolete.Z ]; then
		echo $SUNW_PATCHID >> $savedir/obsoleted_by
	fi
done

# If additional operations are required for this package, place
# those package-specific commands here.

#XXXSpecial_CommandsXXX#

# This script enables and disables sunray usage for CDE
# (dtlogin and dtsession). It modifies CDE X properties to
# add or remove properties that specify whether or not to use
# sunray, and it edits /etc/pam.conf to add or remove
# pam_sunray.so actions.
#
# This script requires that the following CDE patches be installed:
#
#	108919 (minimum -14)
#	109354 (minimum -13)
#

BASENAME="/bin/basename"
     MOD="`$BASENAME $0`"
 DIRNAME="/bin/dirname"
 SHOWREV="/bin/showrev"
PATCH_NUM="111891"

EGREP="/bin/egrep"
   MV="/bin/mv"
   RM="/bin/rm -f"
  AWK="/bin/awk"
   MV="/bin/mv"
 ECHO="/bin/echo"
MKDIR="/bin/mkdir"
   CP="/bin/cp"
 GREP="/bin/grep"

STRING="# Commented out by the patch 111891 "

   # if PKG_INSTALL_ROOT is not assigned from the env then
   # set it to an empty string, set -u in effect below
   #
   if [ -z "$PKG_INSTALL_ROOT" ]; then
	PKG_INSTALL_ROOT=""
   fi

   BASEDIR="`/usr/bin/pkgparam SUNWutps BASEDIR`"

   set -u

   SUNWUTLIB="${PKG_INSTALL_ROOT}${BASEDIR}/SUNWut/lib"

   # override these variables for debugging
   SCETC="/etc"
   SCTMP="/var/run"

     TMP="$SCTMP/$MOD.$$"
 TMP_SR="$TMP.PAMsr"
TMP_CONF="$TMP.pam.conf"

# CDE application names in pam.conf
  DTLOGIN="dtlogin-SunRay"
DTSESSION="dtsession-SunRay"
# (OLD) CDE application names in pam.conf
  DTLOGIN_OLD="dtlogin"
DTSESSION_OLD="dtsession"

PAM_CONF="$SCETC/pam.conf"

# PAM client name X server class (dtlogin/dtsession)
# requires fix for 4452627
XCONFIG_USR_DIR="/usr/dt/config"
XCONFIG_ETC_DIR="/etc/dt/config"
GENERIC_XCONFIG="Xconfig"
PROTO_XCONFIG="Xconfig.SUNWut.prototype"
VALID_PAM_CLASS_TAG="Dtlogin.validPAMclasses"
SUNRAY_XSERVER_CLASS_TYPE="SunRay"

# dtsession autounlock from PAM
# requires fix for 4430559
USR_CDE_DEFAULTS_DIR="/usr/dt/app-defaults/C"
ETC_CDE_DEFAULTS_DIR="/etc/dt/app-defaults/C"
DTSESSION_DEFAULTSFILE="Dtsession"
PAM_PROMPT_NOLOCK_PROP="noPamPromptNoLock"

# PAM modules info
SRLIB="${SUNWUTLIB}/pam_sunray.so"
SRLIBso="`$BASENAME $SRLIB | $AWK -F. '{print $1\".\"$2}'`"
# note single quotes so that $ISA doesn't get expanded by the shell
PAM_UNIX='/usr/lib/security/$ISA/pam_unix.so.1'

SRTAG="SunRay Server Software"

#
# Enable sunray authentication for CDE by adding Sun Ray PAM module
# to both dtlogin and dtsession.
#
add_sr_to_PAM ()
{

    REQ_S="sufficient"
    REQ_R="required"

	for TYPE in auth
	    do
		$AWK   "BEGIN {
			    dtlogin_added=0
			    dtsession_added=0
			}

			/^[ \t]*$DTLOGIN[ \t]*$TYPE/ {
			    if (dtlogin_added == 0)
				print \"# $SRLIBso added to $DTLOGIN by $SRTAG\";
				print \"$DTLOGIN $TYPE $REQ_S $SRLIB\";
				print \"$DTLOGIN $TYPE $REQ_R $PAM_UNIX\";
			    dtlogin_added=1;
			}

			/^[ \t]*$DTSESSION[ \t]*$TYPE/ {
			    if (dtsession_added == 0)
				print \"# $SRLIBso added to $DTSESSION by $SRTAG\";
				print \"$DTSESSION $TYPE $REQ_S $SRLIB syncondisplay\";
				print \"$DTSESSION $TYPE $REQ_R $PAM_UNIX\";
			    dtsession_added=1;
			}

			{ print }

			END {

			    if (dtlogin_added == 0) {
				print \"# $SRLIBso added to $DTLOGIN by $SRTAG\";
				print \"$DTLOGIN $TYPE $REQ_S $SRLIB\";
				print \"$DTLOGIN $TYPE $REQ_R $PAM_UNIX\";
			    }

			    if (dtsession_added == 0) {
				print \"# $SRLIBso added to $DTSESSION by $SRTAG\";
				print \"$DTSESSION $TYPE $REQ_S $SRLIB syncondisplay\";
				print \"$DTSESSION $TYPE $REQ_R $PAM_UNIX\";
			    }

			}

			" $PAM_CONF >$TMP_SR 2>/dev/null

		if [ "$?" = 0 ] ; then
		    $MV $TMP_SR $PAM_CONF
		else
		    $RM $TMP_SR
		    $ECHO "$MOD: error updating $PAM_CONF"
		    exit 1
		fi

	    done

}

#
# Remove the appname + property from the passed file.
#
#    Usage: remove_PAM_prop {filename} {appname} [{propertyname}]
#
#		{propertyname} is optional, and if not set, then
#		all instances of {appname} will be removed
#
remove_PAM_prop ()
{

    FNAME="$1"
    APPNAME="$2"
    PROPNAME="$3"

    $AWK "{
	if (!(\$1 == \"$APPNAME\" && index(\$4, \"$PROPNAME\") > 0))
	    printf( \$0 \"\n\" );
	else
	   printf( \"$STRING\" \$0 \"\n\" );
	}" $FNAME >$TMP_SR 2>/dev/null

    if [ "$?" = 0 ] ; then
	$EGREP -v "$SRTAG" $TMP_SR >$FNAME
	$RM $TMP_SR
    else
	$RM $TMP_SR
	echo "$MOD: error updating $FNAME"
	exit 1
    fi

}

#
# Remove Sun Ray authentication for CDE from $PAM_CONF
#
remove_sr_from_PAM ()
{

    remove_PAM_prop $PAM_CONF $DTLOGIN_OLD $SRLIBso
    remove_PAM_prop $PAM_CONF $DTSESSION_OLD $SRLIBso

}

########################################################################
#                                                                      #
#			Main code starts here.                         #
#                                                                      #
########################################################################

# XXXXX patch revision specific stuff went here. XXXXX
 #
 # Need to know what revision of the 111891 patch are we upgrading from.
 # Since SmartCard Framework was introduced as part of rev-07, some of
 # the changes may already be there.
 #

 #
 # Get the list of 111891 patches installed on this system.
 # Get only the revision number.
 #
 PATCH_LIST=`$SHOWREV -p |$GREP -ws $PATCH_NUM |$AWK -F' ' '{print $2}' | $AWK -F- '{print $2}'`


 #
 # Get the previous patch revision number.
 # Note that, by the time this postinstall kicks off, this patch id/rev also 
 # shows up in /bin/showrev output.
 #
 if [ -n "$PATCH_LIST" ]
  then
    PATCH_REV_LIST=`echo $PATCH_LIST | $AWK '{ if (NF == 1) print 0; \
			else print $(NF-1); }'`

    if [ -n "$PATCH_REV_LIST" -a $PATCH_REV_LIST -lt 7 ]
      then

    	#
    	# Check for some files and directories that we must have
    	# to make this all work.
    	#
    	if test ! -f $PAM_CONF ; then
	    $ECHO "$MOD: $PAM_CONF does not exist"
	    exit 1
    	fi

    	# Remove any existing Sun Ray entries from $PAM_CONF.
    	# This removes all the pre-patch Sun Ray entries that
    	# the FCS postinstall script added.
    	remove_sr_from_PAM

    	# enable Sun Ray authentication for CDE in $PAM_CONF

    	# add Sun Ray PAM module if not already added
    	# XXX important to also copy whatever dtlogin (no X server class)
    	# XXX is using so that "dtlogin-SunRay" does the right thing
    	if [ -z "`/bin/sed 's/#.*//' $PAM_CONF | $EGREP -is $SRLIBso`" ]; then
	    add_sr_to_PAM
    	fi

    	#
    	# Tell dtlogin that Sun Ray is a valid X server class so that
    	# it can register with PAM as the client name "dtlogin-SunRay".
    	# This will also take care of dtsession, which will register
    	# with PAM as the client name "dtsession-SunRay".
    	#
    	# This requires the following bugfix to be installed:
    	#	4452627 dtlogin should register with PAM using a different
    	#		client name when on Sun Ray
    	#
    	# Xconfig changes that need to be preserved over reboots need
    	# to be made to a prototype Xconfig file. If that file does
    	# not exist, we create it.
    	#
    	# XXX Note that this will only look for the valid class property
    	# XXX which may or may not contain $SUNRAY_XSERVER_CLASS_TYPE.
    	# XXX It is possible that other classes are in that property as
    	# XXX well and we should preserve those.
    	# XXX This is a bug which should be fixed.
    	#
    	if test ! -f $XCONFIG_ETC_DIR/$PROTO_XCONFIG ; then
	    $MKDIR -p $XCONFIG_ETC_DIR
	    $CP $XCONFIG_USR_DIR/$GENERIC_XCONFIG $XCONFIG_ETC_DIR/$PROTO_XCONFIG
    	fi

    	$EGREP -is "$VALID_PAM_CLASS_TAG" $XCONFIG_ETC_DIR/$PROTO_XCONFIG
    	if [ $? -eq 1 ]; then
	    $ECHO "$VALID_PAM_CLASS_TAG: $SUNRAY_XSERVER_CLASS_TYPE" \
					>> $XCONFIG_ETC_DIR/$PROTO_XCONFIG
    	fi

    	#
    	# Tell dtsession that it's OK to remove the lockscreen without
    	# requiring the user to press <RETURN> if the PAM module has
    	# validated the user.
    	# Create a Dtsession configuration file in /etc if it doesn't
    	# exist and then update it there.
    	#
    	# This requires the following bugfix to be installed:
    	#   4430559 dtsession requires user input even if PAM says user
    	#	    is authenticated
    	#
    	# XXX How do we know what "language" to use for the dtsession
    	# XXX defaults file? This is $LANG???
    	#
    	if test ! -f $ETC_CDE_DEFAULTS_DIR/$DTSESSION_DEFAULTSFILE ; then
	    $MKDIR -p $ETC_CDE_DEFAULTS_DIR
	    $CP $USR_CDE_DEFAULTS_DIR/$DTSESSION_DEFAULTSFILE $ETC_CDE_DEFAULTS_DIR
    	fi

    	$EGREP -vi "$PAM_PROMPT_NOLOCK_PROP" $ETC_CDE_DEFAULTS_DIR/$DTSESSION_DEFAULTSFILE >$TMP_SR
    	$ECHO "Dtsession*$PAM_PROMPT_NOLOCK_PROP: True" >>$TMP_SR
    	$MV $TMP_SR $ETC_CDE_DEFAULTS_DIR/$DTSESSION_DEFAULTSFILE


    fi
 fi
# XXXXX patch revision specific stuff ended here. XXXXX

exit 0
