summaryrefslogtreecommitdiffstats
path: root/third_party/heimdal/admin
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/heimdal/admin')
-rw-r--r--third_party/heimdal/admin/ChangeLog70
-rw-r--r--third_party/heimdal/admin/Makefile.am44
-rw-r--r--third_party/heimdal/admin/NTMakefile75
-rw-r--r--third_party/heimdal/admin/add.c334
-rw-r--r--third_party/heimdal/admin/change.c297
-rw-r--r--third_party/heimdal/admin/copy.c150
-rw-r--r--third_party/heimdal/admin/destroy.c52
-rw-r--r--third_party/heimdal/admin/get.c269
-rw-r--r--third_party/heimdal/admin/ktutil-commands.in328
-rw-r--r--third_party/heimdal/admin/ktutil-version.rc36
-rw-r--r--third_party/heimdal/admin/ktutil.1229
-rw-r--r--third_party/heimdal/admin/ktutil.c177
-rw-r--r--third_party/heimdal/admin/ktutil_locl.h74
-rw-r--r--third_party/heimdal/admin/list.c306
-rw-r--r--third_party/heimdal/admin/purge.c172
-rw-r--r--third_party/heimdal/admin/remove.c93
-rw-r--r--third_party/heimdal/admin/rename.c113
17 files changed, 2819 insertions, 0 deletions
diff --git a/third_party/heimdal/admin/ChangeLog b/third_party/heimdal/admin/ChangeLog
new file mode 100644
index 0000000..1cdc153
--- /dev/null
+++ b/third_party/heimdal/admin/ChangeLog
@@ -0,0 +1,70 @@
+2006-10-07 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * Makefile.am: Add man_MANS to EXTRA_DIST
+
+ * Makefile.am: split build files into dist_ and noinst_ SOURCES
+
+2005-07-07 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * ktutil.c: rename optind to optidx
+
+ * list.c: make a copy of realm and admin_server to avoid
+ un-consting avoid shadowing
+
+ * get.c: make a copy of realm and admin_server to avoid
+ un-consting avoid shadowing
+
+ * change.c (change_entry): just use global context to avoid
+ shadowing; make a copy of realm and admin_server to avoid
+ un-consting.
+
+2005-05-19 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * change.c (kt_change): plug memory leak from
+ krb5_kt_remove_entry, print principal on error.
+
+2005-05-02 Dave Love <d.love@dl.ac.uk>
+
+ * ktutil.c (help): Don't use non-constant initializer for `fake'.
+
+2005-04-15 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * ktutil_locl.h: include <hex.h>
+
+2005-04-14 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * add.c: add option -H --hex to the add command
+
+ * ktutil-commands.in: add option -H --hex to the add command
+
+ * ktutil.8: document option -H --hex to the add command
+
+2004-09-29 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * list.c: un c99'ify, from Anders.Magnusson@ltu.se
+
+2004-09-23 Johan Danielsson <joda@pdc.kth.se>
+
+ * purge.c: convert to slc; don't purge keys older that a certain
+ time, instead purge keys that have newer versions that are at
+ least a certain age
+
+ * rename.c: convert to slc
+
+ * remove.c: convert to slc
+
+ * get.c: convert to slc; warn if resetting disallow-all-tix
+
+ * copy.c: convert to slc
+
+ * change.c: convert to slc
+
+ * add.c: convert to slc
+
+ * list.c: convert to slc
+
+ * ktutil_locl.h: convert to slc
+
+ * ktutil.c: convert to slc
+
+ * ktutil-commands.in: slc source file
diff --git a/third_party/heimdal/admin/Makefile.am b/third_party/heimdal/admin/Makefile.am
new file mode 100644
index 0000000..1821d4b
--- /dev/null
+++ b/third_party/heimdal/admin/Makefile.am
@@ -0,0 +1,44 @@
+# $Id$
+
+include $(top_srcdir)/Makefile.am.common
+
+AM_CPPFLAGS += $(INCLUDE_readline)
+
+man_MANS = ktutil.1
+
+bin_PROGRAMS = ktutil
+
+dist_ktutil_SOURCES = \
+ add.c \
+ change.c \
+ copy.c \
+ destroy.c \
+ get.c \
+ ktutil.c \
+ ktutil_locl.h \
+ list.c \
+ purge.c \
+ remove.c \
+ rename.c
+
+nodist_ktutil_SOURCES = \
+ ktutil-commands.c
+
+$(ktutil_OBJECTS): ktutil-commands.h
+
+CLEANFILES = ktutil-commands.h ktutil-commands.c
+
+ktutil-commands.c ktutil-commands.h: ktutil-commands.in
+ $(SLC) $(srcdir)/ktutil-commands.in
+
+LDADD = \
+ $(top_builddir)/lib/kadm5/libkadm5clnt.la \
+ $(top_builddir)/lib/krb5/libkrb5.la \
+ $(LIB_hcrypto) \
+ $(top_builddir)/lib/asn1/libasn1.la \
+ $(top_builddir)/lib/sl/libsl.la \
+ $(LIB_heimbase) \
+ $(LIB_readline) \
+ $(LIB_roken)
+
+EXTRA_DIST = NTMakefile ktutil-version.rc $(man_MANS) ktutil-commands.in
diff --git a/third_party/heimdal/admin/NTMakefile b/third_party/heimdal/admin/NTMakefile
new file mode 100644
index 0000000..f78a201
--- /dev/null
+++ b/third_party/heimdal/admin/NTMakefile
@@ -0,0 +1,75 @@
+########################################################################
+#
+# Copyright (c) 2009, Secure Endpoints Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# - Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# - Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+RELDIR=admin
+cincdirs=$(cincdirs) -I$(OBJ)
+!include ../windows/NTMakefile.w32
+
+SBINPROGRAMS=$(SBINDIR)\ktutil.exe
+
+KTUTIL_OBJS= \
+ $(OBJ)\add.obj \
+ $(OBJ)\change.obj \
+ $(OBJ)\copy.obj \
+ $(OBJ)\destroy.obj \
+ $(OBJ)\get.obj \
+ $(OBJ)\ktutil.obj \
+ $(OBJ)\ktutil-commands.obj \
+ $(OBJ)\list.obj \
+ $(OBJ)\purge.obj \
+ $(OBJ)\remove.obj \
+ $(OBJ)\rename.obj
+
+KTUTIL_LIBS= \
+ $(LIBHEIMBASE) \
+ $(LIBHEIMDAL) \
+ $(LIBKADM5SRV) \
+ $(LIBSL) \
+ $(LIBROKEN) \
+ $(LIBVERS)
+
+$(SBINDIR)\ktutil.exe: $(KTUTIL_OBJS) $(KTUTIL_LIBS) $(OBJ)\ktutil-version.res
+ $(EXECONLINK)
+ $(EXEPREP)
+
+$(OBJ)\ktutil-commands.c $(OBJ)\ktutil-commands.h: ktutil-commands.in
+ cd $(OBJ)
+ $(CP) $(SRCDIR)\ktutil-commands.in $(OBJ)
+ $(BINDIR)\slc.exe ktutil-commands.in
+ cd $(SRCDIR)
+
+INCFILES=\
+ $(OBJ)\ktutil-commands.h
+
+all:: $(INCFILES) $(SBINPROGRAMS)
+
+clean::
+ -$(RM) $(SBINPROGRAMS:.exe=.*)
diff --git a/third_party/heimdal/admin/add.c b/third_party/heimdal/admin/add.c
new file mode 100644
index 0000000..5f3d584
--- /dev/null
+++ b/third_party/heimdal/admin/add.c
@@ -0,0 +1,334 @@
+/*
+ * Copyright (c) 1997-2022 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "ktutil_locl.h"
+#include <heimbase.h>
+#include <base64.h>
+
+RCSID("$Id$");
+
+static char *
+readstring(const char *prompt, char *buf, size_t len)
+{
+ printf("%s", prompt);
+ if (fgets(buf, len, stdin) == NULL)
+ return NULL;
+ buf[strcspn(buf, "\r\n")] = '\0';
+ return buf;
+}
+
+int
+kt_add(struct add_options *opt, int argc, char **argv)
+{
+ krb5_error_code ret;
+ krb5_keytab keytab;
+ krb5_keytab_entry entry;
+ char buf[1024];
+ krb5_enctype enctype;
+
+ if((keytab = ktutil_open_keytab()) == NULL)
+ return 1;
+
+ memset(&entry, 0, sizeof(entry));
+ if(opt->principal_string == NULL) {
+ if(readstring("Principal: ", buf, sizeof(buf)) == NULL)
+ return 1;
+ opt->principal_string = buf;
+ }
+ ret = krb5_parse_name(context, opt->principal_string, &entry.principal);
+ if(ret) {
+ krb5_warn(context, ret, "%s", opt->principal_string);
+ goto out;
+ }
+ if(opt->enctype_string == NULL) {
+ if(readstring("Encryption type: ", buf, sizeof(buf)) == NULL) {
+ ret = 1;
+ goto out;
+ }
+ opt->enctype_string = buf;
+ }
+ ret = krb5_string_to_enctype(context, opt->enctype_string, &enctype);
+ if(ret) {
+ int t;
+ if(sscanf(opt->enctype_string, "%d", &t) == 1)
+ enctype = t;
+ else {
+ krb5_warn(context, ret, "%s", opt->enctype_string);
+ goto out;
+ }
+ }
+ if(opt->kvno_integer == -1) {
+ if(readstring("Key version: ", buf, sizeof(buf)) == NULL) {
+ ret = 1;
+ goto out;
+ }
+ if(sscanf(buf, "%u", &opt->kvno_integer) != 1)
+ goto out;
+ }
+ if(opt->password_string == NULL && opt->random_flag == 0) {
+ if(UI_UTIL_read_pw_string(buf, sizeof(buf), "Password: ",
+ UI_UTIL_FLAG_VERIFY)) {
+ ret = 1;
+ goto out;
+ }
+ opt->password_string = buf;
+ }
+ if(opt->password_string) {
+ if (opt->hex_flag) {
+ size_t len;
+ void *data;
+
+ len = (strlen(opt->password_string) + 1) / 2;
+
+ data = malloc(len);
+ if (data == NULL) {
+ krb5_warn(context, ENOMEM, "malloc");
+ goto out;
+ }
+
+ if ((size_t)hex_decode(opt->password_string, data, len) != len) {
+ free(data);
+ krb5_warn(context, ENOMEM, "hex decode failed");
+ goto out;
+ }
+
+ ret = krb5_keyblock_init(context, enctype,
+ data, len, &entry.keyblock);
+ free(data);
+ } else if (!opt->salt_flag) {
+ krb5_salt salt;
+ krb5_data pw;
+
+ salt.salttype = KRB5_PW_SALT;
+ salt.saltvalue.data = NULL;
+ salt.saltvalue.length = 0;
+ pw.data = (void*)opt->password_string;
+ pw.length = strlen(opt->password_string);
+ ret = krb5_string_to_key_data_salt(context, enctype, pw, salt,
+ &entry.keyblock);
+ } else {
+ ret = krb5_string_to_key(context, enctype, opt->password_string,
+ entry.principal, &entry.keyblock);
+ }
+ memset (opt->password_string, 0, strlen(opt->password_string));
+ } else {
+ ret = krb5_generate_random_keyblock(context, enctype, &entry.keyblock);
+ }
+ if(ret) {
+ krb5_warn(context, ret, "add");
+ goto out;
+ }
+ entry.vno = opt->kvno_integer;
+ entry.timestamp = time (NULL);
+ ret = krb5_kt_add_entry(context, keytab, &entry);
+ if(ret)
+ krb5_warn(context, ret, "add");
+ out:
+ krb5_kt_free_entry(context, &entry);
+ if (ret == 0) {
+ ret = krb5_kt_close(context, keytab);
+ if (ret)
+ krb5_warn(context, ret, "Could not write the keytab");
+ } else {
+ krb5_kt_close(context, keytab);
+ }
+ return ret != 0;
+}
+
+/* We might be reading from a pipe, so we can't use rk_undumpdata() */
+static char *
+read_file(FILE *f)
+{
+ size_t alloced;
+ size_t len = 0;
+ size_t bytes;
+ char *res, *end, *p;
+
+ if ((res = malloc(1024)) == NULL)
+ err(1, "Out of memory");
+ alloced = 1024;
+
+ end = res + alloced;
+ p = res;
+ do {
+ if (p == end) {
+ char *tmp;
+
+ if ((tmp = realloc(res, alloced + (alloced > 1))) == NULL)
+ err(1, "Out of memory");
+ alloced += alloced > 1;
+ p = tmp + len;
+ res = tmp;
+ end = res + alloced;
+ }
+ bytes = fread(p, 1, end - p, f);
+ len += bytes;
+ p += bytes;
+ } while (bytes && !feof(f) && !ferror(f));
+
+ if (ferror(f))
+ errx(1, "Could not read all input");
+ if (p == end) {
+ char *tmp;
+
+ if ((tmp = strndup(res, len)) == NULL)
+ err(1, "Out of memory");
+ free(res);
+ res = tmp;
+ }
+ if (strlen(res) != len)
+ err(1, "Embedded NULs in input!");
+ return res;
+}
+
+static void
+json2keytab_entry(heim_dict_t d, krb5_keytab kt, size_t idx)
+{
+ krb5_keytab_entry e;
+ krb5_error_code ret;
+ heim_object_t v;
+ uint64_t u;
+ int64_t i;
+ char *buf = NULL;
+
+ memset(&e, 0, sizeof(e));
+
+ v = heim_dict_get_value(d, HSTR("timestamp"));
+ if (heim_get_tid(v) != HEIM_TID_NUMBER)
+ goto bad;
+ u = heim_number_get_long(v);
+ e.timestamp = u;
+ if (u != (uint64_t)e.timestamp)
+ goto bad;
+
+ v = heim_dict_get_value(d, HSTR("kvno"));
+ if (heim_get_tid(v) != HEIM_TID_NUMBER)
+ goto bad;
+ i = heim_number_get_long(v);
+ e.vno = i;
+ if (i != (int64_t)e.vno)
+ goto bad;
+
+ v = heim_dict_get_value(d, HSTR("enctype_number"));
+ if (heim_get_tid(v) != HEIM_TID_NUMBER)
+ goto bad;
+ i = heim_number_get_long(v);
+ e.keyblock.keytype = i;
+ if (i != (int64_t)e.keyblock.keytype)
+ goto bad;
+
+ v = heim_dict_get_value(d, HSTR("key"));
+ if (heim_get_tid(v) != HEIM_TID_STRING)
+ goto bad;
+ {
+ const char *s = heim_string_get_utf8(v);
+ int declen;
+
+ if ((buf = malloc(strlen(s))) == NULL)
+ err(1, "Out of memory");
+ declen = rk_base64_decode(s, buf);
+ if (declen < 0)
+ goto bad;
+ e.keyblock.keyvalue.data = buf;
+ e.keyblock.keyvalue.length = declen;
+ }
+
+ v = heim_dict_get_value(d, HSTR("principal"));
+ if (heim_get_tid(v) != HEIM_TID_STRING)
+ goto bad;
+ ret = krb5_parse_name(context, heim_string_get_utf8(v), &e.principal);
+ if (ret == 0)
+ ret = krb5_kt_add_entry(context, kt, &e);
+
+ /* For now, ignore aliases; besides, they're never set anywhere in-tree */
+
+ if (ret)
+ krb5_warn(context, ret,
+ "Could not parse or write keytab entry %lu",
+ (unsigned long)idx);
+bad:
+ krb5_free_principal(context, e.principal);
+ free(buf);
+}
+
+int
+kt_import(void *opt, int argc, char **argv)
+{
+ krb5_error_code ret;
+ krb5_keytab kt;
+ heim_object_t o;
+ heim_error_t json_err = NULL;
+ heim_json_flags_t flags = HEIM_JSON_F_STRICT;
+ FILE *f = argc == 0 ? stdin : fopen(argv[0], "r");
+ size_t alen, i;
+ char *json;
+
+ if (f == NULL)
+ err(1, "Could not open file %s", argv[0]);
+
+ json = read_file(f);
+ fclose(f);
+ o = heim_json_create(json, 10, flags, &json_err);
+ free(json);
+ if (o == NULL) {
+ if (json_err != NULL) {
+ o = heim_error_copy_string(json_err);
+ if (o)
+ errx(1, "Could not parse JSON: %s", heim_string_get_utf8(o));
+ }
+ errx(1, "Could not parse JSON");
+ }
+
+ if (heim_get_tid(o) != HEIM_TID_ARRAY)
+ errx(1, "JSON text must be an array");
+
+ alen = heim_array_get_length(o);
+ if (alen == 0)
+ errx(1, "Empty JSON array; not overwriting keytab");
+
+ if ((kt = ktutil_open_keytab()) == NULL)
+ err(1, "Could not open keytab");
+
+ for (i = 0; i < alen; i++) {
+ heim_object_t e = heim_array_get_value(o, i);
+
+ if (heim_get_tid(e) != HEIM_TID_DICT)
+ warnx("Element %ld of JSON text array is not an object", (long)i);
+ else
+ json2keytab_entry(heim_array_get_value(o, i), kt, i);
+ }
+ ret = krb5_kt_close(context, kt);
+ if (ret)
+ krb5_warn(context, ret, "Could not write the keytab");
+ return ret != 0;
+}
diff --git a/third_party/heimdal/admin/change.c b/third_party/heimdal/admin/change.c
new file mode 100644
index 0000000..b9d0e83
--- /dev/null
+++ b/third_party/heimdal/admin/change.c
@@ -0,0 +1,297 @@
+/*
+ * Copyright (c) 1997-2005 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "ktutil_locl.h"
+
+RCSID("$Id$");
+
+static krb5_error_code
+change_entry(krb5_keytab keytab,
+ krb5_principal principal,
+ krb5_kvno kvno,
+ int keep,
+ size_t nkstuple,
+ krb5_key_salt_tuple *kstuple,
+ const char *realm,
+ const char *admin_server,
+ int server_port)
+{
+ krb5_error_code ret;
+ kadm5_config_params conf;
+ void *kadm_handle;
+ char *client_name;
+ krb5_keyblock *keys;
+ size_t i;
+ int num_keys;
+
+ ret = krb5_unparse_name (context, principal, &client_name);
+ if (ret) {
+ krb5_warn (context, ret, "krb5_unparse_name");
+ return ret;
+ }
+
+ memset (&conf, 0, sizeof(conf));
+
+ if(realm == NULL)
+ realm = krb5_principal_get_realm(context, principal);
+ conf.realm = strdup(realm);
+ if (conf.realm == NULL) {
+ free (client_name);
+ krb5_set_error_message(context, ENOMEM, "malloc failed");
+ return ENOMEM;
+ }
+ conf.mask |= KADM5_CONFIG_REALM;
+
+ if (admin_server) {
+ conf.admin_server = strdup(admin_server);
+ if (conf.admin_server == NULL) {
+ free(client_name);
+ free(conf.realm);
+ krb5_set_error_message(context, ENOMEM, "malloc failed");
+ return ENOMEM;
+ }
+ conf.mask |= KADM5_CONFIG_ADMIN_SERVER;
+ }
+
+ if (server_port) {
+ conf.kadmind_port = htons(server_port);
+ conf.mask |= KADM5_CONFIG_KADMIND_PORT;
+ }
+
+ ret = kadm5_init_with_skey_ctx (context,
+ client_name,
+ keytab_string,
+ KADM5_ADMIN_SERVICE,
+ &conf, 0, 0,
+ &kadm_handle);
+ free(conf.admin_server);
+ free(conf.realm);
+ if (ret) {
+ krb5_warn (context, ret,
+ "kadm5_c_init_with_skey_ctx: %s:", client_name);
+ free (client_name);
+ return ret;
+ }
+ ret = kadm5_randkey_principal_3(kadm_handle, principal, keep, nkstuple,
+ kstuple, &keys, &num_keys);
+ kadm5_destroy(kadm_handle);
+ if (ret) {
+ krb5_warn(context, ret, "kadm5_randkey_principal_3: %s:", client_name);
+ free (client_name);
+ return ret;
+ }
+ free(client_name);
+ for (i = 0; i < num_keys; ++i) {
+ krb5_keytab_entry new_entry;
+
+ new_entry.principal = principal;
+ new_entry.timestamp = time (NULL);
+ new_entry.vno = kvno + 1;
+ new_entry.keyblock = keys[i];
+
+ ret = krb5_kt_add_entry (context, keytab, &new_entry);
+ if (ret)
+ krb5_warn (context, ret, "krb5_kt_add_entry");
+ krb5_free_keyblock_contents (context, &keys[i]);
+ }
+ return ret;
+}
+
+/*
+ * loop over all the entries in the keytab (or those given) and change
+ * their keys, writing the new keys
+ */
+
+struct change_set {
+ krb5_principal principal;
+ krb5_kvno kvno;
+};
+
+int
+kt_change(struct change_options *opt, int argc, char **argv)
+{
+ krb5_error_code ret;
+ krb5_keytab keytab;
+ krb5_kt_cursor cursor;
+ krb5_keytab_entry entry;
+ krb5_key_salt_tuple *kstuple = NULL;
+ const char *enctype;
+ size_t i, j, max, nkstuple;
+ int keep = 1;
+ struct change_set *changeset;
+ int errors = 0;
+
+ i = 0;
+
+ if (opt->keepold_flag) {
+ keep = 1;
+ i++;
+ }
+ if (opt->keepallold_flag) {
+ keep = 2;
+ i++;
+ }
+ if (opt->pruneall_flag) {
+ keep = 0;
+ i++;
+ }
+ if (i > 1) {
+ fprintf(stderr, "use only one of --keepold, --keepallold, or --pruneall\n");
+ return EINVAL;
+ }
+
+ enctype = opt->enctype_string;
+ if (enctype == NULL || enctype[0] == '\0')
+ enctype = krb5_config_get_string(context, NULL, "libdefaults",
+ "supported_enctypes", NULL);
+ if (enctype == NULL || enctype[0] == '\0')
+ enctype = "aes128-cts-hmac-sha1-96";
+ ret = krb5_string_to_keysalts2(context, enctype, &nkstuple, &kstuple);
+ if (ret) {
+ fprintf(stderr, "enctype(s) unknown\n");
+ return ret;
+ }
+
+ /* XXX Parameterize keytab name */
+ if ((keytab = ktutil_open_keytab()) == NULL) {
+ free(kstuple);
+ return 1;
+ }
+
+ j = 0;
+ max = 0;
+ changeset = NULL;
+
+ ret = krb5_kt_start_seq_get(context, keytab, &cursor);
+ if(ret){
+ krb5_warn(context, ret, "%s", keytab_string);
+ goto out;
+ }
+
+ while((ret = krb5_kt_next_entry(context, keytab, &entry, &cursor)) == 0) {
+ int add = 0;
+
+ for (i = 0; i < j; ++i) {
+ if (krb5_principal_compare (context, changeset[i].principal,
+ entry.principal)) {
+ if (changeset[i].kvno < entry.vno)
+ changeset[i].kvno = entry.vno;
+ break;
+ }
+ }
+ if (i < j) {
+ krb5_kt_free_entry (context, &entry);
+ continue;
+ }
+
+ if (argc == 0) {
+ add = 1;
+ } else {
+ for (i = 0; i < argc; ++i) {
+ krb5_principal princ;
+
+ ret = krb5_parse_name (context, argv[i], &princ);
+ if (ret) {
+ krb5_warn (context, ret, "%s", argv[i]);
+ continue;
+ }
+ if (krb5_principal_compare (context, princ, entry.principal))
+ add = 1;
+
+ krb5_free_principal (context, princ);
+ }
+ }
+
+ if (add) {
+ if (j >= max) {
+ void *tmp;
+
+ max = max(max * 2, 1);
+ tmp = realloc (changeset, max * sizeof(*changeset));
+ if (tmp == NULL) {
+ krb5_kt_free_entry (context, &entry);
+ krb5_warnx (context, "realloc: out of memory");
+ ret = ENOMEM;
+ break;
+ }
+ changeset = tmp;
+ }
+ ret = krb5_copy_principal (context, entry.principal,
+ &changeset[j].principal);
+ if (ret) {
+ krb5_warn (context, ret, "krb5_copy_principal");
+ krb5_kt_free_entry (context, &entry);
+ break;
+ }
+ changeset[j].kvno = entry.vno;
+ ++j;
+ }
+ krb5_kt_free_entry (context, &entry);
+ }
+ krb5_kt_end_seq_get(context, keytab, &cursor);
+
+ if (ret == KRB5_KT_END) {
+ for (i = 0; i < j; i++) {
+ if (verbose_flag) {
+ char *client_name;
+
+ ret = krb5_unparse_name (context, changeset[i].principal,
+ &client_name);
+ if (ret) {
+ krb5_warn (context, ret, "krb5_unparse_name");
+ } else {
+ printf("Changing %s kvno %d\n",
+ client_name, changeset[i].kvno);
+ free(client_name);
+ }
+ }
+ ret = change_entry(keytab,
+ changeset[i].principal, changeset[i].kvno,
+ keep, nkstuple, kstuple,
+ opt->realm_string,
+ opt->admin_server_string,
+ opt->server_port_integer);
+ if (ret != 0)
+ errors = 1;
+ }
+ } else
+ errors = 1;
+ for (i = 0; i < j; i++)
+ krb5_free_principal (context, changeset[i].principal);
+ free (changeset);
+
+ out:
+ free(kstuple);
+ krb5_kt_close(context, keytab);
+ return errors;
+}
diff --git a/third_party/heimdal/admin/copy.c b/third_party/heimdal/admin/copy.c
new file mode 100644
index 0000000..8acd6e4
--- /dev/null
+++ b/third_party/heimdal/admin/copy.c
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 1997-2004 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "ktutil_locl.h"
+
+RCSID("$Id$");
+
+
+static krb5_boolean
+compare_keyblock(const krb5_keyblock *a, const krb5_keyblock *b)
+{
+ if(a->keytype != b->keytype ||
+ a->keyvalue.length != b->keyvalue.length ||
+ memcmp(a->keyvalue.data, b->keyvalue.data, a->keyvalue.length) != 0)
+ return FALSE;
+ return TRUE;
+}
+
+int
+kt_copy (struct copy_options *opt, int argc, char **argv)
+{
+ krb5_error_code ret;
+ krb5_keytab src_keytab, dst_keytab;
+ krb5_kt_cursor cursor;
+ krb5_keytab_entry entry, dummy;
+ const char *from = argv[0];
+ const char *to = argv[1];
+
+ ret = krb5_kt_resolve (context, from, &src_keytab);
+ if (ret) {
+ krb5_warn (context, ret, "resolving src keytab `%s'", from);
+ return 1;
+ }
+
+ ret = krb5_kt_resolve (context, to, &dst_keytab);
+ if (ret) {
+ krb5_kt_close (context, src_keytab);
+ krb5_warn (context, ret, "resolving dst keytab `%s'", to);
+ return 1;
+ }
+
+ ret = krb5_kt_start_seq_get (context, src_keytab, &cursor);
+ if (ret) {
+ krb5_warn (context, ret, "krb5_kt_start_seq_get %s", keytab_string);
+ goto out;
+ }
+
+ if (verbose_flag)
+ fprintf(stderr, "copying %s to %s\n", from, to);
+
+ while((ret = krb5_kt_next_entry(context, src_keytab,
+ &entry, &cursor)) == 0) {
+ char *name_str;
+ char *etype_str;
+ ret = krb5_unparse_name (context, entry.principal, &name_str);
+ if(ret) {
+ krb5_warn(context, ret, "krb5_unparse_name");
+ name_str = NULL; /* XXX */
+ }
+ ret = krb5_enctype_to_string(context, entry.keyblock.keytype, &etype_str);
+ if(ret) {
+ krb5_warn(context, ret, "krb5_enctype_to_string");
+ etype_str = NULL; /* XXX */
+ }
+ ret = krb5_kt_get_entry(context, dst_keytab,
+ entry.principal,
+ entry.vno,
+ entry.keyblock.keytype,
+ &dummy);
+ if(ret == 0) {
+ /* this entry is already in the new keytab, so no need to
+ copy it; if the keyblocks are not the same, something
+ is weird, so complain about that */
+ if(!compare_keyblock(&entry.keyblock, &dummy.keyblock)) {
+ krb5_warnx(context, "entry with different keyvalue "
+ "already exists for %s, keytype %s, kvno %d",
+ name_str, etype_str, entry.vno);
+ }
+ if (!opt->copy_duplicates_flag) {
+ krb5_kt_free_entry(context, &dummy);
+ krb5_kt_free_entry (context, &entry);
+ free(name_str);
+ free(etype_str);
+ continue;
+ }
+ /*
+ * Because we can end up trying all keys that match the enctype,
+ * copying entries with duplicate principal, vno, and enctype, but
+ * different keys, can be useful.
+ */
+ } else if(ret != KRB5_KT_NOTFOUND) {
+ krb5_warn (context, ret, "%s: fetching %s/%s/%u",
+ to, name_str, etype_str, entry.vno);
+ krb5_kt_free_entry (context, &entry);
+ free(name_str);
+ free(etype_str);
+ break;
+ }
+ if (verbose_flag)
+ fprintf (stderr, "copying %s, keytype %s, kvno %d\n", name_str,
+ etype_str, entry.vno);
+ ret = krb5_kt_add_entry (context, dst_keytab, &entry);
+ krb5_kt_free_entry (context, &entry);
+ if (ret) {
+ krb5_warn (context, ret, "%s: adding %s/%s/%u",
+ to, name_str, etype_str, entry.vno);
+ free(name_str);
+ free(etype_str);
+ break;
+ }
+ free(name_str);
+ free(etype_str);
+ }
+ krb5_kt_end_seq_get (context, src_keytab, &cursor);
+
+ out:
+ krb5_kt_close (context, src_keytab);
+ krb5_kt_close (context, dst_keytab);
+ return ret != 0;
+}
diff --git a/third_party/heimdal/admin/destroy.c b/third_party/heimdal/admin/destroy.c
new file mode 100644
index 0000000..0e989d9
--- /dev/null
+++ b/third_party/heimdal/admin/destroy.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2009 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "ktutil_locl.h"
+
+int
+kt_destroy (void *opt, int argc, char **argv)
+{
+ krb5_error_code ret;
+ krb5_keytab keytab;
+
+ if((keytab = ktutil_open_keytab()) == NULL)
+ return 1;
+
+ ret = krb5_kt_destroy (context, keytab);
+ if (ret) {
+ krb5_warn (context, ret, "destroy keytab failed");
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/third_party/heimdal/admin/get.c b/third_party/heimdal/admin/get.c
new file mode 100644
index 0000000..1c0a633
--- /dev/null
+++ b/third_party/heimdal/admin/get.c
@@ -0,0 +1,269 @@
+/*
+ * Copyright (c) 1997-2004 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "ktutil_locl.h"
+
+RCSID("$Id$");
+
+static void*
+open_kadmin_connection(char *principal,
+ const char *realm,
+ char *admin_server,
+ int server_port)
+{
+ static kadm5_config_params conf;
+ krb5_error_code ret;
+ void *kadm_handle;
+ memset(&conf, 0, sizeof(conf));
+
+ if(realm) {
+ conf.realm = strdup(realm);
+ if (conf.realm == NULL) {
+ krb5_set_error_message(context, 0, "malloc: out of memory");
+ return NULL;
+ }
+ conf.mask |= KADM5_CONFIG_REALM;
+ }
+
+ if (admin_server) {
+ conf.admin_server = admin_server;
+ conf.mask |= KADM5_CONFIG_ADMIN_SERVER;
+ }
+
+ if (server_port) {
+ conf.kadmind_port = htons(server_port);
+ conf.mask |= KADM5_CONFIG_KADMIND_PORT;
+ }
+
+ /* should get realm from each principal, instead of doing
+ everything with the same (local) realm */
+
+ ret = kadm5_init_with_password_ctx(context,
+ principal,
+ NULL,
+ KADM5_ADMIN_SERVICE,
+ &conf, 0, 0,
+ &kadm_handle);
+ free(conf.realm);
+ if(ret) {
+ krb5_warn(context, ret, "kadm5_init_with_password");
+ return NULL;
+ }
+ return kadm_handle;
+}
+
+static int
+parse_enctypes(struct get_options *opt,
+ size_t *nks,
+ krb5_key_salt_tuple **ks)
+{
+ const char *str;
+ char *s = NULL;
+ char *tmp;
+ size_t i;
+ int ret;
+
+ *nks = 0;
+ *ks = NULL;
+ if (opt->enctypes_strings.num_strings == 0) {
+ str = krb5_config_get_string(context, NULL, "libdefaults",
+ "supported_enctypes", NULL);
+ if (str == NULL)
+ str = "aes128-cts-hmac-sha1-96";
+ return krb5_string_to_keysalts2(context, str, nks, ks);
+ }
+
+ for (i = 0; i < opt->enctypes_strings.num_strings; i++) {
+ if (asprintf(&tmp, "%s%s%s", i ? s : "", i ? "," : "",
+ opt->enctypes_strings.strings[i]) == -1) {
+ free(s);
+ return krb5_enomem(context);
+ }
+ free(s);
+ s = tmp;
+ }
+ ret = krb5_string_to_keysalts2(context, s, nks, ks);
+ free(s);
+ return ret;
+}
+
+int
+kt_get(struct get_options *opt, int argc, char **argv)
+{
+ krb5_error_code ret = 0;
+ krb5_keytab keytab;
+ void *kadm_handle = NULL;
+ krb5_key_salt_tuple *ks = NULL;
+ size_t nks;
+ size_t i;
+ int a, j, keep;
+ unsigned int failed = 0;
+
+ i = 0;
+ keep = 1;
+ if (opt->keepallold_flag) {
+ keep = 2;
+ i++;
+ }
+ if (opt->keepold_flag) {
+ keep = 1;
+ i++;
+ }
+ if (opt->pruneall_flag) {
+ keep = 0;
+ i++;
+ }
+ if (i > 1) {
+ fprintf(stderr, "use only one of --keepold, --keepallold, or --pruneall\n");
+ return EINVAL;
+ }
+
+ if ((ret = parse_enctypes(opt, &nks, &ks))) {
+ fprintf(stderr, "invalid enctype(s)\n");
+ return ret;
+ }
+
+ if((keytab = ktutil_open_keytab()) == NULL) {
+ free(ks);
+ return 1;
+ }
+
+ if(opt->realm_string)
+ krb5_set_default_realm(context, opt->realm_string);
+
+ for(a = 0; a < argc; a++){
+ krb5_principal princ_ent;
+ kadm5_principal_ent_rec princ;
+ int mask = 0;
+ krb5_keyblock *keys;
+ int n_keys = 0;
+ int created = 0;
+ krb5_keytab_entry entry;
+
+ ret = krb5_parse_name(context, argv[a], &princ_ent);
+ if (ret) {
+ krb5_warn(context, ret, "can't parse principal %s", argv[a]);
+ failed++;
+ continue;
+ }
+ memset(&princ, 0, sizeof(princ));
+ princ.principal = princ_ent;
+ mask |= KADM5_PRINCIPAL;
+ princ.attributes |= KRB5_KDB_DISALLOW_ALL_TIX;
+ mask |= KADM5_ATTRIBUTES;
+ princ.princ_expire_time = 0;
+ mask |= KADM5_PRINC_EXPIRE_TIME;
+
+ if(kadm_handle == NULL) {
+ const char *r;
+ if(opt->realm_string != NULL)
+ r = opt->realm_string;
+ else
+ r = krb5_principal_get_realm(context, princ_ent);
+ kadm_handle = open_kadmin_connection(opt->principal_string,
+ r,
+ opt->admin_server_string,
+ opt->server_port_integer);
+ if(kadm_handle == NULL)
+ break;
+ }
+
+ if (opt->create_flag) {
+ ret = kadm5_create_principal(kadm_handle, &princ, mask, "thisIs_aUseless.password123");
+ if(ret == 0)
+ created = 1;
+ else if(ret != KADM5_DUP) {
+ krb5_warn(context, ret, "kadm5_create_principal(%s)", argv[a]);
+ krb5_free_principal(context, princ_ent);
+ failed++;
+ continue;
+ }
+ }
+ if (opt->change_keys_flag) {
+ ret = kadm5_randkey_principal_3(kadm_handle, princ_ent, keep, nks, ks,
+ &keys, &n_keys);
+ if (ret) {
+ krb5_warn(context, ret, "kadm5_randkey_principal(%s)", argv[a]);
+ krb5_free_principal(context, princ_ent);
+ failed++;
+ continue;
+ }
+ }
+
+ ret = kadm5_get_principal(kadm_handle, princ_ent, &princ,
+ KADM5_PRINCIPAL | KADM5_KVNO | KADM5_ATTRIBUTES);
+ if (ret) {
+ krb5_warn(context, ret, "kadm5_get_principal(%s)", argv[a]);
+ for (j = 0; j < n_keys; j++)
+ krb5_free_keyblock_contents(context, &keys[j]);
+ krb5_free_principal(context, princ_ent);
+ failed++;
+ continue;
+ }
+ if(!created && (princ.attributes & KRB5_KDB_DISALLOW_ALL_TIX))
+ krb5_warnx(context, "%s: disallow-all-tix flag set - clearing", argv[a]);
+ princ.attributes &= (~KRB5_KDB_DISALLOW_ALL_TIX);
+ mask = KADM5_ATTRIBUTES;
+ if(created) {
+ princ.kvno = 1;
+ mask |= KADM5_KVNO;
+ }
+ ret = kadm5_modify_principal(kadm_handle, &princ, mask);
+ if (ret) {
+ krb5_warn(context, ret, "kadm5_modify_principal(%s)", argv[a]);
+ for (j = 0; j < n_keys; j++)
+ krb5_free_keyblock_contents(context, &keys[j]);
+ krb5_free_principal(context, princ_ent);
+ failed++;
+ continue;
+ }
+ for(j = 0; j < n_keys; j++) {
+ entry.principal = princ_ent;
+ entry.vno = princ.kvno;
+ entry.keyblock = keys[j];
+ entry.timestamp = time (NULL);
+ ret = krb5_kt_add_entry(context, keytab, &entry);
+ if (ret)
+ krb5_warn(context, ret, "krb5_kt_add_entry");
+ krb5_free_keyblock_contents(context, &keys[j]);
+ }
+
+ kadm5_free_principal_ent(kadm_handle, &princ);
+ krb5_free_principal(context, princ_ent);
+ }
+ if (kadm_handle)
+ kadm5_destroy(kadm_handle);
+ krb5_kt_close(context, keytab);
+ free(ks);
+ return ret != 0 || failed > 0;
+}
diff --git a/third_party/heimdal/admin/ktutil-commands.in b/third_party/heimdal/admin/ktutil-commands.in
new file mode 100644
index 0000000..a85eb5c
--- /dev/null
+++ b/third_party/heimdal/admin/ktutil-commands.in
@@ -0,0 +1,328 @@
+/*
+ * Copyright (c) 2004-2022 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/* $Id$ */
+
+command = {
+ name = "add"
+ option = {
+ long = "principal"
+ short = "p"
+ type = "string"
+ help = "principal to add"
+ argument = "principal"
+ default = ""
+ }
+ option = {
+ long = "kvno"
+ short = "V"
+ type = "integer"
+ help = "key version number"
+ default = "-1"
+ }
+ option = {
+ long = "enctype"
+ short = "e"
+ type = "string"
+ argument = "enctype"
+ help = "encryption type(s)"
+ }
+ option = {
+ long = "password"
+ short = "w"
+ type = "string"
+ help = "password for key"
+ }
+ option = {
+ long = "salt"
+ short = "s"
+ type = "-flag"
+ help = "use unsalted keys"
+ default = "1"
+ }
+ option = {
+ long = "random"
+ short = "r"
+ type = "flag"
+ help = "generate random key"
+ }
+ option = {
+ long = "keepold"
+ type = "flag"
+ help = "keep old keys/password needed to decrypt extant tickets (default)"
+ }
+ option = {
+ long = "keepallold"
+ type = "flag"
+ help = "keep all old keys/password"
+ }
+ option = {
+ long = "pruneall"
+ type = "flag"
+ help = "delete all old keys"
+ }
+ option = {
+ long = "hex"
+ short = "H"
+ type = "flag"
+ help = "password is a hexadecimal string"
+ }
+ function = "kt_add"
+ help = "Adds a key to a keytab."
+ max_args = "0"
+}
+command = {
+ name = "change"
+ option = {
+ long = "realm"
+ short = "r"
+ type = "string"
+ argument = "realm"
+ help = "realm to use"
+ }
+ option = {
+ long = "enctype"
+ short = "e"
+ type = "string"
+ argument = "enctype"
+ help = "encryption type(s)"
+ }
+ option = {
+ long = "keepold"
+ type = "flag"
+ help = "keep old keys/password needed to decrypt extant tickets (default)"
+ }
+ option = {
+ long = "keepallold"
+ type = "flag"
+ help = "keep all old keys/password"
+ }
+ option = {
+ long = "pruneall"
+ type = "flag"
+ help = "delete all old keys"
+ }
+ option = {
+ long = "admin-server"
+ short = "a"
+ type = "string"
+ argument = "host"
+ help = "server to contact"
+ }
+ option = {
+ long = "server-port"
+ short = "s"
+ type = "integer"
+ argument = "port number"
+ help = "port number on server"
+ }
+ function = "kt_change"
+ argument = "[principal...]"
+ help = "Change keys for specified principals (default all)."
+}
+command = {
+ name = "copy"
+ name = "merge"
+ function = "kt_copy"
+ option = {
+ long = "copy-duplicates"
+ type = "flag"
+ help = "copy entries for the same principal and kvno, but different keys"
+ }
+ argument = "source destination"
+ min_args = "2"
+ max_args = "2"
+ help = "Merges one keytab into another."
+}
+command = {
+ name = "get"
+ option = {
+ long = "principal"
+ short = "p"
+ type = "string"
+ help = "admin principal"
+ argument = "principal"
+ }
+ option = {
+ long = "create"
+ type = "-flag"
+ help = "do not create the principal"
+ }
+ option = {
+ long = "change-keys"
+ type = "-flag"
+ help = "do not change the principal's keys"
+ }
+ option = {
+ long = "enctypes"
+ short = "e"
+ type = "strings"
+ help = "encryption types to use"
+ argument = "enctype"
+ }
+ option = {
+ long = "keepold"
+ type = "flag"
+ help = "keep old keys/password needed to decrypt extant tickets (default)"
+ }
+ option = {
+ long = "keepallold"
+ type = "flag"
+ help = "keep all old keys/password"
+ }
+ option = {
+ long = "pruneall"
+ type = "flag"
+ help = "delete all old keys"
+ }
+ option = {
+ long = "realm"
+ short = "r"
+ type = "string"
+ argument = "realm"
+ help = "realm to use"
+ }
+ option = {
+ long = "admin-server"
+ short = "a"
+ type = "string"
+ argument = "host"
+ help = "server to contact"
+ }
+ option = {
+ long = "server-port"
+ short = "s"
+ type = "integer"
+ argument = "port number"
+ help = "port number on server"
+ }
+ function = "kt_get"
+ min_args = "1"
+ argument = "principal..."
+ help = "Change keys for specified principals, and add them to the keytab."
+}
+command = {
+ name = "import"
+ function = "kt_import"
+ help = "Imports a keytab from JSON output of ktutil list --json --keys."
+ min_args = "0"
+ max_args = "1"
+ argument = "JSON-FILE"
+}
+command = {
+ name = "list"
+ option = {
+ long = "keys"
+ type = "flag"
+ help = "show key values"
+ }
+ option = {
+ long = "timestamp"
+ 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."
+}
+command = {
+ name = "purge"
+ option = {
+ long = "age"
+ type = "string"
+ help = "age to retiere"
+ default = "1 week";
+ argument = "time"
+ }
+ max_args = "0"
+ function = "kt_purge"
+ help = "Remove superceded keys from keytab."
+}
+command = {
+ name = "remove"
+ name = "delete"
+ option = {
+ long = "principal"
+ short = "p"
+ type = "string"
+ help = "principal to remove"
+ argument = "principal"
+ }
+ option = {
+ long = "kvno"
+ short = "V"
+ type = "integer"
+ help = "key version to remove"
+ argument = "kvno"
+ default = "0"
+ }
+ option = {
+ long = "enctype"
+ short = "e"
+ type = "string"
+ help = "enctype to remove"
+ argument = "enctype"
+ }
+ max_args = "0"
+ function = "kt_remove"
+ help = "Remove keys from keytab."
+}
+command = {
+ name = "rename"
+ function = "kt_rename"
+ argument = "from to"
+ min_args = "2"
+ max_args = "2"
+ help = "Renames an entry in the keytab."
+ option = {
+ long = "delete"
+ type = "-flag"
+ help = "don't delete orignal entry"
+ }
+}
+command = {
+ name = "destroy"
+ function = "kt_destroy"
+ max_args = "0"
+ help = "Destroy (remove) the keytab."
+}
+command = {
+ name = "help"
+ argument = "command"
+ max_args = "1"
+ function = "help"
+}
diff --git a/third_party/heimdal/admin/ktutil-version.rc b/third_party/heimdal/admin/ktutil-version.rc
new file mode 100644
index 0000000..e0e91c5
--- /dev/null
+++ b/third_party/heimdal/admin/ktutil-version.rc
@@ -0,0 +1,36 @@
+/***********************************************************************
+ * Copyright (c) 2010, Secure Endpoints Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ **********************************************************************/
+
+#define RC_FILE_TYPE VFT_APP
+#define RC_FILE_DESC_0409 "Kerberos Keytab Tool"
+#define RC_FILE_ORIG_0409 "ktutil.exe"
+
+#include "../windows/version.rc"
diff --git a/third_party/heimdal/admin/ktutil.1 b/third_party/heimdal/admin/ktutil.1
new file mode 100644
index 0000000..fb8bc38
--- /dev/null
+++ b/third_party/heimdal/admin/ktutil.1
@@ -0,0 +1,229 @@
+.\" Copyright (c) 1997-2004 Kungliga Tekniska Högskolan
+.\" (Royal Institute of Technology, Stockholm, Sweden).
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\"
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\"
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" 3. Neither the name of the Institute nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id$
+.\"
+.Dd April 14, 2005
+.Dt KTUTIL 1
+.Os HEIMDAL
+.Sh NAME
+.Nm ktutil
+.Nd manage Kerberos keytabs
+.Sh SYNOPSIS
+.Nm
+.Oo Fl k Ar keytab \*(Ba Xo
+.Fl Fl keytab= Ns Ar keytab
+.Xc
+.Oc
+.Op Fl v | Fl Fl verbose
+.Op Fl Fl version
+.Op Fl h | Fl Fl help
+.Ar command
+.Op Ar args
+.Sh DESCRIPTION
+.Nm
+is a program for managing keytabs.
+Supported options:
+.Bl -tag -width Ds
+.It Fl v , Fl Fl verbose
+Verbose output.
+.El
+.Pp
+.Ar command
+can be one of the following:
+.Bl -tag -width srvconvert
+.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 \
+Oo Fl Fl password= Ns Ar password Oc Oo Fl r Oc Oo Fl Fl random Oc \
+Oo Fl s Oc Oo Fl Fl no-salt Oc Oo Fl H Oc Op Fl Fl hex
+Adds a key to the keytab. Options that are not specified will be
+prompted for. This requires that you know the password or the hex key of the
+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 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 \
+Oo Fl Fl s Ar port Oc Op Fl Fl server-port= Ns Ar port
+Update one or several keys to new versions. By default, use the admin
+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 Nm copy Oo Fl Fl copy-duplicates Oc Ar keytab-src Ar keytab-dest
+Copies all the entries from
+.Ar keytab-src
+to
+.Ar keytab-dest .
+Because entries already in
+.Ar keytab-dest
+are kept, this command functions to merge keytabs.
+Entries for the same principal, key version number, and
+encryption type in the
+.Ar keytab-src
+that are also in the
+.Ar keytab-dest
+will not be copied to the
+.Ar keytab-dest
+unless the
+.Fl Fl copy-duplicates
+option is given.
+.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 no-create Oc \
+Oo Fl Fl no-change-keys 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 realm= Ns Ar realm Oc Oo Fl a Ar admin server Oc \
+Oo Fl Fl admin-server= Ns Ar admin server Oc Oo Fl s Ar server port Oc \
+Oo Fl Fl server-port= Ns Ar server port Oc Ar principal ...
+.Pp
+For each
+.Ar principal ,
+get a the principal's keys from the KDC via the kadmin protocol,
+creating the principal if it doesn't exist (unless
+.Fl Fl no-create
+is given), and changing its keys to new random keys (unless
+.Fl Fl no-change-keys
+is given).
+.Pp
+If no
+.Ar realm
+is specified, the realm to operate on is taken from the first
+principal.
+.It Nm import Oo JSON-FILE Oc
+Read an array of keytab entries in a JSON file and copy them to
+the keytab.
+Use the
+.Nm list
+command with its
+.Fl Fl json
+option
+and
+.Fl Fl keys
+option to export a keytab.
+.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.
+Use the
+.Fl Fl json
+and
+.Fl Fl keys
+options to export a keytab as JSON for importing with the
+.Nm import
+command.
+.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
+.Ar kvno
+removes keys with any version number. Not specifying an
+.Ar enctype
+removes keys of any type.
+.It Nm merge Oo Fl Fl copy-duplicates Oc Ar keytab-src Ar keytab-dest
+An alias for the
+.Nm copy
+command.
+.It Nm rename Ar from-principal Ar to-principal
+Renames all entries for the
+.Ar from-principal
+in the keytab
+.Ar from-principal
+to
+.Ar to-principal .
+.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
+(default one week) old.
+Note that this does not update the KDC database.
+The
+.Xr kadmin 1
+command has a
+.Nm prune
+command that can do this on the KDC side.
+.El
+.Sh ENVIRONMENT
+.Bl -tag -width Ds
+.It Ev KRB5_KTNAME
+Specifies the default keytab.
+.It Ev KRB5_CONFIG
+The file name of
+.Pa krb5.conf ,
+the default being
+.Pa /etc/krb5.conf .
+.El
+.Sh KEYTAB NAMING
+The syntax for the value of the
+.Ql KRB5_KTNAME
+environment variable and
+.Oo Fl k Ar keytab \*(Ba Xo
+.Fl Fl keytab= Ns Ar keytab
+.Xc
+.Oc
+options is
+.Ql TYPE:name
+where the TYPE is one of
+.Ql FILE ,
+.Ql HDBGET ,
+.Ql HDB ,
+or
+.Ql ANY ,
+and the name syntax is specific to the keytab type.
+.Pp
+For the FILE keytab type the name is the path to a file whose
+format is the well-known keytab file format used by MIT Kerberos,
+Heimdal, Java, and others.
+.Pp
+For the HDB and HDBGET keytab types the name syntax is
+.Ql [<path>][:mkey=<path>]
+where the first path is the path to the HDB and the second path
+is the path to the master key file.
+Note that to use the HDB and HDBGET keytab types in a program
+linked with Heimdal libraries one first load the
+.Ql libhdb
+library and then register their keytab methods using
+.Xr krb5_kt_register 3 .
+Note also that
+.Nm ktutil
+does not load and register the HDB and HDBGET keytab types at
+this time.
+.Pp
+The ANY keytab type name syntax is a sequence of other keytab
+names (including their TYPE: prefix) separated by commas.
+Note that there is no escape sequence for commas in keytab names.
+.Sh SEE ALSO
+.Xr kadmin 1
+.Xr kinit 1
+.Xr krb5_kt_register 3
diff --git a/third_party/heimdal/admin/ktutil.c b/third_party/heimdal/admin/ktutil.c
new file mode 100644
index 0000000..27d0d58
--- /dev/null
+++ b/third_party/heimdal/admin/ktutil.c
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 1997-2004 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "ktutil_locl.h"
+#include <err.h>
+
+RCSID("$Id$");
+
+static int help_flag;
+static int version_flag;
+int verbose_flag;
+char *keytab_string;
+static char keytab_buf[256];
+
+static struct getargs args[] = {
+ {
+ "version",
+ 0,
+ arg_flag,
+ &version_flag,
+ NULL,
+ NULL
+ },
+ {
+ "help",
+ 'h',
+ arg_flag,
+ &help_flag,
+ NULL,
+ NULL
+ },
+ {
+ "keytab",
+ 'k',
+ arg_string,
+ &keytab_string,
+ "keytab",
+ "keytab to operate on"
+ },
+ {
+ "verbose",
+ 'v',
+ arg_flag,
+ &verbose_flag,
+ "verbose",
+ "run verbosely"
+ }
+};
+
+static int num_args = sizeof(args) / sizeof(args[0]);
+
+krb5_context context;
+
+krb5_keytab
+ktutil_open_keytab(void)
+{
+ krb5_error_code ret;
+ krb5_keytab keytab;
+ if (keytab_string == NULL) {
+ ret = krb5_kt_default_name (context, keytab_buf, sizeof(keytab_buf));
+ if (ret) {
+ krb5_warn(context, ret, "krb5_kt_default_name");
+ return NULL;
+ }
+ keytab_string = keytab_buf;
+ }
+ ret = krb5_kt_resolve(context, keytab_string, &keytab);
+ if (ret) {
+ krb5_warn(context, ret, "resolving keytab %s", keytab_string);
+ return NULL;
+ }
+ if (verbose_flag)
+ fprintf (stderr, "Using keytab %s\n", keytab_string);
+
+ return keytab;
+}
+
+int
+help(void *opt, int argc, char **argv)
+{
+ if(argc == 0) {
+ sl_help(commands, 1, argv - 1 /* XXX */);
+ } else {
+ SL_cmd *c = sl_match (commands, argv[0], 0);
+ if(c == NULL) {
+ fprintf (stderr, "No such command: %s. "
+ "Try \"help\" for a list of commands\n",
+ argv[0]);
+ } else {
+ if(c->func) {
+ char shelp[] = "--help";
+ char *fake[3];
+ fake[0] = argv[0];
+ fake[1] = shelp;
+ fake[2] = NULL;
+ (*c->func)(2, fake);
+ fprintf(stderr, "\n");
+ }
+ if(c->help && *c->help)
+ fprintf (stderr, "%s\n", c->help);
+ if((++c)->name && c->func == NULL) {
+ int f = 0;
+ fprintf (stderr, "Synonyms:");
+ while (c->name && c->func == NULL) {
+ fprintf (stderr, "%s%s", f ? ", " : " ", (c++)->name);
+ f = 1;
+ }
+ fprintf (stderr, "\n");
+ }
+ }
+ }
+ return 0;
+}
+
+static void
+usage(int status)
+{
+ arg_printusage(args, num_args, NULL, "command");
+ exit(status);
+}
+
+int
+main(int argc, char **argv)
+{
+ int optidx = 0;
+ krb5_error_code ret;
+ setprogname(argv[0]);
+ ret = krb5_init_context(&context);
+ if (ret)
+ errx (1, "krb5_init_context failed: %d", ret);
+ if(getarg(args, num_args, argc, argv, &optidx))
+ usage(1);
+ if(help_flag)
+ usage(0);
+ if(version_flag) {
+ print_version(NULL);
+ exit(0);
+ }
+ argc -= optidx;
+ argv += optidx;
+ if(argc == 0)
+ usage(1);
+ ret = sl_command(commands, argc, argv);
+ if(ret == -1)
+ krb5_warnx (context, "unrecognized command: %s", argv[0]);
+ return ret;
+}
diff --git a/third_party/heimdal/admin/ktutil_locl.h b/third_party/heimdal/admin/ktutil_locl.h
new file mode 100644
index 0000000..9ecee31
--- /dev/null
+++ b/third_party/heimdal/admin/ktutil_locl.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 1997-2004 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * $Id$
+ */
+
+#ifndef __KTUTIL_LOCL_H__
+#define __KTUTIL_LOCL_H__
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <parse_time.h>
+#include <roken.h>
+
+#include "crypto-headers.h"
+#include <krb5.h>
+#include <kadm5/admin.h>
+#include <kadm5/kadm5_err.h>
+
+#include <sl.h>
+#include <getarg.h>
+#include <hex.h>
+
+extern krb5_context context;
+
+extern int verbose_flag;
+extern char *keytab_string;
+
+krb5_keytab ktutil_open_keytab(void);
+
+#include "ktutil-commands.h"
+
+#endif /* __KTUTIL_LOCL_H__ */
diff --git a/third_party/heimdal/admin/list.c b/third_party/heimdal/admin/list.c
new file mode 100644
index 0000000..22ccdca
--- /dev/null
+++ b/third_party/heimdal/admin/list.c
@@ -0,0 +1,306 @@
+/*
+ * Copyright (c) 1997-2022 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "ktutil_locl.h"
+#include <heimbase.h>
+#include <rtbl.h>
+
+RCSID("$Id$");
+
+static int
+do_list(struct list_options *opt, const char *keytab_str)
+{
+ krb5_error_code ret;
+ krb5_keytab keytab;
+ krb5_keytab_entry entry;
+ krb5_kt_cursor cursor;
+ rtbl_t table;
+
+ /* XXX specialcase the ANY type */
+ if(strncasecmp(keytab_str, "ANY:", 4) == 0) {
+ int flag = 0;
+ char buf[1024];
+ keytab_str += 4;
+ ret = 0;
+ while (strsep_copy((const char**)&keytab_str, ",",
+ buf, sizeof(buf)) != -1) {
+ if(flag)
+ printf("\n");
+ if(do_list(opt, buf))
+ ret = 1;
+ flag = 1;
+ }
+ return ret;
+ }
+
+ 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;
+ }
+
+ printf ("%s:\n\n", keytab_str);
+
+ table = rtbl_create();
+ rtbl_add_column_by_id(table, 0, "Vno", RTBL_ALIGN_RIGHT);
+ rtbl_add_column_by_id(table, 1, "Type", 0);
+ rtbl_add_column_by_id(table, 2, "Principal", 0);
+ if (opt->timestamp_flag)
+ rtbl_add_column_by_id(table, 3, "Date", 0);
+ if(opt->keys_flag)
+ rtbl_add_column_by_id(table, 4, "Key", 0);
+ rtbl_add_column_by_id(table, 5, "Aliases", 0);
+ rtbl_set_separator(table, " ");
+
+ while(krb5_kt_next_entry(context, keytab, &entry, &cursor) == 0){
+ char buf[1024], *s;
+
+ snprintf(buf, sizeof(buf), "%d", entry.vno);
+ rtbl_add_column_entry_by_id(table, 0, buf);
+
+ ret = krb5_enctype_to_string(context,
+ entry.keyblock.keytype, &s);
+ if (ret != 0) {
+ snprintf(buf, sizeof(buf), "unknown (%d)", entry.keyblock.keytype);
+ rtbl_add_column_entry_by_id(table, 1, buf);
+ } else {
+ rtbl_add_column_entry_by_id(table, 1, s);
+ free(s);
+ }
+
+ krb5_unparse_name_fixed(context, entry.principal, buf, sizeof(buf));
+ rtbl_add_column_entry_by_id(table, 2, buf);
+
+ if (opt->timestamp_flag) {
+ krb5_format_time(context, entry.timestamp, buf,
+ sizeof(buf), FALSE);
+ rtbl_add_column_entry_by_id(table, 3, buf);
+ }
+ if(opt->keys_flag) {
+ size_t i;
+ s = malloc(2 * entry.keyblock.keyvalue.length + 1);
+ if (s == NULL) {
+ krb5_warnx(context, "malloc failed");
+ ret = ENOMEM;
+ goto out;
+ }
+ for(i = 0; i < entry.keyblock.keyvalue.length; i++)
+ snprintf(s + 2 * i, 3, "%02x",
+ ((unsigned char*)entry.keyblock.keyvalue.data)[i]);
+ rtbl_add_column_entry_by_id(table, 4, s);
+ free(s);
+ }
+ if (entry.aliases) {
+ unsigned int i;
+ struct rk_strpool *p = NULL;
+
+ for (i = 0; i< entry.aliases->len; i++) {
+ krb5_unparse_name_fixed(context, &entry.aliases->val[i],
+ buf, sizeof(buf));
+ p = rk_strpoolprintf(p, "%s%s", buf,
+ i + 1 < entry.aliases->len ? ", " : "");
+
+ }
+ rtbl_add_column_entry_by_id(table, 5, (s = rk_strpoolcollect(p)));
+ free(s);
+ }
+
+ krb5_kt_free_entry(context, &entry);
+ }
+ ret = krb5_kt_end_seq_get(context, keytab, &cursor);
+ rtbl_format(table, stdout);
+
+out:
+ rtbl_destroy(table);
+
+ krb5_kt_close(context, keytab);
+ 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);
+ }
+
+ 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)
+{
+ krb5_error_code ret;
+ char kt[1024];
+
+ if(verbose_flag)
+ opt->timestamp_flag = 1;
+
+ if (keytab_string == NULL) {
+ if((ret = krb5_kt_default_name(context, kt, sizeof(kt))) != 0) {
+ krb5_warn(context, ret, "getting default keytab name");
+ return 1;
+ }
+ keytab_string = kt;
+ }
+ if (opt->json_flag)
+ return do_list_json(opt, keytab_string) != 0;
+ return do_list(opt, keytab_string) != 0;
+}
diff --git a/third_party/heimdal/admin/purge.c b/third_party/heimdal/admin/purge.c
new file mode 100644
index 0000000..b4667b3
--- /dev/null
+++ b/third_party/heimdal/admin/purge.c
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 1997-2004 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "ktutil_locl.h"
+
+RCSID("$Id$");
+
+/*
+ * keep track of the highest version for every principal.
+ */
+
+struct e {
+ krb5_principal principal;
+ int max_vno;
+ time_t timestamp;
+ struct e *next;
+};
+
+static struct e *
+get_entry (krb5_principal princ, struct e *head)
+{
+ struct e *e;
+
+ for (e = head; e != NULL; e = e->next)
+ if (krb5_principal_compare (context, princ, e->principal))
+ return e;
+ return NULL;
+}
+
+static void
+add_entry (krb5_principal princ, int vno, time_t timestamp, struct e **head)
+{
+ krb5_error_code ret;
+ struct e *e;
+
+ e = get_entry (princ, *head);
+ if (e != NULL) {
+ if(e->max_vno < vno) {
+ e->max_vno = vno;
+ e->timestamp = timestamp;
+ }
+ return;
+ }
+ e = malloc (sizeof (*e));
+ if (e == NULL)
+ krb5_errx (context, 1, "malloc: out of memory");
+ ret = krb5_copy_principal (context, princ, &e->principal);
+ if (ret)
+ krb5_err (context, 1, ret, "krb5_copy_principal");
+ e->max_vno = vno;
+ e->timestamp = timestamp;
+ e->next = *head;
+ *head = e;
+}
+
+static void
+delete_list (struct e *head)
+{
+ while (head != NULL) {
+ struct e *next = head->next;
+ krb5_free_principal (context, head->principal);
+ free (head);
+ head = next;
+ }
+}
+
+/*
+ * Remove all entries that have newer versions and that are older
+ * than `age'
+ */
+
+int
+kt_purge(struct purge_options *opt, int argc, char **argv)
+{
+ krb5_error_code ret = 0;
+ krb5_kt_cursor cursor;
+ krb5_keytab keytab;
+ krb5_keytab_entry entry;
+ int age;
+ struct e *head = NULL;
+ time_t judgement_day;
+
+ age = parse_time(opt->age_string, "s");
+ if(age < 0) {
+ krb5_warnx(context, "unparasable time `%s'", opt->age_string);
+ return 1;
+ }
+
+ if((keytab = ktutil_open_keytab()) == NULL)
+ return 1;
+
+ ret = krb5_kt_start_seq_get(context, keytab, &cursor);
+ if(ret){
+ krb5_warn(context, ret, "%s", keytab_string);
+ goto out;
+ }
+
+ while(krb5_kt_next_entry(context, keytab, &entry, &cursor) == 0) {
+ add_entry (entry.principal, entry.vno, entry.timestamp, &head);
+ krb5_kt_free_entry(context, &entry);
+ }
+ krb5_kt_end_seq_get(context, keytab, &cursor);
+
+ judgement_day = time (NULL);
+
+ ret = krb5_kt_start_seq_get(context, keytab, &cursor);
+ if(ret){
+ krb5_warn(context, ret, "%s", keytab_string);
+ goto out;
+ }
+
+ while(krb5_kt_next_entry(context, keytab, &entry, &cursor) == 0) {
+ struct e *e = get_entry (entry.principal, head);
+
+ if (e == NULL) {
+ krb5_warnx (context, "ignoring extra entry");
+ continue;
+ }
+
+ if (entry.vno < e->max_vno
+ && judgement_day - e->timestamp > age) {
+ if (verbose_flag) {
+ char *name_str;
+
+ krb5_unparse_name (context, entry.principal, &name_str);
+ printf ("removing %s vno %d\n", name_str, entry.vno);
+ free (name_str);
+ }
+ ret = krb5_kt_remove_entry (context, keytab, &entry);
+ if (ret)
+ krb5_warn (context, ret, "remove");
+ }
+ krb5_kt_free_entry(context, &entry);
+ }
+ ret = krb5_kt_end_seq_get(context, keytab, &cursor);
+
+ delete_list (head);
+
+ out:
+ krb5_kt_close (context, keytab);
+ return ret != 0;
+}
diff --git a/third_party/heimdal/admin/remove.c b/third_party/heimdal/admin/remove.c
new file mode 100644
index 0000000..7c30d88
--- /dev/null
+++ b/third_party/heimdal/admin/remove.c
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 1997-2004 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "ktutil_locl.h"
+
+RCSID("$Id$");
+
+int
+kt_remove(struct remove_options *opt, int argc, char **argv)
+{
+ krb5_error_code ret = 0;
+ krb5_keytab_entry entry;
+ krb5_keytab keytab;
+ krb5_principal principal = NULL;
+ krb5_enctype enctype = 0;
+
+ if(opt->principal_string) {
+ ret = krb5_parse_name(context, opt->principal_string, &principal);
+ if(ret) {
+ krb5_warn(context, ret, "%s", opt->principal_string);
+ return 1;
+ }
+ }
+ if(opt->enctype_string) {
+ ret = krb5_string_to_enctype(context, opt->enctype_string, &enctype);
+ if(ret) {
+ int t;
+ if(sscanf(opt->enctype_string, "%d", &t) == 1)
+ enctype = t;
+ else {
+ krb5_warn(context, ret, "%s", opt->enctype_string);
+ if(principal)
+ krb5_free_principal(context, principal);
+ return 1;
+ }
+ }
+ }
+ if (!principal && !enctype && !opt->kvno_integer) {
+ krb5_warnx(context,
+ "You must give at least one of "
+ "principal, enctype or kvno.");
+ ret = EINVAL;
+ goto out;
+ }
+
+ if((keytab = ktutil_open_keytab()) == NULL) {
+ ret = 1;
+ goto out;
+ }
+
+ entry.principal = principal;
+ entry.keyblock.keytype = enctype;
+ entry.vno = opt->kvno_integer;
+ ret = krb5_kt_remove_entry(context, keytab, &entry);
+ krb5_kt_close(context, keytab);
+ if(ret)
+ krb5_warn(context, ret, "remove");
+ out:
+ if(principal)
+ krb5_free_principal(context, principal);
+ return ret != 0;
+}
+
diff --git a/third_party/heimdal/admin/rename.c b/third_party/heimdal/admin/rename.c
new file mode 100644
index 0000000..390776d
--- /dev/null
+++ b/third_party/heimdal/admin/rename.c
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2001-2004 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "ktutil_locl.h"
+
+RCSID("$Id$");
+
+int
+kt_rename(struct rename_options *opt, int argc, char **argv)
+{
+ krb5_error_code ret = 0;
+ krb5_keytab_entry entry;
+ krb5_keytab keytab;
+ krb5_kt_cursor cursor;
+ krb5_principal from_princ, to_princ;
+
+ ret = krb5_parse_name(context, argv[0], &from_princ);
+ if(ret != 0) {
+ krb5_warn(context, ret, "%s", argv[0]);
+ return 1;
+ }
+
+ ret = krb5_parse_name(context, argv[1], &to_princ);
+ if(ret != 0) {
+ krb5_free_principal(context, from_princ);
+ krb5_warn(context, ret, "%s", argv[1]);
+ return 1;
+ }
+
+ if((keytab = ktutil_open_keytab()) == NULL) {
+ krb5_free_principal(context, from_princ);
+ krb5_free_principal(context, to_princ);
+ return 1;
+ }
+
+ ret = krb5_kt_start_seq_get(context, keytab, &cursor);
+ if(ret) {
+ krb5_kt_close(context, keytab);
+ krb5_free_principal(context, from_princ);
+ krb5_free_principal(context, to_princ);
+ return 1;
+ }
+ while(1) {
+ ret = krb5_kt_next_entry(context, keytab, &entry, &cursor);
+ if(ret != 0) {
+ if(ret != KRB5_CC_END && ret != KRB5_KT_END)
+ krb5_warn(context, ret, "getting entry from keytab");
+ else
+ ret = 0;
+ break;
+ }
+ if(krb5_principal_compare(context, entry.principal, from_princ)) {
+ krb5_free_principal(context, entry.principal);
+ entry.principal = to_princ;
+ ret = krb5_kt_add_entry(context, keytab, &entry);
+ if(ret) {
+ entry.principal = NULL;
+ krb5_kt_free_entry(context, &entry);
+ krb5_warn(context, ret, "adding entry");
+ break;
+ }
+ if (opt->delete_flag) {
+ entry.principal = from_princ;
+ ret = krb5_kt_remove_entry(context, keytab, &entry);
+ if(ret) {
+ entry.principal = NULL;
+ krb5_kt_free_entry(context, &entry);
+ krb5_warn(context, ret, "removing entry");
+ break;
+ }
+ }
+ entry.principal = NULL;
+ }
+ krb5_kt_free_entry(context, &entry);
+ }
+ krb5_kt_end_seq_get(context, keytab, &cursor);
+
+ krb5_free_principal(context, from_princ);
+ krb5_free_principal(context, to_princ);
+
+ return ret != 0;
+}
+