#!/bin/ksh -p

#
# ident "@(#)utgenpam.ksh	1.10	06/03/09 SMI"
#
# Copyright 2005-2006 Sun Microsystems, Inc.  All rights reserved.
# Use is subject to license terms.
#

#
# This module configures/unconfigures the PAM stack for all of SRSS
# and replaces the preremove/postinstall actions previously performed by
# SUNWuto and SUNWutps
#
# Arg #1 DEF_OPTION specifies the option to use the entries for the "other"
#	service as the default if the specified OLDAPP is not defined. 
#	See -o option for utpamcfg.  Valid values are DEF_YES and DEF_NO.
# Arg #2 TAG_OPTION specifies if tag is desired.  Valid values are TAG_YES
#	and TAG_NO.
# Arg #3 APPNAME is the application name with the optional module type.  It
#	should be in the "<appname>[:<mod-type>]".  See utpamcfg for more info.
# Arg #4 OLDAPP is the template to be used to create the stack.
# Arg #5 STACK defines if this is an old style pam.conf (i.e. < S8) or newer
#	ones (i.e. > S9).
# Arg #6 MODULE specifies the module to be added on top of the new stack.
# Arg #7 MODOPTS specifies the options to be specified with the module.
#

create_stack() {
    typeset DEF_OPTION="$1"
    typeset TAG_OPTION="$2"
    typeset APPNAME="$3"
    typeset OLDAPP="$4"
    typeset STACK="$5"
    typeset MODULE="${6-}"
    typeset MODOPTS="${7-}"

    typeset FLAGSTR=""
    if [ "$DEF_OPTION" == "DEF_NO" ]; then
	# specify the -o option to utpamcfg
   	FLAGSTR="-o"
    fi

    if [ "$TAG_OPTION" == "TAG_YES" ]; then
	# add tag
	typeset PAMCL=`print $APPNAME | sed -n -e 's/\([^:]*\).*$/\1/p'`
	FLAGSTR="$FLAGSTR -T \"$SRTAG -- $PAMCL\""
    fi

    typeset MODSTR=
    if [ -n "$MODULE" ]; then
	MODSTR="-m $MODULE"
    fi
    if [ -n "$MODOPTS" ]; then
	MODSTR="$MODSTR -M $MODOPTS"
    fi

    eval "$UTPAMCFG -c $APPNAME -t $OLDAPP -n $STACK $FLAGSTR $MODSTR"
}


#
# This modules adds one entry to the stack for the APPNAME specified.
#
# Arg #1 TAG_OPTION specifies if tag is desired.  Valid values are TAG_YES
#	and TAG_NO.
# Arg #2 APPNAME is the application name with the optional module type.  It
#	should be in the "<appname>[:<mod-type>]".  See utpamcfg for more info.
# Arg #3 MODULE specifies the module to be added on top of the new stack.
# Arg #4 MODOPTS specifies the options to be specified with the module.
# Arg #5 FLAG specifies the control flag to be added with the module.
#
add_module() {
    typeset TAG_OPTION="$1"
    typeset APPNAME="$2"
    typeset MODULE="$3"
    typeset MODOPTS="${4-}"
    typeset FLAG="${5-}"

    typeset MODSTR=""
    if [ -n "$MODOPTS" ]; then
	MODSTR="-M $MODOPTS"
    fi

    typeset FLAGSTR=""
    if [ "$TAG_OPTION" == "TAG_YES" ]; then
	# add tag
	typeset PAMCL=`print $APPNAME | sed -n -e 's/\([^:]*\).*$/\1/p'`
	FLAGSTR="-T \"$SRTAG -- $PAMCL\""
    fi
    if [ -n "$FLAG" ]; then
	FLAGSTR="$FLAGSTR -f $FLAG"
    fi
    eval "$UTPAMCFG -a $APPNAME -m $MODULE $MODSTR $FLAGSTR"
}

#
# This module delete the PAM stack for the APPNAME specified.
#
# Arg #1 APPNAME is the application name with the optional module type.  It
#	should be in the "<appname>[:<mod-type>]".  See utpamcfg for more info.

delete_stack() {
    typeset APPNAME="$1"

    $UTPAMCFG -u $APPNAME
}

add_Xserver_Class() {
    # Tell dtlogin that SunRay 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 SunRay
    #
    # 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 Even more XXX, this shouldn't happen here, it should happen in the
    # XXX utacleanup init script where we do the rest of the Xconfig fixups.  

    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
}

delete_Xserver_Class() {
    # Remove $SUNRAY_XSERVER_CLASS_TYPE from Xconfig.
    #
    # This requires the following bugfix to be installed:
    #	4452627 dtlogin should register with PAM using a different
    #		client name when on SunRay
    #
    if test -f $XCONFIG_ETC_DIR/$PROTO_XCONFIG; then
	SCTMP="/var/run"
	TMP="$SCTMP/$MOD.$$"
	TMP_SR="$TMP.PAMsr"

	egrep -is $VALID_PAM_CLASS_TAG $XCONFIG_ETC_DIR/$PROTO_XCONFIG
	if [ $? -ne 1 ]; then
	    egrep -vi "$VALID_PAM_CLASS_TAG" $XCONFIG_ETC_DIR/$PROTO_XCONFIG >$TMP_SR
	    mv $TMP_SR $XCONFIG_ETC_DIR/$PROTO_XCONFIG
	fi
    fi
}

utpam_configure() {
    if [ "$OS" = "SunOS" -a "$OS_REL" = "5.8" ]; then
	NEWSTACK=false
    else
	NEWSTACK=true
    fi

    if [ $OS = "Linux" ]; then
	add_module "TAG_YES" $GDM $AMGHLIB clearuser required
	add_module "TAG_NO" $GDM $SRLIB_GU prompt required
	add_module "TAG_NO" $GDM $AMGHLIB "" required
	add_module "TAG_NO" $GDM $SRLIB_GU property=username requisite
	add_module "TAG_YES" $ADMINGUI $ADMINGUILIB "" sufficient
    else
	create_stack "DEF_YES" "TAG_YES" $XSCREENSAVER other $NEWSTACK $SRLIB syncondisplay

	# we add specific "auth" type service for the dtlogin-SunRay to make sure
	# that we copy the "dtlogin auth" entries currently configured on the system
	# to dtlogin-SunRay stack.  This can either be from the "dtlogin" service
	# stack itself or from the "other" service stack if it's not defined in the
	# dtlogin stack.
	create_stack "DEF_YES" "TAG_YES" $DTLOGIN dtlogin $NEWSTACK
	create_stack "DEF_YES" "TAG_NO" $DTLOGIN:auth dtlogin $NEWSTACK
	add_module "TAG_NO" $DTLOGIN:auth $AMGHLIB clearuser required
	add_module "TAG_NO" $DTLOGIN:auth $SRLIB_GU prompt requisite
	add_module "TAG_NO" $DTLOGIN:auth $AMGHLIB "" required
	add_module "TAG_NO" $DTLOGIN:auth $SRLIB_GU property=username requisite
	add_module "TAG_NO" $DTLOGIN:auth $SRLIB "" sufficient
	create_stack "DEF_YES" "TAG_NO" $DTLOGIN:account dtlogin $NEWSTACK
	add_module "TAG_NO" $DTLOGIN:account $SRLIB "" sufficient

	create_stack "DEF_YES" "TAG_YES" $DTSESSION dtsession $NEWSTACK $SRLIB syncondisplay

	create_stack "DEF_YES" "TAG_YES" $NSCLOGIN dtlogin $NEWSTACK
	create_stack "DEF_YES" "TAG_NO" $NSCLOGIN:auth dtlogin $NEWSTACK
	add_module "TAG_NO" $NSCLOGIN:auth $AMGHLIB "" required
	add_module "TAG_NO" $NSCLOGIN:auth $SRLIB_GU property=username requisite

	add_module "TAG_YES" $ADMINGUI $ADMINGUILIB "" sufficient
        # utgulogin has to be created from scratch - no existing stack to dup
	isguconf=`sed -n  's/^.*utgulogin//p' $PAM_CONF`

	if [ -z "$isguconf" ]; then
	    add_module "TAG_YES" $GULOGIN:auth $AMGHLIB "" required
	    add_module "TAG_NO" $GULOGIN:auth $SRLIB_GU prompt requisite
	    add_module "TAG_NO" $GULOGIN:auth $AMGHLIB "" required
	    add_module "TAG_NO" $GULOGIN:auth $SRLIB_GU token=auth,JavaBadge requisite
	    add_module "TAG_NO" $GULOGIN:auth $SRLIB_GU property=username requisite
	fi

	add_Xserver_Class
    fi
}

clean_gdm_stack() {
    if [ $OS != "SunOS" -a -d $PAM_DIR ]; then
	PAM_CONF=$PKG_INSTALL_ROOT/${PAM_DIR}/gdm
    else
	PAM_CONF=$PKG_INSTALL_ROOT/$PAM_CONF
    fi
    TAGSTR="$SRTAG -- gdm"
    egrep -v \
	-e "\<pam_sunray_amgh.so." \
	-e "\<sunray_get_user.so." \
	-e "$TAGSTR" \
	$PAM_CONF > /tmp/pam.conf.$$
    cp /tmp/pam.conf.$$ $PAM_CONF
    rm -f /tmp/pam.conf.$$
}

utpam_unconfigure() {
    if [ $OS != "SunOS" ]; then
	clean_gdm_stack
	delete_stack $ADMINGUI
	return
    fi

    # Edit pam.conf to remove any configuration for utnsclogin
    # and utgulogin
    #

    delete_stack $DTLOGIN
    delete_stack $DTSESSION
    delete_stack $XSCREENSAVER
    delete_stack $NSCLOGIN
    delete_stack $GULOGIN
    delete_stack $ADMINGUI

    delete_Xserver_Class
}

Usage() {
    printf "Usage: %s: [-r alternate_root] disable|enable\n" $0
}

# main

if [ -z "$DEBUG_ROOT" ]; then DEBUG_ROOT=""; fi
if [ -z "$PKG_INSTALL_ROOT" ]; then PKG_INSTALL_ROOT=""; fi
if [ -z "$CLIENT_BASEDIR" ]; then CLIENT_BASEDIR="/opt"; fi

disable=false
while getopts d:hr: opt; do
    case $opt in
	d)	DEBUG_ROOT="$OPTARG";;
	r)	PKG_INSTALL_ROOT="$OPTARG";;
	h)	Usage
		exit 0;;
	?)	Usage
		exit 1;;
    esac
done
shift $(($OPTIND - 1))

action=
if [ "$1" == "disable" ]; then
    action=disable
    shift
elif [ "$1" == "enable" ]; then
    action=enable
    shift
fi
if [ -n "$*" -o -z "$action" ]; then
    Usage
    exit 1
fi

if [ -z "$BASEDIR_DEFAULT" ]; then
    BASEDIR_DEFAULT="$PKG_INSTALL_ROOT$CLIENT_BASEDIR"
fi

OS=`uname -s`
OS_REL=`uname -r`

PRODINFO=/etc/opt/SUNWut/basedir/lib/utprodinfo

if [ $action = "disable" ] ; then
    BASEDIR_PS="$DEBUG_ROOT`$PRODINFO -r SUNWutps`"
    BASEDIR_O="$DEBUG_ROOT`$PRODINFO -r SUNWuto`"
    BASEDIR_GSM="$DEBUG_ROOT`$PRODINFO -r SUNWutgsm`"
else
    BASEDIR_PS=$BASEDIR_DEFAULT
    BASEDIR_O=$BASEDIR_DEFAULT
    BASEDIR_GSM=$BASEDIR_DEFAULT
fi

LIB_SUNWUTO="$BASEDIR_O/SUNWut/lib"
LIB_SUNWUTPS="$BASEDIR_PS/SUNWut/lib"
LIB_SUNWUTGSM="$BASEDIR_GSM/SUNWut/lib"

UTPAMCFG=$LIB_SUNWUTO/utpamcfg
SRLIB_GU="$LIB_SUNWUTPS/sunray_get_user.so.1"
AMGHLIB="$LIB_SUNWUTGSM/pam_sunray_amgh.so.1"
SRLIB="$LIB_SUNWUTPS/pam_sunray.so"
ADMINGUILIB="$LIB_SUNWUTPS/pam_sunray_admingui.so.1"

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

# SunRay-qualified CDE application names in pam.conf
DTLOGIN="dtlogin-$SUNRAY_XSERVER_CLASS_TYPE"
DTSESSION="dtsession-$SUNRAY_XSERVER_CLASS_TYPE"

# GDM app name in pam.conf
GDM="gdm"

# GNOME application name in pam.conf
XSCREENSAVER="xscreensaver"

PAM_CONF="/etc/pam.conf"
PAM_DIR="/etc/pam.d"

NSCLOGIN=utnsclogin
GULOGIN=utgulogin
ADMINGUI=utadmingui

SRTAG="SunRay Server Software"

export PKG_INSTALL_ROOT

if [ $action = disable ] ; then
    utpam_unconfigure
else
    utpam_configure
fi

exit 0
