Re: PAM_IGNORE (was Re: Why should setcred be called after sessionopen?)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Nico,

On Wed, 16 May 2001, Nicolas Williams wrote:

> > > It's ignored, as if it had not even been mentioned in the config.

> > Exactly, and this is /wrong/.  PAM_IGNORE means "I have nothing useful to
> > contribute".  Returning an error when we don't know who the principal is is
> > not only useful, it's imperative in the case of configs such as the above.  If
> > we want admins to be able to turn this behavior off with a module option,
> > that's fine, but returning PAM_IGNORE here is not sane default behavior.

> I disagree. It's always appropriate to return PAM_IGNORE because it
> cannot contribute to success of the stack.

It also will not contribute to the failure of the stack, which is where the
problem lies.

> > Only if you accept that the above config is reasonable.  This is /not/ a
> > reasonable config; you've just said that the applicant must pass

> It's perfectly reasonable. I said that pam_rhosts is SUFFICIENT for
> authentication. That means that if pam_rhosts:auth succeeds then the
> other auth modules are NOT even tried.

So in this context, what do the lines

 rlogin account required   pam_krb5
 rlogin account required   pam_unix

mean?  I believe this should mean that both pam_krb5 and pam_unix must
*approve* the applicant for access.  If pam_krb5 is going to punt whenever it
doesn't know what to do, then I have no way to achieve the semantics I'm
looking for.[1]  Conversely, there are ways to structure the PAM config to
give you the results you desire without making use of a PAM_IGNORE return code
from pam_krb5.


> > Isn't this what you're really trying to say?  Isn't it more straightforward to
> > simply say this in the config file, rather than opening security holes in the
> > module that will let crippled apps get by with behavior that shouldn't be
> > allowed?

> Nope. There's no security hole there.

> Case 1: a) pam_rhosts:auth succeeds, short-circuiting the remainder of
>            the auth stack
> 	b) pam_krb5:account returns PAM_IGNORE and is ignored
> 	c) pam_unix:account is a pretty simple module and it works as
> 	   expected, even though pam_unix:auth was not tried

> The other cases also have no bug, but I'd have to pick a value for
> "whatever" above to run through all the possibilities.

There's no security hole in your example config, because you're assigning a
different meaning to 'required' than I am.  If I have a config of

 auth    required  pam_krb5
 account required  pam_krb5
 account required  pam_unix

I have an expectation that the users who are granted access to this service
have valid, non-expired Kerberos accounts *and* valid, non-expired Unix
accounts.  If the application calls pam_acct_mgmt() on a different handle than
was used when calling pam_authenticate(), and this triggers pam_krb5 to return
PAM_IGNORE, the user will be granted access.  Now, think about what this means
if the user's password expired, and pam_sm_authenticate() stored a token that
should have been passed to pam_sm_acct_mgmt().  If pam_sm_acct_mgmt() says
'no news is good news' and returns PAM_IGNORE, a user with an expired
principal will get access to the service -- something I've explicitly tried to
prevent in my configuration!  Not only that, but because we don't have a TGT
for the user (can't get one, the user's password is expired), we don't have
cryptographic proof of the user's identity (the KDC's response could've been
spoofed), but we'd be granting him access to the service anyway!

And because this all traces back to brokenness on the part of the application,
I as an admin may never know about the problem until it's too late.

Returning PAM_IGNORE from pam_sm_setcred() is one thing; this function doesn't
really pose a security risk if something goes wrong.  pam_authenticate() and
pam_acct_mgmt(), because they deal with authentication and authorization, must
be treated more cautiously.


> > > Trust me, Solaris PAM does the right thing, and I believe Linux-PAM must
> > > as well. The right thing is to treat modules returning PAM_IGNORE as if
> > > they weren't even on the stack (except that setcred() will be called
> > > even if auth() returned PAM_IGNORE -- similarly with open/close).
> >
> > Yes, the PAM libraries handle a PAM_IGNORE retval correctly.  What's at issue
> > is whether it's appropriate for a module to return PAM_IGNORE when we have
> > reason to believe there's an error which should not be ignored.

> But it's not an error to have no inputs!

Yes, it /is/. :)  Asking pam_krb5 to authorize a user when she has not first
been authenticated against the Kerberos realm is meaningless, and represents
an error in either the PAM config or the application.  If the error should not
be considered fatal, let the admin spell that out in the config.  Don't
override the PAM config by denying that there's an error.

> > In which case there's no harm to the application in calling pam_authenticate()
> > before pam_setcred() and ignoring the result, and there's no harm to the
> > modules if it's not called; either way, the only things you can do in
> > pam_setcred() in this scenario are those which /don't/ require
> > pam_authenticate() to be called successfully, which in fact rules out most
> > credential-setting activities except for those like 'pam_krb5.so acceptor'.

> There may be harm because the auth modules may desire to prompt the user/
> converse with the app, but there's no valid semantics at that point in
> handling such prompts when the user is already authenticated.

> And the acceptor thing in Sun's SEAM is a perfect example of why there
> can be value to calling setcred() when authenticate() is skipped.

Ok, so skip pam_authenticate().  If you call pam_setcred() and it works,
everything's fine (this is the case with pam_krb5 acceptor).  If you call
pam_setcred() and it fails, it's because you're requiring a module in the auth
section that can't fulfill your setcred() request without first calling
authenticate().  In that case, it sounds like a broken config to me -- why is
a module that needs pam_authenticate() found in the config for an application
that isn't calling pam_authenticate()?


> > Ok, so it calls pam_krb5's pam_sm_setcred() function, and this function
> > returns an error.  So what?  If that error was insubstantial in
> > pam_authenticate(), why does it matter now in pam_setcred(), given that
> > the flow of both function calls is governed by the same PAM config lines?

> Because /bin/login will fail if pam_setcred() fails and I can't have
> pam_krb5:setcred() treated differently from pam_krb5:authenticate() as
> far as required/requisite/... is concerned.

In the case of pam_krb5 on Solaris, the only possible reason why
pam_krb5:setcred() is being called when pam_krb5:authenticate() was not is if
there's a module listed above pam_krb5 that returned PAM_SUCCESS and
short-circuited the auth stack.  IOW,

 auth  required    pam_foo
 auth  sufficient  pam_bar
 auth  optional    pam_blee
 auth  required    pam_krb5

and pam_bar:authenticate() returns PAM_SUCCESS, causing the last two modules
in the stack to be skipped.  When the app then calls pam_setcred(), are you
saying that pam_bar:setcred() is going to return something other than
PAM_SUCCESS?  That's the only way I see that pam_krb5:setcred()'s return value
would contribute to the return value of pam_setcred() here.

Unless we're talking again about the 'login -f' case, and the problem is
that you have a single PAM config being used both with and without
pam_authenticate().  Honestly, I don't think this can be made to work reliably
without seriously botching things for other applications.  login needs to have
two different configurations, with two different service names, because the
configuration requirements when pam_authenticate() is used are different than
those when it is not used.

Cheers,
Steve Langasek
postmodern programmer


[1] Ok, with Linux-PAM, this isn't exactly true.  Using Linux-PAM's extended
config syntax, I can map the 'ignore' return code to a failure, but this is
prohibitively complex.  I want a solution that works for more than the dozen
Linux admins on the planet who know about this extended config file syntax. :)





[Index of Archives]     [Fedora Users]     [Kernel]     [Red Hat Install]     [Linux for the blind]     [Gimp]

  Powered by Linux