From 9fb9393ede4ee9d43ff841557f95ed2af7d1a15f Mon Sep 17 00:00:00 2001 From: "Andrew G. Morgan" Date: Mon, 22 Jan 2001 06:07:28 +0000 Subject: 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. --- CHANGELOG | 5 ++ doc/pam_appl.sgml | 87 +++++++++++++++--------- doc/pam_modules.sgml | 28 ++++---- doc/pam_source.sgml | 2 +- libpam/Makefile | 10 +-- libpam/include/security/_pam_types.h | 10 ++- libpam/pam_account.c | 14 +++- libpam/pam_auth.c | 15 ++++- libpam/pam_data.c | 60 +++++++++++------ libpam/pam_delay.c | 2 +- libpam/pam_dispatch.c | 11 ++- libpam/pam_end.c | 7 +- libpam/pam_env.c | 1 + libpam/pam_handlers.c | 2 +- libpam/pam_item.c | 127 ++++++++++++++++++++++++----------- libpam/pam_misc.c | 8 ++- libpam/pam_password.c | 5 ++ libpam/pam_private.h | 16 ++++- libpam/pam_session.c | 16 ++++- libpam/pam_start.c | 10 +-- libpam/pam_tokens.h | 4 +- 21 files changed, 308 insertions(+), 132 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 1a234b51..929e0fa8 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -35,6 +35,11 @@ Where you should replace XXXXX with a bug-id. 0.74: please submit patches for this section with actual code/doc patches! +* libpam - cleaned up a few non-static functions to be static and added + support for libpam to enforce things like pam_[gs]et_data() and + AUTHTOK rules for using the API. Also documented pam_[gs]et_item() + a little better including return codes (Bugs 129027, 128576 - + agmorgan). * pam_access - fixed the non-default config file option (Bug 127561 - agmorgan) * pam.8 manual page clarified with respect to the default location for diff --git a/doc/pam_appl.sgml b/doc/pam_appl.sgml index 16c4f468..b1010203 100644 --- a/doc/pam_appl.sgml +++ b/doc/pam_appl.sgml @@ -45,8 +45,8 @@ DAMAGE.
The Linux-PAM Application Developers' Guide -<author>Andrew G. Morgan, <tt>morgan@linux.kernel.org</tt> -<date>DRAFT v0.73 2000/12/02 +<author>Andrew G. Morgan, <tt>morgan@kernel.org</tt> +<date>DRAFT v0.74 2001/01/21 <abstract> This manual documents what an application developer needs to know about the <bf>Linux-PAM</bf> library. It describes how an application @@ -316,33 +316,41 @@ extern int pam_set_item(pam_handle_t *pamh, int item_type, <tag><tt/PAM_USER/</tag> The user name +<tag><tt/PAM_USER_PROMPT/</tag> + The string used when prompting for a user's name. The default +value for this string is ``Please enter username: ''. + <tag><tt/PAM_TTY/</tag> The terminal name: prefixed by <tt>/dev/</tt> if it is a device file; for graphical, X-based, applications the value for this item should be the <tt/$DISPLAY/ variable. +<tag><tt/PAM_RUSER/</tag> + The requesting user's username + <tag><tt/PAM_RHOST/</tag> - The remote host name + The requesting hostname (the hostname of the machine from which + the <tt/PAM_RUSER/ is requesting service) <tag><tt/PAM_CONV/</tag> The conversation structure (see section <ref id="the-conversation-function" name="below">) -<tag><tt/PAM_RUSER/</tag> - The remote user name - -<tag><tt/PAM_USER_PROMPT/</tag> - The string used when prompting for a user's name. The default -value for this string is ``Please enter username: ''. +<tag><tt/PAM_FAIL_DELAY/</tag> A function pointer to redirect + centrally managed failure delays (see section <ref + id="the-failure-delay-function" name="below">). </descrip> <p> -For all <tt/item_type/s, other than <tt/PAM_CONV/, <tt/item/ is a -pointer to a <tt><NUL></tt> terminated character string. In the -case of <tt/PAM_CONV/, <tt/item/ points to an initialized -<tt/pam_conv/ structure (see section <ref -id="the-conversation-function" name="below">). +For all <tt/item_type/s, other than <tt/PAM_CONV/ and +<tt/PAM_FAIL_DELAY/, <tt/item/ is a pointer to a <tt><NUL></tt> +terminated character string. In the case of <tt/PAM_CONV/, <tt/item/ +points to an initialized <tt/pam_conv/ structure (see section <ref +id="the-conversation-function" name="below">). In the case of +<tt/PAM_FAIL_DELAY/, <tt/item/ is a function pointer: <tt/void +(*delay_fn)(int retval, unsigned usec_delay, void *appdata_ptr)/ (see +section <ref id="the-failure-delay-function" name="below">). <p> A successful call to this function returns <tt/PAM_SUCCESS/. However, @@ -350,13 +358,17 @@ the application should expect one of the following errors: <p> <descrip> +<tag><tt/PAM_SYSTEM_ERR/</tag> + The <tt/pam_handle_t/ passed as a first argument to this + function was invalid. <tag><tt/PAM_PERM_DENIED/</tag> An attempt was made to replace the conversation structure with -a <tt/NULL/ value. + a <tt/NULL/ value. <tag><tt/PAM_BUF_ERR/</tag> The function ran out of memory making a copy of the item. <tag><tt/PAM_BAD_ITEM/</tag> - The application attempted to set an undefined item. + The application attempted to set an undefined or inaccessible + item. </descrip> <sect2>Getting PAM items @@ -375,9 +387,31 @@ This function is used to obtain the value of the indicated <tt/item_type/. Upon successful return, <tt/*item/ contains a pointer to the value of the corresponding item. Note, this is a pointer to the <em/actual/ data and should <em/not/ be <tt/free()/'ed or -over-written! A successful call is signaled by a return value of -<tt/PAM_SUCCESS/. If an attempt is made to get an undefined item, -<tt/PAM_BAD_ITEM/ is returned. +over-written! + +<p> +A successful call is signaled by a return value of <tt/PAM_SUCCESS/. +However, the application should expect one of the following errors: + +<p> +<descrip> +<tag><tt/PAM_SYSTEM_ERR/</tag> + The <tt/pam_handle_t/ passed as a first argument to this + function was invalid. +<tag><tt/PAM_PERM_DENIED/</tag> + The value of <tt/item/ was <tt/NULL/. +<tag><tt/PAM_BAD_ITEM/</tag> + The application attempted to set an undefined or inaccessible + item. +</descrip> + +<p> +Note, in the case of an error, the contents of <tt/item/ is not +modified - that is, it retains its pre-call value. One should take +care to initialize this value prior to calling +<tt/pam_get_item()/. Since, if its value - despite the +<tt/pam_get_item()/ function failing - is to be used the consequences +are undefined. <sect2>Understanding errors <label id="pam-strerror-section"> @@ -395,6 +429,7 @@ error associated with the argument <tt/errnum/. If the error is not recognized ``<tt/Unknown Linux-PAM error/'' is returned. <sect2>Planning for delays +<label id="the-failure-delay-function"> <p> <tscreen> @@ -410,9 +445,9 @@ is returned to the application. When using this function the application programmer should check if it is available with, <tscreen> <verb> -#ifdef HAVE_PAM_FAIL_DELAY +#ifdef PAM_FAIL_DELAY .... -#endif /* HAVE_PAM_FAIL_DELAY */ +#endif /* PAM_FAIL_DELAY */ </verb> </tscreen> @@ -463,7 +498,7 @@ void (*delay_fn)(int retval, unsigned usec_delay, void *appdata_ptr); The arguments being the <tt/retval/ return code of the module stack, the <tt/usec_delay/ micro-second delay that libpam is requesting and the <tt/appdata_ptr/ that the application has associated with the -current <tt/pamh/ (/tt/pam_handle_t/). This last value was set by the +current <tt/pamh/ (<tt/pam_handle_t/). This last value was set by the application when it called <tt/pam_start/ or explicitly with <tt/pam_set_item(... , PAM_CONV, ...)/. Note, if <tt/PAM_FAIL_DELAY/ is unset (or set to <tt/NULL/), then <tt/libpam/ will perform any @@ -745,14 +780,6 @@ extern int pam_putenv(pam_handle_t *pamh, const char *name_value); </verb> </tscreen> -<p> -<em> -Warning, the environment support in <bf/Linux-PAM/ is based solely -on a six line email from the developers at Sun. Its interface is -likely to be generally correct, however, the details are likely to be -changed as more information becomes available. -</em> - <p> This function attempts to (re)set a <bf/Linux-PAM/ environment variable. The <tt/name_value/ argument is a single <tt/NUL/ terminated diff --git a/doc/pam_modules.sgml b/doc/pam_modules.sgml index 8d313261..694eff85 100644 --- a/doc/pam_modules.sgml +++ b/doc/pam_modules.sgml @@ -48,8 +48,8 @@ DAMAGE. <article> <title>The Linux-PAM Module Writers' Guide -<author>Andrew G. Morgan, <tt>morgan@linux.kernel.org</tt> -<date>DRAFT v0.73 2000/12/02 +<author>Andrew G. Morgan, <tt>morgan@kernel.org</tt> +<date>DRAFT v0.74 2001/01/21 <abstract> This manual documents what a programmer needs to know in order to write a module that conforms to the <bf/Linux-PAM/ standard. It also @@ -207,10 +207,9 @@ Setting items Synopsis: <tscreen> <verb> -extern int pam_set_item(pam_handle_t *pamh - , int item_type - , const void *item - ); +extern int pam_set_item(pam_handle_t *pamh, + int item_type, + const void *item); </verb> </tscreen> @@ -227,8 +226,8 @@ following two <tt/item_type/s: <descrip> <tag><tt/PAM_AUTHTOK/</tag> -The authentication token (password). This token should be ignored by -all module functions besides <tt/pam_sm_authenticate()/ and +The authentication token (often a password). This token should be +ignored by all module functions besides <tt/pam_sm_authenticate()/ and <tt/pam_sm_chauthtok()/. In the former function it is used to pass the most recent authentication token from one stacked module to another. In the latter function the token is used for another @@ -258,10 +257,9 @@ Getting items Synopsis: <tscreen> <verb> -extern int pam_get_item(const pam_handle_t *pamh - , int item_type - , const void **item - ); +extern int pam_get_item(const pam_handle_t *pamh, + int item_type, + const void **item); </verb> </tscreen> @@ -413,7 +411,7 @@ extern int pam_putenv(pam_handle_t *pamh, const char *name_value); </tscreen> <p> -<bf/Linux-PAM/ (0.54+) comes equipped with a series of functions for +<bf/Linux-PAM/ comes equipped with a series of functions for maintaining a set of <em/environment/ variables. The environment is initialized by the call to <tt/pam_start()/ and is <bf/erased/ with a call to <tt/pam_end()/. This <em/environment/ is associated with the @@ -531,9 +529,9 @@ is returned to the application. When using this function the module programmer should check if it is available with, <tscreen> <verb> -#ifdef HAVE_PAM_FAIL_DELAY +#ifdef PAM_FAIL_DELAY .... -#endif /* HAVE_PAM_FAIL_DELAY */ +#endif /* PAM_FAIL_DELAY */ </verb> </tscreen> diff --git a/doc/pam_source.sgml b/doc/pam_source.sgml index 346082b0..f3be802e 100644 --- a/doc/pam_source.sgml +++ b/doc/pam_source.sgml @@ -46,7 +46,7 @@ DAMAGE. <title>The Linux-PAM System Administrators' Guide <author>Andrew G. Morgan, <tt>morgan@kernel.org</tt> -<date>DRAFT v0.73 2000/11/03 +<date>DRAFT v0.74 2001/01/21 <abstract> This manual documents what a system-administrator needs to know about the <bf>Linux-PAM</bf> library. It covers the correct syntax of the 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 * -- cgit v1.2.3