krb5, kadm5: refactor plugin API
Refactor plugin framework to use a single list of loaded plugins; add a new plugin API where DSOs export a load function that can declare dependencies and export multiple plugins; refactor kadm5 hook API to use krb5 plugin framework. More information in krb5-plugin(7).
This commit is contained in:

committed by
Nico Williams

parent
e9b3b2326d
commit
803efebca5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018, AuriStor Inc.
|
||||
* Copyright (c) 2018, AuriStor, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -29,9 +29,26 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "kadm5_locl.h"
|
||||
#include <assert.h>
|
||||
|
||||
static char sample_data[1];
|
||||
#include <krb5.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "admin.h"
|
||||
#include "kadm5-hook.h"
|
||||
|
||||
/*
|
||||
* Sample kadm5 hook plugin that just logs when it is called. Install it
|
||||
* somewhere and configure the path in the [kadmin] section of krb5.conf.
|
||||
* e.g.
|
||||
*
|
||||
* [kadmin]
|
||||
* plugin_dir = /usr/local/heimdal/lib/plugin/kadm5
|
||||
*
|
||||
*/
|
||||
|
||||
static char sample_data_1, sample_data_2;
|
||||
|
||||
static krb5_error_code
|
||||
sample_log(krb5_context context,
|
||||
@@ -43,28 +60,52 @@ sample_log(krb5_context context,
|
||||
{
|
||||
char *p = NULL;
|
||||
krb5_error_code ret;
|
||||
int which = 0;
|
||||
|
||||
if (data != sample_data)
|
||||
return EINVAL;
|
||||
if (code != 0 && stage == KADM5_HOOK_STAGE_PRECOMMIT)
|
||||
return EINVAL;
|
||||
/* verify we get called with the right contex tpointer */
|
||||
if (data == &sample_data_1)
|
||||
which = 1;
|
||||
else if (data == &sample_data_2)
|
||||
which = 2;
|
||||
|
||||
assert(which != 0);
|
||||
|
||||
/* code should always be zero on pre-commit */
|
||||
assert(code == 0 || stage == KADM5_HOOK_STAGE_POSTCOMMIT);
|
||||
|
||||
if (princ)
|
||||
ret = krb5_unparse_name(context, princ, &p);
|
||||
|
||||
krb5_warn(context, code, "sample_hook: %s %s hook princ '%s'", tag,
|
||||
krb5_warn(context, code, "sample_hook_%d: %s %s hook princ '%s'", which, tag,
|
||||
stage == KADM5_HOOK_STAGE_PRECOMMIT ? "pre-commit" : "post-commit",
|
||||
p != NULL ? p : "<unknown>");
|
||||
|
||||
krb5_xfree(p);
|
||||
|
||||
/* returning zero and KRB5_PLUGIN_NO_HANDLE are the same for hook plugins */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static krb5_error_code KRB5_CALLCONV
|
||||
sample_init_1(krb5_context context, void **data)
|
||||
{
|
||||
*data = &sample_data_1;
|
||||
krb5_warn(context, 0, "sample_hook_1: initializing");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static krb5_error_code KRB5_CALLCONV
|
||||
sample_init_2(krb5_context context, void **data)
|
||||
{
|
||||
*data = &sample_data_2;
|
||||
krb5_warn(context, 0, "sample_hook_2: initializing");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void KRB5_CALLCONV
|
||||
sample_fini(krb5_context context, void *data)
|
||||
sample_fini(void *data)
|
||||
{
|
||||
krb5_warn(context, 0, "sample_hook: shutting down\n");
|
||||
krb5_warn(NULL, 0, "sample_fini: finalizing");
|
||||
}
|
||||
|
||||
static krb5_error_code KRB5_CALLCONV
|
||||
@@ -150,36 +191,82 @@ sample_set_keys_hook(krb5_context context,
|
||||
return sample_log(context, data, stage, "set_keys", code, princ);
|
||||
}
|
||||
|
||||
static struct kadm5_hook sample_hook = {
|
||||
"sample-hook",
|
||||
static krb5_error_code KRB5_CALLCONV
|
||||
sample_prune_hook(krb5_context context,
|
||||
void *data,
|
||||
enum kadm5_hook_stage stage,
|
||||
krb5_error_code code,
|
||||
krb5_const_principal princ,
|
||||
int kvno)
|
||||
{
|
||||
return sample_log(context, data, stage, "prune", code, princ);
|
||||
}
|
||||
|
||||
|
||||
static const kadm5_hook_ftable sample_hook_1 = {
|
||||
KADM5_HOOK_VERSION_V1,
|
||||
"Heimdal",
|
||||
krb5_init_context,
|
||||
sample_init_1,
|
||||
sample_fini,
|
||||
"sample_hook_1",
|
||||
"Heimdal",
|
||||
sample_chpass_hook,
|
||||
sample_create_hook,
|
||||
sample_modify_hook,
|
||||
sample_delete_hook,
|
||||
sample_randkey_hook,
|
||||
sample_rename_hook,
|
||||
sample_set_keys_hook
|
||||
sample_set_keys_hook,
|
||||
sample_prune_hook,
|
||||
};
|
||||
|
||||
static const kadm5_hook_ftable sample_hook_2 = {
|
||||
KADM5_HOOK_VERSION_V1,
|
||||
sample_init_2,
|
||||
sample_fini,
|
||||
"sample_hook_2",
|
||||
"Heimdal",
|
||||
sample_chpass_hook,
|
||||
sample_create_hook,
|
||||
sample_modify_hook,
|
||||
sample_delete_hook,
|
||||
sample_randkey_hook,
|
||||
sample_rename_hook,
|
||||
sample_set_keys_hook,
|
||||
sample_prune_hook,
|
||||
};
|
||||
|
||||
/* Arrays of pointers, because hooks may be different versions/sizes */
|
||||
static const kadm5_hook_ftable *const sample_hooks[] = {
|
||||
&sample_hook_1,
|
||||
&sample_hook_2,
|
||||
};
|
||||
|
||||
krb5_error_code
|
||||
kadm5_hook_init(krb5_context context, uint32_t vers_max,
|
||||
const kadm5_hook **hook, void **data);
|
||||
kadm5_hook_plugin_load(krb5_context context,
|
||||
krb5_get_instance_func_t *get_instance,
|
||||
size_t *num_hooks,
|
||||
const kadm5_hook_ftable *const **hooks);
|
||||
|
||||
krb5_error_code
|
||||
kadm5_hook_init(krb5_context context, uint32_t vers_max,
|
||||
const kadm5_hook **hook, void **data)
|
||||
static uintptr_t
|
||||
sample_hook_get_instance(const char *libname)
|
||||
{
|
||||
if (vers_max < KADM5_HOOK_VERSION_V1)
|
||||
return EINVAL;
|
||||
|
||||
krb5_warn(context, 0, "sample_hook: init version %u\n", vers_max);
|
||||
|
||||
*hook = &sample_hook;
|
||||
*data = sample_data;
|
||||
if (strcmp(libname, "kadm5") == 0)
|
||||
return kadm5_get_instance(libname);
|
||||
else if (strcmp(libname, "krb5") == 0)
|
||||
return krb5_get_instance(libname);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
krb5_error_code
|
||||
kadm5_hook_plugin_load(krb5_context context,
|
||||
krb5_get_instance_func_t *get_instance,
|
||||
size_t *num_hooks,
|
||||
const kadm5_hook_ftable *const **hooks)
|
||||
{
|
||||
*get_instance = sample_hook_get_instance;
|
||||
*num_hooks = sizeof(sample_hooks) / sizeof(sample_hooks[0]);
|
||||
*hooks = sample_hooks;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Reference in New Issue
Block a user