ktutil: Add list --json option
This commit is contained in:
@@ -37,6 +37,7 @@ LDADD = \
|
||||
$(LIB_hcrypto) \
|
||||
$(top_builddir)/lib/asn1/libasn1.la \
|
||||
$(top_builddir)/lib/sl/libsl.la \
|
||||
$(LIB_heimbase) \
|
||||
$(LIB_readline) \
|
||||
$(LIB_roken)
|
||||
|
||||
|
@@ -226,6 +226,11 @@ command = {
|
||||
type = "flag"
|
||||
help = "show timestamps"
|
||||
}
|
||||
option = {
|
||||
long = "json"
|
||||
type = "flag"
|
||||
help = "output JSON representation"
|
||||
}
|
||||
max_args = "0"
|
||||
function = "kt_list"
|
||||
help = "Show contents of keytab."
|
||||
|
@@ -60,7 +60,7 @@ Verbose output.
|
||||
.Ar command
|
||||
can be one of the following:
|
||||
.Bl -tag -width srvconvert
|
||||
.It add Oo Fl p Ar principal Oc Oo Fl Fl principal= Ns Ar principal Oc \
|
||||
.It Nm add Oo Fl p Ar principal Oc Oo Fl Fl principal= Ns Ar principal Oc \
|
||||
Oo Fl V Ar kvno Oc Oo Fl Fl kvno= Ns Ar kvno Oc Oo Fl e Ar enctype Oc \
|
||||
Oo Fl Fl keepold | Fl Fl keepallold | Fl Fl pruneall Oc \
|
||||
Oo Fl Fl enctype= Ns Ar enctype Oc Oo Fl w Ar password Oc \
|
||||
@@ -72,7 +72,7 @@ principal to add; if what you really want is to add a new principal to
|
||||
the keytab, you should consider the
|
||||
.Ar get
|
||||
command, which talks to the kadmin server.
|
||||
.It change Oo Fl r Ar realm Oc Oo Fl Fl realm= Ns Ar realm Oc \
|
||||
.It Nm change Oo Fl r Ar realm Oc Oo Fl Fl realm= Ns Ar realm Oc \
|
||||
Oo Fl Fl keepold | Fl Fl keepallold | Fl Fl pruneall Oc \
|
||||
Oo Fl Fl enctype= Ns Ar enctype Oc \
|
||||
Oo Fl Fl a Ar host Oc Oo Fl Fl admin-server= Ns Ar host Oc \
|
||||
@@ -82,12 +82,12 @@ server for the realm of a keytab entry. Otherwise it will use the
|
||||
values specified by the options.
|
||||
.Pp
|
||||
If no principals are given, all the ones in the keytab are updated.
|
||||
.It copy Ar keytab-src Ar keytab-dest
|
||||
.It Nm copy Ar keytab-src Ar keytab-dest
|
||||
Copies all the entries from
|
||||
.Ar keytab-src
|
||||
to
|
||||
.Ar keytab-dest .
|
||||
.It get Oo Fl p Ar admin principal Oc \
|
||||
.It Nm get Oo Fl p Ar admin principal Oc \
|
||||
Oo Fl Fl principal= Ns Ar admin principal Oc Oo Fl e Ar enctype Oc \
|
||||
Oo Fl Fl keepold | Fl Fl keepallold | Fl Fl pruneall Oc \
|
||||
Oo Fl Fl enctypes= Ns Ar enctype Oc Oo Fl r Ar realm Oc \
|
||||
@@ -103,9 +103,9 @@ If no
|
||||
.Ar realm
|
||||
is specified, the realm to operate on is taken from the first
|
||||
principal.
|
||||
.It list Oo Fl Fl keys Oc Op Fl Fl timestamp
|
||||
.It Nm list Oo Fl Fl keys Oc Op Fl Fl timestamp Oo Op Fl Fl json Oc
|
||||
List the keys stored in the keytab.
|
||||
.It remove Oo Fl p Ar principal Oc Oo Fl Fl principal= Ns Ar principal Oc \
|
||||
.It Nm remove Oo Fl p Ar principal Oc Oo Fl Fl principal= Ns Ar principal Oc \
|
||||
Oo Fl V kvno Oc Oo Fl Fl kvno= Ns Ar kvno Oc Oo Fl e enctype Oc \
|
||||
Oo Fl Fl enctype= Ns Ar enctype Oc
|
||||
Removes the specified key or keys. Not specifying a
|
||||
@@ -113,12 +113,12 @@ Removes the specified key or keys. Not specifying a
|
||||
removes keys with any version number. Not specifying an
|
||||
.Ar enctype
|
||||
removes keys of any type.
|
||||
.It rename Ar from-principal Ar to-principal
|
||||
.It Nm rename Ar from-principal Ar to-principal
|
||||
Renames all entries in the keytab that match the
|
||||
.Ar from-principal
|
||||
to
|
||||
.Ar to-principal .
|
||||
.It purge Op Fl Fl age= Ns Ar age
|
||||
.It Nm purge Op Fl Fl age= Ns Ar age
|
||||
Removes all old versions of a key for which there is a newer version
|
||||
that is at least
|
||||
.Ar age
|
||||
|
139
admin/list.c
139
admin/list.c
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997-2004 Kungliga Tekniska Högskolan
|
||||
* Copyright (c) 1997-2022 Kungliga Tekniska Högskolan
|
||||
* (Royal Institute of Technology, Stockholm, Sweden).
|
||||
* All rights reserved.
|
||||
*
|
||||
@@ -32,6 +32,7 @@
|
||||
*/
|
||||
|
||||
#include "ktutil_locl.h"
|
||||
#include <heimbase.h>
|
||||
#include <rtbl.h>
|
||||
|
||||
RCSID("$Id$");
|
||||
@@ -131,7 +132,8 @@ do_list(struct list_options *opt, const char *keytab_str)
|
||||
struct rk_strpool *p = NULL;
|
||||
|
||||
for (i = 0; i< entry.aliases->len; i++) {
|
||||
krb5_unparse_name_fixed(context, entry.principal, buf, sizeof(buf));
|
||||
krb5_unparse_name_fixed(context, &entry.aliases->val[i],
|
||||
buf, sizeof(buf));
|
||||
p = rk_strpoolprintf(p, "%s%s", buf,
|
||||
i + 1 < entry.aliases->len ? ", " : "");
|
||||
|
||||
@@ -152,6 +154,137 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
do_list1_json(struct list_options *opt,
|
||||
const char *keytab_str,
|
||||
heim_array_t a)
|
||||
{
|
||||
krb5_error_code ret;
|
||||
krb5_keytab keytab;
|
||||
krb5_keytab_entry entry;
|
||||
krb5_kt_cursor cursor;
|
||||
|
||||
ret = krb5_kt_resolve(context, keytab_str, &keytab);
|
||||
if (ret) {
|
||||
krb5_warn(context, ret, "resolving keytab %s", keytab_str);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = krb5_kt_start_seq_get(context, keytab, &cursor);
|
||||
if(ret) {
|
||||
krb5_warn(context, ret, "krb5_kt_start_seq_get %s", keytab_str);
|
||||
krb5_kt_close(context, keytab);
|
||||
return ret;
|
||||
}
|
||||
|
||||
//if (opt->timestamp_flag)
|
||||
//if (opt->keys_flag)
|
||||
|
||||
while (krb5_kt_next_entry(context, keytab, &entry, &cursor) == 0) {
|
||||
heim_dict_t d = heim_dict_create(5);
|
||||
heim_object_t o;
|
||||
char *s;
|
||||
|
||||
heim_array_append_value(a, d);
|
||||
heim_dict_set_value(d, HSTR("keytab"),
|
||||
o = heim_string_create(keytab_str)); heim_release(o);
|
||||
heim_dict_set_value(d, HSTR("kvno"), o = heim_number_create(entry.vno));
|
||||
heim_release(o);
|
||||
heim_dict_set_value(d, HSTR("enctype_number"),
|
||||
o = heim_number_create(entry.keyblock.keytype));
|
||||
heim_release(o);
|
||||
heim_dict_set_value(d, HSTR("flags"),
|
||||
o = heim_number_create(entry.flags));
|
||||
heim_release(o);
|
||||
ret = krb5_enctype_to_string(context, entry.keyblock.keytype, &s);
|
||||
if (ret == 0) {
|
||||
heim_dict_set_value(d, HSTR("enctype"), o = heim_string_create(s));
|
||||
heim_release(o);
|
||||
free(s);
|
||||
}
|
||||
heim_dict_set_value(d, HSTR("timestamp"),
|
||||
o = heim_number_create(entry.timestamp));
|
||||
heim_release(o);
|
||||
|
||||
ret = krb5_unparse_name(context, entry.principal, &s);
|
||||
if (ret)
|
||||
krb5_err(context, 1, ret, "Could not format principal");
|
||||
heim_dict_set_value(d, HSTR("principal"), o = heim_string_create(s));
|
||||
heim_release(o);
|
||||
free(s);
|
||||
|
||||
if (opt->keys_flag) {
|
||||
o = heim_data_create(entry.keyblock.keyvalue.data,
|
||||
entry.keyblock.keyvalue.length);
|
||||
heim_dict_set_value(d, HSTR("key"), o);
|
||||
heim_release(o);
|
||||
}
|
||||
if (entry.aliases) {
|
||||
heim_array_t aliases = heim_array_create();
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i< entry.aliases->len; i++) {
|
||||
ret = krb5_unparse_name(context, &entry.aliases->val[i], &s);
|
||||
if (ret)
|
||||
krb5_err(context, 1, ret, "Could not format principal");
|
||||
heim_array_append_value(aliases, o = heim_string_create(s));
|
||||
heim_release(o);
|
||||
free(s);
|
||||
}
|
||||
heim_dict_set_value(d, HSTR("aliases"), aliases);
|
||||
heim_release(aliases);
|
||||
free(s);
|
||||
}
|
||||
|
||||
krb5_kt_free_entry(context, &entry);
|
||||
heim_release(d);
|
||||
}
|
||||
|
||||
ret = krb5_kt_end_seq_get(context, keytab, &cursor);
|
||||
krb5_kt_close(context, keytab);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
do_list_json(struct list_options *opt, const char *keytab_str)
|
||||
{
|
||||
krb5_error_code ret = 0;
|
||||
heim_json_flags_t flags =
|
||||
(HEIM_JSON_F_STRICT | HEIM_JSON_F_INDENT2 | HEIM_JSON_F_NO_DATA_DICT) &
|
||||
~HEIM_JSON_F_NO_DATA;
|
||||
heim_array_t a = heim_array_create();
|
||||
heim_string_t s;
|
||||
|
||||
/*
|
||||
* Special-case the ANY: keytab type. What do we get from this? We get to
|
||||
* include the actual keytab name for each entry in its JSON
|
||||
* representation. Otherwise there would be no point because the ANY:
|
||||
* keytab type iterates all the keytabs it joins.
|
||||
*
|
||||
* Why strncasecmp() though? Because do_list() uses it, though it arguably
|
||||
* never should have.
|
||||
*/
|
||||
if (strncasecmp(keytab_str, "ANY:", 4) == 0) {
|
||||
char buf[1024];
|
||||
|
||||
keytab_str += 4;
|
||||
ret = 0;
|
||||
while (strsep_copy((const char**)&keytab_str, ",",
|
||||
buf, sizeof(buf)) != -1) {
|
||||
if (do_list1_json(opt, buf, a))
|
||||
ret = 1;
|
||||
}
|
||||
} else {
|
||||
ret = do_list1_json(opt, keytab_str, a);
|
||||
}
|
||||
|
||||
s = heim_json_copy_serialize(a, flags, NULL);
|
||||
printf("%s", heim_string_get_utf8(s));
|
||||
heim_release(a);
|
||||
heim_release(s);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
kt_list(struct list_options *opt, int argc, char **argv)
|
||||
{
|
||||
@@ -168,5 +301,7 @@ kt_list(struct list_options *opt, int argc, char **argv)
|
||||
}
|
||||
keytab_string = kt;
|
||||
}
|
||||
if (opt->json_flag)
|
||||
return do_list_json(opt, keytab_string) != 0;
|
||||
return do_list(opt, keytab_string) != 0;
|
||||
}
|
||||
|
Reference in New Issue
Block a user