summaryrefslogtreecommitdiff
path: root/src/tests/shlib
diff options
context:
space:
mode:
Diffstat (limited to 'src/tests/shlib')
-rw-r--r--src/tests/shlib/Makefile.in23
-rw-r--r--src/tests/shlib/deps8
-rw-r--r--src/tests/shlib/t_loader.c386
3 files changed, 417 insertions, 0 deletions
diff --git a/src/tests/shlib/Makefile.in b/src/tests/shlib/Makefile.in
new file mode 100644
index 000000000000..ce67be45b561
--- /dev/null
+++ b/src/tests/shlib/Makefile.in
@@ -0,0 +1,23 @@
+mydir=tests$(S)shlib
+BUILDTOP=$(REL)..$(S)..
+
+#VALGRIND=valgrind
+#VALGRINDFLAGS=--tool=memcheck --leak-check=yes --show-reachable=yes
+
+SRCS=$(srcdir)/t_loader.c
+
+all:
+
+run-t_loader: t_loader
+ $(RUN_TEST) ./t_loader
+
+t_loader: t_loader.o
+ $(CC_LINK) -o t_loader t_loader.o $(DL_LIB)
+
+check-unix:
+
+install:
+
+clean:
+ $(RM) t_loader.o t_loader
+
diff --git a/src/tests/shlib/deps b/src/tests/shlib/deps
new file mode 100644
index 000000000000..be6b824f01df
--- /dev/null
+++ b/src/tests/shlib/deps
@@ -0,0 +1,8 @@
+#
+# Generated makefile dependencies follow.
+#
+$(OUTPRE)t_loader.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
+ $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(COM_ERR_DEPS) $(top_srcdir)/include/k5-platform.h \
+ $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/krb5.h \
+ t_loader.c
diff --git a/src/tests/shlib/t_loader.c b/src/tests/shlib/t_loader.c
new file mode 100644
index 000000000000..869be800a079
--- /dev/null
+++ b/src/tests/shlib/t_loader.c
@@ -0,0 +1,386 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* tests/shlib/t_loader.c */
+/*
+ * Copyright (C) 2005 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#include "k5-platform.h"
+#include "krb5.h"
+#include "gssapi/gssapi.h"
+#define HAVE_DLOPEN 1
+
+static int verbose = 1;
+
+#ifdef HAVE_DLFCN_H
+# include <dlfcn.h>
+#endif
+/* Solaris man page recommends link.h too */
+
+/* lazy = 1 means resolve symbols later, 0 means now; any
+ other flags we should be testing? On Windows, maybe?
+
+ Return value is the library handle. On error, print a message and
+ exit. */
+#define do_open(LIB,REV,FLAGS) do_open_1(LIB,REV,FLAGS,__LINE__)
+static void *do_open_1(const char *libname, const char *rev, int lazy, int line);
+
+/* Look up a function symbol in the library and return a pointer.
+
+ The return value may need casting to the correct type. On error,
+ print a message and exit. */
+static void *get_sym_1(void *libhandle, const char *sym, int line);
+#define get_sym(LIB, NAME) get_sym_1(LIB, NAME, __LINE__)
+#define GET_FSYM(TYPE, LIB, NAME) ((TYPE) get_sym(LIB, NAME))
+#define get_gfun(LIB, NAME) ((OM_uint32 KRB5_CALLCONV(*)()) get_sym(LIB, NAME))
+
+/* Close dynamically-opened library.
+
+ If the OS reports an error in doing so, print a message and
+ exit. */
+#define do_close(X) do_close_1(X, __LINE__)
+static void do_close_1(void *libhandle, int line);
+
+#ifdef HAVE_DLOPEN
+
+#ifdef _AIX
+# define SHLIB_SUFFIX ".a"
+#else
+# define SHLIB_SUFFIX ".so"
+#endif
+
+#define HORIZ 25
+
+static void *do_open_1(const char *libname, const char *rev,
+ int lazy, int line)
+{
+ void *p;
+ char *namebuf;
+ int r;
+
+ if (verbose)
+ printf("from line %d: do_open(%s)...%*s", line, libname,
+ HORIZ-strlen(libname), "");
+#ifdef _AIX
+ r = asprintf(&namebuf, "lib%s%s", libname, SHLIB_SUFFIX);
+#else
+ r = asprintf(&namebuf, "lib%s%s(shr.o.%s)", libname, SHLIB_SUFFIX, rev);
+#endif
+ if (r < 0) {
+ perror("asprintf");
+ exit(1);
+ }
+
+#ifndef RTLD_MEMBER
+#define RTLD_MEMBER 0
+#endif
+ p = dlopen(namebuf, (lazy ? RTLD_LAZY : RTLD_NOW) | RTLD_MEMBER);
+ if (p == 0) {
+ fprintf(stderr, "dlopen of %s failed: %s\n", namebuf, dlerror());
+ exit(1);
+ }
+ free(namebuf);
+ if (verbose)
+ printf("done: %p\n", p);
+ return p;
+}
+
+#define SYM_PREFIX ""
+static void *get_sym_1(void *libhandle, const char *symname, int line)
+{
+ void *s;
+
+ /* Bah. Fix this later, if we care. */
+ assert(strlen(SYM_PREFIX) == 0);
+
+ if (verbose)
+ printf("from line %d: get_sym(%s)...%*s", line, symname,
+ HORIZ-strlen(symname), "");
+
+ s = dlsym(libhandle, symname);
+ if (s == 0) {
+ fprintf(stderr, "symbol %s not found\n", symname);
+ exit(1);
+ }
+ if (verbose)
+ printf("done: %p\n", s);
+ return s;
+}
+
+static void do_close_1(void *libhandle, int line)
+{
+ if (verbose) {
+ char pbuf[3*sizeof(libhandle)+4];
+ snprintf(pbuf, sizeof(pbuf), "%p", libhandle);
+ printf("from line %d: do_close(%s)...%*s", line, pbuf,
+ HORIZ-1-strlen(pbuf), "");
+ }
+ if (dlclose(libhandle) != 0) {
+ fprintf(stderr, "dlclose failed: %s\n", dlerror());
+ exit(1);
+ }
+ if (verbose)
+ printf("done\n");
+}
+
+#elif defined _WIN32
+
+static void *do_open(const char *libname, int lazy)
+{
+ /* To be written? */
+ abort();
+}
+
+static void *get_sym(void *libhandle, const char *symname)
+{
+ abort();
+}
+
+static void do_close(void *libhandle)
+{
+ abort();
+}
+
+#else
+
+static void *do_open(const char *libname, int lazy)
+{
+ printf("don't know how to do dynamic loading here, punting\n");
+ exit(0);
+}
+
+static void *get_sym(void *libhandle, const char *symname)
+{
+ abort();
+}
+
+static void do_close(void *libhandle)
+{
+ abort();
+}
+
+#endif
+
+int main()
+{
+ void *celib, *k5lib, *gsslib, *celib2;
+
+ (void) setvbuf(stdout, 0, _IONBF, 0);
+
+#if 0
+ /* Simplest test: Load, then unload out of order. */
+ celib = do_open("com_err", "3.0", 0);
+ k5lib = do_open("krb5", "3.2", 0);
+ gsslib = do_open("gssapi_krb5", "2.2", 0);
+ celib2 = do_open("com_err", "3.0", 0);
+ do_close(celib);
+ do_close(k5lib);
+ do_close(celib2);
+ do_close(gsslib);
+#endif
+
+ celib = do_open("com_err", "3.0", 0);
+ k5lib = do_open("krb5", "3.2", 0);
+ gsslib = do_open("gssapi_krb5", "2.2", 0);
+ celib2 = do_open("com_err", "3.0", 0);
+ do_close(celib2);
+ {
+ typedef krb5_error_code KRB5_CALLCONV (*ict)(krb5_context *);
+ typedef void KRB5_CALLCONV (*fct)(krb5_context);
+
+ ict init_context = (ict) get_sym(k5lib, "krb5_init_context");
+ fct free_context = (fct) get_sym(k5lib, "krb5_free_context");
+ krb5_context ctx;
+ krb5_error_code err;
+
+#define CALLING(S) (verbose ? printf("at line %d: calling %s...%*s", __LINE__, #S, (int)(HORIZ+1-strlen(#S)), "") : 0)
+#define DONE() (verbose ? printf("done\n") : 0)
+
+ CALLING(krb5_init_context);
+ err = init_context(&ctx);
+ DONE();
+ if (err) {
+ fprintf(stderr, "error 0x%lx initializing context\n",
+ (unsigned long) err);
+ exit(1);
+ }
+ CALLING(krb5_free_context);
+ free_context(ctx);
+ DONE();
+ }
+ celib2 = do_open("com_err", "3.0", 0);
+ do_close(celib);
+ do_close(k5lib);
+ do_close(celib2);
+ do_close(gsslib);
+
+ /* Test gssapi_krb5 without having loaded anything else. */
+ gsslib = do_open("gssapi_krb5", "2.2", 1);
+ {
+ OM_uint32 KRB5_CALLCONV (*init_sec_context)(OM_uint32 *, gss_cred_id_t,
+ gss_ctx_id_t *, gss_name_t,
+ gss_OID,
+ OM_uint32, OM_uint32,
+ gss_channel_bindings_t,
+ gss_buffer_t, gss_OID *,
+ gss_buffer_t,
+ OM_uint32 *, OM_uint32 *)
+ = get_gfun(gsslib, "gss_init_sec_context");
+ OM_uint32 KRB5_CALLCONV (*import_name)(OM_uint32 *, gss_buffer_t,
+ gss_OID, gss_name_t *)
+ = get_gfun(gsslib, "gss_import_name");
+ OM_uint32 KRB5_CALLCONV (*release_buffer)(OM_uint32 *, gss_buffer_t)
+ = get_gfun(gsslib, "gss_release_buffer");
+ OM_uint32 KRB5_CALLCONV (*release_name)(OM_uint32 *, gss_name_t *)
+ = get_gfun(gsslib, "gss_release_name");
+ OM_uint32 KRB5_CALLCONV (*delete_sec_context)(OM_uint32 *,
+ gss_ctx_id_t *,
+ gss_buffer_t)
+ = get_gfun(gsslib, "gss_delete_sec_context");
+
+ OM_uint32 gmaj, gmin;
+ OM_uint32 retflags;
+ gss_ctx_id_t gctx = GSS_C_NO_CONTEXT;
+ gss_buffer_desc token;
+ gss_name_t target;
+ static gss_buffer_desc target_name_buf = {
+ 9, "x@mit.edu"
+ };
+ static gss_OID_desc service_name = {
+ 10, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x04"
+ };
+
+ CALLING(gss_import_name);
+ gmaj = import_name(&gmin, &target_name_buf, &service_name, &target);
+ DONE();
+ if (gmaj != GSS_S_COMPLETE) {
+ fprintf(stderr,
+ "import_name reports error major 0x%lx minor 0x%lx(%ld)\n",
+ (unsigned long) gmaj, (unsigned long) gmin,
+ (signed long) gmin);
+ exit(1);
+ }
+ /* This will probably get different errors, depending on
+ whether we have tickets at the time. Doesn't matter much,
+ we're ignoring the error and testing whether we're doing
+ cleanup properly. (Though the internal cleanup needed in
+ the two cases might be different.) */
+ CALLING(gss_init_sec_context);
+ gmaj = init_sec_context(&gmin, GSS_C_NO_CREDENTIAL, &gctx, target,
+ GSS_C_NULL_OID, 0, 0, NULL, GSS_C_NO_BUFFER,
+ NULL, &token, &retflags, NULL);
+ DONE();
+ /* Ignore success/failure indication. */
+ if (token.length) {
+ CALLING(gss_release_buffer);
+ release_buffer(&gmin, &token);
+ DONE();
+ }
+ CALLING(gss_release_name);
+ release_name(&gmin, &target);
+ DONE();
+ if (gctx != GSS_C_NO_CONTEXT) {
+ CALLING(gss_delete_sec_context);
+ delete_sec_context(&gmin, gctx, GSS_C_NO_BUFFER);
+ DONE();
+ }
+ }
+ do_close(gsslib);
+
+ /* Test gssapi_krb5 with com_err already loaded, then unload
+ com_err first. */
+ celib = do_open("com_err", "3.0", 1);
+ gsslib = do_open("gssapi_krb5", "2.2", 1);
+ {
+ OM_uint32 KRB5_CALLCONV (*init_sec_context)(OM_uint32 *, gss_cred_id_t,
+ gss_ctx_id_t *, gss_name_t,
+ gss_OID,
+ OM_uint32, OM_uint32,
+ gss_channel_bindings_t,
+ gss_buffer_t, gss_OID *,
+ gss_buffer_t,
+ OM_uint32 *, OM_uint32 *)
+ = get_gfun(gsslib, "gss_init_sec_context");
+ OM_uint32 KRB5_CALLCONV (*import_name)(OM_uint32 *, gss_buffer_t,
+ gss_OID, gss_name_t *)
+ = get_gfun(gsslib, "gss_import_name");
+ OM_uint32 KRB5_CALLCONV (*release_buffer)(OM_uint32 *, gss_buffer_t)
+ = get_gfun(gsslib, "gss_release_buffer");
+ OM_uint32 KRB5_CALLCONV (*release_name)(OM_uint32 *, gss_name_t *)
+ = get_gfun(gsslib, "gss_release_name");
+ OM_uint32 KRB5_CALLCONV (*delete_sec_context)(OM_uint32 *,
+ gss_ctx_id_t *,
+ gss_buffer_t)
+ = get_gfun(gsslib, "gss_delete_sec_context");
+
+ OM_uint32 gmaj, gmin;
+ OM_uint32 retflags;
+ gss_ctx_id_t gctx = GSS_C_NO_CONTEXT;
+ gss_buffer_desc token;
+ gss_name_t target;
+ static gss_buffer_desc target_name_buf = {
+ 9, "x@mit.edu"
+ };
+ static gss_OID_desc service_name = {
+ 10, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x04"
+ };
+
+ CALLING(gss_import_name);
+ gmaj = import_name(&gmin, &target_name_buf, &service_name, &target);
+ DONE();
+ if (gmaj != GSS_S_COMPLETE) {
+ fprintf(stderr,
+ "import_name reports error major 0x%lx minor 0x%lx(%ld)\n",
+ (unsigned long) gmaj, (unsigned long) gmin,
+ (signed long) gmin);
+ exit(1);
+ }
+ /* This will probably get different errors, depending on
+ whether we have tickets at the time. Doesn't matter much,
+ we're ignoring the error and testing whether we're doing
+ cleanup properly. (Though the internal cleanup needed in
+ the two cases might be different.) */
+ CALLING(gss_init_sec_context);
+ gmaj = init_sec_context(&gmin, GSS_C_NO_CREDENTIAL, &gctx, target,
+ GSS_C_NULL_OID, 0, 0, NULL, GSS_C_NO_BUFFER,
+ NULL, &token, &retflags, NULL);
+ DONE();
+ /* Ignore success/failure indication. */
+ if (token.length) {
+ CALLING(gss_release_buffer);
+ release_buffer(&gmin, &token);
+ DONE();
+ }
+ CALLING(gss_release_name);
+ release_name(&gmin, &target);
+ DONE();
+ if (gctx != GSS_C_NO_CONTEXT) {
+ CALLING(gss_delete_sec_context);
+ delete_sec_context(&gmin, gctx, GSS_C_NO_BUFFER);
+ DONE();
+ }
+ }
+ do_close(celib);
+ do_close(gsslib);
+
+ return 0;
+}