summaryrefslogtreecommitdiff
path: root/libpam
diff options
context:
space:
mode:
Diffstat (limited to 'libpam')
-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
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
*