New and improved pam_exec module

Daniel Richard G. skunk at iSKUNK.ORG
Mon Jul 31 02:04:12 UTC 2006


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 
environment.

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 
  messages).

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

* 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_(OLD)AUTHTOK

  -- 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 
  message.)

* 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:

	expose_account
	try_first_pass
	use_first_pass
	use_mapped_pass

* 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.


Sincerely,


--Daniel


-- 
NAME   = Daniel Richard G.       ##  Remember, skunks       _\|/_  meef?
EMAIL1 = skunk at iskunk.org        ##  don't smell bad---    (/o|o\) /
EMAIL2 = skunk at alum.mit.edu      ##  it's the people who   < (^),>
WWW    = http://www.******.org/  ##  annoy them that do!    /   \
--
(****** = site not yet online)
-------------- next part --------------
A non-text attachment was scrubbed...
Name: new-pam-exec.patch.gz
Type: application/octet-stream
Size: 15679 bytes
Desc: not available
URL: <http://listman.redhat.com/archives/pam-list/attachments/20060730/b7f51ef4/attachment.obj>


More information about the Pam-list mailing list