From da67a7d6126846939fd43b1ddb5aa8c06ee09301 Mon Sep 17 00:00:00 2001 From: "Andrew G. Morgan" Date: Sun, 9 Dec 2001 22:15:11 +0000 Subject: Relevant BUGIDs: 490938 Purpose of commit: new feature Commit summary: --------------- Added libpammodutil and link it with every module as its built. The issue here is that there is a lot of code that the various modules use in common, and this staic library can be used to help make this code more maintainable. I do not intend to make this library dynamic. Especially right now, as I want to be free to chop and change the API and don't want to deal with revision control and third party modules. This checkin makes the pam_rhost_auth module make some use of this new library. I don't intend to add support for any other module prior to releasing 0.76. --- CHANGELOG | 3 + examples/xsh.c | 24 +++++++ modules/Makefile | 6 +- modules/Simple.Rules | 11 +-- modules/pam_rhosts/pam_rhosts_auth.c | 21 +++--- modules/pammodutil/Makefile | 53 ++++++++++++++ modules/pammodutil/README | 15 ++++ modules/pammodutil/include/security/_pam_modutil.h | 33 +++++++++ modules/pammodutil/modutil_cleanup.c | 16 +++++ modules/pammodutil/modutil_getpwnam.c | 80 ++++++++++++++++++++++ modules/pammodutil/modutil_getpwuid.c | 80 ++++++++++++++++++++++ modules/pammodutil/pammodutil.h | 22 ++++++ 12 files changed, 350 insertions(+), 14 deletions(-) create mode 100644 modules/pammodutil/Makefile create mode 100644 modules/pammodutil/README create mode 100644 modules/pammodutil/include/security/_pam_modutil.h create mode 100644 modules/pammodutil/modutil_cleanup.c create mode 100644 modules/pammodutil/modutil_getpwnam.c create mode 100644 modules/pammodutil/modutil_getpwuid.c create mode 100644 modules/pammodutil/pammodutil.h diff --git a/CHANGELOG b/CHANGELOG index 7ceb3318..5b9af1e6 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -55,6 +55,9 @@ bug report - outstanding bugs are listed here: 0.76: please submit patches for this section with actual code/doc patches! +* added a static module helper library object includes a few changes + to examples/xsh.c for testing purposes, and also modified the + pam_rhosts_auth module to use this new library. (Bug 490938 - agmorgan) * documentation: random typo fixes from Nalin and more stuff from me (Bug 476949, Tasks 43507, 17426 - agmorgan) * pam_unix: fix 'likeauth' to kill off the memory leak once and for all. diff --git a/examples/xsh.c b/examples/xsh.c index 7babce42..dbb2416c 100644 --- a/examples/xsh.c +++ b/examples/xsh.c @@ -13,6 +13,10 @@ #include +#include +#include +#include + /* ------ some local (static) functions ------- */ static void bail_out(pam_handle_t *pamh,int really, int code, const char *fn) @@ -56,6 +60,26 @@ int main(int argc, char **argv) retcode = pam_start(service, username, &conv, &pamh); bail_out(pamh,1,retcode,"pam_start"); + /* fill in the RUSER and RHOST fields */ + { + char buffer[100]; + struct passwd *pw; + + pw = getpwuid(getuid()); + if (pw != NULL) { + retcode = pam_set_item(pamh, PAM_RUSER, pw->pw_name); + bail_out(pamh,1,retcode,"pam_set_item(PAM_RUSER)"); + } + retcode = gethostname(buffer, sizeof(buffer)-1); + if (retcode) { + perror("failed to look up hostname"); + retcode = pam_end(pamh, PAM_ABORT); + bail_out(pamh,1,retcode,"pam_end"); + } + retcode = pam_set_item(pamh, PAM_RHOST, buffer); + bail_out(pamh,1,retcode,"pam_set_item(PAM_RHOST)"); + } + /* to avoid using goto we abuse a loop here */ for (;;) { /* authenticate the user --- `0' here, could have been PAM_SILENT diff --git a/modules/Makefile b/modules/Makefile index 51964e5b..93891029 100644 --- a/modules/Makefile +++ b/modules/Makefile @@ -11,6 +11,8 @@ include ../Make.Rules MODDIRS=$(shell /bin/ls -d pam_*) all: + @echo building the static modutil library + make -C pammodutil all @echo modules sources available are: @ls -d $(MODDIRS) 2>/dev/null ; echo :-------- @echo @@ -52,5 +54,5 @@ clean: lclean if [ -d $$i ]; then { \ $(MAKE) -C $$i clean ; \ } fi ; \ - done - + done + make -C pammodutil clean diff --git a/modules/Simple.Rules b/modules/Simple.Rules index 04fafc12..2d79b00c 100644 --- a/modules/Simple.Rules +++ b/modules/Simple.Rules @@ -19,6 +19,9 @@ LIBOBJ = $(addsuffix .o,$(LIBFILES)) LIBOBJD = $(addprefix dynamic/,$(LIBOBJ)) LIBOBJS = $(addprefix static/,$(LIBOBJ)) +LINK_PAMMODUTILS = -L../pammodutil -lpammodutil +INCLUDE_PAMMODUTILS = -I../pammodutil/include + ifdef DYNAMIC LIBSHARED = $(TITLE).so endif @@ -32,10 +35,10 @@ endif all: dirs $(LIBSHARED) $(LIBSTATIC) register dynamic/%.o : %.c - $(CC) $(CFLAGS) $(DYNAMIC) $(TARGET_ARCH) -c $< -o $@ + $(CC) $(CFLAGS) $(INCLUDE_PAMMODUTILS) $(DYNAMIC) $(TARGET_ARCH) -c $< -o $@ static/%.o : %.c - $(CC) $(CFLAGS) $(STATIC) $(TARGET_ARCH) -c $< -o $@ + $(CC) $(CFLAGS) $(INCLUDE_PAMMODUTILS) $(STATIC) $(TARGET_ARCH) -c $< -o $@ dirs: ifdef DYNAMIC @@ -56,7 +59,7 @@ endif ifdef DYNAMIC $(LIBSHARED): $(LIBOBJD) - $(LD_D) -o $@ $(LIBOBJD) $(MODULE_SIMPLE_EXTRALIBS) $(NEED_LINK_LIB_C) + $(LD_D) -o $@ $(LIBOBJD) $(MODULE_SIMPLE_EXTRALIBS) $(NEED_LINK_LIB_C) $(LINK_PAMMODUTILS) endif @@ -66,7 +69,7 @@ endif ifdef STATIC $(LIBSTATIC): $(LIBOBJS) - $(LD) -r -o $@ $(LIBOBJS) $(MODULE_SIMPLE_EXTRALIBS) + $(LD) -r -o $@ $(LIBOBJS) $(MODULE_SIMPLE_EXTRALIBS) $(LINK_PAMMODUTILS) endif install: all diff --git a/modules/pam_rhosts/pam_rhosts_auth.c b/modules/pam_rhosts/pam_rhosts_auth.c index 7ee77f1d..7266b4e8 100644 --- a/modules/pam_rhosts/pam_rhosts_auth.c +++ b/modules/pam_rhosts/pam_rhosts_auth.c @@ -96,6 +96,7 @@ int innetgr(const char *, const char *, const char *,const char *); #include #include +#include /* to the best of my knowledge, all modern UNIX boxes have 32 bit integers */ #define U32 unsigned int @@ -232,15 +233,16 @@ static int pam_get_rhost(pam_handle_t *pamh, const char **rhost * requesting the contents of the PAM_RUSER item. */ -static int pam_get_ruser(pam_handle_t *pamh, const char **ruser - , const char *prompt) +static int pam_get_ruser(pam_handle_t *pamh, const char **ruser, + const char *prompt) { int retval; const char *current; retval = pam_get_item (pamh, PAM_RUSER, (const void **)¤t); - if (retval != PAM_SUCCESS) + if (retval != PAM_SUCCESS) { return retval; + } if (current == NULL) { return PAM_AUTH_ERR; @@ -491,7 +493,7 @@ pam_iruserok(pam_handle_t *pamh, * Identify user's local .rhosts file */ - pwd = getpwnam(luser); + pwd = _pammodutil_getpwnam(pamh, luser); if (pwd == NULL) { /* * luser is assumed to be valid because of an earlier check for uid = 0 @@ -660,10 +662,11 @@ static int _pam_auth_rhosts (pam_handle_t *pamh, const char **argv) { int retval; - const char *luser; - const char *ruser,*rhost; + const char *luser = NULL; + const char *ruser = NULL, *rhost = NULL; struct _options opts; int as_root = 0; + /* * Look at the options and set the flags accordingly. */ @@ -675,6 +678,7 @@ static int _pam_auth_rhosts (pam_handle_t *pamh, for (;;) { /* abuse loop to avoid goto */ /* get the remotehost */ + D(("getting rhost")); retval = pam_get_rhost(pamh, &rhost, NULL); (void) pam_set_item(pamh, PAM_RHOST, rhost); if (retval != PAM_SUCCESS) { @@ -685,6 +689,7 @@ static int _pam_auth_rhosts (pam_handle_t *pamh, } /* get the remote user */ + D(("getting ruser")); retval = pam_get_ruser(pamh, &ruser, NULL); (void) pam_set_item(pamh, PAM_RUSER, ruser); if (retval != PAM_SUCCESS) { @@ -694,8 +699,8 @@ static int _pam_auth_rhosts (pam_handle_t *pamh, } /* get the local user */ + D(("getting user")); retval = pam_get_user(pamh, &luser, NULL); - if (retval != PAM_SUCCESS) { if (opts.opt_debug) _pam_log(LOG_DEBUG, "could not determine name of local user"); @@ -710,7 +715,7 @@ static int _pam_auth_rhosts (pam_handle_t *pamh, if (! opts.opt_no_uid_check) { struct passwd *luser_pwd; - luser_pwd = getpwnam(luser); + luser_pwd = _pammodutil_getpwnam(pamh, luser); if (luser_pwd == NULL) { if (opts.opt_debug) _pam_log(LOG_DEBUG, "user '%s' unknown to this system", diff --git a/modules/pammodutil/Makefile b/modules/pammodutil/Makefile new file mode 100644 index 00000000..a97388ef --- /dev/null +++ b/modules/pammodutil/Makefile @@ -0,0 +1,53 @@ +# +# $Id$ +# +# + +include ../../Make.Rules + +LIBNAME=libpammodutil + +# --------------------------------------------- + +dummy: all + +# --------------------------------------------- + +CFLAGS += $(PIC) $(STATIC) $(MOREFLAGS) \ + -DLIBPAM_VERSION_MAJOR=$(MAJOR_REL) \ + -DLIBPAM_VERSION_MINOR=$(MINOR_REL) + +# all the object files we care about +LIBOBJECTS = modutil_cleanup.o modutil_getpwnam.o modutil_getpwuid.o + +# static library name +LIBSTATIC = $(LIBNAME).a + +SLIBOBJECTS = $(addprefix static/,$(LIBOBJECTS) $(STATICOBJ)) + +# --------------------------------------------- +## rules + +all: dirs $(LIBSTATIC) ../../Make.Rules + +dirs: + $(MKDIR) static + +static/%.o : %.c + $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ + +$(LIBSTATIC): $(SLIBOBJECTS) + ar cr $@ $(SLIBOBJECTS) + $(RANLIB) $@ + +install: + @echo "at this time, we're not installing $(LIBSTATIC)" + +remove: + @echo "at this time, there is nothing to remove" + +clean: + rm -f a.out core *~ static/*.o + rm -f *.a *.o + if [ -d dynamic ]; then rmdir dynamic ; fi + if [ -d static ]; then rmdir static ; fi diff --git a/modules/pammodutil/README b/modules/pammodutil/README new file mode 100644 index 00000000..241f83a7 --- /dev/null +++ b/modules/pammodutil/README @@ -0,0 +1,15 @@ +$Id$ + +This is a libarary of routines for use by modules. The routines seem +to have a common use for modules, but are not part of libpam and never +will be. They are also a convenient layer of abstraction for providing +thread-safe functions that may require use of pam_handle_t 'data' +items to make their thread-safeness tied to the use of a single +pam_handle_t per thread. + +Functions provided so far are all listed in + + include/security/_pam_modutil.h + +. + diff --git a/modules/pammodutil/include/security/_pam_modutil.h b/modules/pammodutil/include/security/_pam_modutil.h new file mode 100644 index 00000000..af8a7ae1 --- /dev/null +++ b/modules/pammodutil/include/security/_pam_modutil.h @@ -0,0 +1,33 @@ +#ifndef _PAM_MODUTIL_H +#define _PAM_MODUTIL_H + +/* + * $Id$ + * + * This file is a list of handy libc wrappers that attempt to provide some + * thread-safe and other convenient functionality to modules in a form that + * is common, but not dynamically linked with yet another dynamic pam + * library extension. + * + * A number of these functions reserve space in a pam_[sg]et_data item. + * In all cases, the name of the item is prefixed with "_pammodutil_*". + * + * On systems that simply can't support thread safe programming, these + * functions don't support it either - sorry. + * + * Copyright (c) 2001 Andrew Morgan + */ + +#include +#include + +extern struct passwd *_pammodutil_getpwnam(pam_handle_t *pamh, + const char *user); + +extern struct passwd *_pammodutil_getpwuid(pam_handle_t *pamh, + uid_t uid); + +extern void _pammodutil_cleanup(pam_handle_t *pamh, void *data, + int error_status); + +#endif /* _PAM_MODUTIL_H */ diff --git a/modules/pammodutil/modutil_cleanup.c b/modules/pammodutil/modutil_cleanup.c new file mode 100644 index 00000000..e95d6100 --- /dev/null +++ b/modules/pammodutil/modutil_cleanup.c @@ -0,0 +1,16 @@ +/* + * $Id$ + * + * This function provides a common pam_set_data() friendly version of free(). + */ + +#include "pammodutil.h" + +void _pammodutil_cleanup(pam_handle_t *pamh, void *data, int error_status) +{ + if (data) { + /* junk it */ + (void) free(data); + } +} + diff --git a/modules/pammodutil/modutil_getpwnam.c b/modules/pammodutil/modutil_getpwnam.c new file mode 100644 index 00000000..287dc065 --- /dev/null +++ b/modules/pammodutil/modutil_getpwnam.c @@ -0,0 +1,80 @@ +/* + * $Id$ + * + * This function provides a thread safer version of getpwnam() for use + * with PAM modules that care about this sort of thing. + * + * XXX - or at least it should provide a thread-safe alternative. + */ + +#include "pammodutil.h" + +#include +#include + +struct passwd *_pammodutil_getpwnam(pam_handle_t *pamh, const char *user) +{ +#ifdef HAVE_GETPWNAM_R + + void *buffer=NULL; + size_t length = PWD_INITIAL_LENGTH; + + do { + int status; + void *new_buffer; + struct passwd *result = NULL; + + new_buffer = realloc(buffer, sizeof(struct passwd) + length); + if (new_buffer == NULL) { + + D(("out of memory")); + + /* no memory for the user - so delete the memory */ + if (buffer) { + free(buffer); + } + return NULL; + } + buffer = new_buffer; + + /* make the re-entrant call to get the pwd structure */ + status = getpwnam_r(user, buffer, + sizeof(struct passwd) + (char *) buffer, + length, &result); + if (!status && result) { + status = pam_set_data(pamh, "_pammodutil_getpwnam", result, + _pammodutil_cleanup); + if (status == PAM_SUCCESS) { + D(("success")); + return result; + } + + D(("was unable to register the data item [%s]", + pam_strerror(pamh, status))); + + free(buffer); + return NULL; + + } + + length <<= 1; + + } while (length < PWD_ABSURD_PWD_LENGTH); + + D(("pwd structure took %u bytes or so of memory", + length+sizeof(struct passwd))); + + free(buffer); + return NULL; + +#else /* ie. ifndef HAVE_GETPWNAM_R */ + + /* + * Sorry, there does not appear to be a reentrant version of + * getpwnam(). So, we use the standard libc function. + */ + + return getpwnam(user); + +#endif /* def HAVE_GETPWNAM_R */ +} diff --git a/modules/pammodutil/modutil_getpwuid.c b/modules/pammodutil/modutil_getpwuid.c new file mode 100644 index 00000000..e200dd1e --- /dev/null +++ b/modules/pammodutil/modutil_getpwuid.c @@ -0,0 +1,80 @@ +/* + * $Id$ + * + * This function provides a thread safer version of getpwuid() for use + * with PAM modules that care about this sort of thing. + * + * XXX - or at least it should provide a thread-safe alternative. + */ + +#include "pammodutil.h" + +#include +#include + +struct passwd *_pammodutil_getpwuid(pam_handle_t *pamh, uid_t uid) +{ +#ifdef HAVE_GETPWNAM_R + + void *buffer=NULL; + size_t length = PWD_INITIAL_LENGTH; + + do { + int status; + void *new_buffer; + struct passwd *result = NULL; + + new_buffer = realloc(buffer, sizeof(struct passwd) + length); + if (new_buffer == NULL) { + + D(("out of memory")); + + /* no memory for the user - so delete the memory */ + if (buffer) { + free(buffer); + } + return NULL; + } + buffer = new_buffer; + + /* make the re-entrant call to get the pwd structure */ + status = getpwuid_r(uid, buffer, + sizeof(struct passwd) + (char *) buffer, + length, &result); + if (!status && result) { + status = pam_set_data(pamh, "_pammodutil_getpwuid", result, + _pammodutil_cleanup); + if (status == PAM_SUCCESS) { + D(("success")); + return result; + } + + D(("was unable to register the data item [%s]", + pam_strerror(pamh, status))); + + free(buffer); + return NULL; + + } + + length <<= 1; + + } while (length < PWD_ABSURD_PWD_LENGTH); + + D(("pwd structure took %u bytes or so of memory", + length+sizeof(struct passwd))); + + free(buffer); + return NULL; + +#else /* ie. ifndef HAVE_GETPWNAM_R */ + + /* + * Sorry, there does not appear to be a reentrant version of + * getpwnam(). So, we use the standard libc function. + */ + + return getpwuid(uid); + +#endif /* def HAVE_GETPWNAM_R */ +} diff --git a/modules/pammodutil/pammodutil.h b/modules/pammodutil/pammodutil.h new file mode 100644 index 00000000..efcc98e1 --- /dev/null +++ b/modules/pammodutil/pammodutil.h @@ -0,0 +1,22 @@ +#ifndef PAMMODUTIL_H +#define PAMMODUTIL_H + +/* + * $Id$ + * + * Copyright (c) 2001 Andrew Morgan + */ + +#include +#include +#include +#include + +#define PWD_INITIAL_LENGTH 0x100 +#define PWD_ABSURD_PWD_LENGTH 0x1000 + +/* This is a simple cleanup, it just free()s the 'data' memory */ +extern void _pammodutil_cleanup(pam_handle_t *pamh, void *data, + int error_status); + +#endif /* PAMMODUTIL_H */ -- cgit v1.2.3