]> granicus.if.org Git - linux-pam/commitdiff
Relevant BUGIDs: 232194
authorAndrew G. Morgan <morgan@kernel.org>
Sun, 9 Dec 2001 22:51:12 +0000 (22:51 +0000)
committerAndrew G. Morgan <morgan@kernel.org>
Sun, 9 Dec 2001 22:51:12 +0000 (22:51 +0000)
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.

CHANGELOG
dynamic/Makefile [new file with mode: 0644]
dynamic/pam.c [new file with mode: 0644]
dynamic/test.c [new file with mode: 0644]

index f8ad1ea9d7824880ee80de6dde204859fd620ab6..f9bb5f8089cd1a956f068a0e62898aa612a30578 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -55,6 +55,11 @@ bug report - outstanding bugs are listed here:
 0.76: please submit patches for this section with actual code/doc
       patches!
 
+* added the dynamic/* directory to the distribution. If you go in
+  there after building the rest of the tree, you'll make a pam.so
+  object that can be used by something like a java runtime with
+  dlopen. Its not very well tested - caveat emptor. (Bug 232194 -
+  agmorgan)
 * somehow pam_unix has started forcing the user prompt to be "login: ".
   This is entirely inapropriate as it overrides PAM_USER_PROMPT. (Bug
   486361 - agmorgan).
diff --git a/dynamic/Makefile b/dynamic/Makefile
new file mode 100644 (file)
index 0000000..09102af
--- /dev/null
@@ -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 (file)
index 0000000..6dd376c
--- /dev/null
@@ -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 <stdio.h>
+#include <dlfcn.h>
+#include <security/pam_appl.h>
+#include <security/_pam_macros.h>
+
+#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 (file)
index 0000000..35496fe
--- /dev/null
@@ -0,0 +1,27 @@
+#include <stdio.h>
+#include <dlfcn.h>
+#include <unistd.h>
+
+#include <security/pam_appl.h>
+#include <security/pam_misc.h>
+
+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);
+}