summaryrefslogtreecommitdiff
path: root/libpam
diff options
context:
space:
mode:
Diffstat (limited to 'libpam')
-rw-r--r--libpam/Makefile.am2
-rw-r--r--libpam/Makefile.in14
-rw-r--r--libpam/include/pam_cc_compat.h20
-rw-r--r--libpam/include/pam_inline.h64
-rw-r--r--libpam/include/security/_pam_macros.h28
-rw-r--r--libpam/include/security/_pam_types.h6
-rw-r--r--libpam/include/security/pam_modutil.h11
-rw-r--r--libpam/pam.pc.in2
-rw-r--r--libpam/pam_dispatch.c17
-rw-r--r--libpam/pam_dynamic.c84
-rw-r--r--libpam/pam_end.c31
-rw-r--r--libpam/pam_env.c9
-rw-r--r--libpam/pam_get_authtok.c17
-rw-r--r--libpam/pam_handlers.c92
-rw-r--r--libpam/pam_item.c20
-rw-r--r--libpam/pam_modutil_getlogin.c50
-rw-r--r--libpam/pam_modutil_priv.c40
-rw-r--r--libpam/pam_vprompt.c6
18 files changed, 285 insertions, 228 deletions
diff --git a/libpam/Makefile.am b/libpam/Makefile.am
index 55222afc..389d5d02 100644
--- a/libpam/Makefile.am
+++ b/libpam/Makefile.am
@@ -21,7 +21,7 @@ noinst_HEADERS = pam_prelude.h pam_private.h pam_tokens.h \
include/pam_inline.h include/test_assert.h
libpam_la_LDFLAGS = -no-undefined -version-info 85:1:85
-libpam_la_LIBADD = @LIBAUDIT@ $(LIBPRELUDE_LIBS) $(ECONF_LIBS) @LIBDL@
+libpam_la_LIBADD = @LIBAUDIT@ $(LIBPRELUDE_LIBS) $(ECONF_LIBS) @LIBDL@ @LTLIBINTL@
if HAVE_VERSIONING
libpam_la_LDFLAGS += -Wl,--version-script=$(srcdir)/libpam.map
diff --git a/libpam/Makefile.in b/libpam/Makefile.in
index 0c2333c0..597c8dcd 100644
--- a/libpam/Makefile.in
+++ b/libpam/Makefile.in
@@ -286,6 +286,7 @@ CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DLLTOOL = @DLLTOOL@
+DOCBOOK_RNG = @DOCBOOK_RNG@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
@@ -298,11 +299,13 @@ EXEEXT = @EXEEXT@
EXE_CFLAGS = @EXE_CFLAGS@
EXE_LDFLAGS = @EXE_LDFLAGS@
FGREP = @FGREP@
+FILECMD = @FILECMD@
FO2PDF = @FO2PDF@
GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@
GMSGFMT = @GMSGFMT@
GMSGFMT_015 = @GMSGFMT_015@
GREP = @GREP@
+HTML_STYLESHEET = @HTML_STYLESHEET@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
@@ -334,12 +337,14 @@ LIBSELINUX = @LIBSELINUX@
LIBTOOL = @LIBTOOL@
LIPO = @LIPO@
LN_S = @LN_S@
+LOGIND_CFLAGS = @LOGIND_CFLAGS@
LTLIBICONV = @LTLIBICONV@
LTLIBINTL = @LTLIBINTL@
LTLIBOBJS = @LTLIBOBJS@
LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
MAKEINFO = @MAKEINFO@
MANIFEST_TOOL = @MANIFEST_TOOL@
+MAN_STYLESHEET = @MAN_STYLESHEET@
MKDIR_P = @MKDIR_P@
MSGFMT = @MSGFMT@
MSGFMT_015 = @MSGFMT_015@
@@ -362,6 +367,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
+PDF_STYLESHEET = @PDF_STYLESHEET@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
@@ -372,12 +378,16 @@ SECUREDIR = @SECUREDIR@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
-STRINGPARAM_HMAC = @STRINGPARAM_HMAC@
+STRINGPARAM_PROFILECONDITIONS = @STRINGPARAM_PROFILECONDITIONS@
STRINGPARAM_VENDORDIR = @STRINGPARAM_VENDORDIR@
STRIP = @STRIP@
+SYSTEMD_CFLAGS = @SYSTEMD_CFLAGS@
+SYSTEMD_LIBS = @SYSTEMD_LIBS@
TIRPC_CFLAGS = @TIRPC_CFLAGS@
TIRPC_LIBS = @TIRPC_LIBS@
+TXT_STYLESHEET = @TXT_STYLESHEET@
USE_NLS = @USE_NLS@
+VENDOR_SCONFIGDIR = @VENDOR_SCONFIGDIR@
VERSION = @VERSION@
WARN_CFLAGS = @WARN_CFLAGS@
XGETTEXT = @XGETTEXT@
@@ -461,7 +471,7 @@ noinst_HEADERS = pam_prelude.h pam_private.h pam_tokens.h \
libpam_la_LDFLAGS = -no-undefined -version-info 85:1:85 \
$(am__append_1)
-libpam_la_LIBADD = @LIBAUDIT@ $(LIBPRELUDE_LIBS) $(ECONF_LIBS) @LIBDL@
+libpam_la_LIBADD = @LIBAUDIT@ $(LIBPRELUDE_LIBS) $(ECONF_LIBS) @LIBDL@ @LTLIBINTL@
lib_LTLIBRARIES = libpam.la
libpam_la_SOURCES = pam_account.c pam_auth.c pam_data.c pam_delay.c \
pam_dispatch.c pam_end.c pam_env.c pam_get_authtok.c \
diff --git a/libpam/include/pam_cc_compat.h b/libpam/include/pam_cc_compat.h
index 69190368..0a6e32d5 100644
--- a/libpam/include/pam_cc_compat.h
+++ b/libpam/include/pam_cc_compat.h
@@ -32,6 +32,11 @@
_Pragma("GCC diagnostic ignored \"-Wcast-align\"")
# define DIAG_POP_IGNORE_CAST_ALIGN \
_Pragma("GCC diagnostic pop")
+# define DIAG_PUSH_IGNORE_FORMAT_NONLITERAL \
+ _Pragma("GCC diagnostic push"); \
+ _Pragma("GCC diagnostic ignored \"-Wformat-nonliteral\"")
+# define DIAG_POP_IGNORE_FORMAT_NONLITERAL \
+ _Pragma("GCC diagnostic pop")
#elif PAM_CLANG_PREREQ(2, 6)
# define DIAG_PUSH_IGNORE_CAST_QUAL \
_Pragma("clang diagnostic push"); \
@@ -43,11 +48,18 @@
_Pragma("clang diagnostic ignored \"-Wcast-align\"")
# define DIAG_POP_IGNORE_CAST_ALIGN \
_Pragma("clang diagnostic pop")
+# define DIAG_PUSH_IGNORE_FORMAT_NONLITERAL \
+ _Pragma("clang diagnostic push"); \
+ _Pragma("clang diagnostic ignored \"-Wformat-nonliteral\"")
+# define DIAG_POP_IGNORE_FORMAT_NONLITERAL \
+ _Pragma("clang diagnostic pop")
#else
-# define DIAG_PUSH_IGNORE_CAST_QUAL /* empty */
-# define DIAG_POP_IGNORE_CAST_QUAL /* empty */
-# define DIAG_PUSH_IGNORE_CAST_ALIGN /* empty */
-# define DIAG_POP_IGNORE_CAST_ALIGN /* empty */
+# define DIAG_PUSH_IGNORE_CAST_QUAL /* empty */
+# define DIAG_POP_IGNORE_CAST_QUAL /* empty */
+# define DIAG_PUSH_IGNORE_CAST_ALIGN /* empty */
+# define DIAG_POP_IGNORE_CAST_ALIGN /* empty */
+# define DIAG_PUSH_IGNORE_FORMAT_NONLITERAL /* empty */
+# define DIAG_POP_IGNORE_FORMAT_NONLITERAL /* empty */
#endif
/*
diff --git a/libpam/include/pam_inline.h b/libpam/include/pam_inline.h
index ec2f3bf0..7721c0b7 100644
--- a/libpam/include/pam_inline.h
+++ b/libpam/include/pam_inline.h
@@ -9,6 +9,7 @@
#define PAM_INLINE_H
#include "pam_cc_compat.h"
+#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
@@ -33,6 +34,12 @@
* 0, otherwise.
*/
#define PAM_MUST_BE_ARRAY(a_) PAM_FAIL_BUILD_ON_ZERO(!PAM_IS_NOT_ARRAY(a_))
+/*
+ * Evaluates to
+ * - a syntax error if the argument is an array,
+ * 0, otherwise.
+ */
+#define PAM_MUST_NOT_BE_ARRAY(a_) PAM_FAIL_BUILD_ON_ZERO(PAM_IS_NOT_ARRAY(a_))
/* Evaluates to the number of elements in the specified array. */
#define PAM_ARRAY_SIZE(a_) (sizeof(a_) / sizeof((a_)[0]) + PAM_MUST_BE_ARRAY(a_))
@@ -66,6 +73,59 @@ pam_str_skip_icase_prefix_len(const char *str, const char *prefix, size_t prefix
#define pam_str_skip_icase_prefix(str_, prefix_) \
pam_str_skip_icase_prefix_len((str_), (prefix_), sizeof(prefix_) - 1 + PAM_MUST_BE_ARRAY(prefix_))
+
+/*
+ * Macros to securely erase memory
+ */
+
+#ifdef HAVE_MEMSET_EXPLICIT
+static inline void pam_overwrite_n(void *ptr, size_t len)
+{
+ if (ptr)
+ memset_explicit(ptr, len);
+}
+#elif defined HAVE_EXPLICIT_BZERO
+static inline void pam_overwrite_n(void *ptr, size_t len)
+{
+ if (ptr)
+ explicit_bzero(ptr, len);
+}
+#else
+static inline void pam_overwrite_n(void *ptr, size_t len)
+{
+ if (ptr) {
+ ptr = memset(ptr, '\0', len);
+ __asm__ __volatile__ ("" : : "r"(ptr) : "memory");
+ }
+}
+#endif
+
+#define pam_overwrite_string(x) \
+do { \
+ char *xx__ = (x) + PAM_MUST_NOT_BE_ARRAY(x); \
+ if (xx__) \
+ pam_overwrite_n(xx__, strlen(xx__)); \
+} while(0)
+
+#define pam_overwrite_array(x) pam_overwrite_n(x, sizeof(x) + PAM_MUST_BE_ARRAY(x))
+
+#define pam_overwrite_object(x) pam_overwrite_n(x, sizeof(*(x)) + PAM_MUST_NOT_BE_ARRAY(x))
+
+static inline void
+pam_drop_response(struct pam_response *reply, int replies)
+{
+ int reply_i;
+
+ for (reply_i = 0; reply_i < replies; ++reply_i) {
+ if (reply[reply_i].resp) {
+ pam_overwrite_string(reply[reply_i].resp);
+ free(reply[reply_i].resp);
+ }
+ }
+ free(reply);
+}
+
+
static inline int
pam_read_passwords(int fd, int npass, char **passwords)
{
@@ -101,7 +161,7 @@ pam_read_passwords(int fd, int npass, char **passwords)
if (npass > 0) {
memcpy(passwords[i], pptr, rbytes);
}
- memset(pptr, '\0', rbytes);
+ pam_overwrite_n(pptr, rbytes);
}
}
offset += rbytes;
@@ -109,7 +169,7 @@ pam_read_passwords(int fd, int npass, char **passwords)
/* clear up */
if (offset > 0 && npass > 0) {
- memset(passwords[i], '\0', offset);
+ pam_overwrite_n(passwords[i], offset);
}
return i;
diff --git a/libpam/include/security/_pam_macros.h b/libpam/include/security/_pam_macros.h
index e891e226..b5129d2a 100644
--- a/libpam/include/security/_pam_macros.h
+++ b/libpam/include/security/_pam_macros.h
@@ -7,6 +7,8 @@
* Organized by Cristian Gafton <gafton@redhat.com>
*/
+#include "_pam_types.h"
+
/* a 'safe' version of strdup */
#include <stdlib.h>
@@ -14,20 +16,22 @@
#define x_strdup(s) ( (s) ? strdup(s):NULL )
-/* Good policy to strike out passwords with some characters not just
- free the memory */
+/*
+ * WARNING: Do NOT use these overwrite macros, as they do not reliable
+ * override the memory.
+ */
-#define _pam_overwrite(x) \
-do { \
- register char *__xx__; \
- if ((__xx__=(x))) \
- while (*__xx__) \
- *__xx__++ = '\0'; \
+#define _pam_overwrite(x) \
+do { \
+ PAM_DEPRECATED register char *__xx__; \
+ if ((__xx__=(x))) \
+ while (*__xx__) \
+ *__xx__++ = '\0'; \
} while (0)
#define _pam_overwrite_n(x,n) \
do { \
- register char *__xx__; \
+ PAM_DEPRECATED register char *__xx__; \
register unsigned int __i__ = 0; \
if ((__xx__=(x))) \
for (;__i__<n; __i__++) \
@@ -46,9 +50,13 @@ do { \
} \
} while (0)
+/*
+ * WARNING: Do NOT use this macro, as it does not reliable override the memory.
+ */
+
#define _pam_drop_reply(/* struct pam_response * */ reply, /* int */ replies) \
do { \
- int reply_i; \
+ PAM_DEPRECATED int reply_i; \
\
for (reply_i=0; reply_i<replies; ++reply_i) { \
if (reply[reply_i].resp) { \
diff --git a/libpam/include/security/_pam_types.h b/libpam/include/security/_pam_types.h
index 2abb7ee5..4d6909e8 100644
--- a/libpam/include/security/_pam_types.h
+++ b/libpam/include/security/_pam_types.h
@@ -160,6 +160,12 @@ typedef struct pam_handle pam_handle_t;
# define PAM_FORMAT(params)
#endif
+#if PAM_GNUC_PREREQ(3,1)
+# define PAM_DEPRECATED __attribute__((__deprecated__))
+#else
+# define PAM_DEPRECATED
+#endif
+
#if PAM_GNUC_PREREQ(3,3) && !defined(LIBPAM_COMPILE)
# define PAM_NONNULL(params) __attribute__((__nonnull__ params))
#else
diff --git a/libpam/include/security/pam_modutil.h b/libpam/include/security/pam_modutil.h
index 33f87b90..c2578323 100644
--- a/libpam/include/security/pam_modutil.h
+++ b/libpam/include/security/pam_modutil.h
@@ -147,7 +147,16 @@ pam_modutil_sanitize_helper_fds(pam_handle_t *pamh,
enum pam_modutil_redirect_fd redirect_stdout,
enum pam_modutil_redirect_fd redirect_stderr);
-/* lookup a value for key in login.defs file or similar key value format */
+/**************************************************
+ * @brief Lookup a value for the key in the file (i.e. login.defs or a similar
+ * key-value format file).
+ *
+ * @param[in] pamh The pam handle structure
+ * @param[in] file_name Configuration file name
+ * @param[in] key Lookup key
+ *
+ * @return value, or NULL if key was not found.
+ **************************************************/
extern char * PAM_NONNULL((1,2,3))
pam_modutil_search_key(pam_handle_t *pamh,
const char *file_name,
diff --git a/libpam/pam.pc.in b/libpam/pam.pc.in
index a7cf852d..c3fafe4b 100644
--- a/libpam/pam.pc.in
+++ b/libpam/pam.pc.in
@@ -1,3 +1,5 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
diff --git a/libpam/pam_dispatch.c b/libpam/pam_dispatch.c
index 974104a2..15cad01f 100644
--- a/libpam/pam_dispatch.c
+++ b/libpam/pam_dispatch.c
@@ -260,22 +260,7 @@ static int _pam_dispatch_aux(pam_handle_t *pamh, int flags, struct handler *h,
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) ) {
- if ( retval != PAM_IGNORE || cached_retval == retval ) {
- if ( impression == _PAM_UNDEF && retval == PAM_SUCCESS ) {
- h->grantor = 1;
- }
- impression = _PAM_POSITIVE;
- status = retval;
- }
- }
- }
+ module as ignored as well as executing the jump. */
/* this means that we need to skip #action stacked modules */
while (h->next != NULL && h->next->stack_level >= stack_level && action > 0) {
diff --git a/libpam/pam_dynamic.c b/libpam/pam_dynamic.c
index c063083f..81f49b43 100644
--- a/libpam/pam_dynamic.c
+++ b/libpam/pam_dynamic.c
@@ -32,107 +32,25 @@
*/
#include "pam_private.h"
-
-#ifdef PAM_SHL
-# include <dl.h>
-#elif defined(PAM_DYLD)
-# include <mach-o/dyld.h>
-#else /* PAM_SHL */
-# include <dlfcn.h>
-#endif /* PAM_SHL */
-
-#ifndef SHLIB_SYM_PREFIX
-#define SHLIB_SYM_PREFIX "_"
-#endif
+#include <dlfcn.h>
void *_pam_dlopen(const char *mod_path)
{
-#ifdef PAM_SHL
- return shl_load(mod_path, BIND_IMMEDIATE, 0L);
-#elif defined(PAM_DYLD)
- NSObjectFileImage ofile;
- void *ret = NULL;
-
- if (NSCreateObjectFileImageFromFile(mod_path, &ofile) !=
- NSObjectFileImageSuccess )
- return NULL;
-
- ret = NSLinkModule(ofile, mod_path, NSLINKMODULE_OPTION_PRIVATE | NSLINKMODULE_OPTION_BINDNOW);
- NSDestroyObjectFileImage(ofile);
-
- return ret;
-#else
return dlopen(mod_path, RTLD_NOW);
-#endif
}
servicefn _pam_dlsym(void *handle, const char *symbol)
{
-#ifdef PAM_SHL
- char *_symbol = NULL;
- servicefn ret;
-
- if( symbol == NULL )
- return NULL;
-
- if( shl_findsym(&handle, symbol, (short) TYPE_PROCEDURE, &ret ){
- _symbol = malloc( strlen(symbol) + sizeof(SHLIB_SYM_PREFIX) + 1 );
- if( _symbol == NULL )
- return NULL;
- strcpy(_symbol, SHLIB_SYM_PREFIX);
- strcat(_symbol, symbol);
- if( shl_findsym(&handle, _symbol,
- (short) TYPE_PROCEDURE, &ret ){
- free(_symbol);
- return NULL;
- }
- free(_symbol);
- }
-
- return ret;
-
-#elif defined(PAM_DYLD)
- NSSymbol nsSymbol;
- char *_symbol;
-
- if( symbol == NULL )
- return NULL;
- _symbol = malloc( strlen(symbol) + 2 );
- if( _symbol == NULL )
- return NULL;
- strcpy(_symbol, SHLIB_SYM_PREFIX);
- strcat(_symbol, symbol);
-
- nsSymbol = NSLookupSymbolInModule(handle, _symbol);
- if( nsSymbol == NULL )
- return NULL;
- free(_symbol);
-
- return (servicefn)NSAddressOfSymbol(nsSymbol);
-#else
return (servicefn) dlsym(handle, symbol);
-#endif
}
void _pam_dlclose(void *handle)
{
-#ifdef PAM_SHL
- shl_unload(handle);
-#elif defined(PAM_DYLD)
- NSUnLinkModule((NSModule)handle, NSUNLINKMODULE_OPTION_NONE);
-#else
dlclose(handle);
-#endif
-
- return;
}
const char *
_pam_dlerror (void)
{
-#if defined(PAM_SHL) || defined(PAM_DYLD)
- return "unknown";
-#else
return dlerror ();
-#endif
}
diff --git a/libpam/pam_end.c b/libpam/pam_end.c
index 406b1478..9179a915 100644
--- a/libpam/pam_end.c
+++ b/libpam/pam_end.c
@@ -5,6 +5,7 @@
*/
#include "pam_private.h"
+#include "pam_inline.h"
#include <stdlib.h>
@@ -41,34 +42,34 @@ int pam_end(pam_handle_t *pamh, int pam_status)
_pam_drop_env(pamh); /* purge the environment */
- _pam_overwrite(pamh->authtok); /* blank out old token */
+ pam_overwrite_string(pamh->authtok); /* blank out old token */
_pam_drop(pamh->authtok);
- _pam_overwrite(pamh->oldauthtok); /* blank out old token */
+ pam_overwrite_string(pamh->oldauthtok); /* blank out old token */
_pam_drop(pamh->oldauthtok);
- _pam_overwrite(pamh->former.prompt);
+ pam_overwrite_string(pamh->former.prompt);
_pam_drop(pamh->former.prompt); /* drop saved prompt */
- _pam_overwrite(pamh->service_name);
+ pam_overwrite_string(pamh->service_name);
_pam_drop(pamh->service_name);
- _pam_overwrite(pamh->user);
+ pam_overwrite_string(pamh->user);
_pam_drop(pamh->user);
- _pam_overwrite(pamh->confdir);
+ pam_overwrite_string(pamh->confdir);
_pam_drop(pamh->confdir);
- _pam_overwrite(pamh->prompt);
+ pam_overwrite_string(pamh->prompt);
_pam_drop(pamh->prompt); /* prompt for pam_get_user() */
- _pam_overwrite(pamh->tty);
+ pam_overwrite_string(pamh->tty);
_pam_drop(pamh->tty);
- _pam_overwrite(pamh->rhost);
+ pam_overwrite_string(pamh->rhost);
_pam_drop(pamh->rhost);
- _pam_overwrite(pamh->ruser);
+ pam_overwrite_string(pamh->ruser);
_pam_drop(pamh->ruser);
_pam_drop(pamh->pam_conversation);
@@ -76,16 +77,16 @@ int pam_end(pam_handle_t *pamh, int pam_status)
_pam_drop(pamh->former.substates);
- _pam_overwrite(pamh->xdisplay);
+ pam_overwrite_string(pamh->xdisplay);
_pam_drop(pamh->xdisplay);
- _pam_overwrite(pamh->xauth.name);
+ pam_overwrite_string(pamh->xauth.name);
_pam_drop(pamh->xauth.name);
- _pam_overwrite_n(pamh->xauth.data, (unsigned int)pamh->xauth.datalen);
+ pam_overwrite_n(pamh->xauth.data, (unsigned int)pamh->xauth.datalen);
_pam_drop(pamh->xauth.data);
- _pam_overwrite_n((char *)&pamh->xauth, sizeof(pamh->xauth));
+ pam_overwrite_object(&pamh->xauth);
- _pam_overwrite(pamh->authtok_type);
+ pam_overwrite_string(pamh->authtok_type);
_pam_drop(pamh->authtok_type);
/* and finally liberate the memory for the pam_handle structure */
diff --git a/libpam/pam_env.c b/libpam/pam_env.c
index 1c8403d6..bfeb57ab 100644
--- a/libpam/pam_env.c
+++ b/libpam/pam_env.c
@@ -11,6 +11,7 @@
*/
#include "pam_private.h"
+#include "pam_inline.h"
#include <string.h>
#include <stdlib.h>
@@ -100,7 +101,7 @@ void _pam_drop_env(pam_handle_t *pamh)
for (i=pamh->env->requested-1; i-- > 0; ) {
D(("dropping #%3d>%s<", i, pamh->env->list[i]));
- _pam_overwrite(pamh->env->list[i]); /* clean */
+ pam_overwrite_string(pamh->env->list[i]); /* clean */
_pam_drop(pamh->env->list[i]); /* forget */
}
pamh->env->requested = 0;
@@ -227,7 +228,7 @@ int pam_putenv(pam_handle_t *pamh, const char *name_value)
} else { /* replace old */
D(("replacing item: %s\n with: %s"
, pamh->env->list[item], name_value));
- _pam_overwrite(pamh->env->list[item]);
+ pam_overwrite_string(pamh->env->list[item]);
_pam_drop(pamh->env->list[item]);
}
@@ -261,7 +262,7 @@ int pam_putenv(pam_handle_t *pamh, const char *name_value)
*/
D(("deleting: env#%3d:[%s]", item, pamh->env->list[item]));
- _pam_overwrite(pamh->env->list[item]);
+ pam_overwrite_string(pamh->env->list[item]);
_pam_drop(pamh->env->list[item]);
--(pamh->env->requested);
D(("mmove: item[%d]+%d -> item[%d]"
@@ -341,7 +342,7 @@ static char **_copy_env(pam_handle_t *pamh)
/* out of memory */
while (dump[++i]) {
- _pam_overwrite(dump[i]);
+ pam_overwrite_string(dump[i]);
_pam_drop(dump[i]);
}
_pam_drop(dump);
diff --git a/libpam/pam_get_authtok.c b/libpam/pam_get_authtok.c
index 3fa7f7df..3f383339 100644
--- a/libpam/pam_get_authtok.c
+++ b/libpam/pam_get_authtok.c
@@ -33,6 +33,7 @@
#include "config.h"
#include "pam_private.h"
+#include "pam_inline.h"
#include <security/pam_ext.h>
@@ -174,6 +175,10 @@ pam_get_authtok_internal (pam_handle_t *pamh, int item,
(chpass > 1 && resp[1] == NULL))
{
/* We want to abort */
+ pam_overwrite_string (resp[0]);
+ _pam_drop (resp[0]);
+ pam_overwrite_string (resp[1]);
+ _pam_drop (resp[1]);
if (chpass)
pam_error (pamh, _("Password change has been aborted."));
return PAM_AUTHTOK_ERR;
@@ -182,18 +187,18 @@ pam_get_authtok_internal (pam_handle_t *pamh, int item,
if (chpass > 1 && strcmp (resp[0], resp[1]) != 0)
{
pam_error (pamh, MISTYPED_PASS);
- _pam_overwrite (resp[0]);
+ pam_overwrite_string (resp[0]);
_pam_drop (resp[0]);
- _pam_overwrite (resp[1]);
+ pam_overwrite_string (resp[1]);
_pam_drop (resp[1]);
return PAM_TRY_AGAIN;
}
- _pam_overwrite (resp[1]);
+ pam_overwrite_string (resp[1]);
_pam_drop (resp[1]);
retval = pam_set_item (pamh, item, resp[0]);
- _pam_overwrite (resp[0]);
+ pam_overwrite_string (resp[0]);
_pam_drop (resp[0]);
if (retval != PAM_SUCCESS)
return retval;
@@ -263,13 +268,13 @@ pam_get_authtok_verify (pam_handle_t *pamh, const char **authtok,
{
pam_set_item (pamh, PAM_AUTHTOK, NULL);
pam_error (pamh, MISTYPED_PASS);
- _pam_overwrite (resp);
+ pam_overwrite_string (resp);
_pam_drop (resp);
return PAM_TRY_AGAIN;
}
retval = pam_set_item (pamh, PAM_AUTHTOK, resp);
- _pam_overwrite (resp);
+ pam_overwrite_string (resp);
_pam_drop (resp);
if (retval != PAM_SUCCESS)
return retval;
diff --git a/libpam/pam_handlers.c b/libpam/pam_handlers.c
index ffa5e4ae..dc5f81fa 100644
--- a/libpam/pam_handlers.c
+++ b/libpam/pam_handlers.c
@@ -123,6 +123,10 @@ static int _pam_parse_conf_file(pam_handle_t *pamh, FILE *f
module_type = PAM_T_ACCT;
} else if (!strcasecmp("password", tok)) {
module_type = PAM_T_PASS;
+ } else if (!strcasecmp("@include", tok)) {
+ pam_include = 1;
+ module_type = requested_module_type;
+ goto parsing_done;
} else {
/* Illegal module type */
D(("_pam_init_handlers: bad module type: %s", tok));
@@ -193,8 +197,10 @@ static int _pam_parse_conf_file(pam_handle_t *pamh, FILE *f
_pam_set_default_control(actions, _PAM_ACTION_BAD);
}
+parsing_done:
tok = _pam_StrTok(NULL, " \n\t", &nexttok);
if (pam_include) {
+ struct stat include_dir;
if (substack) {
res = _pam_add_handler(pamh, PAM_HT_SUBSTACK, other,
stack_level, module_type, actions, tok,
@@ -205,13 +211,35 @@ static int _pam_parse_conf_file(pam_handle_t *pamh, FILE *f
return PAM_ABORT;
}
}
- if (_pam_load_conf_file(pamh, tok, this_service, module_type,
- stack_level + substack
+ if (tok[0] == '/') {
+ if (_pam_load_conf_file(pamh, tok, this_service,
+ module_type, stack_level + substack
+#ifdef PAM_READ_BOTH_CONFS
+ , !other
+#endif /* PAM_READ_BOTH_CONFS */
+ ) == PAM_SUCCESS)
+ continue;
+ }
+ else if (!stat(PAM_CONFIG_D, &include_dir)
+ && S_ISDIR(include_dir.st_mode))
+ {
+ char *include_file;
+ if (asprintf (&include_file, PAM_CONFIG_DF, tok) < 0) {
+ pam_syslog(pamh, LOG_CRIT, "asprintf failed");
+ return PAM_ABORT;
+ }
+ if (_pam_load_conf_file(pamh, include_file, this_service,
+ module_type, stack_level + substack
#ifdef PAM_READ_BOTH_CONFS
, !other
#endif /* PAM_READ_BOTH_CONFS */
- ) == PAM_SUCCESS)
- continue;
+ ) == PAM_SUCCESS)
+ {
+ free(include_file);
+ continue;
+ }
+ free(include_file);
+ }
_pam_set_default_control(actions, _PAM_ACTION_BAD);
mod_path = NULL;
handler_type = PAM_HT_MUST_FAIL;
@@ -281,7 +309,7 @@ _pam_open_config_file(pam_handle_t *pamh
, char **path
, FILE **file)
{
- const char *pamd_dirs[] = { PAM_CONFIG_DF, PAM_CONFIG_DIST_DF
+ const char *const pamd_dirs[] = { PAM_CONFIG_DF, PAM_CONFIG_DIST_DF
#ifdef VENDORDIR
, PAM_CONFIG_DIST2_DF
#endif
@@ -317,10 +345,12 @@ _pam_open_config_file(pam_handle_t *pamh
}
for (i = 0; i < PAM_ARRAY_SIZE(pamd_dirs); i++) {
- if (asprintf (&p, pamd_dirs[i], service) < 0) {
+ DIAG_PUSH_IGNORE_FORMAT_NONLITERAL
+ if (asprintf (&p, pamd_dirs[i], service) < 0) {
pam_syslog(pamh, LOG_CRIT, "asprintf failed");
return PAM_BUF_ERR;
}
+ DIAG_POP_IGNORE_FORMAT_NONLITERAL
D(("opening %s", p));
f = fopen(p, "r");
@@ -707,7 +737,27 @@ _pam_load_module(pam_handle_t *pamh, const char *mod_path, int handler_type)
success = PAM_ABORT;
D(("_pam_load_module: _pam_dlopen(%s)", mod_path));
- mod->dl_handle = _pam_dlopen(mod_path);
+ if (mod_path[0] == '/') {
+ mod->dl_handle = _pam_dlopen(mod_path);
+ } else {
+ char *mod_full_path = NULL;
+ if (asprintf(&mod_full_path, "%s%s",
+ DEFAULT_MODULE_PATH, mod_path) >= 0) {
+ mod->dl_handle = _pam_dlopen(mod_full_path);
+ _pam_drop(mod_full_path);
+ } else {
+ pam_syslog(pamh, LOG_CRIT, "cannot malloc full mod path");
+ }
+ if (!mod->dl_handle) {
+ if (asprintf(&mod_full_path, "%s/%s",
+ _PAM_ISA, mod_path) >= 0) {
+ mod->dl_handle = _pam_dlopen(mod_full_path);
+ _pam_drop(mod_full_path);
+ } else {
+ pam_syslog(pamh, LOG_CRIT, "cannot malloc full mod path");
+ }
+ }
+ }
D(("_pam_load_module: _pam_dlopen'ed"));
D(("_pam_load_module: dlopen'ed"));
if (mod->dl_handle == NULL) {
@@ -784,7 +834,6 @@ int _pam_add_handler(pam_handle_t *pamh
struct handler **handler_p2;
struct handlers *the_handlers;
const char *sym, *sym2;
- char *mod_full_path;
servicefn func, func2;
int mod_type = PAM_MT_FAULTY_MOD;
@@ -796,16 +845,7 @@ int _pam_add_handler(pam_handle_t *pamh
if ((handler_type == PAM_HT_MODULE || handler_type == PAM_HT_SILENT_MODULE) &&
mod_path != NULL) {
- if (mod_path[0] == '/') {
- mod = _pam_load_module(pamh, mod_path, handler_type);
- } else if (asprintf(&mod_full_path, "%s%s",
- DEFAULT_MODULE_PATH, mod_path) >= 0) {
- mod = _pam_load_module(pamh, mod_full_path, handler_type);
- _pam_drop(mod_full_path);
- } else {
- pam_syslog(pamh, LOG_CRIT, "cannot malloc full mod path");
- return PAM_ABORT;
- }
+ mod = _pam_load_module(pamh, mod_path, handler_type);
if (mod == NULL) {
/* if we get here with NULL it means allocation error */
@@ -889,8 +929,8 @@ int _pam_add_handler(pam_handle_t *pamh
handler_p = &((*handler_p)->next);
}
- if ((*handler_p = malloc(sizeof(struct handler))) == NULL) {
- pam_syslog(pamh, LOG_CRIT, "cannot malloc struct handler #1");
+ if ((*handler_p = calloc(1, sizeof(struct handler))) == NULL) {
+ pam_syslog(pamh, LOG_CRIT, "cannot allocate struct handler #1");
return (PAM_ABORT);
}
@@ -904,8 +944,6 @@ int _pam_add_handler(pam_handle_t *pamh
(*handler_p)->argv = argv; /* not a copy */
if (((*handler_p)->mod_name = extract_modulename(mod_path)) == NULL)
return PAM_ABORT;
- (*handler_p)->grantor = 0;
- (*handler_p)->next = NULL;
/* some of the modules have a second calling function */
if (handler_p2) {
@@ -914,8 +952,8 @@ int _pam_add_handler(pam_handle_t *pamh
handler_p2 = &((*handler_p2)->next);
}
- if ((*handler_p2 = malloc(sizeof(struct handler))) == NULL) {
- pam_syslog(pamh, LOG_CRIT, "cannot malloc struct handler #2");
+ if ((*handler_p2 = calloc(1, sizeof(struct handler))) == NULL) {
+ pam_syslog(pamh, LOG_CRIT, "cannot allocate struct handler #2");
return (PAM_ABORT);
}
@@ -933,13 +971,9 @@ int _pam_add_handler(pam_handle_t *pamh
return (PAM_ABORT);
}
memcpy((*handler_p2)->argv, argv, argvlen);
- } else {
- (*handler_p2)->argv = NULL; /* no arguments */
}
if (((*handler_p2)->mod_name = extract_modulename(mod_path)) == NULL)
return PAM_ABORT;
- (*handler_p2)->grantor = 0;
- (*handler_p2)->next = NULL;
}
D(("_pam_add_handler: returning successfully"));
@@ -1037,7 +1071,7 @@ void _pam_free_handlers_aux(struct handler **hp)
_pam_drop(h->argv); /* This is all allocated in a single chunk */
_pam_drop(h->mod_name);
h = h->next;
- memset(last, 0, sizeof(*last));
+ pam_overwrite_object(last);
free(last);
}
diff --git a/libpam/pam_item.c b/libpam/pam_item.c
index d6af710b..42857da5 100644
--- a/libpam/pam_item.c
+++ b/libpam/pam_item.c
@@ -5,6 +5,7 @@
*/
#include "pam_private.h"
+#include "pam_inline.h"
#include <ctype.h>
#include <stdlib.h>
@@ -79,7 +80,7 @@ int pam_set_item (pam_handle_t *pamh, int item_type, const void *item)
*/
if (__PAM_FROM_MODULE(pamh)) {
if (pamh->authtok != item) {
- _pam_overwrite(pamh->authtok);
+ pam_overwrite_string(pamh->authtok);
TRY_SET(pamh->authtok, item);
}
} else {
@@ -95,7 +96,7 @@ int pam_set_item (pam_handle_t *pamh, int item_type, const void *item)
*/
if (__PAM_FROM_MODULE(pamh)) {
if (pamh->oldauthtok != item) {
- _pam_overwrite(pamh->oldauthtok);
+ pam_overwrite_string(pamh->oldauthtok);
TRY_SET(pamh->oldauthtok, item);
}
} else {
@@ -139,24 +140,23 @@ int pam_set_item (pam_handle_t *pamh, int item_type, const void *item)
if (&pamh->xauth == item)
break;
if (pamh->xauth.namelen) {
- _pam_overwrite(pamh->xauth.name);
+ pam_overwrite_string(pamh->xauth.name);
free(pamh->xauth.name);
}
if (pamh->xauth.datalen) {
- _pam_overwrite_n(pamh->xauth.data,
- (unsigned int) pamh->xauth.datalen);
+ pam_overwrite_n(pamh->xauth.data, (unsigned int) pamh->xauth.datalen);
free(pamh->xauth.data);
}
pamh->xauth = *((const struct pam_xauth_data *) item);
if ((pamh->xauth.name=_pam_strdup(pamh->xauth.name)) == NULL) {
- memset(&pamh->xauth, '\0', sizeof(pamh->xauth));
+ pam_overwrite_object(&pamh->xauth);
return PAM_BUF_ERR;
}
if ((pamh->xauth.data=_pam_memdup(pamh->xauth.data,
pamh->xauth.datalen)) == NULL) {
- _pam_overwrite(pamh->xauth.name);
+ pam_overwrite_string(pamh->xauth.name);
free(pamh->xauth.name);
- memset(&pamh->xauth, '\0', sizeof(pamh->xauth));
+ pam_overwrite_object(&pamh->xauth);
return PAM_BUF_ERR;
}
break;
@@ -330,7 +330,7 @@ int pam_get_user(pam_handle_t *pamh, const char **user, const char *prompt)
/* ok, we can resume where we left off last time */
pamh->former.want_user = PAM_FALSE;
- _pam_overwrite(pamh->former.prompt);
+ pam_overwrite_string(pamh->former.prompt);
_pam_drop(pamh->former.prompt);
}
@@ -388,7 +388,7 @@ int pam_get_user(pam_handle_t *pamh, const char **user, const char *prompt)
* note 'resp' is allocated by the application and is
* correctly free()'d here
*/
- _pam_drop_reply(resp, 1);
+ pam_drop_response(resp, 1);
}
D(("completed"));
diff --git a/libpam/pam_modutil_getlogin.c b/libpam/pam_modutil_getlogin.c
index 04a20fd8..2e7a0116 100644
--- a/libpam/pam_modutil_getlogin.c
+++ b/libpam/pam_modutil_getlogin.c
@@ -10,7 +10,6 @@
#include <stdlib.h>
#include <unistd.h>
-#include <utmp.h>
#define _PAMMODUTIL_GETLOGIN "_pammodutil_getlogin"
@@ -19,62 +18,29 @@ pam_modutil_getlogin(pam_handle_t *pamh)
{
int status;
const void *logname;
- const void *void_curr_tty;
- const char *curr_tty;
char *curr_user;
- struct utmp *ut, line;
status = pam_get_data(pamh, _PAMMODUTIL_GETLOGIN, &logname);
if (status == PAM_SUCCESS) {
return logname;
}
- status = pam_get_item(pamh, PAM_TTY, &void_curr_tty);
- if ((status != PAM_SUCCESS) || (void_curr_tty == NULL))
- curr_tty = ttyname(0);
- else
- curr_tty = (const char*)void_curr_tty;
-
- if (curr_tty == NULL) {
- return NULL;
- }
-
- if (curr_tty[0] == '/') { /* full path */
- const char *t;
- curr_tty++;
- if ((t = strchr(curr_tty, '/')) != NULL) {
- curr_tty = t + 1;
- }
- }
- logname = NULL;
-
- setutent();
- strncpy(line.ut_line, curr_tty, sizeof(line.ut_line));
-
- if ((ut = getutline(&line)) == NULL) {
- goto clean_up_and_go_home;
+ logname = getlogin();
+ if (logname == NULL) {
+ return NULL;
}
- curr_user = calloc(sizeof(line.ut_user)+1, 1);
+ curr_user = strdup(logname);
if (curr_user == NULL) {
- goto clean_up_and_go_home;
+ return NULL;
}
- strncpy(curr_user, ut->ut_user, sizeof(ut->ut_user));
- /* calloc already zeroed the memory */
-
status = pam_set_data(pamh, _PAMMODUTIL_GETLOGIN, curr_user,
pam_modutil_cleanup);
if (status != PAM_SUCCESS) {
- free(curr_user);
- goto clean_up_and_go_home;
+ free(curr_user);
+ return NULL;
}
- logname = curr_user;
-
-clean_up_and_go_home:
-
- endutent();
-
- return logname;
+ return curr_user;
}
diff --git a/libpam/pam_modutil_priv.c b/libpam/pam_modutil_priv.c
index a463e06a..7df6e6b1 100644
--- a/libpam/pam_modutil_priv.c
+++ b/libpam/pam_modutil_priv.c
@@ -14,7 +14,9 @@
#include <syslog.h>
#include <pwd.h>
#include <grp.h>
+#ifdef HAVE_SYS_FSUID_H
#include <sys/fsuid.h>
+#endif /* HAVE_SYS_FSUID_H */
/*
* Two setfsuid() calls in a row are necessary to check
@@ -22,17 +24,55 @@
*/
static int change_uid(uid_t uid, uid_t *save)
{
+#ifdef HAVE_SYS_FSUID_H
uid_t tmp = setfsuid(uid);
if (save)
*save = tmp;
return (uid_t) setfsuid(uid) == uid ? 0 : -1;
+#else
+ uid_t euid = geteuid();
+ uid_t ruid = getuid();
+ if (save)
+ *save = ruid;
+ if (ruid == uid && uid != 0)
+ if (setreuid(euid, uid))
+ return -1;
+ else {
+ setreuid(0, -1);
+ if (setreuid(-1, uid)) {
+ setreuid(-1, 0);
+ setreuid(0, -1);
+ if (setreuid(-1, uid))
+ return -1;
+ }
+ }
+#endif
}
static int change_gid(gid_t gid, gid_t *save)
{
+#ifdef HAVE_SYS_FSUID_H
gid_t tmp = setfsgid(gid);
if (save)
*save = tmp;
return (gid_t) setfsgid(gid) == gid ? 0 : -1;
+#else
+ gid_t egid = getegid();
+ gid_t rgid = getgid();
+ if (save)
+ *save = rgid;
+ if (rgid == gid)
+ if (setregid(egid, gid))
+ return -1;
+ else {
+ setregid(0, -1);
+ if (setregid(-1, gid)) {
+ setregid(-1, 0);
+ setregid(0, -1);
+ if (setregid(-1, gid))
+ return -1;
+ }
+ }
+#endif
}
static int cleanup(struct pam_modutil_privs *p)
diff --git a/libpam/pam_vprompt.c b/libpam/pam_vprompt.c
index c53079b5..8c9d63d5 100644
--- a/libpam/pam_vprompt.c
+++ b/libpam/pam_vprompt.c
@@ -40,10 +40,10 @@
#include <errno.h>
#include <security/pam_modules.h>
-#include <security/_pam_macros.h>
#include <security/pam_ext.h>
#include "pam_private.h"
+#include "pam_inline.h"
int
pam_vprompt (pam_handle_t *pamh, int style, char **response,
@@ -88,10 +88,10 @@ pam_vprompt (pam_handle_t *pamh, int style, char **response,
*response = pam_resp == NULL ? NULL : pam_resp->resp;
else if (pam_resp && pam_resp->resp)
{
- _pam_overwrite (pam_resp->resp);
+ pam_overwrite_string (pam_resp->resp);
_pam_drop (pam_resp->resp);
}
- _pam_overwrite (msgbuf);
+ pam_overwrite_string (msgbuf);
_pam_drop (pam_resp);
free (msgbuf);
if (retval != PAM_SUCCESS)