summaryrefslogtreecommitdiff
path: root/third_party/heimdal/lib/kadm5
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/heimdal/lib/kadm5')
-rw-r--r--third_party/heimdal/lib/kadm5/ad.c38
-rw-r--r--third_party/heimdal/lib/kadm5/common_glue.c15
-rw-r--r--third_party/heimdal/lib/kadm5/context_s.c10
-rw-r--r--third_party/heimdal/lib/kadm5/create_s.c8
-rw-r--r--third_party/heimdal/lib/kadm5/destroy_s.c12
-rw-r--r--third_party/heimdal/lib/kadm5/get_c.c2
-rw-r--r--third_party/heimdal/lib/kadm5/get_princs_c.c186
-rw-r--r--third_party/heimdal/lib/kadm5/get_princs_s.c124
-rw-r--r--third_party/heimdal/lib/kadm5/init_c.c52
-rw-r--r--third_party/heimdal/lib/kadm5/init_s.c15
-rw-r--r--third_party/heimdal/lib/kadm5/iprop.846
-rw-r--r--third_party/heimdal/lib/kadm5/ipropd_slave.c46
-rw-r--r--third_party/heimdal/lib/kadm5/libkadm5srv-exports.def2
-rw-r--r--third_party/heimdal/lib/kadm5/private.h2
-rw-r--r--third_party/heimdal/lib/kadm5/version-script-client.map5
-rw-r--r--third_party/heimdal/lib/kadm5/version-script.map2
16 files changed, 518 insertions, 47 deletions
diff --git a/third_party/heimdal/lib/kadm5/ad.c b/third_party/heimdal/lib/kadm5/ad.c
index 58ccf32eacd..b9b9c9023b9 100644
--- a/third_party/heimdal/lib/kadm5/ad.c
+++ b/third_party/heimdal/lib/kadm5/ad.c
@@ -1066,6 +1066,33 @@ kadm5_ad_get_principals(void *server_handle,
}
static kadm5_ret_t
+kadm5_ad_iter_principals(void *server_handle,
+ const char *expression,
+ int (*cb)(void *, const char *),
+ void *cbdata)
+{
+ kadm5_ad_context *context = server_handle;
+
+#ifdef OPENLDAP
+ kadm5_ret_t ret;
+
+ ret = ad_get_cred(context, NULL);
+ if (ret)
+ return ret;
+
+ ret = _kadm5_ad_connect(server_handle);
+ if (ret)
+ return ret;
+
+ krb5_set_error_message(context->context, KADM5_RPC_ERROR, "Function not implemented");
+ return KADM5_RPC_ERROR;
+#else
+ krb5_set_error_message(context->context, KADM5_RPC_ERROR, "Function not implemented");
+ return KADM5_RPC_ERROR;
+#endif
+}
+
+static kadm5_ret_t
kadm5_ad_get_privs(void *server_handle, uint32_t*privs)
{
kadm5_ad_context *context = server_handle;
@@ -1169,7 +1196,7 @@ kadm5_ad_modify_principal(void *server_handle,
if (entry->attributes & KRB5_KDB_REQUIRES_HW_AUTH)
i |= UF_SMARTCARD_REQUIRED;
else
- i &= UF_SMARTCARD_REQUIRED;
+ i &= ~UF_SMARTCARD_REQUIRED;
if (entry->attributes & KRB5_KDB_DISALLOW_SVR)
i &= ~UF_WORKSTATION_TRUST_ACCOUNT;
else
@@ -1388,6 +1415,9 @@ set_funcs(kadm5_ad_context *c)
SET(c, lock);
SET(c, unlock);
SETNOTIMP(c, setkey_principal_3);
+ SETNOTIMP(c, prune_principal);
+ SET(c, iter_principals);
+ SET(c, dup_context);
}
kadm5_ret_t
@@ -1456,6 +1486,12 @@ kadm5_ad_init_with_password_ctx(krb5_context context,
}
kadm5_ret_t
+kadm5_ad_dup_context(void *in, void **out)
+{
+ return ENOTSUP;
+}
+
+kadm5_ret_t
kadm5_ad_init_with_password(const char *client_name,
const char *password,
const char *service_name,
diff --git a/third_party/heimdal/lib/kadm5/common_glue.c b/third_party/heimdal/lib/kadm5/common_glue.c
index 9993b0a349e..210bf93b91c 100644
--- a/third_party/heimdal/lib/kadm5/common_glue.c
+++ b/third_party/heimdal/lib/kadm5/common_glue.c
@@ -39,6 +39,12 @@ RCSID("$Id$");
#define __CALLABLE(F) (((kadm5_common_context*)server_handle)->funcs.F != 0)
kadm5_ret_t
+kadm5_dup_context(void *server_handle, void **dup_server_handle)
+{
+ return __CALL(dup_context, (server_handle, dup_server_handle));
+}
+
+kadm5_ret_t
kadm5_chpass_principal(void *server_handle,
krb5_principal princ,
const char *password)
@@ -223,6 +229,15 @@ kadm5_get_principals(void *server_handle,
}
kadm5_ret_t
+kadm5_iter_principals(void *server_handle,
+ const char *expression,
+ int (*cb)(void *, const char *),
+ void *cbdata)
+{
+ return __CALL(iter_principals, (server_handle, expression, cb, cbdata));
+}
+
+kadm5_ret_t
kadm5_get_privs(void *server_handle,
uint32_t *privs)
{
diff --git a/third_party/heimdal/lib/kadm5/context_s.c b/third_party/heimdal/lib/kadm5/context_s.c
index 0c154ecfef0..5c9b3e31c81 100644
--- a/third_party/heimdal/lib/kadm5/context_s.c
+++ b/third_party/heimdal/lib/kadm5/context_s.c
@@ -112,6 +112,8 @@ set_funcs(kadm5_server_context *c)
SET(c, lock);
SET(c, unlock);
SET(c, setkey_principal_3);
+ SET(c, iter_principals);
+ SET(c, dup_context);
}
#ifndef NO_UNIX_SOCKETS
@@ -250,6 +252,8 @@ _kadm5_s_init_context(kadm5_server_context **ctx,
krb5_add_et_list (context, initialize_kadm5_error_table_r);
#define is_set(M) (params && params->mask & KADM5_CONFIG_ ## M)
+ if (params)
+ (*ctx)->config.mask = params->mask;
if (is_set(REALM)) {
(*ctx)->config.realm = strdup(params->realm);
if ((*ctx)->config.realm == NULL)
@@ -275,9 +279,9 @@ _kadm5_s_init_context(kadm5_server_context **ctx,
return krb5_enomem(context);
}
- find_db_spec(*ctx);
-
- ret = _kadm5_s_init_hooks(*ctx);
+ ret = find_db_spec(*ctx);
+ if (ret == 0)
+ ret = _kadm5_s_init_hooks(*ctx);
if (ret != 0) {
kadm5_s_destroy(*ctx);
*ctx = NULL;
diff --git a/third_party/heimdal/lib/kadm5/create_s.c b/third_party/heimdal/lib/kadm5/create_s.c
index 1c2ab15f30d..e603497ace2 100644
--- a/third_party/heimdal/lib/kadm5/create_s.c
+++ b/third_party/heimdal/lib/kadm5/create_s.c
@@ -50,6 +50,14 @@ get_default(kadm5_server_context *context, krb5_principal princ,
ret = kadm5_s_get_principal(context, def_principal, def,
KADM5_PRINCIPAL_NORMAL_MASK);
krb5_free_principal (context->context, def_principal);
+
+ if (ret) {
+ /* Copy defaults from kadmin/init.c */
+ memset(def, 0, sizeof(*def));
+ def->max_life = 24 * 60 * 60;
+ def->max_renewable_life = 7 * def->max_life;
+ def->attributes = KRB5_KDB_DISALLOW_ALL_TIX;
+ }
return ret;
}
diff --git a/third_party/heimdal/lib/kadm5/destroy_s.c b/third_party/heimdal/lib/kadm5/destroy_s.c
index fc86e5960e6..0558b45c577 100644
--- a/third_party/heimdal/lib/kadm5/destroy_s.c
+++ b/third_party/heimdal/lib/kadm5/destroy_s.c
@@ -42,10 +42,12 @@ RCSID("$Id$");
static void
destroy_config (kadm5_config_params *c)
{
- free (c->realm);
- free (c->dbname);
- free (c->acl_file);
- free (c->stash_file);
+ if (!c)
+ return;
+ free(c->realm);
+ free(c->dbname);
+ free(c->acl_file);
+ free(c->stash_file);
}
/*
@@ -55,6 +57,8 @@ destroy_config (kadm5_config_params *c)
static void
destroy_kadm5_log_context (kadm5_log_context *c)
{
+ if (!c)
+ return;
free(c->log_file);
if (c->socket_fd != rk_INVALID_SOCKET)
rk_closesocket(c->socket_fd);
diff --git a/third_party/heimdal/lib/kadm5/get_c.c b/third_party/heimdal/lib/kadm5/get_c.c
index 5b2bcca762a..1c1fd9dce80 100644
--- a/third_party/heimdal/lib/kadm5/get_c.c
+++ b/third_party/heimdal/lib/kadm5/get_c.c
@@ -89,7 +89,7 @@ kadm5_c_get_principal(void *server_handle,
out_keep_error:
if (ret == 0)
- kadm5_ret_principal_ent(sp, ent);
+ ret = kadm5_ret_principal_ent(sp, ent);
krb5_storage_free(sp);
krb5_data_free(&reply);
return ret;
diff --git a/third_party/heimdal/lib/kadm5/get_princs_c.c b/third_party/heimdal/lib/kadm5/get_princs_c.c
index 4998223d260..93d7ce7ed1b 100644
--- a/third_party/heimdal/lib/kadm5/get_princs_c.c
+++ b/third_party/heimdal/lib/kadm5/get_princs_c.c
@@ -66,7 +66,7 @@ kadm5_c_get_principals(void *server_handle,
ret = krb5_store_int32(sp, kadm_get_princs);
if (ret)
goto out;
- ret = krb5_store_int32(sp, expression != NULL);
+ ret = krb5_store_int32(sp, expression != NULL ? 1 : 0);
if (ret)
goto out;
if (expression) {
@@ -117,3 +117,187 @@ kadm5_c_get_principals(void *server_handle,
krb5_data_free(&reply);
return ret;
}
+
+kadm5_ret_t
+kadm5_c_iter_principals(void *server_handle,
+ const char *expression,
+ int (*cb)(void *, const char *),
+ void *cbdata)
+{
+ kadm5_client_context *context = server_handle;
+ kadm5_ret_t ret;
+ krb5_storage *sp;
+ unsigned char buf[1024];
+ int32_t tmp;
+ krb5_data reply;
+ size_t i;
+
+ ret = _kadm5_connect(server_handle, 0 /* want_write */);
+ if (ret)
+ return ret;
+
+ krb5_data_zero(&reply);
+
+ sp = krb5_storage_from_mem(buf, sizeof(buf));
+ if (sp == NULL) {
+ ret = krb5_enomem(context->context);
+ goto out_keep_error;
+ }
+ ret = krb5_store_int32(sp, kadm_get_princs);
+ if (ret)
+ goto out;
+
+ /*
+ * Our protocol has an int boolean for this operation to indicate whether
+ * there's an expression. What we'll do here is that instead of sending
+ * just false or trueish, for online iteration we'll send a number other
+ * than 0 or 1 -- a magic value > 0 and < INT_MAX.
+ *
+ * In response we'll expect multiple replies, each with up to some small
+ * number of principal names. See kadmin/server.c.
+ */
+ ret = krb5_store_int32(sp, 0x55555555);
+ if (ret)
+ goto out;
+ ret = krb5_store_string(sp, expression ? expression : "");
+ if (ret)
+ goto out;
+ ret = _kadm5_client_send(context, sp);
+ if (ret)
+ goto out_keep_error;
+ ret = _kadm5_client_recv(context, &reply);
+ if (ret)
+ goto out_keep_error;
+ krb5_storage_free(sp);
+ sp = krb5_storage_from_data (&reply);
+ if (sp == NULL) {
+ ret = krb5_enomem(context->context);
+ goto out_keep_error;
+ }
+ ret = krb5_ret_int32(sp, &tmp);
+ if (ret == 0)
+ ret = tmp;
+
+ if (ret)
+ goto out;
+
+ ret = krb5_ret_int32(sp, &tmp);
+ if (ret)
+ goto out;
+
+ if (tmp < 0) {
+ size_t n = -tmp;
+ int more = 1;
+ int stop = 0;
+
+ /* The server supports online iteration, hooray! */
+
+ while (more) {
+ /*
+ * We expect any number of chunks, each having `n' names, except
+ * the last one would have fewer than `n' (possibly zero, even).
+ *
+ * After that we expect one more reply with just a final return
+ * code.
+ */
+ krb5_data_free(&reply);
+ krb5_storage_free(sp);
+ sp = NULL;
+ ret = _kadm5_client_recv(context, &reply);
+ if (ret == 0 && (sp = krb5_storage_from_data(&reply)) == NULL)
+ ret = krb5_enomem(context->context);
+ if (ret)
+ goto out;
+
+ /* Every chunk begins with a status code */
+ ret = krb5_ret_int32(sp, &tmp);
+ if (ret == 0)
+ ret = tmp;
+ if (ret)
+ goto out;
+
+ /* We expect up to -tmp principals per reply */
+ for (i = 0; i < n; i++) {
+ char *princ = NULL;
+
+ ret = krb5_ret_string(sp, &princ);
+ if (ret == HEIM_ERR_EOF) {
+ /* This was the last reply */
+ more = 0;
+ ret = 0;
+ break;
+ }
+ if (ret)
+ goto out;
+ if (!stop) {
+ stop = cb(cbdata, princ);
+ if (stop) {
+ /*
+ * Tell the server to stop.
+ *
+ * We use a NOP for this, but with a payload that says
+ * "don't reply to the NOP" just in case the NOP
+ * arrives and is processed _after_ the LISTing has
+ * finished.
+ */
+ krb5_storage_free(sp);
+ if ((sp = krb5_storage_emem()) &&
+ krb5_store_int32(sp, kadm_nop) == 0 &&
+ krb5_store_int32(sp, 0))
+ (void) _kadm5_client_send(context, sp);
+ }
+ }
+ free(princ);
+ }
+
+ if (!more) {
+ if (ret == 0)
+ ret = stop;
+ break;
+ }
+ }
+ /* Get the final result code */
+ krb5_data_free(&reply);
+ krb5_storage_free(sp);
+ sp = NULL;
+ ret = _kadm5_client_recv(context, &reply);
+ if (ret == 0 && (sp = krb5_storage_from_data(&reply)) == NULL)
+ ret = krb5_enomem(context->context);
+ if (ret)
+ goto out;
+ ret = krb5_ret_int32(sp, &tmp);
+ if (ret == 0)
+ ret = tmp;
+ if (!stop) {
+ /*
+ * Send our "interrupt" after the last chunk if we hand't
+ * interrupted already.
+ */
+ krb5_storage_free(sp);
+ if ((sp = krb5_storage_emem()) &&
+ krb5_store_int32(sp, kadm_nop) == 0)
+ (void) _kadm5_client_send(context, sp);
+ }
+ } else {
+ size_t n = tmp;
+
+ /* Old server -- listing not online */
+ for (i = 0; i < n; i++) {
+ char *princ = NULL;
+
+ ret = krb5_ret_string(sp, &princ);
+ if (ret)
+ goto out;
+ cb(cbdata, princ);
+ free(princ);
+ }
+ }
+
+ out:
+ krb5_clear_error_message(context->context);
+
+ out_keep_error:
+ krb5_storage_free(sp);
+ krb5_data_free(&reply);
+ return ret;
+}
diff --git a/third_party/heimdal/lib/kadm5/get_princs_s.c b/third_party/heimdal/lib/kadm5/get_princs_s.c
index 27fac2bbb0b..14d3907d759 100644
--- a/third_party/heimdal/lib/kadm5/get_princs_s.c
+++ b/third_party/heimdal/lib/kadm5/get_princs_s.c
@@ -39,17 +39,27 @@ struct foreach_data {
const char *exp;
char *exp2;
char **princs;
- int count;
+ size_t nalloced;
+ size_t count;
};
static krb5_error_code
add_princ(krb5_context context, struct foreach_data *d, char *princ)
{
- char **tmp;
- tmp = realloc(d->princs, (d->count + 1) * sizeof(*tmp));
- if (tmp == NULL)
- return krb5_enomem(context);
- d->princs = tmp;
+
+ if (d->count == INT_MAX)
+ return ERANGE;
+ if (d->nalloced == d->count) {
+ size_t n = d->nalloced + (d->nalloced >> 1) + 128; /* No O(N^2) pls */
+ char **tmp;
+
+ if (SIZE_MAX / sizeof(*tmp) <= n)
+ return ERANGE;
+ if ((tmp = realloc(d->princs, n * sizeof(*tmp))) == NULL)
+ return krb5_enomem(context);
+ d->princs = tmp;
+ d->nalloced = n;
+ }
d->princs[d->count++] = princ;
return 0;
}
@@ -84,7 +94,7 @@ kadm5_s_get_principals(void *server_handle,
{
struct foreach_data d;
kadm5_server_context *context = server_handle;
- kadm5_ret_t ret;
+ kadm5_ret_t ret = 0;
if (!context->keep_open) {
ret = context->db->hdb_open(context->context, context->db, O_RDONLY, 0);
@@ -94,33 +104,103 @@ kadm5_s_get_principals(void *server_handle,
}
}
d.exp = expression;
- {
+ d.exp2 = NULL;
+ if (expression) {
krb5_realm r;
int aret;
ret = krb5_get_default_realm(context->context, &r);
- if (ret)
- goto out;
- aret = asprintf(&d.exp2, "%s@%s", expression, r);
- free(r);
- if (aret == -1 || d.exp2 == NULL) {
- ret = krb5_enomem(context->context);
- goto out;
- }
+ if (ret == 0) {
+ aret = asprintf(&d.exp2, "%s@%s", expression, r);
+ free(r);
+ if (aret == -1 || d.exp2 == NULL)
+ ret = krb5_enomem(context->context);
+ }
}
d.princs = NULL;
+ d.nalloced = 0;
d.count = 0;
- ret = hdb_foreach(context->context, context->db, HDB_F_ADMIN_DATA, foreach, &d);
+ if (ret == 0)
+ ret = hdb_foreach(context->context, context->db, HDB_F_ADMIN_DATA,
+ foreach, &d);
if (ret == 0)
ret = add_princ(context->context, &d, NULL);
- if (ret == 0){
+ if (d.count >= INT_MAX)
+ *count = INT_MAX;
+ else
+ *count = d.count - 1;
+ if (ret == 0)
*princs = d.princs;
- *count = d.count - 1;
- } else
- kadm5_free_name_list(context, d.princs, &d.count);
+ else
+ kadm5_free_name_list(context, d.princs, count);
+ free(d.exp2);
+ if (!context->keep_open)
+ context->db->hdb_close(context->context, context->db);
+ return _kadm5_error_code(ret);
+}
+
+struct foreach_online_data {
+ const char *exp;
+ char *exp2;
+ int (*cb)(void *, const char *);
+ void *cbdata;
+};
+
+static krb5_error_code
+foreach_online(krb5_context context, HDB *db, hdb_entry *ent, void *data)
+{
+ struct foreach_online_data *d = data;
+ krb5_error_code ret;
+ char *princ = NULL;
+
+ ret = krb5_unparse_name(context, ent->principal, &princ);
+ if (ret == 0) {
+ if (!d->exp ||
+ fnmatch(d->exp, princ, 0) == 0 || fnmatch(d->exp2, princ, 0) == 0)
+ ret = d->cb(d->cbdata, princ);
+ free(princ);
+ }
+ return ret;
+}
+
+kadm5_ret_t
+kadm5_s_iter_principals(void *server_handle,
+ const char *expression,
+ int (*cb)(void *, const char *),
+ void *cbdata)
+{
+ struct foreach_online_data d;
+ kadm5_server_context *context = server_handle;
+ kadm5_ret_t ret = 0;
+
+ if (!context->keep_open) {
+ ret = context->db->hdb_open(context->context, context->db, O_RDONLY, 0);
+ if (ret) {
+ krb5_warn(context->context, ret, "opening database");
+ return ret;
+ }
+ }
+ d.exp = expression;
+ d.exp2 = NULL;
+ d.cb = cb;
+ d.cbdata = cbdata;
+ if (expression) {
+ krb5_realm r;
+ int aret;
+
+ ret = krb5_get_default_realm(context->context, &r);
+ if (ret == 0) {
+ aret = asprintf(&d.exp2, "%s@%s", expression, r);
+ free(r);
+ if (aret == -1 || d.exp2 == NULL)
+ ret = krb5_enomem(context->context);
+ }
+ }
+ if (ret == 0)
+ ret = hdb_foreach(context->context, context->db, HDB_F_ADMIN_DATA,
+ foreach_online, &d);
free(d.exp2);
- out:
if (!context->keep_open)
context->db->hdb_close(context->context, context->db);
return _kadm5_error_code(ret);
diff --git a/third_party/heimdal/lib/kadm5/init_c.c b/third_party/heimdal/lib/kadm5/init_c.c
index 5d585d1a295..ffbb639581c 100644
--- a/third_party/heimdal/lib/kadm5/init_c.c
+++ b/third_party/heimdal/lib/kadm5/init_c.c
@@ -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,56 @@ _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) {
+ ctx->my_context = TRUE;
+ 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);
+ }
+ ctx->sock = -1;
+ 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,
diff --git a/third_party/heimdal/lib/kadm5/init_s.c b/third_party/heimdal/lib/kadm5/init_s.c
index 1b1d7f2ff58..35402d88a52 100644
--- a/third_party/heimdal/lib/kadm5/init_s.c
+++ b/third_party/heimdal/lib/kadm5/init_s.c
@@ -109,6 +109,21 @@ kadm5_s_init_with_context(krb5_context context,
}
kadm5_ret_t
+kadm5_s_dup_context(void *vin, void **out)
+{
+ kadm5_server_context *in = vin;
+ kadm5_ret_t ret;
+ char *p = NULL;
+
+ ret = krb5_unparse_name(in->context, in->caller, &p);
+ if (ret == 0)
+ ret = kadm5_s_init_with_context(in->context, p, NULL,
+ &in->config, 0, 0, out);
+ free(p);
+ return ret;
+}
+
+kadm5_ret_t
kadm5_s_init_with_password_ctx(krb5_context context,
const char *client_name,
const char *password,
diff --git a/third_party/heimdal/lib/kadm5/iprop.8 b/third_party/heimdal/lib/kadm5/iprop.8
index b881c441a1a..41aac061829 100644
--- a/third_party/heimdal/lib/kadm5/iprop.8
+++ b/third_party/heimdal/lib/kadm5/iprop.8
@@ -68,6 +68,8 @@
.Oo Fl r Ar string \*(Ba Xo Fl Fl realm= Ns Ar string Xc Oc
.Oo Fl d Ar file \*(Ba Xo Fl Fl database= Ns Ar file Xc Oc
.Oo Fl k Ar kspec \*(Ba Xo Fl Fl keytab= Ns Ar kspec Xc Oc
+.Oo Xo Fl Fl no-keytab Xc Oc
+.Oo Xo Fl Fl cache= Ns Ar cspec Xc Oc
.Op Fl Fl statusfile= Ns Ar file
.Op Fl Fl hostname= Ns Ar hostname
.Op Fl Fl port= Ns Ar port
@@ -125,10 +127,40 @@ This should normally be defined as
in
.Pa /etc/services
or another source of the services database.
-The master and slaves
-must each have access to a keytab with keys for the
-.Nm iprop
-service principal on the local host.
+.Pp
+The
+.Nm ipropd-master
+and
+.Nm ipropd-slave
+programs require acceptor and initiator credentials,
+respectively, for host-based principals for the
+.Ar iprop
+service and the fully-qualified hostnames of the hosts on which
+they run.
+.Pp
+The
+.Nm ipropd-master
+program uses, by default, the HDB-backed keytab
+.Ar HDBGET: ,
+though a file-based keytab can also be specified.
+.Pp
+The
+.Nm ipropd-slave
+program uses the default keytab, which is specified by the
+.Ev KRB5_KTNAME
+environment variable, or the value of the
+.Ar default_keytab_name
+configuration parameter in the
+.Ar [libdefaults]
+section.
+However, if the
+.Fl Fl no-keytab
+option is given, then
+.Nm ipropd-slave
+will use the given or default credentials cache, and it will
+expect that cache to be kept fresh externally (such as by the
+.Nm kinit
+program).
.Pp
There is a keep-alive feature logged in the master's
.Pa slave-stats
@@ -150,6 +182,11 @@ Supported options for
Keytab for authenticating
.Nm ipropd-slave
clients.
+.It Fl Fl cache= Ns Ar cspec
+If the keytab given is the empty string then credentials will be
+used from the default credentials cache, or from the
+.Ar cspec
+if given.
.It Fl d Ar file , Fl Fl database= Ns Ar file
Database (default per KDC)
.It Fl Fl slave-stats-file= Ns Ar file
@@ -201,6 +238,7 @@ in the database directory, or in the directory named by the
.Ev HEIM_PIDFILE_DIR
environment variable.
.Sh SEE ALSO
+.Xr kinit 1 ,
.Xr krb5.conf 5 ,
.Xr hprop 8 ,
.Xr hpropd 8 ,
diff --git a/third_party/heimdal/lib/kadm5/ipropd_slave.c b/third_party/heimdal/lib/kadm5/ipropd_slave.c
index 2b1be00ea60..f92b20c8569 100644
--- a/third_party/heimdal/lib/kadm5/ipropd_slave.c
+++ b/third_party/heimdal/lib/kadm5/ipropd_slave.c
@@ -39,6 +39,9 @@ static const char *config_name = "ipropd-slave";
static int verbose;
static int async_hdb = 0;
+static int no_keytab_flag;
+static char *ccache_str;
+static char *keytab_str;
static krb5_log_facility *log_facility;
static char five_min[] = "5 min";
@@ -115,8 +118,7 @@ connect_to_master (krb5_context context, const char *master,
}
static void
-get_creds(krb5_context context, const char *keytab_str,
- krb5_ccache *cache, const char *serverhost)
+get_creds(krb5_context context, krb5_ccache *cache, const char *serverhost)
{
krb5_keytab keytab;
krb5_principal client;
@@ -127,13 +129,33 @@ get_creds(krb5_context context, const char *keytab_str,
char keytab_buf[256];
int aret;
+ if (no_keytab_flag) {
+ /* We're using an externally refreshed ccache */
+ if (*cache == NULL) {
+ if (ccache_str == NULL)
+ ret = krb5_cc_default(context, cache);
+ else
+ ret = krb5_cc_resolve(context, ccache_str, cache);
+ if (ret)
+ krb5_err(context, 1, ret, "Could not resolve the default cache");
+ }
+ return;
+ }
+
if (keytab_str == NULL) {
ret = krb5_kt_default_name (context, keytab_buf, sizeof(keytab_buf));
- if (ret)
- krb5_err (context, 1, ret, "krb5_kt_default_name");
- keytab_str = keytab_buf;
+ if (ret == 0) {
+ keytab_str = keytab_buf;
+ } else {
+ krb5_warn(context, ret, "Using HDBGET: as the default keytab");
+ keytab_str = "HDBGET:";
+ }
}
+ if (*cache)
+ krb5_cc_destroy(context, *cache);
+ *cache = NULL;
+
ret = krb5_kt_resolve(context, keytab_str, &keytab);
if(ret)
krb5_err(context, 1, ret, "%s", keytab_str);
@@ -690,7 +712,6 @@ static char *status_file;
static char *config_file;
static int version_flag;
static int help_flag;
-static char *keytab_str;
static char *port_str;
static int detach_from_console;
static int daemon_child = -1;
@@ -699,8 +720,12 @@ static struct getargs args[] = {
{ "config-file", 'c', arg_string, &config_file, NULL, NULL },
{ "realm", 'r', arg_string, &realm, NULL, NULL },
{ "database", 'd', arg_string, &database, "database", "file"},
+ { "no-keytab", 0, arg_flag, &no_keytab_flag,
+ "use externally refreshed cache", NULL },
+ { "ccache", 0, arg_string, &ccache_str,
+ "client credentials", "CCACHE" },
{ "keytab", 'k', arg_string, &keytab_str,
- "keytab to get authentication from", "kspec" },
+ "client credentials keytab", "KEYTAB" },
{ "time-lost", 0, arg_string, &server_time_lost,
"time before server is considered lost", "time" },
{ "status-file", 0, arg_string, &status_file,
@@ -740,7 +765,7 @@ main(int argc, char **argv)
kadm5_server_context *server_context;
kadm5_config_params conf;
int master_fd;
- krb5_ccache ccache;
+ krb5_ccache ccache = NULL;
krb5_principal server;
char **files;
int optidx = 0;
@@ -858,7 +883,7 @@ main(int argc, char **argv)
if (ret)
krb5_err(context, 1, ret, "db->close");
- get_creds(context, keytab_str, &ccache, master);
+ get_creds(context, &ccache, master);
ret = krb5_sname_to_principal (context, master, IPROP_NAME,
KRB5_NT_SRV_HST, &server);
@@ -923,8 +948,7 @@ main(int argc, char **argv)
if (auth_context) {
krb5_auth_con_free(context, auth_context);
auth_context = NULL;
- krb5_cc_destroy(context, ccache);
- get_creds(context, keytab_str, &ccache, master);
+ get_creds(context, &ccache, master);
}
if (verbose)
krb5_warnx(context, "authenticating to master");
diff --git a/third_party/heimdal/lib/kadm5/libkadm5srv-exports.def b/third_party/heimdal/lib/kadm5/libkadm5srv-exports.def
index 72ba4174c1f..56366ae2046 100644
--- a/third_party/heimdal/lib/kadm5/libkadm5srv-exports.def
+++ b/third_party/heimdal/lib/kadm5/libkadm5srv-exports.def
@@ -15,6 +15,7 @@ EXPORTS
kadm5_delete_policy
kadm5_delete_principal
kadm5_destroy
+ kadm5_dup_context
kadm5_flush
kadm5_free_key_data
kadm5_free_name_list
@@ -32,6 +33,7 @@ EXPORTS
kadm5_init_with_password_ctx
kadm5_init_with_skey
kadm5_init_with_skey_ctx
+ kadm5_iter_principals
kadm5_lock
kadm5_modify_policy
kadm5_modify_principal
diff --git a/third_party/heimdal/lib/kadm5/private.h b/third_party/heimdal/lib/kadm5/private.h
index 88c2f2823d2..1cb8e3918f5 100644
--- a/third_party/heimdal/lib/kadm5/private.h
+++ b/third_party/heimdal/lib/kadm5/private.h
@@ -68,6 +68,8 @@ struct kadm_func {
int, krb5_key_salt_tuple *,
krb5_keyblock *, int);
kadm5_ret_t (*prune_principal) (void *, krb5_principal, int);
+ kadm5_ret_t (*iter_principals) (void*, const char*, int (*)(void *, const char *), void *);
+ kadm5_ret_t (*dup_context) (void*, void **);
};
typedef struct kadm5_hook_context {
diff --git a/third_party/heimdal/lib/kadm5/version-script-client.map b/third_party/heimdal/lib/kadm5/version-script-client.map
index 4d89fabf308..baae30b1173 100644
--- a/third_party/heimdal/lib/kadm5/version-script-client.map
+++ b/third_party/heimdal/lib/kadm5/version-script-client.map
@@ -11,6 +11,7 @@ HEIMDAL_KADM5_CLIENT_1.0 {
kadm5_c_create_principal;
kadm5_c_delete_principal;
kadm5_c_destroy;
+ kadm5_c_dup_context;
kadm5_c_flush;
kadm5_c_get_principal;
kadm5_c_get_principals;
@@ -21,6 +22,8 @@ HEIMDAL_KADM5_CLIENT_1.0 {
kadm5_c_init_with_password_ctx;
kadm5_c_init_with_skey;
kadm5_c_init_with_skey_ctx;
+ kadm5_c_iter_principals;
+ kadm5_c_get_privs;
kadm5_c_modify_principal;
kadm5_c_prune_principal;
kadm5_c_randkey_principal;
@@ -30,6 +33,7 @@ HEIMDAL_KADM5_CLIENT_1.0 {
kadm5_create_principal;
kadm5_delete_principal;
kadm5_destroy;
+ kadm5_dup_context;
kadm5_flush;
kadm5_free_key_data;
kadm5_free_name_list;
@@ -43,6 +47,7 @@ HEIMDAL_KADM5_CLIENT_1.0 {
kadm5_init_with_password_ctx;
kadm5_init_with_skey;
kadm5_init_with_skey_ctx;
+ kadm5_iter_principals;
kadm5_modify_principal;
kadm5_randkey_principal;
kadm5_randkey_principal_3;
diff --git a/third_party/heimdal/lib/kadm5/version-script.map b/third_party/heimdal/lib/kadm5/version-script.map
index e4b4100f334..6de88fc2217 100644
--- a/third_party/heimdal/lib/kadm5/version-script.map
+++ b/third_party/heimdal/lib/kadm5/version-script.map
@@ -16,6 +16,7 @@ HEIMDAL_KAMD5_SERVER_1.0 {
kadm5_create_principal_3;
kadm5_delete_principal;
kadm5_destroy;
+ kadm5_dup_context;
kadm5_decrypt_key;
kadm5_delete_policy;
kadm5_flush;
@@ -35,6 +36,7 @@ HEIMDAL_KAMD5_SERVER_1.0 {
kadm5_init_with_password_ctx;
kadm5_init_with_skey;
kadm5_init_with_skey_ctx;
+ kadm5_iter_principals;
kadm5_lock;
kadm5_modify_principal;
kadm5_modify_policy;