diff options
author | Dag-Erling Smørgrav <des@FreeBSD.org> | 2002-01-24 15:30:03 +0000 |
---|---|---|
committer | Dag-Erling Smørgrav <des@FreeBSD.org> | 2002-01-24 15:30:03 +0000 |
commit | e9ae7bc23482c20cdefe4845a80cba54bb221534 (patch) | |
tree | 76e70ca2bfa4da76aa868ee1fd2ea3c96fc99735 | |
parent | a3e5380a47a146bdeff8bc89c7100af2490efc4d (diff) | |
download | src-e9ae7bc23482c20cdefe4845a80cba54bb221534.tar.gz src-e9ae7bc23482c20cdefe4845a80cba54bb221534.zip |
This commit disables chain caching.
Chain caching is a feature of Linux-PAM, where pam_authenticate() and
pam_open_session() "freeze" the chain so that their companion
primitive (pam_setcred() and pam_close_session() respectively) will
call the exact same modules, skipping those that failed in the
previous call.
There are several reasons not to do this, the most prominent of which
is that it makes it impossible to call pam_setcred() without first
calling pam_authenticate() - which is perfectly valid according to
DCE/RFC 86.0 and XSSO, and is necessary to make 'login -f' work.
Instead of chain caching, implement something similar to the way
Solaris' libpam behaves: pam_setcred treats "sufficient" modules as if
they were "required", i.e. does not break the chain when they succeed.
PAM modules whose pam_sm_setcred() should not be called unless their
pam_sm_authenticate() succeeded can simply set a state variable using
pam_set_data() in pam_sm_authenticate(), and use pam_get_data() to
check it in pam_sm_setcred().
Sponsored by: DARPA, NAI Labs
Notes
Notes:
svn path=/head/; revision=89738
-rw-r--r-- | contrib/libpam/libpam/pam_dispatch.c | 73 |
1 files changed, 11 insertions, 62 deletions
diff --git a/contrib/libpam/libpam/pam_dispatch.c b/contrib/libpam/libpam/pam_dispatch.c index ffb50f5226e8..d9b3de081ba1 100644 --- a/contrib/libpam/libpam/pam_dispatch.c +++ b/contrib/libpam/libpam/pam_dispatch.c @@ -4,6 +4,8 @@ * Copyright (c) 1998 Andrew G. Morgan <morgan@kernel.org> * * $Id: pam_dispatch.c,v 1.3 2001/02/05 06:50:41 agmorgan Exp $ + * + * $FreeBSD$ */ #include <stdlib.h> @@ -28,7 +30,7 @@ */ static int _pam_dispatch_aux(pam_handle_t *pamh, int flags, struct handler *h, - _pam_boolean resumed, int use_cached_chain) + _pam_boolean resumed, int ignore_sufficient) { int depth, impression, status, skip_depth; @@ -99,46 +101,18 @@ static int _pam_dispatch_aux(pam_handle_t *pamh, int flags, struct handler *h, return retval; } - if (use_cached_chain) { - /* a former stack execution has frozen the chain */ - cached_retval = *(h->cached_retval_p); - } else { - /* this stack execution is defining the frozen chain */ - cached_retval = h->cached_retval = retval; - } - /* verify that the return value is a valid one */ - if ((cached_retval < PAM_SUCCESS) - || (cached_retval >= _PAM_RETURN_VALUES)) { + if ((retval < PAM_SUCCESS) || (retval >= _PAM_RETURN_VALUES)) { retval = PAM_MUST_FAIL_CODE; action = _PAM_ACTION_BAD; } else { - /* We treat the current retval with some respect. It may - (for example, in the case of setcred) have a value that - needs to be propagated to the user. We want to use the - cached_retval to determine the modules to be executed - in the stacked chain, but we want to treat each - non-ignored module in the cached chain as now being - 'required'. We only need to treat the, - _PAM_ACTION_IGNORE, _PAM_ACTION_IS_JUMP and - _PAM_ACTION_RESET actions specially. */ - - action = h->actions[cached_retval]; + action = h->actions[retval]; } - D((stderr, - "use_cached_chain=%d action=%d cached_retval=%d retval=%d\n", - use_cached_chain, action, cached_retval, retval)); - /* decide what to do */ switch (action) { case _PAM_ACTION_RESET: - /* if (use_cached_chain) { - XXX - we need to consider the use_cached_chain case - do we want to trash accumulated info here..? - } */ - impression = _PAM_UNDEF; status = PAM_MUST_FAIL_CODE; break; @@ -146,16 +120,13 @@ static int _pam_dispatch_aux(pam_handle_t *pamh, int flags, struct handler *h, case _PAM_ACTION_OK: case _PAM_ACTION_DONE: - /* XXX - should we maintain cached_status and status in - the case of use_cached_chain? The same with BAD&DIE - below */ - if ( impression == _PAM_UNDEF || (impression == _PAM_POSITIVE && status == PAM_SUCCESS) ) { impression = _PAM_POSITIVE; status = retval; } - if ( impression == _PAM_POSITIVE && action == _PAM_ACTION_DONE ) { + if ( impression == _PAM_POSITIVE && action == _PAM_ACTION_DONE + && !ignore_sufficient ) { goto decision_made; } break; @@ -179,11 +150,6 @@ static int _pam_dispatch_aux(pam_handle_t *pamh, int flags, struct handler *h, break; case _PAM_ACTION_IGNORE: - /* if (use_cached_chain) { - XXX - when evaluating a cached - chain, do we still want to ignore the module's - return value? - } */ break; /* if we get here, we expect action is a positive number -- @@ -192,19 +158,6 @@ static int _pam_dispatch_aux(pam_handle_t *pamh, int flags, struct handler *h, default: if ( _PAM_ACTION_IS_JUMP(action) ) { - /* If we are evaluating a cached chain, we treat this - module as required (aka _PAM_ACTION_OK) as well as - executing the jump. */ - - if (use_cached_chain) { - if (impression == _PAM_UNDEF - || (impression == _PAM_POSITIVE - && status == PAM_SUCCESS) ) { - impression = _PAM_POSITIVE; - status = retval; - } - } - /* this means that we need to skip #action stacked modules */ do { h = h->next; @@ -245,7 +198,7 @@ decision_made: /* by getting here we have made a decision */ int _pam_dispatch(pam_handle_t *pamh, int flags, int choice) { struct handler *h = NULL; - int retval, use_cached_chain; + int retval, ignore_sufficient; _pam_boolean resumed; IF_NO_PAMH("_pam_dispatch", pamh, PAM_SYSTEM_ERR); @@ -262,7 +215,7 @@ int _pam_dispatch(pam_handle_t *pamh, int flags, int choice) return retval; } - use_cached_chain = 0; /* default to setting h->cached_retval */ + ignore_sufficient = 0; /* default to setting h->cached_retval */ switch (choice) { case PAM_AUTHENTICATE: @@ -270,7 +223,7 @@ int _pam_dispatch(pam_handle_t *pamh, int flags, int choice) break; case PAM_SETCRED: h = pamh->handlers.conf.setcred; - use_cached_chain = 1; + ignore_sufficient = 1; break; case PAM_ACCOUNT: h = pamh->handlers.conf.acct_mgmt; @@ -280,13 +233,9 @@ int _pam_dispatch(pam_handle_t *pamh, int flags, int choice) break; case PAM_CLOSE_SESSION: h = pamh->handlers.conf.close_session; - use_cached_chain = 1; break; case PAM_CHAUTHTOK: h = pamh->handlers.conf.chauthtok; - if (flags & PAM_UPDATE_AUTHTOK) { - use_cached_chain = 1; - } break; default: _pam_system_log(LOG_ERR, "undefined fn choice; %d", choice); @@ -333,7 +282,7 @@ int _pam_dispatch(pam_handle_t *pamh, int flags, int choice) __PAM_TO_MODULE(pamh); /* call the list of module functions */ - retval = _pam_dispatch_aux(pamh, flags, h, resumed, use_cached_chain); + retval = _pam_dispatch_aux(pamh, flags, h, resumed, ignore_sufficient); resumed = PAM_FALSE; __PAM_TO_APP(pamh); |