Subject: PAM stinks.
To: None <>
From: Miles Nordin <carton@Ivy.NET>
List: netbsd-advocacy
Date: 09/30/2001 15:36:40
begin quotation.
> *** Wouldn't PAM be easier and promote more code sharing? 

I remember several PAM debates, but I can't seem to find any with htDig 
or Google.

In short, my opinion is, it's the description of PAM which is so 
enticing.  Every actual implementation of PAM fails to deliver what it 
claims, is clumsily insecure, is buggy, or all three.

For example, I've seen PAM bugs on Linux systems that reveal whether 
or not a user exists at the login prompt.

The PAMs that I've seen are very bad at catching and reporting errors 
sanely.  That said, reporting authentication errors to someone 
requesting authentication is probably a bad idea, so this needs 
further elaboration---I only remember, ``poor error handling'' from 
when I used PAM.

Because PAM is incapable of interacting with the user (otherwise, the 
same module could not serve for xdm and login), less conventional 
authentication frameworks like S/Key, SecurID, crypto-iButtons, and 
so on render its entire architecture obsolete.

Something like ssh authentication or POP3-over-SSL is hard to 
sledgehammer into the PAM framework.  You end up with even more 
special cases in programs like netatalk and Samba that require weird 
proprietary non-Unix authentication schemes to work optimally.  Do I 
want to:
  a) send passwords in-the-clear over the network?, or
  b) open up my Unix box to all the authentication bugs and back-doors 
     in NTAS?
uu-uh.  uuh.  uhhhuhuh.  Doesn't PAM just make everything secure by 
centralizing it?

To sum up, there is something wrong with the problem-statement that 
PAM is supposed to solve, so of course its architecture is 
fundamentally flawed.

If you want to introduce a new authentication framework, I think an 
authentication daemon might be interesting.  Instead of login having 
the authority to judge credentials based on its root uid, run login 
as some ordinary uid.  When login wants to change uid/gids, it makes 
a systemcall including (new uid/gids, credentials).  The 
kernel wraps (requesting pid, new uid/gids, credentials) into a 
microkernel-style message and passes it to the ``authentication 
daemon'', which is the only program on the system allowed to judge 
credentials (meaning, the kernel permits only one process to attach 
the message channel).  At high securelevels, it might be impossible to 
restart the authentication daemon if it crashes and impossible for a 
process to have both the message channel and a debugger attached at 
once.  The authentication daemon needn't necessarily run as 'root'.

This architecture shares all PAM's awkwardness with ssh, SSL, netatalk, 
and Samba, with at least four major advantages:

  o Unlike PAM, it improves security rather than harming it, by reducing 
    the amount of code you need to get correct.  Bugs in login or sshd 
    are not a problem so long as you've properly defined what a 
    'credential' is.

  o Unlike PAM, it force^Whelps you to think clearly about security.  You 
    must reduce every authentication event into the simplest 
    ``credential'' possible that is still submittable for judgement.  
    The fact that the credential must be a piece of data (not a 
    combination of circumstances), and that the authentication daemon 
    must judge without access to the internal state of the requesting 
    program, is a huge departure from current Unix security.  No doubt 
    impatient people will still find ways to subvert it, but it's a 
    start toward basic sanity.  In other words, the framework I'm 
    suggesting has useful limitations that one should not work around, 
    while PAM has only stupid and annoying arbitrary limitations that 
    one is forced to work around.

  o The authentication daemon can serve things other than uid/gids-
    changing by adding another system call which passees a similar 
    message and simply returns success or failure.  Of course this is 
    not quite as elegant since it depends on the calling program to 
    enforce the authentication daemon's judgement, but it is cleaner 
    than current ways of doing web-page-authentication, and it works 
    in a chroot(...) sandbox.

  o If you have a pet fascist access policy like ``only men may start 
    using the System at night'', you can accomodate it by modifying 
    the authentication daemon's source code.  Because the daemon must 
    be simple and well-organized to be secure, changing source code is 
    probably easier than deciphering PAM's cockroach-nest of config files, 
    loadable modules, and default search paths, all of which are 
    documented ``by example.''  

    This is good, because it's inappropriate to use trial-and-error 
    techniques to modify an authentication system.  The daemon can be 
    tested offline for its response to arbitrary tuples.  One can run 
    it under a normal debugger.  One can write regression-tests for it.  
    One can use code instrumentation on it like Purify and Pure Coverage.  
    PAM can accomodate none of these bug-testing and code-auditing 
I'm sure none of this is new.  There is probably all sorts of interesting 
stuff going on in Usenix Unix-security-meetings.  but, that I can come up 
with this blatantly superior architecture off the top of my head shows 
how incredibly shabby and shallow PAM really is.