# This script creates the backout package for a patch package
#
# directory format options.
#
# @(#) postinstall 1.13 01/01/12 SMI
#
# Copyright (c) 1995 by Sun Microsystems, Inc.
# All rights reserved
#

# 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#

#
# Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
# Use is subject to license terms.
#
#ident	"@(#)postinstall	1.63	05/04/14 SMI"
#
# Generate security certificates, start Apache, print startup message.

##############################################################################
#
# Default settings
#
##############################################################################
PERL=/usr/perl5/bin/perl
PERLINC=${PKG_INSTALL_ROOT}/opt/SUNWscvw/lib/perl
HOSTNAME=`hostname`

PASSWORD=sPm30c9o # Must match server-request.conf
PROG=SUNWscspmr.postinstall
PKGROOT=${PKG_INSTALL_ROOT}/opt/SUNWscvw
PKGCONF=${PKGROOT}/conf
PKGSSL=${PKGCONF}/ssl
LOGDIR=${PKG_INSTALL_ROOT}/var/cluster/spm
PERL=/usr/perl5/bin/perl
OPENSSL=${PKG_INSTALL_ROOT}/opt/SUNWscva/bin/openssl
LOGFILE=${LOGDIR}/messages
ROOTCERT=${PKGSSL}/sun-ca.crt
SERVER_SIGN_CONF=${PKGSSL}/server-sign.conf
RANDFILE=${PKGSSL}/random-bits; export RANDFILE
SERVER_REQUEST_CONF=${PKGSSL}/server-request.conf

##############################################################################
#
# set_hostname
#
# Attempt to get the fully qualified domain name for the host. If this
# succeeds, reset the parameters which rely upon it.
#
##############################################################################

set_hostname()
{
    TEMP=`${PERL} -I${PERLINC} -e "use Net::Domain qw(hostfqdn); print hostfqdn();"`

    if [ "$TEMP" != "" ]
    then
	HOSTNAME=${TEMP}
    fi

    SERVER_KEY=${PKGSSL}/${HOSTNAME}.key
    SERVER_REQUEST=${PKGSSL}/${HOSTNAME}.csr
    SERVER_CERT=${PKGSSL}/${HOSTNAME}.crt
}

##############################################################################
#
# Print internationalized error message
#
##############################################################################
error()
{
    echo "${PROG}: $@"
}

##############################################################################
#
# Generate the server key
#
##############################################################################
generate_server_key()
{
    ${OPENSSL} genrsa -out ${SERVER_KEY} 1024 > ${LOGFILE} 2>&1

    if [ $? -ne 0 ]
    then
	error `gettext "generate server key failed"`
    fi
}

##############################################################################
#
# Generate the certificate request
#
##############################################################################
generate_certificate_request()
{
    ${OPENSSL} req -new -config ${SERVER_REQUEST_CONF} \
		   -key ${SERVER_KEY} -out ${SERVER_REQUEST} \
		   >> ${LOGFILE} 2>&1
    
    if [ $? -ne 0 ]
    then
	error `gettext "generate certificate request failed"`
    fi
}

##############################################################################
#
# Sign the certificate request
#
##############################################################################
sign_server_certificate()
{
    # Generate a random certificate serial number
    RANDVAL=`generate_serial_number`

    # Create the necessary support directories
    mkdir -p ${PKGSSL}/ca.db.certs

    if [ $? -ne 0 ]
    then
	error `gettext "failed to created ca.db.certs directory"`
    fi

    echo ${RANDVAL} > ${PKGSSL}/ca.db.serial

    if [ $? -ne 0 ]
    then
	error `gettext "failed to created ca.db.serial file"`
    fi

    touch $PKGSSL/ca.db.index

    if [ $? -ne 0 ]
    then
	error `gettext "failed to created ca.db.index file"`
    fi

    # Sign the certificate
    ${OPENSSL} ca -config ${SERVER_SIGN_CONF} \
		  -key ${PASSWORD} -out ${SERVER_CERT} \
		  -batch -infiles ${SERVER_REQUEST} \
		  >> ${LOGFILE} 2>&1
    
    if [ $? -ne 0 ]
    then
	error `gettext "sign server certificate failed"`
    fi

    # Remove the support directories
    rm -rf $PKGSSL/ca.db.*

    if [ $? -ne 0 ]
    then
	error `gettext "ca support file removal failed"`
    fi
}

##############################################################################
#
# Verify the server certificate
#
##############################################################################
verify_server_certificate()
{
    ${OPENSSL} verify -CAfile ${ROOTCERT} ${SERVER_CERT} >> ${LOGFILE} 2>&1

    if [ $? -ne 0 ]
    then
	error `gettext "verify server certificate failed"`
    fi
}

##############################################################################
#
# Generate the serial number
#
##############################################################################
generate_serial_number() {
    SER=`${PERL} -e 'srand(time()^($$+($$<<15))); print int(rand 64000) + 1;'`
    NUMCHAR=`echo ${SER} | wc -m`
    ODDCHAR=`echo "(${NUMCHAR} - 1) % 2" | bc`

    if [ ${ODDCHAR} = 1 ]
    then
	echo "0${SER}"
    else
	echo $SER
    fi
}

##############################################################################
#
# Start or restart the server if we're not jumpstarting 
#
##############################################################################
start_apache()
{
    if [ ! -d /var/run/apache ]
    then
	/usr/bin/mkdir -p -m 755 /var/run/apache
    fi
    if [ -f /var/cluster/spm/httpd.pid ]
    then
	/opt/SUNWscvw/bin/apachectl restart > /dev/null
    elif [ -f /usr/apache/bin/httpd ]
    then
	/opt/SUNWscvw/bin/apachectl startssl > /dev/null
    fi
    
    if [ $? -ne 0 ]
    then
	error `gettext "Apache start failed"`
	exit 0
    fi
}

##############################################################################
#
# Print out the final message if we're not jumpstarting
#
##############################################################################
print_final_message()
{
    echo
    echo "######################################################################"

    # If the Apache packages are not installed, print out a message telling the
    # user to install them
    if [ ! -f ${PKG_INSTALL_ROOT}/usr/apache/bin/httpd ]
    then
	echo "NOTE: To finish installing the SunPlex Installer, you must install"
	echo "the SUNWapchr and SUNWapchu Solaris packages and any associated"
	echo "patches."
	if [ ! -f ${BASEDIR}/usr/sbin/svcadm ]; then
		echo " Then run '/etc/init.d/initspm start' to start the server."
	fi
    fi
    echo "Welcome to the SunPlex Installer. Your cluster is now ready to be"
    echo "installed from a web browser. You may access the"
    echo "SunPlex Installer through your web browser by securely connecting"
    echo "to port 3000 on any node of your cluster, such as:"
    echo " "
    echo "	  https://${HOSTNAME}:3000"
    echo " "
    echo "If you are using the SunPlex Installer to install Sun Cluster, you"
    echo "must login as root or any other user which has a user id (uid) of 0."
    echo "The user must have the same password on each node. For further "
    echo "instructions see the Sun Cluster System Administration Guide."
    echo "######################################################################"
}

enable_manifests()
{

	upgrade_file=${BASEDIR}/var/svc/profile/upgrade

        if [[ ! -f ${upgrade_file} ]]; then
                /usr/bin/touch ${upgrade_file}
        fi

        echo '/usr/sbin/svcadm enable svc:/system/cluster/spm:default' >> ${upgrade_file}

        return 0

}

##############################################################################
#
# Main function
#
##############################################################################

# Add the spm user profile
chroot ${PKG_INSTALL_ROOT:-/} /usr/sbin/usermod -P "SPM User" spmadmin
if [ $? -ne 0 ]
then
    echo "${PROG}: Failed to add the 'SPM User' RBAC profile to the spmadmin user"
fi

# Create and change the ownership of the files in /var/cluster/spm
mkdir -p ${PKG_INSTALL_ROOT}/var/cluster/spm &&
for i in ssl_request_log ssl_engine_log error_log access_log; do
    touch ${PKG_INSTALL_ROOT}/var/cluster/spm/${i}
done &&
chroot ${PKG_INSTALL_ROOT:-/} /usr/bin/chown -R spmadmin /var/cluster/spm

if [ $? -ne 0 ]
then
    echo "${PROG}: Failed to create and change ownership of /var/cluster/spm"
fi

# Set the hostname and related parameters
set_hostname

# Generate the server certificate 
generate_server_key
generate_certificate_request
sign_server_certificate
verify_server_certificate

# Change the ownership of the messages file
chroot ${PKG_INSTALL_ROOT:-/} /usr/bin/chown spmadmin /var/cluster/spm/messages

# Start the server if we're not jumpstarting
if [ "$PKG_INSTALL_ROOT" = "/" ] || [ "$PKG_INSTALL_ROOT" = "" ]
then
	start_apache
fi

# Test for SMF
if [ -f ${BASEDIR}/usr/sbin/svcadm ]; then
	enable_manifests	|| errs=`expr ${errs} + 1`
fi

# Print the final message
print_final_message

# Exit 0 so that scinstall will succeed even if there are errors
exit 0
