diff options
author | Andrew G. Morgan <morgan@kernel.org> | 2001-01-22 06:07:28 +0000 |
---|---|---|
committer | Andrew G. Morgan <morgan@kernel.org> | 2001-01-22 06:07:28 +0000 |
commit | 9fb9393ede4ee9d43ff841557f95ed2af7d1a15f (patch) | |
tree | 34a3323fac5906ceb5aa54b5d482090bdaba47c0 /libpam | |
parent | e6d5049a8d484fb7a764a125d830b23f59a0c685 (diff) | |
download | pam-9fb9393ede4ee9d43ff841557f95ed2af7d1a15f.tar.gz pam-9fb9393ede4ee9d43ff841557f95ed2af7d1a15f.tar.bz2 pam-9fb9393ede4ee9d43ff841557f95ed2af7d1a15f.zip |
Relevant BUGIDs: 129027, 128576
Purpose of commit: new feature + documentation
Commit summary:
---------------
Cleaned up the handling of AUTHTOK items and pam_[gs]et_data() functions.
Added more clear documentation about the pam_[gs]et_item() functions to
the pam_appl and pam_modules programmer guides.
Diffstat (limited to 'libpam')
-rw-r--r-- | libpam/Makefile | 10 | ||||
-rw-r--r-- | libpam/include/security/_pam_types.h | 10 | ||||
-rw-r--r-- | libpam/pam_account.c | 14 | ||||
-rw-r--r-- | libpam/pam_auth.c | 15 | ||||
-rw-r--r-- | libpam/pam_data.c | 60 | ||||
-rw-r--r-- | libpam/pam_delay.c | 2 | ||||
-rw-r--r-- | libpam/pam_dispatch.c | 11 | ||||
-rw-r--r-- | libpam/pam_end.c | 7 | ||||
-rw-r--r-- | libpam/pam_env.c | 1 | ||||
-rw-r--r-- | libpam/pam_handlers.c | 2 | ||||
-rw-r--r-- | libpam/pam_item.c | 127 | ||||
-rw-r--r-- | libpam/pam_misc.c | 8 | ||||
-rw-r--r-- | libpam/pam_password.c | 5 | ||||
-rw-r--r-- | libpam/pam_private.h | 16 | ||||
-rw-r--r-- | libpam/pam_session.c | 16 | ||||
-rw-r--r-- | libpam/pam_start.c | 10 | ||||
-rw-r--r-- | libpam/pam_tokens.h | 4 |
17 files changed, 232 insertions, 86 deletions
diff --git a/libpam/Makefile b/libpam/Makefile index b734dfa4..64fe13a4 100644 --- a/libpam/Makefile +++ b/libpam/Makefile @@ -22,7 +22,9 @@ dummy: ../Make.Rules all # --------------------------------------------- -CFLAGS += $(DYNAMIC) $(STATIC) $(MOREFLAGS) +CFLAGS += $(DYNAMIC) $(STATIC) $(MOREFLAGS) \ + -DLIBPAM_VERSION_MAJOR=$(MAJOR_REL) \ + -DLIBPAM_VERSION_MINOR=$(MINOR_REL) # dynamic library names @@ -95,9 +97,9 @@ ifeq ($(DYNAMIC_LIBPAM),yes) endif ifeq ($(NEEDSONAME),yes) rm -f $(LIBPAMFULL) - ln -s $(LIBPAM) $(LIBPAMFULL) + ln -sf $(LIBPAM) $(LIBPAMFULL) rm -f $(LIBPAMNAME) - ln -s $(LIBPAM) $(LIBPAMNAME) + ln -sf $(LIBPAM) $(LIBPAMNAME) endif endif @@ -122,7 +124,7 @@ ifeq ($(DYNAMIC_LIBPAM),yes) $(LDCONFIG) ifneq ($(DYNTYPE),"sl") ( cd $(FAKEROOT)$(libdir) ; rm -f $(LIBPAM) ; \ - ln -s $(LIBPAMNAME) $(LIBPAM) ) + ln -sf $(LIBPAMNAME) $(LIBPAM) ) endif endif ifeq ($(STATIC_LIBPAM),yes) diff --git a/libpam/include/security/_pam_types.h b/libpam/include/security/_pam_types.h index f192409e..871bfbf2 100644 --- a/libpam/include/security/_pam_types.h +++ b/libpam/include/security/_pam_types.h @@ -14,6 +14,11 @@ #ifndef _SECURITY__PAM_TYPES_H #define _SECURITY__PAM_TYPES_H +#ifndef __LIBPAM_VERSION +# define __LIBPAM_VERSION __libpam_version +#endif +extern unsigned int __libpam_version; + /* * include local definition for POSIX - NULL */ @@ -86,7 +91,10 @@ typedef struct pam_handle pam_handle_t; calling again, verify that conversation is completed */ -/* Add new #define's here */ +/* + * Add new #define's here - take care to also extend the libpam code: + * pam_strerror() and "libpam/pam_tokens.h" . + */ #define _PAM_RETURN_VALUES 32 /* this is the number of return values */ diff --git a/libpam/pam_account.c b/libpam/pam_account.c index ffc01acd..71e04f15 100644 --- a/libpam/pam_account.c +++ b/libpam/pam_account.c @@ -6,8 +6,18 @@ int pam_acct_mgmt(pam_handle_t *pamh, int flags) { + int retval; + D(("called")); - IF_NO_PAMH("pam_acct_mgmt",pamh,PAM_SYSTEM_ERR); - return _pam_dispatch(pamh, flags, PAM_ACCOUNT); + IF_NO_PAMH("pam_acct_mgmt", pamh, PAM_SYSTEM_ERR); + + if (__PAM_FROM_MODULE(pamh)) { + D(("called from module!?")); + return PAM_SYSTEM_ERR; + } + + retval = _pam_dispatch(pamh, flags, PAM_ACCOUNT); + + return retval; } diff --git a/libpam/pam_auth.c b/libpam/pam_auth.c index 8ee14ac0..dbbdf00f 100644 --- a/libpam/pam_auth.c +++ b/libpam/pam_auth.c @@ -16,6 +16,13 @@ int pam_authenticate(pam_handle_t *pamh, int flags) D(("pam_authenticate called")); + IF_NO_PAMH("pam_authenticate", pamh, PAM_SYSTEM_ERR); + + if (__PAM_FROM_MODULE(pamh)) { + D(("called from module!?")); + return PAM_SYSTEM_ERR; + } + if (pamh->former.choice == PAM_NOT_STACKED) { _pam_sanitize(pamh); _pam_start_timer(pamh); /* we try to make the time for a failure @@ -23,7 +30,6 @@ int pam_authenticate(pam_handle_t *pamh, int flags) fail */ } - IF_NO_PAMH("pam_authenticate",pamh,PAM_SYSTEM_ERR); retval = _pam_dispatch(pamh, flags, PAM_AUTHENTICATE); if (retval != PAM_INCOMPLETE) { @@ -41,9 +47,14 @@ int pam_setcred(pam_handle_t *pamh, int flags) { int retval; + D(("pam_setcred called")); + IF_NO_PAMH("pam_setcred", pamh, PAM_SYSTEM_ERR); - D(("pam_setcred called")); + if (__PAM_FROM_MODULE(pamh)) { + D(("called from module!?")); + return PAM_SYSTEM_ERR; + } if (! flags) { flags = PAM_ESTABLISH_CRED; diff --git a/libpam/pam_data.c b/libpam/pam_data.c index 6422b10e..06aa837f 100644 --- a/libpam/pam_data.c +++ b/libpam/pam_data.c @@ -9,7 +9,26 @@ #include "pam_private.h" -struct pam_data *_pam_locate_data(const pam_handle_t *pamh, const char *name); +static struct pam_data *_pam_locate_data(const pam_handle_t *pamh, + const char *name) +{ + struct pam_data *data; + + D(("called")); + + IF_NO_PAMH("_pam_locate_data", pamh, NULL); + + data = pamh->data; + + while (data) { + if (!strcmp(data->name, name)) { + return data; + } + data = data->next; + } + + return NULL; +} int pam_set_data( pam_handle_t *pamh, @@ -19,7 +38,14 @@ int pam_set_data( { struct pam_data *data_entry; - IF_NO_PAMH("pam_set_data",pamh,PAM_SYSTEM_ERR); + D(("called")); + + IF_NO_PAMH("pam_set_data", pamh, PAM_SYSTEM_ERR); + + if (__PAM_FROM_APP(pamh)) { + D(("called from application!?")); + return PAM_SYSTEM_ERR; + } /* first check if there is some data already. If so clean it up */ @@ -57,7 +83,14 @@ int pam_get_data( { struct pam_data *data; - IF_NO_PAMH("pam_get_data",pamh,PAM_SYSTEM_ERR); + D(("called")); + + IF_NO_PAMH("pam_get_data", pamh, PAM_SYSTEM_ERR); + + if (__PAM_FROM_APP(pamh)) { + D(("called from application!?")); + return PAM_SYSTEM_ERR; + } data = _pam_locate_data(pamh, module_data_name); if (data) { @@ -68,29 +101,14 @@ int pam_get_data( return PAM_NO_MODULE_DATA; } -struct pam_data *_pam_locate_data(const pam_handle_t *pamh, const char *name) -{ - struct pam_data *data; - - IF_NO_PAMH("_pam_locate_data",pamh,NULL); - data = pamh->data; - - while (data) { - if (!strcmp(data->name, name)) { - return data; - } - data = data->next; - } - - return NULL; -} - void _pam_free_data(pam_handle_t *pamh, int status) { struct pam_data *last; struct pam_data *data; - IF_NO_PAMH("_pam_free_data",pamh,/* no return value for void fn */); + D(("called")); + + IF_NO_PAMH("_pam_free_data", pamh, /* no return value for void fn */); data = pamh->data; while (data) { diff --git a/libpam/pam_delay.c b/libpam/pam_delay.c index 8884879e..1b8d34fb 100644 --- a/libpam/pam_delay.c +++ b/libpam/pam_delay.c @@ -1,7 +1,7 @@ /* * pam_delay.c * - * Copyright (c) Andrew G. Morgan <morgan@linux.kernel.org> 1996-9 + * Copyright (c) Andrew G. Morgan <morgan@kernel.org> 1996-9 * All rights reserved. * * $Id$ diff --git a/libpam/pam_dispatch.c b/libpam/pam_dispatch.c index 285f3316..02325665 100644 --- a/libpam/pam_dispatch.c +++ b/libpam/pam_dispatch.c @@ -195,7 +195,12 @@ int _pam_dispatch(pam_handle_t *pamh, int flags, int choice) int retval; _pam_boolean resumed; - IF_NO_PAMH("_pam_dispatch",pamh,PAM_SYSTEM_ERR); + IF_NO_PAMH("_pam_dispatch", pamh, PAM_SYSTEM_ERR); + + if (__PAM_FROM_MODULE(pamh)) { + D(("called from a module!?")); + return PAM_SYSTEM_ERR; + } /* Load all modules, resolve all symbols */ @@ -265,10 +270,14 @@ int _pam_dispatch(pam_handle_t *pamh, int flags, int choice) resumed = PAM_FALSE; } + __PAM_TO_MODULE(pamh); + /* call the list of module functions */ retval = _pam_dispatch_aux(pamh, flags, h, resumed); resumed = PAM_FALSE; + __PAM_TO_APP(pamh); + /* Should we recall where to resume next time? */ if (retval == PAM_INCOMPLETE) { D(("module [%d] returned PAM_INCOMPLETE")); diff --git a/libpam/pam_end.c b/libpam/pam_end.c index b389038f..735da62e 100644 --- a/libpam/pam_end.c +++ b/libpam/pam_end.c @@ -12,9 +12,14 @@ int pam_end(pam_handle_t *pamh, int pam_status) { int ret; + D(("entering pam_end()")); + IF_NO_PAMH("pam_end", pamh, PAM_SYSTEM_ERR); - D(("entering pam_end()")); + if (__PAM_FROM_MODULE(pamh)) { + D(("called from module!?")); + return PAM_SYSTEM_ERR; + } /* first liberate the modules (it is not inconcevible that the modules may need to use the service_name etc. to clean up) */ diff --git a/libpam/pam_env.c b/libpam/pam_env.c index a1e744b7..86a2889e 100644 --- a/libpam/pam_env.c +++ b/libpam/pam_env.c @@ -47,6 +47,7 @@ static void _pam_dump_env(pam_handle_t *pamh) int _pam_make_env(pam_handle_t *pamh) { D(("called.")); + IF_NO_PAMH("_pam_make_env", pamh, PAM_ABORT); /* diff --git a/libpam/pam_handlers.c b/libpam/pam_handlers.c index 569335e6..a22d66f6 100644 --- a/libpam/pam_handlers.c +++ b/libpam/pam_handlers.c @@ -399,7 +399,7 @@ int _pam_init_handlers(pam_handle_t *pamh) * preceeded by lines of comments and also extended with "\\\n" */ -int _pam_assemble_line(FILE *f, char *buffer, int buf_len) +static int _pam_assemble_line(FILE *f, char *buffer, int buf_len) { char *p = buffer; char *s, *os; diff --git a/libpam/pam_item.c b/libpam/pam_item.c index 2a545d6f..2b4c32ef 100644 --- a/libpam/pam_item.c +++ b/libpam/pam_item.c @@ -21,12 +21,13 @@ } \ } +/* handy version id */ + +unsigned int __libpam_version = LIBPAM_VERSION; + /* functions */ -int pam_set_item ( - pam_handle_t *pamh, - int item_type, - const void *item) +int pam_set_item (pam_handle_t *pamh, int item_type, const void *item) { int retval; @@ -37,6 +38,7 @@ int pam_set_item ( retval = PAM_SUCCESS; switch (item_type) { + case PAM_SERVICE: /* Setting handlers_loaded to 0 will cause the handlers * to be reloaded on the next call to a service module. @@ -49,53 +51,68 @@ int pam_set_item ( *tmp = tolower(*tmp); /* require lower case */ } break; + case PAM_USER: RESET(pamh->user, item); break; + case PAM_USER_PROMPT: RESET(pamh->prompt, item); break; + case PAM_TTY: D(("setting tty to %s", item)); RESET(pamh->tty, item); break; + case PAM_RUSER: RESET(pamh->ruser, item); break; + case PAM_RHOST: RESET(pamh->rhost, item); break; + case PAM_AUTHTOK: - /* - * The man page says this is only supposed to be available to - * the module providers. In order to use this item the app - * has to #include <security/pam_modules.h>. This is something - * it is *not* supposed to do with "Linux-"PAM! - AGM. - */ - { - char *_TMP_ = pamh->authtok; - if (_TMP_ == item) /* not changed so leave alone */ - break; - pamh->authtok = (item) ? _pam_strdup(item) : NULL; - if (_TMP_) { - _pam_overwrite(_TMP_); - free(_TMP_); + /* + * PAM_AUTHTOK and PAM_OLDAUTHTOK are only accessible from + * modules. + */ + if (__PAM_FROM_MODULE(pamh)) { + char *_TMP_ = pamh->authtok; + if (_TMP_ == item) /* not changed so leave alone */ + break; + pamh->authtok = (item) ? _pam_strdup(item) : NULL; + if (_TMP_) { + _pam_overwrite(_TMP_); + free(_TMP_); + } + } else { + retval = PAM_BAD_ITEM; } + break; - } + case PAM_OLDAUTHTOK: - /* See note above. */ - { - char *_TMP_ = pamh->oldauthtok; - if (_TMP_ == item) /* not changed so leave alone */ - break; - pamh->oldauthtok = (item) ? _pam_strdup(item) : NULL; - if (_TMP_) { - _pam_overwrite(_TMP_); - free(_TMP_); + /* + * PAM_AUTHTOK and PAM_OLDAUTHTOK are only accessible from + * modules. + */ + if (__PAM_FROM_MODULE(pamh)) { + char *_TMP_ = pamh->oldauthtok; + if (_TMP_ == item) /* not changed so leave alone */ + break; + pamh->oldauthtok = (item) ? _pam_strdup(item) : NULL; + if (_TMP_) { + _pam_overwrite(_TMP_); + free(_TMP_); + } + } else { + retval = PAM_BAD_ITEM; } + break; - } + case PAM_CONV: /* want to change the conversation function */ if (item == NULL) { _pam_system_log(LOG_ERR, @@ -117,23 +134,24 @@ int pam_set_item ( } } break; + case PAM_FAIL_DELAY: pamh->fail_delay.delay_fn_ptr = item; break; + default: retval = PAM_BAD_ITEM; } - return (retval); + return retval; } -int pam_get_item ( - const pam_handle_t *pamh, - int item_type, - const void **item) +int pam_get_item (const pam_handle_t *pamh, int item_type, const void **item) { + int retval = PAM_SUCCESS; + D(("called.")); - IF_NO_PAMH("pam_get_item",pamh,PAM_SYSTEM_ERR); + IF_NO_PAMH("pam_get_item", pamh, PAM_SYSTEM_ERR); if (item == NULL) { _pam_system_log(LOG_ERR, @@ -145,45 +163,72 @@ int pam_get_item ( case PAM_SERVICE: *item = pamh->service_name; break; + case PAM_USER: D(("returning user=%s", pamh->user)); *item = pamh->user; break; + case PAM_USER_PROMPT: D(("returning userprompt=%s", pamh->user)); *item = pamh->prompt; break; + case PAM_TTY: D(("returning tty=%s", pamh->tty)); *item = pamh->tty; break; + case PAM_RUSER: *item = pamh->ruser; break; + case PAM_RHOST: *item = pamh->rhost; break; + case PAM_AUTHTOK: - *item = pamh->authtok; + /* + * PAM_AUTHTOK and PAM_OLDAUTHTOK are only accessible from + * modules. + */ + if (__PAM_FROM_MODULE(pamh)) { + *item = pamh->authtok; + } else { + retval = PAM_BAD_ITEM; + } break; + case PAM_OLDAUTHTOK: - *item = pamh->oldauthtok; + /* + * PAM_AUTHTOK and PAM_OLDAUTHTOK are only accessible from + * modules. + */ + if (__PAM_FROM_MODULE(pamh)) { + *item = pamh->oldauthtok; + } else { + retval = PAM_BAD_ITEM; + } break; + case PAM_CONV: *item = pamh->pam_conversation; break; + case PAM_FAIL_DELAY: *item = pamh->fail_delay.delay_fn_ptr; break; + default: - /* XXX - I made this up */ - return PAM_BAD_ITEM; + retval = PAM_BAD_ITEM; } - return PAM_SUCCESS; + return retval; } -/* added by AGM 1996/3/2 */ +/* + * This function is the 'preferred method to obtain the username'. + */ int pam_get_user(pam_handle_t *pamh, const char **user, const char *prompt) { diff --git a/libpam/pam_misc.c b/libpam/pam_misc.c index 9bd52bfa..2d93a946 100644 --- a/libpam/pam_misc.c +++ b/libpam/pam_misc.c @@ -177,11 +177,15 @@ int _pam_mkargv(char *s, char ***argv, int *argc) void _pam_sanitize(pam_handle_t *pamh) { + int old_caller_is = pamh->caller_is; + /* * this is for security. We reset the auth-tokens here. */ - pam_set_item(pamh,PAM_AUTHTOK,NULL); - pam_set_item(pamh,PAM_OLDAUTHTOK,NULL); + __PAM_TO_MODULE(pamh); + pam_set_item(pamh, PAM_AUTHTOK, NULL); + pam_set_item(pamh, PAM_OLDAUTHTOK, NULL); + pamh->caller_is = old_caller_is; } /* diff --git a/libpam/pam_password.c b/libpam/pam_password.c index afbaa580..8e36971e 100644 --- a/libpam/pam_password.c +++ b/libpam/pam_password.c @@ -19,6 +19,11 @@ int pam_chauthtok(pam_handle_t *pamh, int flags) IF_NO_PAMH("pam_chauthtok", pamh, PAM_SYSTEM_ERR); + if (__PAM_FROM_MODULE(pamh)) { + D(("called from module!?")); + return PAM_SYSTEM_ERR; + } + if (pamh->former.choice == PAM_NOT_STACKED) { _pam_start_timer(pamh); /* we try to make the time for a failure independent of the time it takes to diff --git a/libpam/pam_private.h b/libpam/pam_private.h index 7b36fb02..2aa90bd4 100644 --- a/libpam/pam_private.h +++ b/libpam/pam_private.h @@ -126,6 +126,7 @@ struct _pam_former_state { struct pam_handle { char *authtok; + unsigned caller_is; struct pam_conv *pam_conversation; char *oldauthtok; char *prompt; /* for use by pam_get_user() */ @@ -268,9 +269,22 @@ if ((pamh) == NULL) { \ #include <security/_pam_macros.h> +/* used to work out where control currently resides (in an application + or in a module) */ + +#define _PAM_CALLED_FROM_MODULE 1 +#define _PAM_CALLED_FROM_APP 2 + +#define __PAM_FROM_MODULE(pamh) ((pamh)->caller_is == _PAM_CALLED_FROM_MODULE) +#define __PAM_FROM_APP(pamh) ((pamh)->caller_is == _PAM_CALLED_FROM_APP) +#define __PAM_TO_MODULE(pamh) \ + do { (pamh)->caller_is = _PAM_CALLED_FROM_MODULE; } while (0) +#define __PAM_TO_APP(pamh) \ + do { (pamh)->caller_is = _PAM_CALLED_FROM_APP; } while (0) + /* * Copyright (C) 1995 by Red Hat Software, Marc Ewing - * Copyright (c) 1996-8, Andrew G. Morgan <morgan@linux.kernel.org> + * Copyright (c) 1996-8,2001 by Andrew G. Morgan <morgan@kernel.org> * * All rights reserved * diff --git a/libpam/pam_session.c b/libpam/pam_session.c index de2538d0..16b021df 100644 --- a/libpam/pam_session.c +++ b/libpam/pam_session.c @@ -12,7 +12,13 @@ int pam_open_session(pam_handle_t *pamh, int flags) { D(("called")); - IF_NO_PAMH("pam_open_session",pamh,PAM_SYSTEM_ERR); + IF_NO_PAMH("pam_open_session", pamh, PAM_SYSTEM_ERR); + + if (__PAM_FROM_MODULE(pamh)) { + D(("called from module!?")); + return PAM_SYSTEM_ERR; + } + return _pam_dispatch(pamh, flags, PAM_OPEN_SESSION); } @@ -20,6 +26,12 @@ int pam_close_session(pam_handle_t *pamh, int flags) { D(("called")); - IF_NO_PAMH("pam_close_session",pamh,PAM_SYSTEM_ERR); + IF_NO_PAMH("pam_close_session", pamh, PAM_SYSTEM_ERR); + + if (__PAM_FROM_MODULE(pamh)) { + D(("called from module!?")); + return PAM_SYSTEM_ERR; + } + return _pam_dispatch(pamh, flags, PAM_CLOSE_SESSION); } diff --git a/libpam/pam_start.c b/libpam/pam_start.c index fb222d62..0e50bb40 100644 --- a/libpam/pam_start.c +++ b/libpam/pam_start.c @@ -29,6 +29,11 @@ int pam_start ( return (PAM_BUF_ERR); } + /* Mark the caller as the application - permission to do certain + things is limited to a module or an application */ + + __PAM_TO_APP(*pamh); + if (service_name) { char *tmp; @@ -92,11 +97,6 @@ int pam_start ( /* According to the SunOS man pages, loading modules and resolving * symbols happens on the first call from the application. */ - /* - * XXX - should we call _pam_init_handlers() here ? The following - * is new as of Linux-PAM 0.55 - */ - if ( _pam_init_handlers(*pamh) != PAM_SUCCESS ) { _pam_system_log(LOG_ERR, "pam_start: failed to initialize handlers"); _pam_drop_env(*pamh); /* purge the environment */ diff --git a/libpam/pam_tokens.h b/libpam/pam_tokens.h index 881fcc47..fad30759 100644 --- a/libpam/pam_tokens.h +++ b/libpam/pam_tokens.h @@ -59,13 +59,15 @@ const char * const _pam_token_returns[_PAM_RETURN_VALUES+1] = { "authtok_expired", /* 27 */ "module_unknown", /* 28 */ "bad_item", /* 29 */ + "conv_again", /* 30 */ + "incomplete", /* 31 */ /* add new return codes here */ "default" /* this is _PAM_RETURN_VALUES and indicates the default return action */ }; /* - * Copyright (C) 1998, Andrew G. Morgan <morgan@linux.kernel.org> + * Copyright (C) 1998,2001 Andrew G. Morgan <morgan@kernel.org> * * All rights reserved * |