Blame src/tests/shlib/t_loader.c

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