summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew G. Morgan <morgan@kernel.org>2001-01-22 06:07:28 +0000
committerAndrew G. Morgan <morgan@kernel.org>2001-01-22 06:07:28 +0000
commit9fb9393ede4ee9d43ff841557f95ed2af7d1a15f (patch)
tree34a3323fac5906ceb5aa54b5d482090bdaba47c0
parente6d5049a8d484fb7a764a125d830b23f59a0c685 (diff)
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.
-rw-r--r--CHANGELOG5
-rw-r--r--doc/pam_appl.sgml87
-rw-r--r--doc/pam_modules.sgml28
-rw-r--r--doc/pam_source.sgml2
-rw-r--r--libpam/Makefile10
-rw-r--r--libpam/include/security/_pam_types.h10
-rw-r--r--libpam/pam_account.c14
-rw-r--r--libpam/pam_auth.c15
-rw-r--r--libpam/pam_data.c60
-rw-r--r--libpam/pam_delay.c2
-rw-r--r--libpam/pam_dispatch.c11
-rw-r--r--libpam/pam_end.c7
-rw-r--r--libpam/pam_env.c1
-rw-r--r--libpam/pam_handlers.c2
-rw-r--r--libpam/pam_item.c127
-rw-r--r--libpam/pam_misc.c8
-rw-r--r--libpam/pam_password.c5
-rw-r--r--libpam/pam_private.h16
-rw-r--r--libpam/pam_session.c16
-rw-r--r--libpam/pam_start.c10
-rw-r--r--libpam/pam_tokens.h4
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.
<article>
<title>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/&dollar;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>&lt;NUL&gt;</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>&lt;NUL&gt;</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
@@ -746,14 +781,6 @@ extern int pam_putenv(pam_handle_t *pamh, const char *name_value);
</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
string of one of the following forms:
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
*