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.
This commit is contained in:
Andrew G. Morgan 2001-12-09 22:15:11 +00:00
parent cb7734d408
commit da67a7d612
12 changed files with 350 additions and 14 deletions

View File

@ -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.

View File

@ -13,6 +13,10 @@
#include <security/_pam_aconf.h>
#include <pwd.h>
#include <sys/types.h>
#include <unistd.h>
/* ------ 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

View File

@ -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

View File

@ -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

View File

@ -96,6 +96,7 @@ int innetgr(const char *, const char *, const char *,const char *);
#include <security/pam_modules.h>
#include <security/_pam_macros.h>
#include <security/_pam_modutil.h>
/* 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 **)&current);
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",

View File

@ -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

15
modules/pammodutil/README Normal file
View File

@ -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
.

View File

@ -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 <morgan@kernel.org>
*/
#include <pwd.h>
#include <sys/types.h>
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 */

View File

@ -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);
}
}

View File

@ -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 <pwd.h>
#include <stdlib.h>
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 */
}

View File

@ -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 <pwd.h>
#include <stdlib.h>
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 */
}

View File

@ -0,0 +1,22 @@
#ifndef PAMMODUTIL_H
#define PAMMODUTIL_H
/*
* $Id$
*
* Copyright (c) 2001 Andrew Morgan <morgan@kernel.org>
*/
#include <security/_pam_aconf.h>
#include <security/_pam_macros.h>
#include <security/pam_modules.h>
#include <security/_pam_modutil.h>
#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 */