ktutil: Add list --json option
This commit is contained in:
@@ -37,6 +37,7 @@ LDADD = \
|
|||||||
$(LIB_hcrypto) \
|
$(LIB_hcrypto) \
|
||||||
$(top_builddir)/lib/asn1/libasn1.la \
|
$(top_builddir)/lib/asn1/libasn1.la \
|
||||||
$(top_builddir)/lib/sl/libsl.la \
|
$(top_builddir)/lib/sl/libsl.la \
|
||||||
|
$(LIB_heimbase) \
|
||||||
$(LIB_readline) \
|
$(LIB_readline) \
|
||||||
$(LIB_roken)
|
$(LIB_roken)
|
||||||
|
|
||||||
|
@@ -226,6 +226,11 @@ command = {
|
|||||||
type = "flag"
|
type = "flag"
|
||||||
help = "show timestamps"
|
help = "show timestamps"
|
||||||
}
|
}
|
||||||
|
option = {
|
||||||
|
long = "json"
|
||||||
|
type = "flag"
|
||||||
|
help = "output JSON representation"
|
||||||
|
}
|
||||||
max_args = "0"
|
max_args = "0"
|
||||||
function = "kt_list"
|
function = "kt_list"
|
||||||
help = "Show contents of keytab."
|
help = "Show contents of keytab."
|
||||||
|
@@ -60,7 +60,7 @@ Verbose output.
|
|||||||
.Ar command
|
.Ar command
|
||||||
can be one of the following:
|
can be one of the following:
|
||||||
.Bl -tag -width srvconvert
|
.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 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 keepold | Fl Fl keepallold | Fl Fl pruneall Oc \
|
||||||
Oo Fl Fl enctype= Ns Ar enctype Oc Oo Fl w Ar password 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
|
the keytab, you should consider the
|
||||||
.Ar get
|
.Ar get
|
||||||
command, which talks to the kadmin server.
|
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 keepold | Fl Fl keepallold | Fl Fl pruneall Oc \
|
||||||
Oo Fl Fl enctype= Ns Ar enctype 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 \
|
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.
|
values specified by the options.
|
||||||
.Pp
|
.Pp
|
||||||
If no principals are given, all the ones in the keytab are updated.
|
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
|
Copies all the entries from
|
||||||
.Ar keytab-src
|
.Ar keytab-src
|
||||||
to
|
to
|
||||||
.Ar keytab-dest .
|
.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 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 keepold | Fl Fl keepallold | Fl Fl pruneall Oc \
|
||||||
Oo Fl Fl enctypes= Ns Ar enctype Oc Oo Fl r Ar realm Oc \
|
Oo Fl Fl enctypes= Ns Ar enctype Oc Oo Fl r Ar realm Oc \
|
||||||
@@ -103,9 +103,9 @@ If no
|
|||||||
.Ar realm
|
.Ar realm
|
||||||
is specified, the realm to operate on is taken from the first
|
is specified, the realm to operate on is taken from the first
|
||||||
principal.
|
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.
|
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 V kvno Oc Oo Fl Fl kvno= Ns Ar kvno Oc Oo Fl e enctype Oc \
|
||||||
Oo Fl Fl enctype= Ns Ar enctype Oc
|
Oo Fl Fl enctype= Ns Ar enctype Oc
|
||||||
Removes the specified key or keys. Not specifying a
|
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
|
removes keys with any version number. Not specifying an
|
||||||
.Ar enctype
|
.Ar enctype
|
||||||
removes keys of any type.
|
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
|
Renames all entries in the keytab that match the
|
||||||
.Ar from-principal
|
.Ar from-principal
|
||||||
to
|
to
|
||||||
.Ar to-principal .
|
.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
|
Removes all old versions of a key for which there is a newer version
|
||||||
that is at least
|
that is at least
|
||||||
.Ar age
|
.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).
|
* (Royal Institute of Technology, Stockholm, Sweden).
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
@@ -32,6 +32,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ktutil_locl.h"
|
#include "ktutil_locl.h"
|
||||||
|
#include <heimbase.h>
|
||||||
#include <rtbl.h>
|
#include <rtbl.h>
|
||||||
|
|
||||||
RCSID("$Id$");
|
RCSID("$Id$");
|
||||||
@@ -131,7 +132,8 @@ do_list(struct list_options *opt, const char *keytab_str)
|
|||||||
struct rk_strpool *p = NULL;
|
struct rk_strpool *p = NULL;
|
||||||
|
|
||||||
for (i = 0; i< entry.aliases->len; i++) {
|
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,
|
p = rk_strpoolprintf(p, "%s%s", buf,
|
||||||
i + 1 < entry.aliases->len ? ", " : "");
|
i + 1 < entry.aliases->len ? ", " : "");
|
||||||
|
|
||||||
@@ -152,6 +154,137 @@ out:
|
|||||||
return ret;
|
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
|
int
|
||||||
kt_list(struct list_options *opt, int argc, char **argv)
|
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;
|
keytab_string = kt;
|
||||||
}
|
}
|
||||||
|
if (opt->json_flag)
|
||||||
|
return do_list_json(opt, keytab_string) != 0;
|
||||||
return do_list(opt, keytab_string) != 0;
|
return do_list(opt, keytab_string) != 0;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user