1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
|
/*
* Tests for the MIT Kerberos module API.
*
* This just checks that we can call all of the functions and that they return
* appropriate error messages for a non-existent queue. We don't try to do
* any end-to-end testing of the functionality.
*
* Written by Russ Allbery <eagle@eyrie.org>
* Copyright 2012, 2013
* The Board of Trustees of the Leland Stanford Junior University
*
* See LICENSE for licensing terms.
*/
#include <config.h>
#include <portable/kadmin.h>
#include <portable/krb5.h>
#include <portable/system.h>
#include <dlfcn.h>
#include <errno.h>
#ifdef HAVE_KRB5_KADM5_HOOK_PLUGIN_H
# include <krb5/kadm5_hook_plugin.h>
#endif
#include <tests/tap/basic.h>
#include <tests/tap/kerberos.h>
#include <tests/tap/string.h>
#ifndef HAVE_KRB5_KADM5_HOOK_PLUGIN_H
int
main(void)
{
skip_all("not built with MIT Kerberos support");
}
#else
int
main(void)
{
char *path, *krb5_config, *plugin;
krb5_error_code code;
krb5_context ctx;
krb5_principal princ;
void *handle = NULL;
krb5_error_code (*init)(krb5_context, int, int, krb5_plugin_vtable);
kadm5_hook_vftable_1 vtable;
kadm5_hook_modinfo *data = NULL;
kadm5_principal_ent_rec entity;
const char *message;
char *wanted;
/* Set up the default krb5.conf file. */
path = test_file_path("data/krb5.conf");
if (path == NULL)
bail("cannot find data/krb5.conf in the test suite");
basprintf(&krb5_config, "KRB5_CONFIG=%s", path);
if (putenv(krb5_config) < 0)
sysbail("cannot set KRB5CCNAME");
/* Obtain a Kerberos context. */
code = krb5_init_context(&ctx);
if (code != 0)
bail_krb5(ctx, code, "cannot initialize Kerberos context");
/* Parse a test principal into a krb5_principal structure. */
code = krb5_parse_name(ctx, "test@EXAMPLE.COM", &princ);
if (code != 0)
bail_krb5(ctx, code, "cannot parse principal test@EXAMPLE.COM");
/*
* Load the module. We assume that the plugin is available as sync.so in
* a .libs directory since we don't want to embed Libtool's libtldl just
* to run a test. If that's not correct for the local platform, we skip
* this test.
*/
plugin = test_file_path("../plugin/.libs/sync.so");
if (plugin == NULL)
skip_all("unknown plugin naming scheme");
handle = dlopen(plugin, RTLD_NOW);
if (handle == NULL)
bail("cannot dlopen %s: %s", plugin, dlerror());
test_file_path_free(plugin);
/* Find the entry point function. */
init = dlsym(handle, "kadm5_hook_sync_initvt");
if (init == NULL)
bail("cannot get kadm5_hook_sync_initvt symbol: %s", dlerror());
/* No more skipping, so now we can report a plan. */
plan(12);
/* Test for correct results when requesting the wrong API version. */
code = init(ctx, 2, 0, (krb5_plugin_vtable) &vtable);
is_int(code, KRB5_PLUGIN_VER_NOTSUPP,
"Correct status for bad major API version");
/* Call that function properly to get the vtable. */
memset(&vtable, 0, sizeof(vtable));
code = init(ctx, 1, 0, (krb5_plugin_vtable) &vtable);
if (code != 0)
bail_krb5(ctx, code, "cannot obtain module vtable");
/* Check that all of the expected vtable entries are present. */
if (vtable.init == NULL || vtable.fini == NULL || vtable.chpass == NULL
|| vtable.create == NULL || vtable.modify == NULL)
bail("missing function in module vtable");
/* Verify the metadata. */
is_string("krb5-sync", vtable.name, "Hook name is correct");
/*
* Call the chpass function, which should fail with errors about queuing
* since the queue doesn't exist.
*/
basprintf(&wanted, "cannot open lock file queue/.lock: %s",
strerror(ENOENT));
is_int(0, vtable.init(ctx, &data), "init");
ok(data != NULL, "...and data is not NULL");
code = vtable.chpass(ctx, data, KADM5_HOOK_STAGE_PRECOMMIT, princ, false,
0, NULL, "test");
is_int(ENOENT, code, "chpass");
message = krb5_get_error_message(ctx, code);
is_string(wanted, message, "...with correct error message");
krb5_free_error_message(ctx, message);
/* Test chpass with a NULL password, which should do nothing. */
code = vtable.chpass(ctx, data, KADM5_HOOK_STAGE_PRECOMMIT, princ, false,
0, NULL, NULL);
is_int(0, code, "chpass with NULL password");
/*
* Set up an entry for creating an account. Everything in the entity is
* ignored except the principal and attributes, so don't bother to fake
* much up here.
*/
memset(&entity, 0, sizeof(entity));
entity.principal = princ;
entity.attributes = KRB5_KDB_DISALLOW_ALL_TIX;
/* Test creation with no queue directory. */
code = vtable.create(ctx, data, KADM5_HOOK_STAGE_PRECOMMIT, &entity, 0, 0,
NULL, "test");
is_int(ENOENT, code, "create");
message = krb5_get_error_message(ctx, code);
is_string(wanted, message, "...with correct error message");
krb5_free_error_message(ctx, message);
/* Test disabling with no queue directory. */
code = vtable.modify(ctx, data, KADM5_HOOK_STAGE_POSTCOMMIT, &entity,
KADM5_ATTRIBUTES);
is_int(ENOENT, code, "modify");
message = krb5_get_error_message(ctx, code);
is_string(wanted, message, "...with correct error message");
krb5_free_error_message(ctx, message);
/* Test creation with a NULL password, which should do nothing. */
code = vtable.create(ctx, data, KADM5_HOOK_STAGE_PRECOMMIT, &entity, 0, 0,
NULL, NULL);
is_int(0, code, "create with NULL password");
/* Close down the module. */
vtable.fini(ctx, data);
if (dlclose(handle) != 0)
bail("cannot close plugin: %s", dlerror());
free(wanted);
/* Clean up. */
krb5_free_principal(ctx, princ);
krb5_free_context(ctx);
test_file_path_free(path);
free(krb5_config);
return 0;
}
#endif /* HAVE_KRB5_KADM5_HOOK_PLUGIN_H */
|