On Wed, 16 May 2001, Nicolas Williams wrote: > When a module returns PAM_IGNORE< it's ignored, EVEN IF it was a > required module -- i.e., it's treated as if it hadn't even been on the > stack. Certainly this is how Solaris PAM works. I know, not only > empirically, but also because I have access to Solaris source code. > > However, consider this configuration: > > auth sufficient pam_krb5.so > > account requisite pam_krb5.so > > account requisite pam_unix.so > > This config specifies that pam_krb5 is used for all authentication, and that > > the user must pass /both/ Kerberos /and/ Unix (shadow) authorization checks > > in order to gain access. Is this a valid config? If so, what happens when > > pam_sm_acct_mgmt() returns PAM_IGNORE because it doesn't /know/ if the user > > is authorized? > 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. If I list two authorization modules as 'requisite' or 'required' in my PAM config, then by God, I don't want that user to be allowed access to the service unless both of those modules are *sure* that he should be. > Consider this: > rlogin auth sufficient pam_rhosts > rlogin auth whatever pam_krb5 > rlogin auth whatever pam_unix > rlogin account required pam_krb5 > rlogin account required pam_unix > If pam_rhosts succeeds, then pam_krb5:auth will never be tried, but > pam_krb5:account MUST be tried just in case pam_krb5:auth was tried. So > pam_krb5:account is tried, but it can't actually *DO* anything, so it > MUST return PAM_IGNORE. 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 authorization checks with both pam_krb5 and pam_unix, but you're allowing them to authenticate using only pam_rhosts -- so they're not authenticated to the Kerberos realm, and they /can't/ pass the authorization checks. This is an inconsistent PAM config, and the config needs to be fixed, not the modules. rlogin auth sufficient pam_rhosts rlogin auth whatever pam_krb5 rlogin auth whatever pam_unix rlogin account optional pam_krb5 rlogin account optional pam_unix 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? > 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. > > Under Solaris w/ rlogin, is pam_krb5's pam_sm_setcred() being called even > > though its pam_sm_authenticate() function was never called? Some of your > Yes. Andrew Morgan says this would not be the case with Linux-PAM, > ALTHOUGH, if PAM_KRB5:pam_sm_authenticate() is called and returns > PAM)IGNORE, then PAM_KRB5:pam_sm_setcred() WOULD be called in the > Linux-PAM case. Ok, then pam_krb5 will need to handle this Solaris case. > > > The problem is: how can PAM_KRB5 detect if pam_sm_authenticate() was not > > > called because: > > > a) the app didn't call it (e.g. login -f) > > Hmm... I think the app is allowed to ignore the return value of > > pam_authenticate(), but I'm not sure the spec allows the app to not call it. > > In this config, pam_krb5 is aware it's configured in 'acceptor' mode, > > correct? So it has enough information about the environment to always do > > the right thing, whether or not pam_authenticate() was called. > How is /bin/login supposed to communicate the -f argument to PAM? So the > user is authenticated, but there is still value in doing setcred() and > acct_mgmt() and firends... >From your descriptions of kerberized login in the past, I understood that this is communicated to PAM by means of the service name -- login will invoke PAM with a different service name for an already-authenticated user than for one that still needs to be authenticated. 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'. > > In which case, does it matter that pam_krb5 doesn't return success? If > > pam_authenticate() didn't need a go-ahead from pam_krb5 in order to succeed, > > why should it care about it when calling pam_setcred()? > Because Solaris PAM calls ALL auth module's setcred() method, regardless > of the return values of the sm_authenticate() calls, or even if some > modules' pam_sm_authenticate() did not get called. 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? > > See above for possible reasons why PAM_IGNORE is not appropriate in this > > situation. I consider the above scenario, in which the app cares about > > pam_krb5's retval from pam_sm_acct_mgmt() but did not call > > pam_authenticate() correctly, to be a bug in either the application or the > > PAM configuration. > It's always appropriate to return PAM_IGNORE if there's nothing the > method can do to satisfy its purpose. This is because PAM_IGNORE cannot > contribute to the success of the stack. The authorization module's purpose is to guarantee that the applicant is authorized. Returning PAM_IGNORE when we know the applicant is /not/ authorized is inconsistent with this goal. Steve Langasek postmodern programmer