Skip to content

Commit

Permalink
kdc --builtin-hdb should list loadable backends
Browse files Browse the repository at this point in the history
This fixes the following problems from #210:

 - hdb_ldap doesn't load even when installed correctly
 - loadable hdb backends not listed by kdc --builtin-hdb

Not fixed:

 - hdb_ldap.so not installed in plugin dir
  • Loading branch information
nicowilliams committed Nov 15, 2016
1 parent c69a205 commit 09f0a25
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 25 deletions.
100 changes: 75 additions & 25 deletions lib/hdb/hdb.c
Expand Up @@ -90,6 +90,9 @@ static struct hdb_method methods[] = {
#if defined(OPENLDAP) && !defined(OPENLDAP_MODULE)
{ HDB_INTERFACE_VERSION, NULL, NULL, "ldap:", hdb_ldap_create},
{ HDB_INTERFACE_VERSION, NULL, NULL, "ldapi:", hdb_ldapi_create},
#elif defined(OPENLDAP)
{ HDB_INTERFACE_VERSION, NULL, NULL, "ldap:", NULL},
{ HDB_INTERFACE_VERSION, NULL, NULL, "ldapi:", NULL},
#endif
#ifdef HAVE_SQLITE3
{ HDB_INTERFACE_VERSION, NULL, NULL, "sqlite:", hdb_sqlite_create},
Expand Down Expand Up @@ -349,6 +352,44 @@ find_method (const char *filename, const char **rest)
return NULL;
}

struct cb_s {
const char *residual;
const char *filename;
const struct hdb_method *h;
};

static krb5_error_code KRB5_LIB_CALL
callback(krb5_context context, const void *plug, void *plugctx, void *userctx)
{
const struct hdb_method *h = (const struct hdb_method *)plug;
struct cb_s *cb_ctx = (struct cb_s *)userctx;

if (strncmp(cb_ctx->filename, h->prefix, strlen(h->prefix)) == 0) {
cb_ctx->residual = cb_ctx->filename + strlen(h->prefix);
cb_ctx->h = h;
return 0;
}
return KRB5_PLUGIN_NO_HANDLE;
}

static char *
make_sym(const char *prefix)
{
char *s, *sym;

errno = 0;
if (prefix == NULL || prefix[0] == '\0')
return NULL;
if ((s = strdup(prefix)) == NULL)
return NULL;
if (strchr(s, ':') != NULL)
*strchr(s, ':') = '\0';
if (asprintf(&sym, "hdb_%s_interface", s) == -1)
sym = NULL;
free(s);
return sym;
}

krb5_error_code
hdb_list_builtin(krb5_context context, char **list)
{
Expand All @@ -365,12 +406,34 @@ hdb_list_builtin(krb5_context context, char **list)
len += 1;
buf = malloc(len);
if (buf == NULL) {
krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
return ENOMEM;
return krb5_enomem(context);
}
buf[0] = '\0';

for (h = methods; h->prefix != NULL; ++h) {
if (h->create == NULL) {
struct cb_s cb_ctx;
char *f;
char *sym;

/* Try loading the plugin */
if (asprintf(&f, "%sfoo", h->prefix) == -1)
f = NULL;
if ((sym = make_sym(h->prefix)) == NULL) {
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);
free(f);
free(sym);
if (cb_ctx.h == NULL || cb_ctx.h->create == NULL)
continue;
}
if (h != methods)
strlcat(buf, ", ", len);
strlcat(buf, h->prefix, len);
Expand Down Expand Up @@ -408,26 +471,6 @@ _hdb_keytab2hdb_entry(krb5_context context,
* use O_CREAT to tell the backend to create the file.
*/

struct cb_s {
const char *residual;
const char *filename;
const struct hdb_method *h;
};

static krb5_error_code KRB5_LIB_CALL
callback(krb5_context context, const void *plug, void *plugctx, void *userctx)
{
const struct hdb_method *h = (const struct hdb_method *)plug;
struct cb_s *cb_ctx = (struct cb_s *)userctx;

if (strncmp(cb_ctx->filename, h->prefix, strlen(h->prefix)) == 0) {
cb_ctx->residual = cb_ctx->filename + strlen(h->prefix);
cb_ctx->h = h;
return 0;
}
return KRB5_PLUGIN_NO_HANDLE;
}

krb5_error_code
hdb_create(krb5_context context, HDB **db, const char *filename)
{
Expand All @@ -438,9 +481,16 @@ hdb_create(krb5_context context, HDB **db, const char *filename)
cb_ctx.h = find_method (filename, &cb_ctx.residual);
cb_ctx.filename = filename;

if (cb_ctx.h == NULL) {
(void)_krb5_plugin_run_f(context, "krb5", "hdb",
HDB_INTERFACE_VERSION, 0, &cb_ctx, callback);
if (cb_ctx.h == NULL || cb_ctx.h->create == NULL) {
char *sym;

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

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

free(sym);
}
if (cb_ctx.h == NULL)
krb5_errx(context, 1, "No database support for %s", cb_ctx.filename);
Expand Down
1 change: 1 addition & 0 deletions tests/ldap/krb5.conf.in
Expand Up @@ -3,6 +3,7 @@
[libdefaults]
default_realm = TEST.H5L.SE
no-addresses = TRUE
plugin_dir = @objdir@/../../lib/hdb @objdir@/../../lib/hdb/.libs

[realms]
TEST.H5L.SE = {
Expand Down

0 comments on commit 09f0a25

Please sign in to comment.