Subject: New and improved pam_exec module

Hello everyone.

Recently, I found myself needing the ability to do user login session
setup/teardown in the form of a shell script invoked as root. PAM seemed
the right place to hook this in, and I came across pam_script and no less
than four different implementations of pam_exec to do the job.

All of these, however, left something to be desired. Most notably, all but
one didn't allow sending standard-channel output to the user [via the
conversation function], and none provided a way of modifying the PAM

I have taken the current Linux-PAM implementation of pam_exec, and expanded
it to include (1) the features I needed, (2) the superset of features in
all the aforementioned implementations of this concept, and (3) some extra
niceties that I didn't need, but might find useful someday.

A summary of features of the new implementation:

* The external program's stdout is sent to the PAM conversation function,
provided that the PAM_SILENT flag has not been set.

* The program's stderr is sent to syslog (as specially-marked LOG_INFO

* If a certain module option is specified, the program can write
pseudo-shell-ish directives to fd 3 to set and unset PAM environment

* Piped output from the program is checked for illegal characters
(currently via isprint(), for locale-friendliness).

* Overlong output lines from the program are detected and dropped.

* Several classes of environment variables are provided to the program:

-- Everything in the current PAM environment

-- All PAM items (PAM_USER, PAM_RHOST, etc.), with the exception of

-- PAM_AUTHTOK and PAM_OLDAUTHTOK are provided if an additional option is
given (described with suitably scary warnings in the documentation)

-- The various fields of the user's passwd entry (PW_GECOS, PW_GID,
PW_SHELL et al.)

-- Various PAM return codes (e.g. EXIT_PAM_SUCCESS, EXIT_PAM_PERM_DENIED)
so that the program can return error codes meaningful to PAM (imagine
a shell script with "exit $EXIT_PAM_IGNORE" or similar). Inapplicable
return values are filtered out at the end of each of the module's
entry points.

* When being invoked as a session module, an option can be specified to
invoke the program only on opening or closing a session. (The default is
both; the program can distinguish between the two using the ACTION
environment variable.)

* Instead of directly exec'ing a named program, the module invokes a
/bin/sh command string, for greater flexibility.

* The program can be invoked with a different UID/GID than the PAM-enabled
application; the UID/GID can be specified by name or by number.

* The module's command-line syntax allows specifying a shell command string
without any option-or-command ambiguity.

* The code is portable to OpenPAM. (I will make an effort to contribute it
to that project as well; Dag-Erling Smørgrav has received a copy of this

* The code is mostly portable to Solaris, just for giggles. (The only issue
is a missing setenv() implementation.)

There are still some things that need to be addressed, however:

* Is the syslog interaction properly following convention? I noticed an
inconsistency in the formatting of syslog messages between pam_exec and
pam_unix (both invoked from sshd)...

Jul 7 15:12:53 bassoon pam_exec[28567]: Command exited with status 0
Jul 7 15:12:53 bassoon sshd[28567]: (pam_unix) session opened for
user skunk by (uid=0)

...but am uncertain of how things ought to be done here.

* The module will accept the following options, but I'm not sure what
exactly it should do (if anything) with them:


* Stylistically, PAM options sometimes use run-together words (e.g.
"authtok", "nullok", "readenv"), sometimes words separated by underscores
("expose_account", "try_mapped_pass"), and sometimes even a combination
of the two ("nullok_secure"). Is my choice of option names a reasonable
fit to those currently in use?

* I'm a bit unclear on how pam_fail_delay() is supposed to work. Is the
manner in which I handled it---and described it in the documentation---at
all incorrect?

* The man page still needs fleshing out, mainly in describing all the
environment variables that the module provides (see all the "????????"
strings). Because these map mostly one-to-one to their namesake PAM
constants, there may be some redundancy in describing them; I'm not quite
sure what is the best way to deal with this.

* Some parts of the man page are a bit confused vis-a-vis "services."
There's the service provided by the PAM-enabled application (e.g.
"Welcome to localhost's ftp service"), the PAM service name (e.g. "ssh",
"login"), and the PAM module service ("auth", "account", "session",
"passwd"). It is a little difficult to keep all these conceptually
distinct, especially the latter two.

* I'm not very good at editing DocBook XML. I would like someone to review
my draft, particularly to check for wrong or poorly-chosen tags. (One
thing that I couldn't figure out is how to make the environment variable
names in the lists appear boldfaced in the nroff output; another is how
to get a forward section reference to work.)

* The man page presents four different synopses, corresponding to the
different options available in the four ways the module can be invoked.
Did I lay this out correctly?

* The nroff stylesheet doesn't handle long-lined <programlisting> blocks
very gracefully; see my silly example with beep(1).

* (Not specific to pam_exec) The nroff stylesheet doesn't set the title
that you sometimes see centered at the top; I believe that "Linux-PAM
Manual" should be up there, from the XML's <refmiscinfo> tag.

Attached is a patch against current CVS to pam_exec.c and pam_exec.8.xml.
It is gzipped, owing to its size.

I would appreciate feedback from close scrutiny of the code. It was written
with the goals of security, correctness and clarity in mind, but there may
be spots or areas lacking in these. (This goes for the comments as well.)

I would likewise appreciate being informed of any desirable/necessary
conventions that have not been followed. I am by no means a regular
contributor to this project, nor any related projects; while I have read
the documentation, and referred to other Linux-PAM code in some instances,
this is probably not enough to bring me up to speed on everything.

Of course, there is room as well for design and stylistic feedback. While I
would shy away from suggestions to the effect of rewriting large portions
of the module, smaller changes that would make its use and execution more
sensible overall will be welcomed.

Everything should be here. I look forward to hearing feedback on this list.



NAME = Daniel Richard G. ## Remember, skunks _\|/_ meef?
EMAIL1 = [email protected] ## don't smell bad--- (/o|o\) /
EMAIL2 = [email protected] ## it's the people who < (^),>
WWW = http://www.******.org/ ## annoy them that do! / \
(****** = site not yet online)

Attachment: new-pam-exec.patch.gz
Description: Binary data

Pam-list mailing list
[email protected]

Programming list archiving by: Enterprise Git Hosting