summaryrefslogtreecommitdiff
path: root/third_party/heimdal/appl/kf
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2022-01-19 13:15:45 +0100
committerJoseph Sutton <jsutton@samba.org>2022-01-19 21:41:59 +0000
commit7055827b8ffd3823c1240ba3f0b619dd6068cd51 (patch)
treeabb14aa7455bde7b1b33b706123c57ccfc28fcaa /third_party/heimdal/appl/kf
parent1954e50f266256c9e153c9613f49f9d9f5dbf67b (diff)
downloadsamba-7055827b8ffd3823c1240ba3f0b619dd6068cd51.tar.gz
HEIMDAL: move code from source4/heimdal* to third_party/heimdal*
This makes it clearer that we always want to do heimdal changes via the lorikeet-heimdal repository. Signed-off-by: Stefan Metzmacher <metze@samba.org> Reviewed-by: Joseph Sutton <josephsutton@catalyst.net.nz> Autobuild-User(master): Joseph Sutton <jsutton@samba.org> Autobuild-Date(master): Wed Jan 19 21:41:59 UTC 2022 on sn-devel-184
Diffstat (limited to 'third_party/heimdal/appl/kf')
-rw-r--r--third_party/heimdal/appl/kf/Makefile.am20
-rw-r--r--third_party/heimdal/appl/kf/NTMakefile35
-rw-r--r--third_party/heimdal/appl/kf/kf.1112
-rw-r--r--third_party/heimdal/appl/kf/kf.c347
-rw-r--r--third_party/heimdal/appl/kf/kf_locl.h81
-rw-r--r--third_party/heimdal/appl/kf/kfd.885
-rw-r--r--third_party/heimdal/appl/kf/kfd.c311
7 files changed, 991 insertions, 0 deletions
diff --git a/third_party/heimdal/appl/kf/Makefile.am b/third_party/heimdal/appl/kf/Makefile.am
new file mode 100644
index 00000000000..0b38057ca6d
--- /dev/null
+++ b/third_party/heimdal/appl/kf/Makefile.am
@@ -0,0 +1,20 @@
+# $Id$
+
+include $(top_srcdir)/Makefile.am.common
+
+bin_PROGRAMS = kf
+
+libexec_PROGRAMS = kfd
+
+man_MANS = kf.1 kfd.8
+
+kf_SOURCES = kf.c kf_locl.h
+
+kfd_SOURCES = kfd.c kf_locl.h
+
+LDADD = $(top_builddir)/lib/krb5/libkrb5.la \
+ $(LIB_hcrypto) \
+ $(top_builddir)/lib/asn1/libasn1.la \
+ $(LIB_roken)
+
+EXTRA_DIST = NTMakefile $(man_MANS)
diff --git a/third_party/heimdal/appl/kf/NTMakefile b/third_party/heimdal/appl/kf/NTMakefile
new file mode 100644
index 00000000000..6ade4ab9bfe
--- /dev/null
+++ b/third_party/heimdal/appl/kf/NTMakefile
@@ -0,0 +1,35 @@
+########################################################################
+#
+# 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=appl\kf
+
+!include ../../windows/NTMakefile.w32
+
diff --git a/third_party/heimdal/appl/kf/kf.1 b/third_party/heimdal/appl/kf/kf.1
new file mode 100644
index 00000000000..290e6bb5215
--- /dev/null
+++ b/third_party/heimdal/appl/kf/kf.1
@@ -0,0 +1,112 @@
+.\" Copyright (c) 2000 - 2001 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 July 2, 2000
+.Dt KF 1
+.Os
+.Sh NAME
+.Nm kf
+.Nd securely forward tickets
+.Sh SYNOPSIS
+.Nm
+.Oo
+.Fl p Ar port |
+.Fl Fl port Ns = Ns Ar port
+.Oc
+.Oo
+.Fl l Ar login |
+.Fl Fl login Ns = Ns Ar login
+.Oc
+.Oo
+.Fl c Ar ccache |
+.Fl Fl ccache Ns = Ns Ar ccache
+.Oc
+.Op Fl F | -forwardable
+.Op Fl G | -no-forwardable
+.Op Fl h | -help
+.Op Fl Fl version
+.Ar host ...
+.Sh DESCRIPTION
+The
+.Nm
+program forwards tickets to a remote host through an authenticated
+and encrypted stream.
+Options supported are:
+.Bl -tag -width indent
+.It Xo
+.Fl p Ar port ,
+.Fl Fl port Ns = Ns Ar port
+.Xc
+port to connect to
+.It Xo
+.Fl l Ar login ,
+.Fl Fl login Ns = Ns Ar login
+.Xc
+remote login name
+.It Xo
+.Fl c Ar ccache ,
+.Fl Fl ccache Ns = Ns Ar ccache
+.Xc
+remote cred cache
+.It Fl F , -forwardable
+forward forwardable credentials
+.It Fl G , -no-forwardable
+do not forward forwardable credentials
+.It Fl h , -help
+.It Fl Fl version
+.El
+.Pp
+.Nm
+is useful when you do not want to enter your password on a remote host
+but want to have your tickets one for example AFS.
+.Pp
+In order for
+.Nm
+to work you will need to acquire your initial ticket with forwardable
+flag, i.e.
+.Nm kinit Fl Fl forwardable .
+.Pp
+.Nm telnet
+is able to forward tickets by itself.
+.\".Sh ENVIRONMENT
+.\".Sh FILES
+.\".Sh EXAMPLES
+.\".Sh DIAGNOSTICS
+.Sh SEE ALSO
+.Xr kinit 1 ,
+.Xr telnet 1 ,
+.Xr kfd 8
+.\".Sh STANDARDS
+.\".Sh HISTORY
+.\".Sh AUTHORS
+.\".Sh BUGS
diff --git a/third_party/heimdal/appl/kf/kf.c b/third_party/heimdal/appl/kf/kf.c
new file mode 100644
index 00000000000..ecef93965ac
--- /dev/null
+++ b/third_party/heimdal/appl/kf/kf.c
@@ -0,0 +1,347 @@
+/*
+ * Copyright (c) 1997 - 2000, 2002 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 "kf_locl.h"
+RCSID("$Id$");
+
+krb5_context context;
+static int help_flag;
+static int version_flag;
+static char *port_str;
+const char *service = KF_SERVICE;
+const char *remote_name = NULL;
+int forwardable = 0;
+const char *ccache_name = NULL;
+
+static struct getargs args[] = {
+ { "port", 'p', arg_string, &port_str, "port to connect to", "port" },
+ { "login", 'l',arg_string, &remote_name,"remote login name","login"},
+ { "ccache", 'c',arg_string, &ccache_name, "remote cred cache","ccache"},
+ { "forwardable",'F',arg_flag,&forwardable,
+ "Forward forwardable credentials", NULL },
+ { "forwardable",'G',arg_negative_flag,&forwardable,
+ "Don't forward forwardable credentials", NULL },
+ { "help", 'h', arg_flag, &help_flag, NULL, NULL },
+ { "version", 0, arg_flag, &version_flag, NULL, NULL }
+};
+
+static int num_args = sizeof(args) / sizeof(args[0]);
+
+static void
+usage(int code, struct getargs *inargs, int num_inargs)
+{
+ arg_printusage(inargs, num_inargs, NULL, "hosts");
+ exit(code);
+}
+
+static int
+client_setup(krb5_context *ctx, int *argc, char **argv)
+{
+ int optidx = 0;
+ int port = 0;
+ int status;
+
+ setprogname (argv[0]);
+
+ status = krb5_init_context (ctx);
+ if (status)
+ errx(1, "krb5_init_context failed: %d", status);
+
+ forwardable = krb5_config_get_bool (*ctx, NULL,
+ "libdefaults",
+ "forwardable",
+ NULL);
+
+ if (getarg (args, num_args, *argc, argv, &optidx))
+ usage(1, args, num_args);
+
+ if(help_flag)
+ usage (0, args, num_args);
+ if(version_flag) {
+ print_version(NULL);
+ exit(0);
+ }
+
+ if(port_str) {
+ struct servent *s = roken_getservbyname(port_str, "tcp");
+ if(s)
+ port = s->s_port;
+ else {
+ char *ptr;
+
+ port = strtol (port_str, &ptr, 10);
+ if (port == 0 && ptr == port_str)
+ errx (1, "Bad port `%s'", port_str);
+ port = htons(port);
+ }
+ }
+
+ if (port == 0)
+ port = krb5_getportbyname (*ctx, KF_PORT_NAME, "tcp", KF_PORT_NUM);
+
+ if(*argc - optidx < 1)
+ usage(1, args, num_args);
+ *argc = optidx;
+
+ return port;
+}
+
+/*
+ * forward creds to `hostname'/`service' over `sock'
+ * return 0 iff OK
+ */
+
+static int
+proto (int sock, const char *hostname, const char *svc,
+ char *message, size_t len)
+{
+ krb5_auth_context auth_context;
+ krb5_error_code status;
+ krb5_principal server;
+ krb5_data data;
+ krb5_data data_send;
+
+ krb5_ccache ccache;
+ krb5_creds creds;
+ krb5_kdc_flags flags;
+ krb5_principal principal;
+
+ status = krb5_auth_con_init (context, &auth_context);
+ if (status) {
+ krb5_warn (context, status, "krb5_auth_con_init");
+ return 1;
+ }
+
+ status = krb5_auth_con_setaddrs_from_fd (context,
+ auth_context,
+ &sock);
+ if (status) {
+ krb5_auth_con_free(context, auth_context);
+ krb5_warn (context, status, "krb5_auth_con_setaddr");
+ return 1;
+ }
+
+ status = krb5_sname_to_principal (context,
+ hostname,
+ svc,
+ KRB5_NT_SRV_HST,
+ &server);
+ if (status) {
+ krb5_auth_con_free(context, auth_context);
+ krb5_warn (context, status, "krb5_sname_to_principal");
+ return 1;
+ }
+
+ status = krb5_sendauth (context,
+ &auth_context,
+ &sock,
+ KF_VERSION_1,
+ NULL,
+ server,
+ AP_OPTS_MUTUAL_REQUIRED | AP_OPTS_USE_SUBKEY,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ if (status) {
+ krb5_auth_con_free(context, auth_context);
+ krb5_warn(context, status, "krb5_sendauth");
+ return 1;
+ }
+
+ if (ccache_name == NULL)
+ ccache_name = "";
+
+ data_send.data = (void *)remote_name;
+ data_send.length = strlen(remote_name) + 1;
+ status = krb5_write_priv_message(context, auth_context, &sock, &data_send);
+ if (status) {
+ krb5_auth_con_free(context, auth_context);
+ krb5_warn (context, status, "krb5_write_message");
+ return 1;
+ }
+ data_send.data = (void *)ccache_name;
+ data_send.length = strlen(ccache_name)+1;
+ status = krb5_write_priv_message(context, auth_context, &sock, &data_send);
+ if (status) {
+ krb5_auth_con_free(context, auth_context);
+ krb5_warn (context, status, "krb5_write_message");
+ return 1;
+ }
+
+ memset (&creds, 0, sizeof(creds));
+
+ status = krb5_cc_default (context, &ccache);
+ if (status) {
+ krb5_auth_con_free(context, auth_context);
+ krb5_warn (context, status, "krb5_cc_default");
+ return 1;
+ }
+
+ status = krb5_cc_get_principal (context, ccache, &principal);
+ if (status) {
+ krb5_auth_con_free(context, auth_context);
+ krb5_warn (context, status, "krb5_cc_get_principal");
+ return 1;
+ }
+
+ creds.client = principal;
+
+ status = krb5_make_principal (context,
+ &creds.server,
+ principal->realm,
+ KRB5_TGS_NAME,
+ principal->realm,
+ NULL);
+
+ if (status) {
+ krb5_auth_con_free(context, auth_context);
+ krb5_warn (context, status, "krb5_make_principal");
+ return 1;
+ }
+
+ creds.times.endtime = 0;
+
+ flags.i = 0;
+ flags.b.forwarded = 1;
+ flags.b.forwardable = forwardable;
+
+ status = krb5_get_forwarded_creds (context,
+ auth_context,
+ ccache,
+ flags.i,
+ hostname,
+ &creds,
+ &data);
+ if (status) {
+ krb5_auth_con_free(context, auth_context);
+ krb5_warn (context, status, "krb5_get_forwarded_creds");
+ return 1;
+ }
+
+ status = krb5_write_priv_message(context, auth_context, &sock, &data);
+
+ if (status) {
+ krb5_auth_con_free(context, auth_context);
+ krb5_warn (context, status, "krb5_mk_priv");
+ return 1;
+ }
+
+ krb5_data_free (&data);
+
+ status = krb5_read_priv_message(context, auth_context, &sock, &data);
+ krb5_auth_con_free(context, auth_context);
+ if (status) {
+ krb5_warn (context, status, "krb5_mk_priv");
+ return 1;
+ }
+ if(data.length >= len) {
+ krb5_warnx (context, "returned string is too long, truncating");
+ memcpy(message, data.data, len);
+ message[len - 1] = '\0';
+ } else {
+ memcpy(message, data.data, data.length);
+ message[data.length] = '\0';
+ }
+ krb5_data_free (&data);
+
+ return strcmp(message, "ok") != 0;
+}
+
+static int
+doit (const char *hostname, int port, const char *svc,
+ char *message, size_t len)
+{
+ struct addrinfo *ai, *a;
+ struct addrinfo hints;
+ int error;
+ char portstr[NI_MAXSERV];
+
+ memset (&hints, 0, sizeof(hints));
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = IPPROTO_TCP;
+
+ snprintf (portstr, sizeof(portstr), "%u", ntohs(port));
+
+ error = getaddrinfo (hostname, portstr, &hints, &ai);
+ if (error) {
+ errx (1, "getaddrinfo(%s): %s", hostname, gai_strerror(error));
+ }
+
+ for (a = ai; a != NULL; a = a->ai_next) {
+ int s;
+
+ s = socket (a->ai_family, a->ai_socktype, a->ai_protocol);
+ if (s < 0)
+ continue;
+ if (connect (s, a->ai_addr, a->ai_addrlen) < 0) {
+ warn ("connect(%s)", hostname);
+ close (s);
+ continue;
+ }
+ freeaddrinfo (ai);
+ return proto (s, hostname, svc, message, len);
+ }
+ warnx ("failed to contact %s", hostname);
+ freeaddrinfo (ai);
+ return 1;
+}
+
+int
+main(int argc, char **argv)
+{
+ char userbuf[128];
+ int argcc,port,i;
+ int ret=0;
+
+ argcc = argc;
+ port = client_setup(&context, &argcc, argv);
+
+ if (remote_name == NULL) {
+ remote_name = roken_get_username(userbuf, sizeof(userbuf));
+ if (remote_name == NULL)
+ errx (1, "who are you?");
+ }
+
+ for (i = argcc;i < argc; i++) {
+ char message[128];
+ ret = doit (argv[i], port, service, message, sizeof(message));
+ if(ret == 0)
+ warnx ("%s: ok", argv[i]);
+ else
+ warnx ("%s: failed: %s", argv[i], message);
+ }
+ return(ret);
+}
diff --git a/third_party/heimdal/appl/kf/kf_locl.h b/third_party/heimdal/appl/kf/kf_locl.h
new file mode 100644
index 00000000000..3ddee48d692
--- /dev/null
+++ b/third_party/heimdal/appl/kf/kf_locl.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 1997 - 1999, 2002 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$ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <ctype.h>
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NETINET_IN6_H
+#include <netinet/in6.h>
+#endif
+#ifdef HAVE_NETINET6_IN6_H
+#include <netinet6/in6.h>
+#endif
+
+#ifdef HAVE_PWD_H
+#include <pwd.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#include <errno.h>
+#include <roken.h>
+#include <getarg.h>
+#include <err.h>
+#include <krb5.h>
+
+#define KF_SERVICE "host"
+
+#define KF_PORT_NAME "kf"
+#define KF_PORT_NUM 2110
+#define KF_VERSION_1 "KFWDV0.1"
diff --git a/third_party/heimdal/appl/kf/kfd.8 b/third_party/heimdal/appl/kf/kfd.8
new file mode 100644
index 00000000000..4b8b82299f9
--- /dev/null
+++ b/third_party/heimdal/appl/kf/kfd.8
@@ -0,0 +1,85 @@
+.\" Copyright (c) 2000 - 2002 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 July 2, 2000
+.Dt KFD 8
+.Os
+.Sh NAME
+.Nm kfd
+.Nd receive forwarded tickets
+.Sh SYNOPSIS
+.Nm
+.Oo
+.Fl p Ar port |
+.Fl Fl port Ns = Ns Ar port
+.Oc
+.Op Fl i | -inetd
+.Oo
+.Fl R Ar regpag |
+.Fl Fl regpag Ns = Ns Ar regpag
+.Oc
+.Op Fl h | -help
+.Op Fl Fl version
+.Sh DESCRIPTION
+This is the daemon for
+.Xr kf 1 .
+Supported options:
+.Bl -tag -width indent
+.It Xo
+.Fl p Ar port ,
+.Fl Fl port Ns = Ns Ar port
+.Xc
+port to listen to
+.It Fl i , -inetd
+not started from inetd
+.It Xo
+.Fl R Ar regpag ,
+.Fl Fl regpag= Ns Ar regpag
+.Xc
+path to regpag binary
+.El
+.\".Sh ENVIRONMENT
+.\".Sh FILES
+.Sh EXAMPLES
+Put the following in
+.Pa /etc/inetd.conf :
+.Bd -literal
+kf stream tcp nowait root /usr/heimdal/libexec/kfd kfd
+.Ed
+.\".Sh DIAGNOSTICS
+.Sh SEE ALSO
+.Xr kf 1
+.\".Sh STANDARDS
+.\".Sh HISTORY
+.\".Sh AUTHORS
+.\".Sh BUGS
diff --git a/third_party/heimdal/appl/kf/kfd.c b/third_party/heimdal/appl/kf/kfd.c
new file mode 100644
index 00000000000..9099bab9b87
--- /dev/null
+++ b/third_party/heimdal/appl/kf/kfd.c
@@ -0,0 +1,311 @@
+/*
+ * Copyright (c) 1997 - 2002 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 "kf_locl.h"
+RCSID("$Id$");
+
+krb5_context context;
+char krb5_tkfile[MAXPATHLEN];
+
+static int help_flag;
+static int version_flag;
+static char *port_str;
+char *service = KF_SERVICE;
+int do_inetd = 0;
+static char *regpag_str=NULL;
+
+static struct getargs args[] = {
+ { "port", 'p', arg_string, &port_str, "port to listen to", "port" },
+ { "inetd",'i',arg_flag, &do_inetd,
+ "Not started from inetd", NULL },
+ { "regpag",'R',arg_string,&regpag_str,"path to regpag binary","regpag"},
+ { "help", 'h', arg_flag, &help_flag, NULL, NULL },
+ { "version", 0, arg_flag, &version_flag, NULL, NULL }
+};
+
+static int num_args = sizeof(args) / sizeof(args[0]);
+
+static void
+usage(int code, struct getargs *inargs, int num_inargs)
+{
+ arg_printusage(inargs, num_inargs, NULL, "");
+ exit(code);
+}
+
+static int
+server_setup(krb5_context *ctx, int argc, char **argv)
+{
+ int port = 0;
+ int local_argc;
+
+ local_argc = krb5_program_setup(ctx, argc, argv, args, num_args, usage);
+
+ if(help_flag)
+ (*usage)(0, args, num_args);
+ if(version_flag) {
+ print_version(NULL);
+ exit(0);
+ }
+
+ if(port_str){
+ struct servent *s = roken_getservbyname(port_str, "tcp");
+ if(s)
+ port = s->s_port;
+ else {
+ char *ptr;
+
+ port = strtol (port_str, &ptr, 10);
+ if (port == 0 && ptr == port_str)
+ errx (1, "Bad port `%s'", port_str);
+ port = htons(port);
+ }
+ }
+
+ if (port == 0)
+ port = krb5_getportbyname (*ctx, KF_PORT_NAME, "tcp", KF_PORT_NUM);
+
+ if(argv[local_argc] != NULL)
+ usage(1, args, num_args);
+
+ return port;
+}
+
+static int protocol_version;
+
+static krb5_boolean
+kfd_match_version(const void *arg, const char *version)
+{
+ if(strcmp(version, KF_VERSION_1) == 0) {
+ protocol_version = 1;
+ return TRUE;
+ } else if (strlen(version) == 4 &&
+ version[0] == '0' &&
+ version[1] == '.' &&
+ (version[2] == '4' || version[2] == '3') &&
+ islower((unsigned char)version[3])) {
+ protocol_version = 0;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static int
+proto (int sock, const char *svc)
+{
+ krb5_auth_context auth_context;
+ krb5_error_code status;
+ krb5_principal server;
+ krb5_ticket *ticket;
+ char *name;
+ char ret_string[10];
+ char hostname[MAXHOSTNAMELEN];
+ krb5_data data;
+ krb5_data remotename;
+ krb5_data tk_file;
+ krb5_ccache ccache;
+ char ccname[MAXPATHLEN];
+ struct passwd *pwd;
+
+ status = krb5_auth_con_init (context, &auth_context);
+ if (status)
+ krb5_err(context, 1, status, "krb5_auth_con_init");
+
+ status = krb5_auth_con_setaddrs_from_fd (context,
+ auth_context,
+ &sock);
+ if (status)
+ krb5_err(context, 1, status, "krb5_auth_con_setaddr");
+
+ if(gethostname (hostname, sizeof(hostname)) < 0)
+ krb5_err(context, 1, errno, "gethostname");
+
+ status = krb5_sname_to_principal (context,
+ hostname,
+ svc,
+ KRB5_NT_SRV_HST,
+ &server);
+ if (status)
+ krb5_err(context, 1, status, "krb5_sname_to_principal");
+
+ status = krb5_recvauth_match_version (context,
+ &auth_context,
+ &sock,
+ kfd_match_version,
+ NULL,
+ server,
+ 0,
+ NULL,
+ &ticket);
+ if (status)
+ krb5_err(context, 1, status, "krb5_recvauth");
+
+ status = krb5_unparse_name (context,
+ ticket->client,
+ &name);
+ if (status)
+ krb5_err(context, 1, status, "krb5_unparse_name");
+
+ if(protocol_version == 0) {
+ data.data = "old clnt"; /* XXX old clients only had room for
+ 10 bytes of message, and also
+ didn't show it to the user */
+ data.length = strlen(data.data) + 1;
+ krb5_write_message(context, &sock, &data);
+ sleep(2); /* XXX give client time to finish */
+ krb5_errx(context, 1, "old client; exiting");
+ }
+
+ status=krb5_read_priv_message (context, auth_context,
+ &sock, &remotename);
+ if (status)
+ krb5_err(context, 1, status, "krb5_read_message");
+ status=krb5_read_priv_message (context, auth_context,
+ &sock, &tk_file);
+ if (status)
+ krb5_err(context, 1, status, "krb5_read_message");
+
+ krb5_data_zero (&data);
+
+ if(((char*)remotename.data)[remotename.length-1] != '\0')
+ krb5_errx(context, 1, "unterminated received");
+ if(((char*)tk_file.data)[tk_file.length-1] != '\0')
+ krb5_errx(context, 1, "unterminated received");
+
+ status = krb5_read_priv_message(context, auth_context, &sock, &data);
+
+ if (status) {
+ krb5_err(context, 1, errno, "krb5_read_priv_message");
+ goto out;
+ }
+
+ pwd = getpwnam ((char *)(remotename.data));
+ if (pwd == NULL) {
+ status=1;
+ krb5_warnx(context, "getpwnam: %s failed",(char *)(remotename.data));
+ goto out;
+ }
+
+ if(!krb5_kuserok (context,
+ ticket->client,
+ (char *)(remotename.data))) {
+ status=1;
+ krb5_warnx(context, "krb5_kuserok: permission denied");
+ goto out;
+ }
+
+ if (setgid(pwd->pw_gid) < 0) {
+ krb5_warn(context, errno, "setgid");
+ goto out;
+ }
+ if (setuid(pwd->pw_uid) < 0) {
+ krb5_warn(context, errno, "setuid");
+ goto out;
+ }
+
+ if (tk_file.length != 1)
+ snprintf (ccname, sizeof(ccname), "%s", (char *)(tk_file.data));
+ else
+ snprintf (ccname, sizeof(ccname), "FILE:/tmp/krb5cc_%lu",
+ (unsigned long)pwd->pw_uid);
+
+ status = krb5_cc_resolve (context, ccname, &ccache);
+ if (status) {
+ krb5_warn(context, status, "krb5_cc_resolve");
+ goto out;
+ }
+ status = krb5_cc_initialize (context, ccache, ticket->client);
+ if (status) {
+ krb5_warn(context, status, "krb5_cc_initialize");
+ goto out;
+ }
+ status = krb5_rd_cred2 (context, auth_context, ccache, &data);
+ krb5_cc_close (context, ccache);
+ if (status) {
+ krb5_warn(context, status, "krb5_rd_cred");
+ goto out;
+
+ }
+ strlcpy(krb5_tkfile,ccname,sizeof(krb5_tkfile));
+ krb5_warnx(context, "%s forwarded ticket to %s,%s",
+ name,
+ (char *)(remotename.data),ccname);
+ out:
+ if (status) {
+ strlcpy(ret_string, "no", sizeof(ret_string));
+ krb5_warnx(context, "failed");
+ } else {
+ strlcpy(ret_string, "ok", sizeof(ret_string));
+ }
+
+ krb5_data_free (&tk_file);
+ krb5_data_free (&remotename);
+ krb5_data_free (&data);
+ free(name);
+
+ data.data = ret_string;
+ data.length = strlen(ret_string) + 1;
+ status = krb5_write_priv_message(context, auth_context, &sock, &data);
+ krb5_auth_con_free(context, auth_context);
+
+ return status;
+}
+
+static int
+doit (int port, const char *svc)
+{
+ if (do_inetd)
+ mini_inetd(port, NULL);
+ return proto (STDIN_FILENO, svc);
+}
+
+int
+main(int argc, char **argv)
+{
+ int port;
+ int ret;
+ krb5_log_facility *fac;
+
+ setprogname (argv[0]);
+ roken_openlog (argv[0], LOG_ODELAY | LOG_PID,LOG_AUTH);
+ port = server_setup(&context, argc, argv);
+ ret = krb5_openlog(context, "kfd", &fac);
+ if(ret) krb5_err(context, 1, ret, "krb5_openlog");
+ ret = krb5_set_warn_dest(context, fac);
+ if(ret) krb5_err(context, 1, ret, "krb5_set_warn_dest");
+
+ ret = doit (port, service);
+ closelog();
+ if (ret == 0 && regpag_str != NULL)
+ ret = execl(regpag_str, "regpag", "-t", krb5_tkfile, "-r", NULL);
+ return ret;
+}