Subject: PAM proposal
To: None <tech-security@NetBSD.org>
From: Roland Dowdeswell <elric@imrryr.org>
List: tech-security
Date: 05/07/2005 11:22:57
When we imported PAM we changed the semantics to fail closed rather
than to fail open.  We did this by denying an authentication if
neither a required nor a sufficient returns true.

The language describing the PAM keywords is rather confusing, so
I will construct a table of how [our] PAM works.  The four columns
represent:

	continue:F	will continue on failure
	S		will continue on success
	can succeed	sets the ``can succeed'' flag
	force deny	sets the ``will be denied'' flag

requests which make it through the stack will succeed if both
the ``can succeed'' flag is set and the ``force deny'' flag is
not set.

So, here is how I read our current set of keywords:

keyword		continue:F	S	can succeed	force deny
-------		----------	-	-----------	----------
required	yes		yes	yes		yes
requisite	no		yes	yes		yes
sufficient	yes		yes	yes		no
optional	yes		yes	no		no
binding		yes		no	yes		yes

Now, if we consider a module such as pam_nologin.so, none of
those definitions make sense.  We really want something like:

X		yes		yes	no		yes

which is unrepresented in the table.

Or in English: the success of pam_nologin.so should not by
itself allow you to log in to the system.  Consider /etc/pam.d/login:

auth            sufficient      pam_self.so             no_warn
auth            required        pam_nologin.so          no_warn
auth            sufficient      pam_krb5.so             no_warn try_first_pass
auth            required        pam_unix.so             no_warn try_first_pass

If a system administrator naively comments out pam_unix.so, then
anyone can log into the system at any time---so we still have a
system which can [sort of] fail open.

This, IMO, needs to be fixed.  So, we can take either one of two
paths.  The first would be to come up with a PAM configuration
syntax which has some semblence of sanity.  This would diverge from
the standards which would be unfortunate.  The other would be to
change the semantics of a keyword or add a keyword.

I think that it might be a better idea to just extend the current
syntax to include an additional keyword ``neccessary'' which would
specifically not imply any kind of sufficiency.  The table above
would become:

keyword		continue:F	S	can succeed	force deny
-------		----------	-	-----------	----------
required	yes		yes	yes		yes
requisite	no		yes	yes		yes
necessary	yes		yes	no		yes
sufficient	yes		yes	yes		no
optional	yes		yes	no		no
binding		yes		no	yes		yes

And /etc/pam.d/login would become:

auth            sufficient      pam_self.so             no_warn
auth            necessary       pam_nologin.so          no_warn
auth            sufficient      pam_krb5.so             no_warn try_first_pass
auth            required        pam_unix.so             no_warn try_first_pass

or

auth            sufficient      pam_self.so             no_warn
auth            necessary       pam_nologin.so          no_warn
auth            sufficient      pam_krb5.so             no_warn try_first_pass
auth            sufficient      pam_unix.so             no_warn try_first_pass

At this point, if one comments out the last line the request will
fail if pam_krb5.so fails which is more intuitive.

``Necessary'' might be a bad choice of words, but at this point I
think that all of the words except sufficient and optional are poor
choices...

Comments?

--
    Roland Dowdeswell                      http://www.Imrryr.ORG/~elric/