New version of my hint.

Stef Bon stef at bononline.nl
Fri Oct 21 03:29:28 PDT 2005


Hello,

Again some changes:

- forget pam_storepw and make us of pam_script version 0.1.5, which can handle
the password too. 
- make use of sudo in stead of su.

Stef Bon
-------------- next part --------------
AUTHOR: Stef Bon <stef at bononline dot nl>

DATE: 2005-10-21

LICENSE: GNU Free Documentation License Version 1.2

SYNOPSIS: Execute scripts at begin and end of a usersession using PAM with some examples like dbus.

DESCRIPTION:
This hint is about the ability to execute scripts when a session for a user starts, 
and when it ends. 

I started to when I was looking for a sollution to store my kde settings on a central 
computer. Later I discovered that scripts for other purposes are possible.

It works via pam. I know this can be done via 
the scripts in the profile.d directory which are executed when a shell starts, 
but pam is in my opinion the best place to this. 

The original hint is at http://linux.bononline.nl. You can download all the scripts there too.

ATTACHMENTS:


PREREQUISITES:
This hint requires that you have sufficient knowledge of LINUX in general, and 
PAM in particular.
shadow-4.0.3 or shadow-4.0.11.1 or 4.0.12 (at this moment the latest). 
For the option runas=root to work, you'll need these. 
Other versions of shadow (4.0.4.1 and 4.0.7) are causing problems. In the 
code of login of these versions, root privileges are dropped too early 
(before the pam_close_session call).


HINT:

1. Use scripts at begin and end of a session: introduction
-----------------------------------------------------------------------------

When using modern Linux systems, you can use your account on more 
systems to login. This is possible with LDAP, nss-ldap and pam-ldap.
But every machine has it's own settings for kde for example, so you can't 
take your settings with you, just like "roamingprofiles".

I started to look for a sollution to solve this, and with PAM and a module pam_script,
this was possible.

When looking at PAM for Linux, it has the ability to use a loadable plugin, which will 
take care for retrieving settings from a central network host when a session opens, 
and storing the same settings to the same host when a sessions closes.

This is not possible for a standard PAM installation. There is no standard pam module
which will execute scripts in general.  But there is a module, developed seperately, 
pam_script, which will do this.

Later I discovered that I could use this construction for more purposes:
- browsing the network using FUSE, fusesmb using the credentials provided at login; 
- start dbus-launcher per session/user and make environmentvariables available;



2. Installing the software
--------------------------


2.1 pam_script
--------------


Get the module pam_script from http://freshmeat.net/projects/pam_script. 
I'm using version 0.1.5.

unpack:

tar -xzf pam-script-*.tar.gz

compile and move to the proper place:

cd pam-script-*

make
mv pam_script.so /lib/security
chown root:root /lib/security/pam_script.so
chmod 755 /lib/security/pam_script.so


2.2 Adjusting pam configuration
-------------------------------


Adjusting the /etc/pam.d/login file:


-- snip --

session		optional	pam_mail.so dir=/var/mail noenv close empty
session		optional	pam_motd.so
session		required	pam_unix.so shadow md5
session		required	pam_script.so runas=root
session		required	pam_ldap.so


Pam_script has the ability (from version 0.1.5) to get the password provided at login, 
and make this available via an environmentvariable PAM_AUTHTOK to scripts. 
Insert it in the authpart:


-- snip --

auth		required	pam_shells.so
auth		sufficient	pam_unix.so shadow md5
auth		required	pam_script.so expose=1
auth		required	pam_ldap.so use_first_pass


Note that if the module pam_unix.so succees, pam_script.so is skipped. This no problem for me. On my
desktop I only want pam_script and the scripts for my normal users, which are in the LDAP database.
I had to do this, because version 0.1.5 does not ask for a password: another module has to do that. 
That other module is pam_ldap.so or pam_unix.so.

When using other ways for users to login than the standard, like a X-based login as kdm,
adjust them the same way. On my machine I login frequently in with kdm, and that uses the 
kde-service, which is a symlink to the login-service:

cd /etc/pam.d

ls -al

drwxr-xr-x   2 root root  392 2005-07-11 13:59 .
drwxr-xr-x  36 root root 3152 2005-07-19 14:09 ..
-rw-r--r--   1 root root  253 2004-05-12 16:06 chage
-rw-r--r--   1 root root   69 2005-01-12 00:20 cups
-rw-r--r--   1 root root  330 2005-01-19 10:00 fcron
-rw-r--r--   1 root root  506 2004-12-22 23:04 fcrontab
lrwxrwxrwx   1 root root    5 2005-07-11 13:59 kde -> login
lrwxrwxrwx   1 root root    5 2005-07-11 13:59 kde-np -> login
-rw-r--r--   1 root root  931 2005-07-19 13:20 login
-rw-r--r--   1 root root  305 2005-07-16 22:46 other
-rw-r--r--   1 root root  282 2003-08-13 18:22 passwd
-rw-r--r--   1 root root  411 2003-08-12 17:53 shadow
-rw-r--r--   1 root root  448 2005-07-18 10:18 su
-rw-r--r--   1 root root  666 2005-02-28 12:59 sudo
-rw-r--r--   1 root root  257 2004-05-12 16:05 useradd
-rw-r--r--   1 root root  200 2005-04-25 09:05 xscreensaver



Notes:

- the pam_script.so uses some parameters. All of them are described in the README in the
source directory.
I use expose=1 in the autpart because I want the password to be used by fusesmb.
And in the sessionpart I use runas=root because some actions (like umount) have to be run as root.
- when logging out using the normal console, the service is 'login'. Login did not call
all the modules. I had to add a new parameter to the /etc/login.defs :

CLOSE_SESSIONS        yes

This option is there already in the shadow package since 2002-10-14, according to the ChangeLog,
but does not appear in the login.defs, but is important for closing a session when the service is 
login.
In the newest shadow package (4.0.12) this option is removed completely: the session is always 
closed.



2.3 Creating the session scripts
--------------------------------


The pam_script works with two standard scripts, onsessionopen and onsessionclose in the
/etc/security directory. 
	
cat >> /etc/security/onsessionopen << "EOF"
#!/bin/bash

userid=$1
service=$2
userproperties=$(getent passwd | grep -E "^$userid")

if [ -z "$userproperties" ]; then

	#
	# userproperties not found: something wrong
	#

	echo "User not found."
	exit

fi;

nrusers=$(w -h  $userid | wc -l );

firstsession=0;

case "$service" in
    login)
	if [ $nrusers -eq 0 ]; then

	    firstsession=1;

	fi;
	;;
    kde)
	if [ $nrusers -eq 0 ]; then

	    firstsession=1;
	fi;
	;;
esac;



if [ $firstsession -eq 1 ]; then

    # There are no other pending sessions for this user

    if [ -d /var/lib/pam/scripts/onsessionopen ]; then

	for script in /var/lib/pam/scripts/onsessionopen/*.sh; do
	    if [ -x $script ] ; then
		eval $script $userid
	    fi;
	done;
	
    fi;	

fi;

EOF



cat >> /etc/security/onsessionclose << "EOF"
#!/bin/bash

userid=$1
service=$2

userproperties=$(getent passwd | grep -E "^$userid");

if [ -z "$userproperties" ]; then

	#
	# userproperties not found: something wrong
	#

	echo "User not found."
	exit

fi;

nrusers=$(w -h $userid | wc -l );

lastsession=0;

case "$service" in
	login)
		if [ $nrusers -eq 1 ]; then

			lastsession=1;

		fi;
		;;
	kde)
		if [ $nrusers -eq 0 ]; then

			lastsession=1;
		fi;
		;;
esac;


if [ $lastsession -eq 1 ]; then

    # This is the last session for this user

    if [ -d /var/lib/pam/scripts/onsessionclose ]; then

	for script in /var/lib/pam/scripts/onsessionclose/*.sh ; do
	    if [ -x $script ] ; then
		eval $script $userid
	    fi;
	done;
	
    fi;	

fi;

EOF

cat >> /etc/security/onauth << "EOF"
#!/bin/bash

userid=$1
service=$2
userproperties=$(getent passwd | grep -E "^$userid")

if [ -z "$userproperties" ]; then

    #
    # userproperties not found: something wrong
    #
    
    echo "User not found."
    exit
    
fi;


homedir=$(echo $userproperties | cut -d ":" -f 6);
gidnr=$(echo $userproperties | cut -d ":" -f 4);
uidnr=$(echo $userproperties | cut -d ":" -f 3);

nrusers=$(w -h $userid | wc -l);

firstsession=0;

case "$service" in

    login)
	
	if [ $nrusers -eq 0 ]; then
	    
	    firstsession=1;
	    
	fi;
	;;

    kde)
	
	if [ $nrusers -eq 0 ]; then
	    
	    firstsession=1;
	    
	fi;
	;;
esac;	    


if [ $firstsession -eq 1 ]; then
        
    if [ -d /var/lib/pam/scripts ]; then
	    
	for script in /var/lib/pam/scripts/onauth/*.sh; do
	
	    if [ -x $script ]; then
		
		eval $script $userid $service $PAM_AUTHTOK
		
	    fi;
	done;
	
    fi;

fi;

exit 0
EOF


chown root:root /etc/security/onsession*
chmod 755 /etc/security/onsession*
chown root:root /etc/security/onauth
chmod 755 /etc/security/onauth


Create the following directories:

mkdir -p /var/lib/pam/scripts/onsessionopen
mkdir -p /var/lib/pam/scripts/onsessionclose
mkdir -p /var/lib/pam/scripts/onauth

Here is where the scripts will go.


Notes:

-  as you can see I use the command "w" to determine the users logged in. 
Other utilities as who, users and last gave not reliable information. It 
looks as if the utmp file is not always presenting the right values. 
Utilities as who,users and last show information from utmp without any check, so 
they inherit the faults. 'w' does some extra checking, which makes it more 
usable. 
Other pammodules, like pam_mount, have other ways to keep track of the amount of logins 
per user. With pam_mount a seperate file (/var/run/pam_mount/$userid) is created for
this purpose.
Anyone knowing a better way to determine how many times a user is logged 
in, please let me know.

- Sudo in needed.
in the examples 'sudo' is used. This is not difficult. Sudo does not have to support PAM.
That's not neccasary. It's only needed to execute a command as normal user when the id is root.

- Some remarks about the behaviour of the command "w"
The number of sessions is zero when logging in: the user is still not logged in. This 
happens with all the services I'm using: login and kdm.
When logging out, something strange happens: it's one when logging out when the service 
is 'login', zero when service is "kde" (and this user is not logged in on any other way).
I've just discovered what's causing this. The program "login" is responsible. It stores a
record in the utmp-database with the pid of the login-proces (the parent), not the pid of the 
shell (the child). When the session is closed, the proces with the pid stored in the 
utmp database isn't closed at all. That's the login program itself, which is still running.
So, when using "w" to check the users logged in, it finds that the proces with the pid in the 
utmp database for this user is still running, it concludes this user must still be logged in, which is not
the case.<br>
I've posted a message about this issue on the maillinglist op shadow. 
(http://lists.pld.org.pl/mailman/pipermail/shadow/2005-October/thread.html)

- I choose to execute the scripts only when it's the first time a user logs in, or the
last time he/she logs out. It's also possible to leave that to the scripts (in /var/lib/pam/scripts).




3. Examples


3.1 Scripts for storing and retrieving my kde-settings on a central server
--------------------------------------------------------------------------


When using modern Linux systems, you can use your account on more 
systems to login. This is possible with LDAP, nss-ldap and pam-ldap.
But every machine has it's own settings for kde for example, so you can't 
take your settings with you, just like "roamingprofiles".

I started to look for a sollution to solve this, and with PAM and a module pam_script,
this was possible.

First the script to get the settings from the central rsync server:


cd /var/lib/pam/scripts/onsessionopen

cat >> kde.sh << "EOF"
#!/bin/bash

retcode=0;

userid=$1
userproperties=$(getent passwd | grep -E "^$userid")
homedir=$(echo $userproperties | cut -d ":" -f 6);
gidnr=$(echo $userproperties | cut -d ":" -f 4);
uidnr=$(echo $userproperties | cut -d ":" -f 3);


if [ -d $homedir ]; then

	usershareavailable=$(rsync 192.168.0.3::4users | grep -w $userid );

	retcode=$?

	if [ $retcode -eq 0 ]; then

		#
		# no error
		#

		if [ -z "$usershareavailable" ]; then

			#
			# directory for this user does not exist
			#
			# maybe a default?
			#

			echo "No directory on rsyncserver available for this user."

		else

			thereisarchive=$(rsync 192.168.0.3::4users/$userid/.kde | grep -w ".kde");

			retcode=$?

			if [ $retcode -eq 0 ]; then

				if [ -n "$thereisarchive" ]; then

					#
					# no error & archive found
					#

					rsync -rptgozu 192.168.0.3::4users/$userid/.kde/ $homedir/.kde

					chown -R $uidnr:$gidnr $homedir/.kde

				else

					echo "No kde-settings for this user available on rsyncserver."
				fi;

			fi;
		fi;
	fi;
fi;

if [ $retcode -ne 0 ]; then
	echo "An error with the rsynccommando for kde ($retcode)."
fi;

exit $retcode

EOF

And the logout script:

cd ../onsessionclose

cat >> kde.sh << "EOF"
#!/bin/bash

retcode=0;

userid=$1
userproperties=$(getent passwd | grep -E "^$userid")
homedir=$(echo $userproperties | cut -d ":" -f 6);
gidnr=$(echo $userproperties | cut -d ":" -f 4);
uidnr=$(echo $userproperties | cut -d ":" -f 3);

if [ -d $homedir/.kde ]; then
	
	#
	# there is something to sync
	#

	usershareavailable=$(rsync 192.168.0.3::4users | grep -w $userid );

	retcode=$?

	if [ $retcode -eq 0 ]; then

		#
		# no error
		#

		if [ -z "$usershareavailable" ]; then

			#
			# directory for this user does not exist yet
			#
			# a trick to create a directory on the rsyncserver

			mkdir /tmp/$userid

			rsync -dptgoz /tmp/$userid 192.168.0.3::4users

			rmdir /tmp/$userid

		fi;

		if [ $retcode -eq 0 ]; then

			#
			# no error found
			#

			rsync -rptgoz --delete $homedir/.kde 192.168.0.3::4users/$userid

			retcode=$?

		fi;
	fi;
fi;

if [ $retcode -ne 0 ]; then
	echo "An error with the rsynccommando for kde ($retcode)."
fi

exit $retcode

EOF

Notes:

- see the difference between the rsync commando for login and logout. 
First the -u flag at login and not logout.
I don't want newer files get overwritten on login. When due to some reason 
the settings are not saved properly, the most recent settings are still on the
workstation and not on the server. You don't want them to be overwritten. That's
reason for the -u flag at login. Not at logout. Why? Good question. 
Now the --delete flag at logout.
Obvious, you don't want that there are still files on the server, which are not 
there (anymore?) on the workstation.

- Storing settings on a central server can become very complicated when one user is 
logged on more than one machine at the same time. There is now way to 
'merge' the settings. The setting saved at the last logout are the ones which 
will remain on the server. Windows uses the same strategy.

- These scripts are for the settings of kde. But this is just an example.
You can put any script ( with the .sh extension )
in this directory. The bookmarks of Firefox for example.

The rsyncserver is hosted at 192.168.0.3, with a share [4users]. This share
can be accessed without credentials: public access. Making it work with 
user-based access is not so simple. The rsyncdaemon does not support pam yet. 
This could work when shell for transport is ssh. Work to be done.

As you can see I use the rsync algoritm, but you can use also a
ftp server with write-access. The big advantage of rsync however 
is the efficient way it handles (non)changes.

This way it looks at the way Windows workstations handle settings: 
when there is a [profiles] share, the server supports "roamingprofiles".
I think the way the saving en getting the "profile" at these 
Windows machines looks a lot like rsync for Linux.



3.2 Browsing the network using FUSE, fusesmb and pam_storepw
------------------------------------------------------------

Very new is FUSE. At this moment the FUSE package contains a kernelmodule, a library and utilities.
Soon the module will be standard in the kernel. For more information see the website of course.<br>
Pam_script has the ability (from version 0.1.5) to get the password provided at login, and provide
this via an evironmentvariable PAM_AUTHTOK to scripts. A script for fusesmb can write this value to
a configurationfile (~/.smb/fusesmb.conf) to browse the network with the credentials provided at login.

Get it from the projectsite:

http://fuse.sourceforge.net

Installing FUSE:

cd fuse-2.3.0
./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var --enable-kernel-module --enable-lib --enable-util
make
make install

A module is installed, fuse.
To load it:

modprobe fuse

and add it to /etc/sysconfig/modules.

Configuration of fuse goes via the fuse.conf file in the /etc directory:

cat >> /etc/fuse.conf << "EOF"

mount_max = 999

user_allow_other
EOF

Get fusesmb:

Look for a link at the site of FUSE.

Installing fusesmb:

cd fusesmb-0.8.1
./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var
make
make install

It requires samba-3.0.*.
With samba-3.0.14a it works fine. Not with samba-3.0.20 at this moment. Check the website for more info.


Now the actual scripts:

cd /var/lib/pam/onsessionopen

cat >> fusesmb.sh << "EOF"
#!/bin/bash

retcode=0;

userid=$1
userproperties=$(getent passwd | grep -E "^$userid")
homedir=$(echo $userproperties | cut -d ":" -f 6);
gidnr=$(echo $userproperties | cut -d ":" -f 4);
uidnr=$(echo $userproperties | cut -d ":" -f 3);

if [ -d $homedir ]; then

    if [ ! -d $homedir/network ]; then
	mkdir -p $homedir/network
	chown $uidnr:$gidnr $homedir/network
    fi

    if [ $(id -u) -eq 0 ]; then
 	sudo -H -u $userid /bin/sh -c "fusesmb $homedir/network -o fsname=fusesmb,default_permissions,allow_other"
	retcode=$?
    elif [ $(id -u) -eq $uidnr ]; then 
    	fusesmb $homedir/network -o fsname=fusesmb,default_permissions,allow_other
	retcode=$?
    fi	
    
fi;


if [ $retcode -ne 0 ]; then
    echo "An error with fusesmb ($retcode)."
fi;

exit $retcode
EOF

And the logout script:

cd ../onsessionclose

cat >> fusesmb.sh << "EOF"
#!/bin/bash

retcode=0;

userid=$1
userproperties=$(getent passwd | grep -E "^$userid")
homedir=$(echo $userproperties | cut -d ":" -f 6);
gidnr=$(echo $userproperties | cut -d ":" -f 4);
uidnr=$(echo $userproperties | cut -d ":" -f 3);

if [ -d $homedir ]; then

    if [ -n "$(mount | grep $homedir/network)" ]; then

	fusermount -u $homedir/network

    fi;
    
    if [ -e $homedir/.smb/fusesmb.conf ]; then
    
	rm -f $homedir/.smb/fusesmb.conf
    
    fi;

fi;


if [ $retcode -ne 0 ]; then
    echo "An error with fusesmb ($retcode)."
fi;

exit $retcode
EOF


And the onauth script:

cat >> /var/pam/scripts/onauth/fusesmb.sh << "EOF"
#!/bin/bash

retcode=0;

userid=$1
service=$2
authtok=$3

userproperties=$(getent passwd | grep -E "^$userid")
homedir=$(echo $userproperties | cut -d ":" -f 6);
gidnr=$(echo $userproperties | cut -d ":" -f 4);
uidnr=$(echo $userproperties | cut -d ":" -f 3);

if [ -d $homedir ]; then


	if [ ! -d $homedir/.smb ]; then

	    mkdir -p $homedir/.smb
	    chown $uidnr:$gidnr $homedir/.smb
	    chmod 755 $homedir/.smb

	fi

	if [ -n "$authtok" ]; then

	    rm -f $homedir/.smb/fusesmb.conf

	    touch $homedir/.smb/fusesmb.conf
	    chown $uidnr:$gidnr $homedir/.smb/fusesmb.conf
	    chmod 600 $homedir/.smb/fusesmb.conf

	    echo "[global]" > $homedir/.smb/fusesmb.conf
	    echo "username = $userid" >> $homedir/.smb/fusesmb.conf
	    echo "password = $authtok" >> $homedir/.smb/fusesmb.conf
    
	fi;

fi;


if [ $retcode -ne 0 ]; then
    echo "An error with fusesmb ($retcode)."
fi;

exit $retcode
EOF


Notes:

- The fusesmb script in the onauth directory overwrites any existing fusesmb.conf in the ~/.smb 
directory. I do not have any simple sollution to do otherwise. One way to do that is the use of 
a template. In this template the variables username and password get inserted with 'sed'.



3.3 Starting the sessiondaemon of dbus and make the environmentvariables available
----------------------------------------------------------------------------------

The dbus package is split up in two parts: one systemwide part and one for (each) session/user.
The systemwide part (a daemon) is started at boottime, with special privileges of a dedicated user.
The sessionwide part (also a daemon) has to started when a session for a user begins, 
and stopped when the session ends.

The construction with pam I'm using here is ideal for this. Create a script in the login directory to
start the sessiondaemon for a user, running with the privileges of that user. In the logout directory an 
other script has to stop that daemon.
But is not so simple as that. Some variables (DBUS_SESSION_BUS_ADDRESS and DBUS_SESSION_BUS_PID) have to 
be available in the environment to every application which works with dbus. 
IMHO the setting of these variables should go in the bash-startupscripts.
Then whatever script or application you're running, these variables are set
to the right value. 

Bash Shell startupfiles
-----------------------


                     global             user
		 ------------------------------
		     
		 /etc/bashrc          ~/.bashrc
		 /etc/profile         ~/.bash_profile
		 /etc/profile.d       no equivalent
		 
When bash is started by "login" as an interactive login shell, it reads /etc/profile and ~/.bash_profile.
Bash is also started by "kdm", and the files /etc/profile and ~/.bash_profile are sourced.

The sessionwide environmentvariables can't go in the /etc/profile.d directory, because it differs for every user. 
There is no equivalent in de homedirectory in startup of BASH in BLFS at this moment. My idea
is to create a .profile.d directory in the homedirectory of a user, containing scripts which has
to be executed when a BASH session is started for that user.

By adding the following code to the $HOME/.bash_profile at the end of it any script with the .sh extension
will be executed for this user only:

-- snip --

for script in $HOME/.profile.d/*.sh ; do
        if [ -x $script ]; then
                . $script
        fi
done

-- snip --

Now create as a user in his/her homedirectory:

mkdir $HOME/.profile.d


Compiling and installing it is described in the latest versions of BLFS 
(beginning 200510..). 

I assume that dbus is installed, and that it is started at boottime.

Create a script in the onsessionopen directory dbus.sh:

cd /var/lib/pam/onsessionopen

cat >> dbus.sh << "EOF"
#!/bin/bash

retcode=0;

userid=$1
userproperties=$(getent passwd | grep -E "^$userid")
homedir=$(echo $userproperties | cut -d ":" -f 6);
gidnr=$(echo $userproperties | cut -d ":" -f 4);
uidnr=$(echo $userproperties | cut -d ":" -f 3);

if [ -d $homedir ]; then

    if [ -d $homedir/.profile.d ]; then
	
	if [ $(id -u) -eq 0 ]; then
 	    sudo -u $userid /bin/sh -c "dbus-launch --auto-syntax > $homedir/.profile.d/dbus.sh"
	    retcode=$?
	    chown $uidnr:$gidnr $homedir/.profile.d/dbus.sh
	    chmod u+x $homedir/.profile.d/dbus.sh
	elif [ $(id -u) -eq $uidnr ]; then 
    	    dbus-launch --auto-syntax > $homedir/.profile.d/dbus.sh
	    retcode=$?
	    chmod u+x $homedir/.profile.d/dbus.sh
	fi
	retcode=$?

    fi

fi;


if [ $retcode -ne 0 ]; then
    echo "An error with dbus ($retcode)."
fi;

exit $retcode
EOF

This script will start the dbus session daemon for this user, and will create a dbus.sh script in the .profile.d
directory of this user. 

Creating the dbus.sh script in the logout directory:

cd ../onsessionclose

cat >> dbus.sh << "EOF"
#!/bin/bash

retcode=0;

userid=$1
userproperties=$(getent passwd | grep -E "^$userid")
homedir=$(echo $userproperties | cut -d ":" -f 6);
gidnr=$(echo $userproperties | cut -d ":" -f 4);
uidnr=$(echo $userproperties | cut -d ":" -f 3);

if [ -d $homedir ]; then

    if [ -d $homedir/.profile.d ]; then
	
	if [ -f $homedir/.profile.d/dbus.sh ]; then
	    . $homedir/.profile.d/dbus.sh
	    if [ -n "$DBUS_SESSION_BUS_PID" ]; then
		if [ $(id -u) -eq 0 ]; then
		    sudo -H -u $userid /bin/sh -c "kill $DBUS_SESSION_BUS_PID"
		    retcode=$?
		    rm $homedir/.profile.d/dbus.sh
		elif [ $(id -u) -eq $uidnr ]; then
		    kill $DBUS_SESSION_BUS_PID
		    retcode=$?
		    rm $homedir/.profile.d/dbus.sh
		fi        
	    fi
	fi
    fi

fi;


if [ $retcode -ne 0 ]; then
    echo "An error with dbus ($retcode)."
fi;

exit $retcode
EOF

Now when bash is started, the dbus.sh script in the $HOME/.profile.d is found and executed
by $HOME/.bash_profile. 


ACKNOWLEDGEMENTS:
Thanks to the author of pam_script, Izak Burger.

CHANGELOG:
[2005-07-18]
  * Initial hint.
[2005-07-20]
  * Some text changes: things could be explained better
  * remove the -f parameter in the 'last' command. It works now with the standard
    /var/log/wtmp file. The /var/run/utmp file was not so reliable after all.
  * added the --delete flag to the rsync commando at logout. 
  * added the -u flag when getting the settings at login. 
  * added more comment on saving and restoring settings in a mutiuser/multihost (wow!)
    environment.
[2005-07-27]
  * Use the command 'w' to determine how many times a user is logged in on the
    system in stead of 'last'.
  * Correction of some phrases: incorrect English. 
[2005-08-10]
  * added some comment about the version of shadow to use. Some versions caused
    problems.
  * corrected some typos.
  * added some comment about the option runas=root which can be very insecure     
[2005-08-23]
  * moved the scriptdirectory to a central place (/var/lib/sync4settings) in stead of
    the homedirectory. This was very insecure.
    The scripts have to handle a general $userid.
    Created a central map on the resyncserver [4users] where the settings are stored
    Added a check what the service is at logout: kdm or login. The command 'w' gives 
    different output. 
    Added comment about the removal of the option "CLOSE_SESSIONS" in version 4.0.12 
    of the shadow package.
[2005-09-27]
  * moved the scriptdirectory to /var/lib/pam/scripts in stead of
    /var/lib/sync4settings.
  * to execute a script use the command "eval".
  * more comment.
[2005-09-29]
  * Changed the name of the hint: Execute scripts at begin and end of a usersession using PAM 
  * added two examples: fusesmb and dbus.
[2005-10-21]
  * Use sudo in stead of su to execute scripts as a normal user
  * Use pam_script-0.1.5. The important change in this version is the ability to make the 
    authtentification tokens available to the scripts. This means that I do not have to use
    the module pam_storepw anymore.
    Added the onauth script in /etc and the /var/lib/pam/scripts/onauth directory. 
  *


TODO:

  * look for some way to show information about progres and/or errors when executing
    the scripts when using a graphical login. xconsole?
  * add another example like mounting shares with mount.cifs.
  * what to do when system crashes at the next reboot?
  * 'shutdown' does close the shellsessions properly. Why?

DONE:
  * find out why runas=root does not work with pam_script at logout for me:
    all the credits should go to the maintainer of pam_script.


More information about the hints mailing list