From 2acda542874f720091f6bfcb7aad09e35a8b2375 Mon Sep 17 00:00:00 2001 From: "Andrew G. Morgan" Date: Sun, 9 Dec 2001 22:51:12 +0000 Subject: Relevant BUGIDs: 232194 Purpose of commit: new feature Commit summary: --------------- If you are looking for an object that you can blindly dlopen() and use to bind to pam w/ modules, this commit is for you. Its not fully integrated into the build tree, but I'd like some feedback before wiring it in as a regular feature. --- dynamic/Makefile | 70 ++++++++++++++++++++++ dynamic/pam.c | 180 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ dynamic/test.c | 27 +++++++++ 3 files changed, 277 insertions(+) create mode 100644 dynamic/Makefile create mode 100644 dynamic/pam.c create mode 100644 dynamic/test.c (limited to 'dynamic') diff --git a/dynamic/Makefile b/dynamic/Makefile new file mode 100644 index 00000000..09102af0 --- /dev/null +++ b/dynamic/Makefile @@ -0,0 +1,70 @@ +# +# $Id$ +# +# + +include ../Make.Rules + +ifeq ($(WITH_LIBDEBUG),yes) + LIBNAME=pamd +else + LIBNAME=pam +endif +VERSION=.$(MAJOR_REL) +MODIFICATION=.$(MINOR_REL) + +# --------------------------------------------- + +dummy: ../Make.Rules all + +# --------------------------------------------- + +# dynamic library names + +PAMSHOBJ = pam.so +PAMSHOBJMAJ = $(PAMSHOBJ)$(VERSION) + +DLIBOBJECTS = pam.o + +# --------------------------------------------- +## rules + +all: dirs $(PAMSHOBJ) ../Make.Rules + +dirs: +ifeq ($(DYNAMIC_LIBPAM),yes) + $(MKDIR) dynamic +endif +ifeq ($(STATIC_LIBPAM),yes) + $(MKDIR) static +endif + +dynamic/%.o : %.c + $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ + +static/%.o : %.c + $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@ + +$(PAMSHOBJ): $(DLIBOBJECTS) +ifeq ($(USESONAME),yes) + $(LD_L) $(SOSWITCH) $(PAMSHOBJMAJ) -o $@ $+ $(LINKLIBS) +else + $(LD_L) -o $@ $(DLIBOBJECTS) $(LINKLIBS) +endif + +install: all + $(MKDIR) $(FAKEROOT)$(libdir) +ifeq ($(DYNAMIC_LIBPAM),yes) + $(INSTALL) -m $(SHLIBMODE) $(PAMSHOBJ) $(FAKEROOT)$(libdir)/$(PAMSHOBJ) + $(LDCONFIG) +endif + +remove: + rm -f $(FAKEROOT)$(libdir)/$(LIBPAM) + $(LDCONFIG) + +clean: + rm -f a.out core *~ static/*.o dynamic/*.o + rm -f *.a *.o *.so ./include/security/*~ + if [ -d dynamic ]; then rmdir dynamic ; fi + if [ -d static ]; then rmdir static ; fi diff --git a/dynamic/pam.c b/dynamic/pam.c new file mode 100644 index 00000000..6dd376c2 --- /dev/null +++ b/dynamic/pam.c @@ -0,0 +1,180 @@ +/* + * $Id$ + * + * If you want to dynamically load libpam using dlopen() or something, + * then dlopen( ' this shared object ' ); It takes care of exporting + * the right symbols to any modules loaded by libpam. + */ + +#include +#include +#include +#include + +#ifndef LIBPAMPATH +#define LIBPAMPATH "/lib/libpam.so" +#endif + +static void *libpam_h = NULL; + +#define CONFIRM_PAM_FUNCTION(x, y, z, err) \ + do { \ + union { const void *tpointer; y (*fn) z ; } fptr; \ + fptr.tpointer = dlsym(libpam_h, #x); real_##x = fptr.fn; \ + if (real_##x == NULL) { \ + D(("unable to resolve '" #x "': %s", dlerror())); \ + return err; \ + } \ + } while (0) + + +extern void _init(void); + +void _init() +{ + if (libpam_h == NULL) { + libpam_h = dlopen(LIBPAMPATH, RTLD_GLOBAL|RTLD_NOW); + } +} + +extern void _fini(void); + +void _fini() +{ + if (libpam_h != NULL) { + dlclose(libpam_h); + } +} + +int pam_start(const char *service_name, const char *user, + const struct pam_conv *pam_conversation, + pam_handle_t **pamh) +{ + static int (*real_pam_start)(const char *, const char *, + const struct pam_conv *, + pam_handle_t **); + CONFIRM_PAM_FUNCTION(pam_start, int, (const char *, const char *, + const struct pam_conv *, + pam_handle_t **), PAM_ABORT); + return real_pam_start(service_name, user, pam_conversation, pamh); +} + +int pam_end(pam_handle_t *pamh, int pam_status) +{ + static int (*real_pam_end)(pam_handle_t *, int); + CONFIRM_PAM_FUNCTION(pam_end, int, (pam_handle_t *, int), PAM_ABORT); + return real_pam_end(pamh, pam_status); +} + +int pam_set_item(pam_handle_t *pamh, int item_type, const void *item) +{ + static int (*real_pam_set_item)(pam_handle_t *, int, const void *); + CONFIRM_PAM_FUNCTION(pam_set_item, int, + (pam_handle_t *, int, const void *), PAM_ABORT); + return real_pam_set_item(pamh, item_type, item); +} + +int pam_get_item(const pam_handle_t *pamh, int item_type, const void **item) +{ + static int (*real_pam_get_item)(const pam_handle_t *, int, const void **); + CONFIRM_PAM_FUNCTION(pam_get_item, int, + (const pam_handle_t *, int, const void **), + PAM_ABORT); + return real_pam_get_item(pamh, item_type, item); +} + +int pam_fail_delay(pam_handle_t *pamh, unsigned int musec_delay) +{ + static int (*real_pam_fail_delay)(pam_handle_t *, unsigned int); + CONFIRM_PAM_FUNCTION(pam_fail_delay, int, (pam_handle_t *, unsigned int), + PAM_ABORT); + return real_pam_fail_delay(pamh, musec_delay); +} + +typedef const char * const_char_pointer; + +const_char_pointer pam_strerror(pam_handle_t *pamh, int errnum) +{ + static const_char_pointer (*real_pam_strerror)(pam_handle_t *, int); + CONFIRM_PAM_FUNCTION(pam_strerror, const_char_pointer, + (pam_handle_t *, int), NULL); + return real_pam_strerror(pamh, errnum); +} + +int pam_putenv(pam_handle_t *pamh, const char *name_value) +{ + static int (*real_pam_putenv)(pam_handle_t *, const char *); + CONFIRM_PAM_FUNCTION(pam_putenv, int, (pam_handle_t *, const char *), + PAM_ABORT); + return real_pam_putenv(pamh, name_value); +} + +const_char_pointer pam_getenv(pam_handle_t *pamh, const char *name) +{ + static const_char_pointer (*real_pam_getenv)(pam_handle_t *, const char *); + CONFIRM_PAM_FUNCTION(pam_getenv, const_char_pointer, + (pam_handle_t *, const char *), NULL); + return real_pam_getenv(pamh, name); +} + +typedef char ** char_ppointer; +char_ppointer pam_getenvlist(pam_handle_t *pamh) +{ + static char_ppointer (*real_pam_getenvlist)(pam_handle_t *); + CONFIRM_PAM_FUNCTION(pam_getenvlist, char_ppointer, (pam_handle_t *), + NULL); + return real_pam_getenvlist(pamh); +} + +/* Authentication management */ + +int pam_authenticate(pam_handle_t *pamh, int flags) +{ + static int (*real_pam_authenticate)(pam_handle_t *, int); + CONFIRM_PAM_FUNCTION(pam_authenticate, int, (pam_handle_t *, int), + PAM_ABORT); + return real_pam_authenticate(pamh, flags); +} + +int pam_setcred(pam_handle_t *pamh, int flags) +{ + static int (*real_pam_setcred)(pam_handle_t *, int); + CONFIRM_PAM_FUNCTION(pam_setcred, int, (pam_handle_t *, int), PAM_ABORT); + return real_pam_setcred(pamh, flags); +} + +/* Account Management API's */ + +int pam_acct_mgmt(pam_handle_t *pamh, int flags) +{ + static int (*real_pam_acct_mgmt)(pam_handle_t *, int); + CONFIRM_PAM_FUNCTION(pam_acct_mgmt, int, (pam_handle_t *, int), PAM_ABORT); + return real_pam_acct_mgmt(pamh, flags); +} + +/* Session Management API's */ + +int pam_open_session(pam_handle_t *pamh, int flags) +{ + static int (*real_pam_open_session)(pam_handle_t *, int); + CONFIRM_PAM_FUNCTION(pam_open_session, int, (pam_handle_t *, int), + PAM_ABORT); + return real_pam_open_session(pamh, flags); +} + +int pam_close_session(pam_handle_t *pamh, int flags) +{ + static int (*real_pam_close_session)(pam_handle_t *, int); + CONFIRM_PAM_FUNCTION(pam_close_session, int, (pam_handle_t *, int), + PAM_ABORT); + return real_pam_close_session(pamh, flags); +} + +/* Password Management API's */ + +int pam_chauthtok(pam_handle_t *pamh, int flags) +{ + static int (*real_pam_chauthtok)(pam_handle_t *, int); + CONFIRM_PAM_FUNCTION(pam_chauthtok, int, (pam_handle_t *, int), PAM_ABORT); + return real_pam_chauthtok(pamh, flags); +} diff --git a/dynamic/test.c b/dynamic/test.c new file mode 100644 index 00000000..35496fe4 --- /dev/null +++ b/dynamic/test.c @@ -0,0 +1,27 @@ +#include +#include +#include + +#include +#include + +int main(int argc, char **argv) +{ + void *handle; + + handle = dlopen("./pam.so", RTLD_NOW); + if (handle == NULL) { + fprintf(stderr, "failed to load pam.so: %s\n", dlerror()); + exit(1); + } + + /* handle->XXX points to each of the PAM functions */ + + + if (dlclose(handle)) { + fprintf(stderr, "failed to unload pam.so: %s\n", dlerror()); + exit(1); + } + + exit(0); +} -- cgit v1.2.3