Re: Dynamically creating users at login



> > I'm not aware of any PAM module that does this for the local unix pwd
> > database.  But I suppose someone could modify the pam_unix module to
> > just run useradd and try again.
> > 
> Could you tell me where to start on that?
> Like I said, I'm a newbie when it comes to PAM.

We have a config file in /etc/pam.d:

--------------------------------------------------
# Allow either NetWare or Unix authentication.
# Future versions may only allow NetWare.
auth            required        pam_listfile.so item=user sense=deny file=/etc/s
ecurity/fakeusers
auth            required        pam_nologin.so
auth            sufficient      pam_unix.so
auth            requisite       pam_ncp_auth.so
auth            required        pam_cachepw.so

account         required        pam_run.so /usr/sbin/pwfsession

session         required        pam_run.so /usr/sbin/pwfsession
session         required        pam_unix.so
session         optional        pam_console.so
session         optional        pam_lastlog.so
session         optional        pam_motd.so

password        required        pam_ncp_auth.so 

------------------------------------------------

And then we have /usr/sbin/pwfsession (see attatched) which indeed calls
useradd (along with some other magic).  The script itself is tailored to our
specific needs, but should be usable as a template to create your own.

We are aware that it has shortcomings, but it has worked for a while.

Note, that the code is (as far as we are concerned) released under the GPL,
and for the purpose of this email is copyright Ben Harris.

Additionally you'll need pam-run, which is a small pam module which
executes the appropriate code with the appropriate options, that should be
attatched too.

This is also I believe copyright Ben Harris, and made available under the
GPL.

I know that we haven't included copyright headers, I hope that people will
do the correct thing, not least of all because it is mostly, pretty
trivial code.


Note, that whilst what I have included does work you may need to patch
things like gdm in order to use them - I would have to check.  We
submitted and had accepted our patch to xdm however.  Also ssh is a pain
because they don't understand (or agree with our understanding) of PAM.
:-)


> Thanks,
> Harold

I hope that helps,

Julian
--
Julian King
Computer Officer, University of Cambridge, Unix Support
#! /bin/bash
# $Id: pwfsession,v 1.6 2002/06/21 15:02:37 bjh21 Exp $

trap "" 1

export PATH=/usr/sbin:/usr/bin:/sbin:/bin

#exec >/dev/null 2>&1

mkdir -p /var/run/pwfsession
COUNTFILE=/var/run/pwfsession/$2

lockfile () {
    # Not NFS-safe.  Sorry.
    set -C
    while ! true 2>/dev/null >$1; do sleep 1; done
    set +C
}

LOGGER="logger -t pwfsession[$1/$2]"
case $1 in
    acct)
	if id $2 >/dev/null 2>&1; then
	    $LOGGER user $2 already exists here
	else
	    $LOGGER adding user $2...
	    groupadd $2
	    useradd -M -d /dev/null -g $2 $2
	fi
	# Lines below here used to be in the "open" section,
	# but the Red Hat login(8) seems to read the home dir
	# before opening the session.  xdm seems to do it even
	# earlier.
	$LOGGER attaching to PWF...
	lockfile ${COUNTFILE}.lock
	touch ${COUNTFILE}
	count=$(($(cat ${COUNTFILE}) + 1))
	echo $count > ${COUNTFILE}
	if [ ! "$2" = root ]; then
	    pwfmount $2 2>&1 | $LOGGER
	    usermod -d $(pwfhomedir $2) $2
	    rm -f /var/run/nwclient/$2
	fi
	rm -f ${COUNTFILE}.lock
	;;
    close)
	lockfile ${COUNTFILE}.lock
	count=$(($(cat ${COUNTFILE}) - 1))
	echo $count > ${COUNTFILE}
	if [ ! "$2" = root ]; then
	    if [ $count = 0 ]; then
	        $LOGGER "last logout -- detaching from PWF"
	        pwfumount $2 2>&1 | $LOGGER
	    fi
	fi
	rm -f ${COUNTFILE}.lock
	;;
esac
#include <sys/types.h>

#include <sys/wait.h>

#include <stdio.h>
#include <unistd.h>

#define PAM_SM_AUTH
#define PAM_SM_ACCOUNT
#define PAM_SM_SESSION

#include <security/pam_modules.h>

static int
runit(pam_handle_t *pamh, int flags, int argc, char const **argv,
      char const *action, int failure)
{
	pid_t pid;
	int status, ret;
	char const *newargv[4];

	if (argc != 1)
		return failure;
	newargv[0] = argv[0];
	newargv[1] = action;
	pam_get_user(pamh, &newargv[2], NULL);
	newargv[3] = NULL;
	switch(pid = fork()) {
	case -1:
		perror("fork");
		return failure;
	case 0:
		execv(newargv[0], newargv);
		perror("exec");
		return failure;
	default:
		ret = waitpid(pid, &status, 0);
		if (ret < 0) {
			perror("waitpid");
			return failure;
		}
		if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
			return PAM_SUCCESS;
	}
	return failure;
}

PAM_EXTERN int
pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, char const **argv)
{

	return runit(pamh, flags, argc, argv, "auth", PAM_AUTH_ERR);
}

PAM_EXTERN int
pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, char const **argv)
{

	return runit(pamh, flags, argc, argv, "setcred", PAM_CRED_ERR);
}

PAM_EXTERN int
pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, char const **argv)
{

	return runit(pamh, flags, argc, argv, "acct", PAM_AUTH_ERR);
}

PAM_EXTERN int
pam_sm_open_session(pam_handle_t *pamh, int flags, int argc, char const **argv)
{

	return runit(pamh, flags, argc, argv, "open", PAM_SESSION_ERR);
}

PAM_EXTERN int
pam_sm_close_session(pam_handle_t *pamh, int flags, int argc,
		     char const **argv)
{

	return runit(pamh, flags, argc, argv, "close", PAM_SESSION_ERR);
}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]