kadm5: Add online kadm5_iter_principals()

kadm5_get_principals() is not online.  If you have... many principals,
it will be slow.  At least it's no longer quadratic, but it, it's still
slow.  Time to add a version that uses a callback:

    kadm5_ret_t
    kadm5_iter_principals(void *server_handle,
                          const char *expression,
                          int (*cb)(void *, const char *),
                          void *cbdata)

The callback gets called with the given callback data and one principal
name (unparsed).

Note that the callback MUST NOT re-enter the kadm5 library with the
*same* kadm handle.  For example, the kadmin protocol doesn't really
multiplex requests well, though it could pipeline them, but it can't
pipeline when LIST is running, not with the protocol implemented here,
so a separate connection is needed, and that requires a separate kadm
handle.  We add kadm5_dup_context() to deal with this.
This commit is contained in:
Nicolas Williams
2022-03-17 22:00:49 -05:00
parent e6a543fa1a
commit ed4b1be5bb
12 changed files with 396 additions and 20 deletions

View File

@@ -78,6 +78,8 @@ set_funcs(kadm5_client_context *c)
SET(c, lock);
SET(c, unlock);
SETNOTIMP(c, setkey_principal_3);
SET(c, iter_principals);
SET(c, dup_context);
}
kadm5_ret_t
@@ -192,6 +194,53 @@ _kadm5_c_init_context(kadm5_client_context **ctx,
return 0;
}
kadm5_ret_t
kadm5_c_dup_context(void *vin, void **out)
{
krb5_error_code ret;
kadm5_client_context *in = vin;
krb5_context context = in->context;
kadm5_client_context *ctx;
*out = NULL;
ctx = malloc(sizeof(*ctx));
if (ctx == NULL)
return krb5_enomem(in->context);
memset(ctx, 0, sizeof(*ctx));
set_funcs(ctx);
ctx->readonly_kadmind_port = in->readonly_kadmind_port;
ctx->kadmind_port = in->kadmind_port;
ret = krb5_copy_context(context, &(ctx->context));
if (ret == 0)
ret = krb5_add_et_list(ctx->context, initialize_kadm5_error_table_r);
if (ret == 0 && (ctx->realm = strdup(in->realm)) == NULL)
ret = krb5_enomem(context);
if (ret == 0 &&
(ctx->admin_server = strdup(in->admin_server)) == NULL)
ret = krb5_enomem(context);
if (in->readonly_admin_server &&
(ctx->readonly_admin_server = strdup(in->readonly_admin_server)) == NULL)
ret = krb5_enomem(context);
if (in->keytab && (ctx->keytab = strdup(in->keytab)) == NULL)
ret = krb5_enomem(context);
if (in->ccache) {
char *fullname = NULL;
ret = krb5_cc_get_full_name(context, in->ccache, &fullname);
if (ret == 0)
ret = krb5_cc_resolve(context, fullname, &ctx->ccache);
free(fullname);
}
if (ret == 0)
*out = ctx;
else
kadm5_c_destroy(ctx);
return ret;
}
static krb5_error_code
get_kadm_ticket(krb5_context context,
krb5_ccache id,