kadmin: Use kadm5_iter_principals() to list princs
Now that we have a properly working API for listing principals in an online way, and a server-side implementation of it, use it. This should work with old and new servers, but it will only be online and fast when talking to new servers. (Old servers have a bug though that prevents LIST from working.)
This commit is contained in:
@@ -73,7 +73,7 @@ do_check_entry(krb5_principal principal, void *data)
|
|||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
memset (&princ, 0, sizeof(princ));
|
memset (&princ, 0, sizeof(princ));
|
||||||
ret = kadm5_get_principal(kadm_handle, principal, &princ,
|
ret = kadm5_get_principal(data, principal, &princ,
|
||||||
KADM5_PRINCIPAL | KADM5_KEY_DATA);
|
KADM5_PRINCIPAL | KADM5_KEY_DATA);
|
||||||
if(ret) {
|
if(ret) {
|
||||||
krb5_warn(context, ret, "Failed to get principal: %s", name);
|
krb5_warn(context, ret, "Failed to get principal: %s", name);
|
||||||
@@ -95,7 +95,7 @@ do_check_entry(krb5_principal principal, void *data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
free(name);
|
free(name);
|
||||||
kadm5_free_principal_ent(kadm_handle, &princ);
|
kadm5_free_principal_ent(data, &princ);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -106,6 +106,7 @@ check(void *opt, int argc, char **argv)
|
|||||||
kadm5_principal_ent_rec ent;
|
kadm5_principal_ent_rec ent;
|
||||||
krb5_error_code ret;
|
krb5_error_code ret;
|
||||||
char *realm = NULL, *p, *p2;
|
char *realm = NULL, *p, *p2;
|
||||||
|
void *inner_kadm_handle = NULL;
|
||||||
int found;
|
int found;
|
||||||
|
|
||||||
if (argc == 0) {
|
if (argc == 0) {
|
||||||
@@ -254,7 +255,15 @@ check(void *opt, int argc, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach_principal("*", do_check_entry, "check", NULL);
|
ret = kadm5_dup_context(kadm_handle, &inner_kadm_handle);
|
||||||
|
if (ret == 0)
|
||||||
|
ret = foreach_principal("*", do_check_entry, "check", inner_kadm_handle);
|
||||||
|
if (inner_kadm_handle)
|
||||||
|
kadm5_destroy(inner_kadm_handle);
|
||||||
|
if (ret) {
|
||||||
|
krb5_warn(context, ret, "Could not iterate principals in realm");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
free(realm);
|
free(realm);
|
||||||
return 0;
|
return 0;
|
||||||
|
20
kadmin/get.c
20
kadmin/get.c
@@ -84,6 +84,7 @@ struct get_entry_data {
|
|||||||
struct field_info *chead, **ctail;
|
struct field_info *chead, **ctail;
|
||||||
const char *krb5_config_fname;
|
const char *krb5_config_fname;
|
||||||
uint32_t n;
|
uint32_t n;
|
||||||
|
int upto;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@@ -478,6 +479,11 @@ do_get_entry(krb5_principal principal, void *data)
|
|||||||
krb5_error_code ret;
|
krb5_error_code ret;
|
||||||
struct get_entry_data *e = data;
|
struct get_entry_data *e = data;
|
||||||
|
|
||||||
|
if (e->upto == 0)
|
||||||
|
return EINTR;
|
||||||
|
if (e->upto > 0)
|
||||||
|
e->upto--;
|
||||||
|
|
||||||
memset(&princ, 0, sizeof(princ));
|
memset(&princ, 0, sizeof(princ));
|
||||||
ret = kadm5_get_principal(kadm_handle, principal,
|
ret = kadm5_get_principal(kadm_handle, principal,
|
||||||
&princ,
|
&princ,
|
||||||
@@ -534,8 +540,14 @@ static int
|
|||||||
do_list_entry(krb5_principal principal, void *data)
|
do_list_entry(krb5_principal principal, void *data)
|
||||||
{
|
{
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
|
int *upto = data;
|
||||||
krb5_error_code ret;
|
krb5_error_code ret;
|
||||||
|
|
||||||
|
if (*upto == 0)
|
||||||
|
return EINTR;
|
||||||
|
if (*upto > 0)
|
||||||
|
(*upto)--;
|
||||||
|
|
||||||
ret = krb5_unparse_name_fixed_short(context, principal, buf, sizeof(buf));
|
ret = krb5_unparse_name_fixed_short(context, principal, buf, sizeof(buf));
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
return ret;
|
return ret;
|
||||||
@@ -544,13 +556,13 @@ do_list_entry(krb5_principal principal, void *data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
listit(const char *funcname, int argc, char **argv)
|
listit(const char *funcname, int upto, int argc, char **argv)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
krb5_error_code ret, saved_ret = 0;
|
krb5_error_code ret, saved_ret = 0;
|
||||||
|
|
||||||
for (i = 0; i < argc; i++) {
|
for (i = 0; i < argc; i++) {
|
||||||
ret = foreach_principal(argv[i], do_list_entry, funcname, NULL);
|
ret = foreach_principal(argv[i], do_list_entry, funcname, &upto);
|
||||||
if (saved_ret == 0 && ret != 0)
|
if (saved_ret == 0 && ret != 0)
|
||||||
saved_ret = ret;
|
saved_ret = ret;
|
||||||
}
|
}
|
||||||
@@ -577,7 +589,7 @@ getit(struct get_options *opt, const char *name, int argc, char **argv)
|
|||||||
opt->short_flag = 1;
|
opt->short_flag = 1;
|
||||||
|
|
||||||
if (opt->terse_flag)
|
if (opt->terse_flag)
|
||||||
return listit(name, argc, argv);
|
return listit(name, opt->upto_integer, argc, argv);
|
||||||
|
|
||||||
data.table = NULL;
|
data.table = NULL;
|
||||||
data.chead = NULL;
|
data.chead = NULL;
|
||||||
@@ -585,6 +597,7 @@ getit(struct get_options *opt, const char *name, int argc, char **argv)
|
|||||||
data.mask = 0;
|
data.mask = 0;
|
||||||
data.extra_mask = 0;
|
data.extra_mask = 0;
|
||||||
data.krb5_config_fname = opt->krb5_config_file_string;
|
data.krb5_config_fname = opt->krb5_config_file_string;
|
||||||
|
data.upto = opt->upto_integer;
|
||||||
data.n = 0;
|
data.n = 0;
|
||||||
|
|
||||||
if(opt->short_flag) {
|
if(opt->short_flag) {
|
||||||
@@ -638,5 +651,6 @@ list_princs(struct list_options *opt, int argc, char **argv)
|
|||||||
get_opt.short_flag = opt->short_flag;
|
get_opt.short_flag = opt->short_flag;
|
||||||
get_opt.terse_flag = opt->terse_flag;
|
get_opt.terse_flag = opt->terse_flag;
|
||||||
get_opt.column_info_string = opt->column_info_string;
|
get_opt.column_info_string = opt->column_info_string;
|
||||||
|
get_opt.upto_integer = opt->upto_integer;
|
||||||
return getit(&get_opt, "list", argc, argv);
|
return getit(&get_opt, "list", argc, argv);
|
||||||
}
|
}
|
||||||
|
@@ -500,6 +500,12 @@ command = {
|
|||||||
type = "string"
|
type = "string"
|
||||||
help = "filename to save the principal's krb5.confg in"
|
help = "filename to save the principal's krb5.confg in"
|
||||||
}
|
}
|
||||||
|
option = {
|
||||||
|
long = "upto"
|
||||||
|
type = "integer"
|
||||||
|
default = "-1"
|
||||||
|
help = "maximum number of principals to get/list"
|
||||||
|
}
|
||||||
argument = "principal..."
|
argument = "principal..."
|
||||||
min_args = "1"
|
min_args = "1"
|
||||||
help = "Shows information about principals matching the expressions."
|
help = "Shows information about principals matching the expressions."
|
||||||
@@ -674,6 +680,13 @@ command = {
|
|||||||
option = {
|
option = {
|
||||||
long = "krb5-config-file"
|
long = "krb5-config-file"
|
||||||
type = "string"
|
type = "string"
|
||||||
|
help = "only use this option with the get command"
|
||||||
|
}
|
||||||
|
option = {
|
||||||
|
long = "upto"
|
||||||
|
type = "integer"
|
||||||
|
default = "-1"
|
||||||
|
help = "maximum number of principals to get/list"
|
||||||
}
|
}
|
||||||
argument = "principal..."
|
argument = "principal..."
|
||||||
min_args = "1"
|
min_args = "1"
|
||||||
|
121
kadmin/util.c
121
kadmin/util.c
@@ -605,6 +605,34 @@ is_expression(const char *string)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct foreach_principal_data {
|
||||||
|
krb5_error_code ret;
|
||||||
|
const char *funcname;
|
||||||
|
int (*func)(krb5_principal, void *);
|
||||||
|
void *data;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
foreach_principal_cb(void *data, const char *p)
|
||||||
|
{
|
||||||
|
struct foreach_principal_data *d = data;
|
||||||
|
krb5_principal princ;
|
||||||
|
krb5_error_code ret;
|
||||||
|
|
||||||
|
ret = krb5_parse_name(context, p, &princ);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
d->ret = d->func(princ, d->data);
|
||||||
|
krb5_free_principal(context, princ);
|
||||||
|
if (d->ret) {
|
||||||
|
krb5_warn(context, d->ret, "%s %s", d->funcname, p);
|
||||||
|
krb5_clear_error_message(context);
|
||||||
|
ret = d->ret ? d->ret : ret;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Loop over all principals matching exp. If any of calls to `func'
|
* Loop over all principals matching exp. If any of calls to `func'
|
||||||
* failes, the first error is returned when all principals are
|
* failes, the first error is returned when all principals are
|
||||||
@@ -616,52 +644,67 @@ foreach_principal(const char *exp_str,
|
|||||||
const char *funcname,
|
const char *funcname,
|
||||||
void *data)
|
void *data)
|
||||||
{
|
{
|
||||||
char **princs = NULL;
|
struct foreach_principal_data d;
|
||||||
int num_princs = 0;
|
krb5_error_code ret;
|
||||||
int i;
|
krb5_principal p;
|
||||||
krb5_error_code saved_ret = 0, ret = 0;
|
|
||||||
krb5_principal princ_ent;
|
|
||||||
int is_expr;
|
int is_expr;
|
||||||
|
int go_slow =
|
||||||
|
secure_getenv("KADMIN_USE_GET_PRINCIPALS") != NULL &&
|
||||||
|
*secure_getenv("KADMIN_USE_GET_PRINCIPALS") != '\0';
|
||||||
|
|
||||||
/* if this isn't an expression, there is no point in wading
|
/* if this isn't an expression, there is no point in wading
|
||||||
through the whole database looking for matches */
|
through the whole database looking for matches */
|
||||||
is_expr = is_expression(exp_str);
|
is_expr = is_expression(exp_str);
|
||||||
if(is_expr)
|
|
||||||
ret = kadm5_get_principals(kadm_handle, exp_str, &princs, &num_princs);
|
d.funcname = funcname;
|
||||||
if(!is_expr || ret == KADM5_AUTH_LIST) {
|
d.func = func;
|
||||||
/* we might be able to perform the requested opreration even
|
d.data = data;
|
||||||
if we're not allowed to list principals */
|
d.ret = 0;
|
||||||
num_princs = 1;
|
|
||||||
princs = malloc(sizeof(*princs));
|
if (is_expr && !go_slow) {
|
||||||
if(princs == NULL)
|
ret = kadm5_iter_principals(kadm_handle, exp_str,
|
||||||
return ENOMEM;
|
foreach_principal_cb, &d);
|
||||||
princs[0] = strdup(exp_str);
|
if (ret == 0)
|
||||||
if(princs[0] == NULL){
|
return 0;
|
||||||
free(princs);
|
if (ret != KADM5_AUTH_LIST) {
|
||||||
return ENOMEM;
|
krb5_warn(context, ret, "kadm5_iter_principals");
|
||||||
}
|
return d.ret;
|
||||||
} else if(ret) {
|
}
|
||||||
krb5_warn(context, ret, "kadm5_get_principals");
|
} else if (is_expr) {
|
||||||
return ret;
|
char **princs = NULL;
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is just for testing, and maybe in case there are HDB backends
|
||||||
|
* that are not re-entrant (LDAP?).
|
||||||
|
*/
|
||||||
|
ret = kadm5_get_principals(kadm_handle, exp_str, &princs, &count);
|
||||||
|
if (ret == 0 && count > 0) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; ret == 0 && i < count; i++)
|
||||||
|
ret = foreach_principal_cb(&d, princs[i]);
|
||||||
|
kadm5_free_name_list(kadm_handle, princs, &count);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
if (ret != KADM5_AUTH_LIST) {
|
||||||
|
krb5_warn(context, ret, "kadm5_iter_principals");
|
||||||
|
return d.ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for(i = 0; i < num_princs; i++) {
|
/* we might be able to perform the requested opreration even
|
||||||
ret = krb5_parse_name(context, princs[i], &princ_ent);
|
if we're not allowed to list principals */
|
||||||
if(ret){
|
ret = krb5_parse_name(context, exp_str, &p);
|
||||||
krb5_warn(context, ret, "krb5_parse_name(%s)", princs[i]);
|
if (ret) {
|
||||||
continue;
|
krb5_warn(context, ret, "krb5_parse_name(%s)", exp_str);
|
||||||
}
|
return ret;
|
||||||
ret = (*func)(princ_ent, data);
|
|
||||||
if(ret) {
|
|
||||||
krb5_warn(context, ret, "%s %s", funcname, princs[i]);
|
|
||||||
krb5_clear_error_message(context);
|
|
||||||
if (saved_ret == 0)
|
|
||||||
saved_ret = ret;
|
|
||||||
}
|
|
||||||
krb5_free_principal(context, princ_ent);
|
|
||||||
}
|
}
|
||||||
if (ret == 0 && saved_ret != 0)
|
ret = (*func)(p, data);
|
||||||
ret = saved_ret;
|
if (ret) {
|
||||||
kadm5_free_name_list(kadm_handle, princs, &num_princs);
|
krb5_warn(context, ret, "%s %s", funcname, exp_str);
|
||||||
|
krb5_clear_error_message(context);
|
||||||
|
}
|
||||||
|
krb5_free_principal(context, p);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user