Subject: PAM stinks.
To: None <netbsd-advocacy@netbsd.org>
From: Miles Nordin <carton@Ivy.NET>
List: netbsd-advocacy
Date: 09/30/2001 15:36:40
begin kpneal@pobox.com 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
methods.
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.