Skip to content

Commit

Permalink
krb5, kadm5: refactor plugin API
Browse files Browse the repository at this point in the history
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).
  • Loading branch information
lhoward authored and nicowilliams committed Jan 4, 2019
1 parent e9b3b23 commit 803efeb
Show file tree
Hide file tree
Showing 37 changed files with 1,300 additions and 646 deletions.
46 changes: 38 additions & 8 deletions kdc/windc.c
Expand Up @@ -39,6 +39,21 @@ static int have_plugin = 0;
* Pick the first WINDC module that we find.
*/

static const char *windc_plugin_deps[] = {
"kdc",
"krb5",
"hdb",
NULL
};

static struct krb5_plugin_data windc_plugin_data = {
"krb5",
"windc",
KRB5_WINDC_PLUGIN_MINOR,
windc_plugin_deps,
kdc_get_instance
};

static krb5_error_code KRB5_LIB_CALL
load(krb5_context context, const void *plug, void *plugctx, void *userctx)
{
Expand All @@ -49,8 +64,8 @@ load(krb5_context context, const void *plug, void *plugctx, void *userctx)
krb5_error_code
krb5_kdc_windc_init(krb5_context context)
{
(void)_krb5_plugin_run_f(context, "krb5", "windc",
KRB5_WINDC_PLUGIN_MINOR, 0, NULL, load);
(void)_krb5_plugin_run_f(context, &windc_plugin_data, 0, NULL, load);

return 0;
}

Expand Down Expand Up @@ -84,8 +99,8 @@ _kdc_pac_generate(krb5_context context,
uc.client = client;
uc.pac = pac;

(void)_krb5_plugin_run_f(context, "krb5", "windc",
KRB5_WINDC_PLUGIN_MINOR, 0, &uc, generate);
(void)_krb5_plugin_run_f(context, &windc_plugin_data,
0, &uc, generate);
return 0;
}

Expand Down Expand Up @@ -141,8 +156,8 @@ _kdc_pac_verify(krb5_context context,
uc.pac = pac;
uc.verified = verified;

(void)_krb5_plugin_run_f(context, "krb5", "windc",
KRB5_WINDC_PLUGIN_MINOR, 0, &uc, verify);
(void)_krb5_plugin_run_f(context, &windc_plugin_data,
0, &uc, verify);
return 0;
}

Expand Down Expand Up @@ -191,8 +206,8 @@ _kdc_check_access(krb5_context context,
uc.req = req;
uc.method_data = method_data;

ret = _krb5_plugin_run_f(context, "krb5", "windc",
KRB5_WINDC_PLUGIN_MINOR, 0, &uc, check);
ret = _krb5_plugin_run_f(context, &windc_plugin_data,
0, &uc, check);
}

if (ret == KRB5_PLUGIN_NO_HANDLE)
Expand All @@ -202,3 +217,18 @@ _kdc_check_access(krb5_context context,
req->msg_type == krb_as_req);
return ret;
}

uintptr_t
kdc_get_instance(const char *libname)
{
static const char *instance = "libkdc";

if (strcmp(libname, "kdc") == 0)
return (uintptr_t)instance;
else if (strcmp(libname, "hdb") == 0)
return hdb_get_instance(libname);
else if (strcmp(libname, "krb5") == 0)
return krb5_get_instance(libname);

return 0;
}
44 changes: 34 additions & 10 deletions lib/hdb/hdb.c
Expand Up @@ -390,6 +390,8 @@ make_sym(const char *prefix)
return sym;
}

static const char *hdb_plugin_deps[] = { "hdb", "krb5", NULL };

krb5_error_code
hdb_list_builtin(krb5_context context, char **list)
{
Expand All @@ -414,24 +416,28 @@ hdb_list_builtin(krb5_context context, char **list)
if (h->create == NULL) {
struct cb_s cb_ctx;
char *f;
char *sym;
struct krb5_plugin_data hdb_plugin_data;

hdb_plugin_data.module = "krb5";
hdb_plugin_data.min_version = HDB_INTERFACE_VERSION;
hdb_plugin_data.deps = hdb_plugin_deps;
hdb_plugin_data.get_instance = hdb_get_instance;

/* Try loading the plugin */
if (asprintf(&f, "%sfoo", h->prefix) == -1)
f = NULL;
if ((sym = make_sym(h->prefix)) == NULL) {
if ((hdb_plugin_data.name = make_sym(h->prefix)) == NULL) {
free(buf);
free(f);
return krb5_enomem(context);
}
cb_ctx.filename = f;
cb_ctx.residual = NULL;
cb_ctx.h = NULL;
(void)_krb5_plugin_run_f(context, "krb5", sym,
HDB_INTERFACE_VERSION, 0, &cb_ctx,
callback);
(void)_krb5_plugin_run_f(context, &hdb_plugin_data, 0,
&cb_ctx, callback);
free(f);
free(sym);
free(rk_UNCONST(hdb_plugin_data.name));
if (cb_ctx.h == NULL || cb_ctx.h->create == NULL)
continue;
}
Expand Down Expand Up @@ -483,17 +489,35 @@ hdb_create(krb5_context context, HDB **db, const char *filename)
cb_ctx.filename = filename;

if (cb_ctx.h == NULL || cb_ctx.h->create == NULL) {
char *sym;
struct krb5_plugin_data hdb_plugin_data;

hdb_plugin_data.module = "krb5";
hdb_plugin_data.min_version = HDB_INTERFACE_VERSION;
hdb_plugin_data.deps = hdb_plugin_deps;
hdb_plugin_data.get_instance = hdb_get_instance;

if ((sym = make_sym(filename)) == NULL)
if ((hdb_plugin_data.name = make_sym(filename)) == NULL)
return krb5_enomem(context);

(void)_krb5_plugin_run_f(context, "krb5", sym, HDB_INTERFACE_VERSION,
(void)_krb5_plugin_run_f(context, &hdb_plugin_data,
0, &cb_ctx, callback);

free(sym);
free(rk_UNCONST(hdb_plugin_data.name));
}
if (cb_ctx.h == NULL)
krb5_errx(context, 1, "No database support for %s", cb_ctx.filename);
return (*cb_ctx.h->create)(context, db, cb_ctx.residual);
}

uintptr_t
hdb_get_instance(const char *libname)
{
static const char *instance = "libhdb";

if (strcmp(libname, "hdb") == 0)
return (uintptr_t)instance;
else if (strcmp(libname, "krb5") == 0)
return krb5_get_instance(libname);

return 0;
}
2 changes: 1 addition & 1 deletion lib/hdb/keys.c
Expand Up @@ -31,6 +31,7 @@
* SUCH DAMAGE.
*/

#include "krb5_locl.h"
#include "hdb_locl.h"

struct hx509_certs_data;
Expand All @@ -45,7 +46,6 @@ struct _krb5_key_data;
struct _krb5_encryption_type;
struct _krb5_key_type;
#include <pkinit_asn1.h>
#include <krb5-private.h>
#include <base64.h>

/*
Expand Down
1 change: 1 addition & 0 deletions lib/hdb/libhdb-exports.def
Expand Up @@ -43,6 +43,7 @@ EXPORTS
hdb_generate_key_set_password
hdb_generate_key_set_password_with_ks_tuple
hdb_get_dbinfo
hdb_get_instance
hdb_init_db
hdb_interface_version DATA
hdb_key2principal
Expand Down
1 change: 1 addition & 0 deletions lib/hdb/version-script.map
Expand Up @@ -46,6 +46,7 @@ HEIMDAL_HDB_1.0 {
hdb_generate_key_set_password;
hdb_generate_key_set_password_with_ks_tuple;
hdb_get_dbinfo;
hdb_get_instance;
hdb_init_db;
hdb_key2principal;
hdb_kvno2keys;
Expand Down
7 changes: 7 additions & 0 deletions lib/kadm5/Makefile.am
Expand Up @@ -3,6 +3,7 @@
include $(top_srcdir)/Makefile.am.common

libkadm5srv_la_CPPFLAGS = -I$(srcdir)/../krb5
libkadm5clnt_la_CPPFLAGS = -I$(srcdir)/../krb5

lib_LTLIBRARIES = libkadm5srv.la libkadm5clnt.la
libkadm5srv_la_LDFLAGS = -version-info 8:1:0
Expand Down Expand Up @@ -34,6 +35,7 @@ libkadm5clnt_la_LIBADD = \
libexec_PROGRAMS = ipropd-master ipropd-slave

default_keys_SOURCES = default_keys.c
default_keys_CPPFLAGS = -I$(srcdir)/../krb5

kadm5includedir = $(includedir)/kadm5
buildkadm5include = $(buildinclude)/kadm5
Expand Down Expand Up @@ -130,8 +132,10 @@ dist_iprop_log_SOURCES = iprop-log.c
nodist_iprop_log_SOURCES = iprop-commands.c

ipropd_master_SOURCES = ipropd_master.c ipropd_common.c iprop.h kadm5_locl.h
ipropd_master_CPPFLAGS = -I$(srcdir)/../krb5

ipropd_slave_SOURCES = ipropd_slave.c ipropd_common.c iprop.h kadm5_locl.h
ipropd_slave_CPPFLAGS = -I$(srcdir)/../krb5

man_MANS = kadm5_pwcheck.3 iprop.8 iprop-log.8

Expand All @@ -146,6 +150,7 @@ LDADD = \
$(LIB_dlopen) \
$(LIB_pidfile)


iprop_log_LDADD = \
libkadm5srv.la \
$(top_builddir)/lib/hdb/libhdb.la \
Expand All @@ -159,6 +164,7 @@ iprop_log_LDADD = \
$(LIB_dlopen) \
$(LIB_pidfile)

iprop_log_CPPFLAGS = -I$(srcdir)/../krb5

iprop-commands.c iprop-commands.h: iprop-commands.in
$(SLC) $(srcdir)/iprop-commands.in
Expand All @@ -182,6 +188,7 @@ ALL_OBJECTS += $(ipropd_slave_OBJECTS)
ALL_OBJECTS += $(iprop_log_OBJECTS)
ALL_OBJECTS += $(test_pw_quality_OBJECTS)
ALL_OBJECTS += $(sample_passwd_check_la_OBJECTS)
ALL_OBJECTS += $(sample_hook_la_OBJECTS)
ALL_OBJECTS += $(default_keys_OBJECTS)

$(ALL_OBJECTS): $(srcdir)/kadm5-protos.h $(srcdir)/kadm5-private.h
Expand Down
4 changes: 2 additions & 2 deletions lib/kadm5/NTMakefile
Expand Up @@ -268,10 +268,10 @@ EXPORTS
<<
$(DLLPREP_NODIST)

$(OBJ)\sample_hook.dll: $(OBJ)\sample_hook.obj $(LIBHEIMDAL)
$(OBJ)\sample_hook.dll: $(OBJ)\sample_hook.obj $(LIBKADM5SRV) $(LIBHEIMDAL)
$(DLLGUILINK) /DEF:<<
EXPORTS
kadm5_hook_init
kadm5_hook_plugin_load
<<
$(DLLPREP_NODIST)

Expand Down
70 changes: 52 additions & 18 deletions lib/kadm5/chpass_s.c
Expand Up @@ -35,6 +35,42 @@

RCSID("$Id$");

struct chpass_principal_hook_ctx {
kadm5_server_context *context;
enum kadm5_hook_stage stage;
krb5_error_code code;
krb5_const_principal princ;
uint32_t flags;
size_t n_ks_tuple;
krb5_key_salt_tuple *ks_tuple;
const char *password;
};

static krb5_error_code
chpass_principal_hook_cb(krb5_context context,
const void *hook,
void *hookctx,
void *userctx)
{
krb5_error_code ret;
const struct kadm5_hook_ftable *ftable = hook;
struct chpass_principal_hook_ctx *ctx = userctx;

ret = ftable->chpass(context, hookctx,
ctx->stage, ctx->code, ctx->princ,
ctx->flags, ctx->n_ks_tuple, ctx->ks_tuple,
ctx->password);
if (ret != 0 && ret != KRB5_PLUGIN_NO_HANDLE)
_kadm5_s_set_hook_error_message(ctx->context, ret, "chpass",
hook, ctx->stage);

/* only pre-commit plugins can abort */
if (ret == 0 || ctx->stage == KADM5_HOOK_STAGE_POSTCOMMIT)
ret = KRB5_PLUGIN_NO_HANDLE;

return ret;
}

static kadm5_ret_t
chpass_principal_hook(kadm5_server_context *context,
enum kadm5_hook_stage stage,
Expand All @@ -45,24 +81,22 @@ chpass_principal_hook(kadm5_server_context *context,
krb5_key_salt_tuple *ks_tuple,
const char *password)
{
krb5_error_code ret = 0;
size_t i;

for (i = 0; i < context->num_hooks; i++) {
kadm5_hook_context *hook = context->hooks[i];

if (hook->hook->chpass != NULL) {
ret = hook->hook->chpass(context->context, hook->data,
stage, code, princ, flags,
n_ks_tuple, ks_tuple, password);
if (ret != 0) {
_kadm5_s_set_hook_error_message(context, ret, "chpass",
hook->hook, stage);
if (stage == KADM5_HOOK_STAGE_PRECOMMIT)
break;
}
}
}
krb5_error_code ret;
struct chpass_principal_hook_ctx ctx;

ctx.context = context;
ctx.stage = stage;
ctx.code = code;
ctx.princ = princ;
ctx.flags = flags;
ctx.n_ks_tuple = n_ks_tuple;
ctx.ks_tuple = ks_tuple;
ctx.password = password;

ret = _krb5_plugin_run_f(context->context, &kadm5_hook_plugin_data,
0, &ctx, chpass_principal_hook_cb);
if (ret == KRB5_PLUGIN_NO_HANDLE)
ret = 0;

return ret;
}
Expand Down

0 comments on commit 803efeb

Please sign in to comment.