r994 - trunk

archaic at linuxfromscratch.org archaic at linuxfromscratch.org
Fri Oct 21 07:26:37 PDT 2005


Author: archaic
Date: 2005-10-21 08:26:37 -0600 (Fri, 21 Oct 2005)
New Revision: 994

Modified:
   trunk/execute-session-scripts-using-pam.txt
Log:
Updated: execute-session-scripts-using-pam.txt

Modified: trunk/execute-session-scripts-using-pam.txt
===================================================================
--- trunk/execute-session-scripts-using-pam.txt	2005-10-18 04:02:56 UTC (rev 993)
+++ trunk/execute-session-scripts-using-pam.txt	2005-10-21 14:26:37 UTC (rev 994)
@@ -1,6 +1,6 @@
 AUTHOR: Stef Bon <stef at bononline dot nl>
 
-DATE: 2005-10-04
+DATE: 2005-10-21
 
 LICENSE: GNU Free Documentation License Version 1.2
 
@@ -17,6 +17,8 @@
 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:
 
 
@@ -52,8 +54,8 @@
 pam_script, which will do this.
 
 Later I discovered that I could use this construction for more purposes:
-- browsing the network using FUSE, fusesmb and pam_storepw. 
-- start dbus-launcher per session/user and make environmentvariables available 
+- browsing the network using FUSE, fusesmb using the credentials provided at login; 
+- start dbus-launcher per session/user and make environmentvariables available;
 
 
 
@@ -66,7 +68,7 @@
 
 
 Get the module pam_script from http://freshmeat.net/projects/pam_script. 
-I'm using version 0.1.3.
+I'm using version 0.1.5.
 
 unpack:
 
@@ -88,13 +90,34 @@
 
 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
+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:
@@ -125,10 +148,9 @@
 Notes:
 
 - the pam_script.so uses some parameters. All of them are described in the README in the
-source directory. One of them, runas, when used as runas=root did not work for me. It appears
-that it's the login command - part of the shadow package - is causing the problems. 
-Shadow-4.0.11.1 and later work fine.
-
+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 :
 
@@ -169,13 +191,33 @@
 
 nrusers=$(w -h  $userid | wc -l );
 
-if [ $nrusers -eq 0 ]; then
+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/login ]; then
+    if [ -d /var/lib/pam/scripts/onsessionopen ]; then
 
-	for script in /var/lib/pam/scripts/login/*.sh; do
+	for script in /var/lib/pam/scripts/onsessionopen/*.sh; do
 	    if [ -x $script ] ; then
 		eval $script $userid
 	    fi;
@@ -210,30 +252,32 @@
 
 nrusers=$(w -h $userid | wc -l );
 
-syncsettings=0;
+lastsession=0;
 
 case "$service" in
 	login)
 		if [ $nrusers -eq 1 ]; then
 
-			syncsettings=1;
+			lastsession=1;
 
 		fi;
+		;;
 	kde)
 		if [ $nrusers -eq 0 ]; then
 
-			syncsettings=1;
+			lastsession=1;
 		fi;
+		;;
 esac;
 
 
-if [ $syncsettings -eq 1 ]; then
+if [ $lastsession -eq 1 ]; then
 
     # This is the last session for this user
 
-    if [ -d /var/lib/pam/scripts/logout ]; then
+    if [ -d /var/lib/pam/scripts/onsessionclose ]; then
 
-	for script in /var/lib/pam/scripts/logout/*.sh ; do
+	for script in /var/lib/pam/scripts/onsessionclose/*.sh ; do
 	    if [ -x $script ] ; then
 		eval $script $userid
 	    fi;
@@ -245,13 +289,87 @@
 
 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/login
-mkdir -p /var/lib/pam/scripts/logout
+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.
 
@@ -270,15 +388,27 @@
 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 can't explain this difference. I'm trying to find this out. WORK TO BE DONE.
+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 logs out. It's also possible to leave that to the scripts (in /var/lib/pam/scripts).
+last time he/she logs out. It's also possible to leave that to the scripts (in /var/lib/pam/scripts).
 
 
 
@@ -290,9 +420,19 @@
 --------------------------------------------------------------------------
 
 
+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".
 
-cd /var/lib/pam/scripts/login
+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
 
@@ -365,7 +505,7 @@
 
 And the logout script:
 
-cd ../logout
+cd ../onsessionclose
 
 cat >> kde.sh << "EOF"
 #!/bin/bash
@@ -471,7 +611,11 @@
 3.2 Browsing the network using FUSE, fusesmb and pam_storepw
 ------------------------------------------------------------
 
-Very new is FUSE. 
+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:
 
@@ -491,7 +635,15 @@
 
 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.
@@ -506,32 +658,10 @@
 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.
 
-Installing pam_storepw:
 
-cd libpam_storepw-0.1
-
-make
-mv pam_storepw.so /lib/security
-chown root:root /lib/security/pam_storepw.so
-chmod 755 /lib/security/pam_storepw.so
-
-Adjusting the /etc/pam.d/login file:
-
---snip--
-
-auth		required	pam_shells.so
-auth		required	pam_storepw.so
-auth		sufficient	pam_ldap.so 
-auth		required	pam_unix.so use_first_pass,shadow
-
-Now, whenever somebody logs in, a file with the credentials is created in the 
-/var/run/pw directory. The format is:
-username = whatever
-password = secretofwhatever
-
 Now the actual scripts:
 
-cd /var/lib/pam/login
+cd /var/lib/pam/onsessionopen
 
 cat >> fusesmb.sh << "EOF"
 #!/bin/bash
@@ -546,45 +676,19 @@
 
 if [ -d $homedir ]; then
 
-    if [ $(id -u) -eq 0 ]; then
-
-	if [ ! -d $homedir/.smb ]; then
-	
-	    mkdir -p $homedir/.smb
-	    chown $uidnr:$gidnr $homedir/.smb
-	    chmod 755 $homedir/.smb
-
-	fi
-	
-	if [ -f /var/run/pw/$userid ]; 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
-	
-	    cat /var/run/pw/$userid >> $homedir/.smb/fusesmb.conf
-
-	fi;
-	
-	
-    fi;
-	
     if [ ! -d $homedir/network ]; then
 	mkdir -p $homedir/network
 	chown $uidnr:$gidnr $homedir/network
     fi
 
-
     if [ $(id -u) -eq 0 ]; then
- 	su - $userid -c "fusesmb $homedir/network -o fsname=fusesmb" >> /dev/null
+ 	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
+    	fusesmb $homedir/network -o fsname=fusesmb,default_permissions,allow_other
+	retcode=$?
     fi	
-
+    
 fi;
 
 
@@ -597,7 +701,7 @@
 
 And the logout script:
 
-cd ../logout
+cd ../onsessionclose
 
 cat >> fusesmb.sh << "EOF"
 #!/bin/bash
@@ -614,9 +718,15 @@
 
     if [ -n "$(mount | grep $homedir/network)" ]; then
 
-	umount $homedir/network
+	fusermount -u $homedir/network
 
     fi;
+    
+    if [ -e $homedir/.smb/fusesmb.conf ]; then
+    
+	rm -f $homedir/.smb/fusesmb.conf
+    
+    fi;
 
 fi;
 
@@ -629,18 +739,66 @@
 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:
 
-- when logging in the fusesmb.sh script creates a new fusesmb.conf file, overwriting any old one.
-This is good for me, and I'm not planning to do so. If you don't want this, feel free to write this 
-yourself.
+- 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'.
 
-- the password is stored in the /var/run/pw/$userid file, with only root access, and later in the 
-$homedir/.smb/fusesmb.conf, with only this user access. Maybe not secure at all. But I do not know any other 
-way to do this.
 
 
-
 3.3 Starting the sessiondaemon of dbus and make the environmentvariables available
 ----------------------------------------------------------------------------------
 
@@ -657,7 +815,22 @@
 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. 
-This information can't go in the /etc/profile.d directory, because it differs for every user. 
+
+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.
@@ -685,8 +858,10 @@
 
 I assume that dbus is installed, and that it is started at boottime.
 
-Create a script in the login directory dbus.sh:
+Create a script in the onsessionopen directory dbus.sh:
 
+cd /var/lib/pam/onsessionopen
+
 cat >> dbus.sh << "EOF"
 #!/bin/bash
 
@@ -703,11 +878,14 @@
     if [ -d $homedir/.profile.d ]; then
 	
 	if [ $(id -u) -eq 0 ]; then
- 	    su - $userid -c "dbus-launch --auto-syntax > $homedir/.profile.d/dbus.sh 2>&1" >> /dev/null
+ 	    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=$?
 
@@ -728,6 +906,8 @@
 
 Creating the dbus.sh script in the logout directory:
 
+cd ../onsessionclose
+
 cat >> dbus.sh << "EOF"
 #!/bin/bash
 
@@ -746,11 +926,17 @@
 	if [ -f $homedir/.profile.d/dbus.sh ]; then
 	    . $homedir/.profile.d/dbus.sh
 	    if [ -n "$DBUS_SESSION_BUS_PID" ]; then
-		su - $userid -c "kill -SIGTERM $DBUS_SESSION_BUS_PID 2>/dev/null" >> /dev/null 2>&1
-		rm $homedir/.profile.d/dbus.sh
+		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;	
-	retcode=$?
+	fi
     fi
 
 fi;
@@ -807,12 +993,22 @@
 [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:




More information about the hints mailing list