summaryrefslogtreecommitdiffstats
path: root/third_party/heimdal/appl/test
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/heimdal/appl/test')
-rw-r--r--third_party/heimdal/appl/test/Makefile.am46
-rw-r--r--third_party/heimdal/appl/test/NTMakefile35
-rw-r--r--third_party/heimdal/appl/test/common.c180
-rw-r--r--third_party/heimdal/appl/test/gss_common.c154
-rw-r--r--third_party/heimdal/appl/test/gss_common.h49
-rw-r--r--third_party/heimdal/appl/test/gssapi_client.c307
-rw-r--r--third_party/heimdal/appl/test/gssapi_server.c404
-rw-r--r--third_party/heimdal/appl/test/http_client.c517
-rw-r--r--third_party/heimdal/appl/test/jgssapi_server.java148
-rw-r--r--third_party/heimdal/appl/test/nt_gss_client.c167
-rw-r--r--third_party/heimdal/appl/test/nt_gss_common.c135
-rw-r--r--third_party/heimdal/appl/test/nt_gss_common.h45
-rw-r--r--third_party/heimdal/appl/test/nt_gss_server.c244
-rw-r--r--third_party/heimdal/appl/test/tcp_client.c132
-rw-r--r--third_party/heimdal/appl/test/tcp_server.c205
-rw-r--r--third_party/heimdal/appl/test/test_locl.h89
-rw-r--r--third_party/heimdal/appl/test/uu_client.c192
-rw-r--r--third_party/heimdal/appl/test/uu_server.c195
18 files changed, 3244 insertions, 0 deletions
diff --git a/third_party/heimdal/appl/test/Makefile.am b/third_party/heimdal/appl/test/Makefile.am
new file mode 100644
index 0000000..15ed68f
--- /dev/null
+++ b/third_party/heimdal/appl/test/Makefile.am
@@ -0,0 +1,46 @@
+# $Id$
+
+include $(top_srcdir)/Makefile.am.common
+
+WFLAGS += $(WFLAGS_LITE)
+
+noinst_PROGRAMS = tcp_client tcp_server gssapi_server gssapi_client \
+ uu_server uu_client nt_gss_server nt_gss_client http_client
+
+tcp_client_SOURCES = tcp_client.c common.c test_locl.h
+
+tcp_server_SOURCES = tcp_server.c common.c test_locl.h
+
+gssapi_server_SOURCES = gssapi_server.c gss_common.c common.c \
+ gss_common.h test_locl.h
+
+gssapi_client_SOURCES = gssapi_client.c gss_common.c common.c \
+ gss_common.h test_locl.h
+
+http_client_SOURCES = http_client.c gss_common.c common.c \
+ gss_common.h test_locl.h
+
+uu_server_SOURCES = uu_server.c common.c test_locl.h
+
+uu_client_SOURCES = uu_client.c common.c test_locl.h
+
+gssapi_server_LDADD = $(top_builddir)/lib/gssapi/libgssapi.la $(LDADD)
+
+gssapi_client_LDADD = $(gssapi_server_LDADD)
+
+http_client_LDADD = $(top_builddir)/lib/gssapi/libgssapi.la $(LDADD)
+
+nt_gss_client_SOURCES = nt_gss_client.c nt_gss_common.c nt_gss_common.h common.c
+
+nt_gss_server_SOURCES = nt_gss_server.c nt_gss_common.c nt_gss_common.h
+
+nt_gss_client_LDADD = $(gssapi_server_LDADD)
+
+nt_gss_server_LDADD = $(nt_gss_client_LDADD)
+
+LDADD = $(top_builddir)/lib/krb5/libkrb5.la \
+ $(LIB_hcrypto) \
+ $(top_builddir)/lib/asn1/libasn1.la \
+ $(LIB_roken)
+
+EXTRA_DIST = NTMakefile jgssapi_server.java
diff --git a/third_party/heimdal/appl/test/NTMakefile b/third_party/heimdal/appl/test/NTMakefile
new file mode 100644
index 0000000..15bea96
--- /dev/null
+++ b/third_party/heimdal/appl/test/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\test
+
+!include ../../windows/NTMakefile.w32
+
diff --git a/third_party/heimdal/appl/test/common.c b/third_party/heimdal/appl/test/common.c
new file mode 100644
index 0000000..3f0fc23
--- /dev/null
+++ b/third_party/heimdal/appl/test/common.c
@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) 1997 - 2000 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 "test_locl.h"
+
+static int help_flag;
+static int version_flag;
+static char *port_str;
+char *keytab_str;
+krb5_keytab keytab;
+char *service = SERVICE;
+char *mech = "krb5";
+int fork_flag;
+char *password = NULL;
+
+static struct getargs args[] = {
+ { "port", 'p', arg_string, &port_str, "port to listen to", "port" },
+ { "service", 's', arg_string, &service, "service to use", "service" },
+ { "keytab", 'k', arg_string, &keytab_str, "keytab to use", "keytab" },
+ { "mech", 'm', arg_string, &mech, "gssapi mech to use", "mech" },
+ { "password", 'P', arg_string, &password, "password to use", "password" },
+ { "fork", 'f', arg_flag, &fork_flag, "do fork", 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
+server_usage(int code, struct getargs *args, int num_args)
+{
+ arg_printusage(args, num_args, NULL, "");
+ exit(code);
+}
+
+static void
+client_usage(int code, struct getargs *args, int num_args)
+{
+ arg_printusage(args, num_args, NULL, "host");
+ exit(code);
+}
+
+
+static int
+common_setup(krb5_context *context, int *argc, char **argv,
+ void (*usage)(int, struct getargs*, int))
+{
+ int port = 0;
+ *argc = krb5_program_setup(context, *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 (*context, PORT, "tcp", 4711);
+
+ return port;
+}
+
+int
+server_setup(krb5_context *context, int argc, char **argv)
+{
+ int port = common_setup(context, &argc, argv, server_usage);
+ krb5_error_code ret;
+
+ if(argv[argc] != NULL)
+ server_usage(1, args, num_args);
+ if (keytab_str != NULL) {
+ ret = krb5_kt_resolve (*context, keytab_str, &keytab);
+ if (ret)
+ krb5_err (*context, 1, ret, "krb5_kt_resolve");
+ } else {
+ ret = krb5_kt_default (*context, &keytab);
+ if (ret)
+ krb5_err (*context, 1, ret, "krb5_kt_default");
+ }
+ return port;
+}
+
+int
+client_setup(krb5_context *context, int *argc, char **argv)
+{
+ int optind = *argc;
+ int port = common_setup(context, &optind, argv, client_usage);
+ if(*argc - optind != 1)
+ client_usage(1, args, num_args);
+ *argc = optind;
+ return port;
+}
+
+int
+client_doit (const char *hostname, int port, const char *service,
+ int (*func)(int, const char *hostname, const char *service))
+{
+ 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, "%s: %s", hostname, gai_strerror(error));
+ return -1;
+ }
+
+ 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;
+
+ socket_set_ipv6only(s, 1);
+
+ if (connect (s, a->ai_addr, a->ai_addrlen) < 0) {
+ warn ("connect(%s)", hostname);
+ close (s);
+ continue;
+ }
+ freeaddrinfo (ai);
+ return (*func) (s, hostname, service);
+ }
+ warnx ("failed to contact %s", hostname);
+ freeaddrinfo (ai);
+ return 1;
+}
diff --git a/third_party/heimdal/appl/test/gss_common.c b/third_party/heimdal/appl/test/gss_common.c
new file mode 100644
index 0000000..6a0eb77
--- /dev/null
+++ b/third_party/heimdal/appl/test/gss_common.c
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 1997 - 2000 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 "test_locl.h"
+#include <gssapi/gssapi.h>
+#include <gssapi/gssapi_krb5.h>
+#include <gssapi/gssapi_spnego.h>
+#include "gss_common.h"
+RCSID("$Id$");
+
+void
+write_token (int sock, gss_buffer_t buf)
+{
+ uint32_t len, net_len;
+ OM_uint32 min_stat;
+
+ len = buf->length;
+
+ net_len = htonl(len);
+
+ if (net_write (sock, &net_len, 4) != 4)
+ err (1, "write");
+ if (net_write (sock, buf->value, len) != len)
+ err (1, "write");
+
+ gss_release_buffer (&min_stat, buf);
+}
+
+static void
+enet_read(int fd, void *buf, size_t len)
+{
+ ssize_t ret;
+
+ ret = net_read (fd, buf, len);
+ if (ret == 0)
+ errx (1, "EOF in read");
+ else if (ret < 0)
+ errx (1, "read");
+}
+
+void
+read_token (int sock, gss_buffer_t buf)
+{
+ uint32_t len, net_len;
+
+ enet_read (sock, &net_len, 4);
+ len = ntohl(net_len);
+ buf->length = len;
+ buf->value = emalloc(len);
+ enet_read (sock, buf->value, len);
+}
+
+void
+gss_print_errors (int min_stat)
+{
+ OM_uint32 new_stat;
+ OM_uint32 msg_ctx = 0;
+ gss_buffer_desc status_string;
+ OM_uint32 ret;
+
+ do {
+ ret = gss_display_status (&new_stat,
+ min_stat,
+ GSS_C_MECH_CODE,
+ GSS_C_NO_OID,
+ &msg_ctx,
+ &status_string);
+ fprintf (stderr, "%.*s\n", (int)status_string.length,
+ (char *)status_string.value);
+ gss_release_buffer (&new_stat, &status_string);
+ } while (!GSS_ERROR(ret) && msg_ctx != 0);
+}
+
+void
+gss_verr(int exitval, int status, const char *fmt, va_list ap)
+{
+ vwarnx (fmt, ap);
+ gss_print_errors (status);
+ exit (exitval);
+}
+
+void
+gss_err(int exitval, int status, const char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ gss_verr (exitval, status, fmt, args);
+ va_end(args);
+}
+
+gss_OID
+select_mech(const char *mech)
+{
+ if (strcasecmp(mech, "krb5") == 0)
+ return GSS_KRB5_MECHANISM;
+ else if (strcasecmp(mech, "spnego") == 0)
+ return GSS_SPNEGO_MECHANISM;
+ else if (strcasecmp(mech, "no-oid") == 0)
+ return GSS_C_NO_OID;
+ else
+ errx (1, "Unknown mechanism '%s' (spnego, krb5, no-oid)", mech);
+}
+
+void
+print_gss_name(const char *prefix, gss_name_t name)
+{
+ OM_uint32 maj_stat, min_stat;
+ gss_buffer_desc name_token;
+
+ maj_stat = gss_display_name (&min_stat,
+ name,
+ &name_token,
+ NULL);
+ if (GSS_ERROR(maj_stat))
+ gss_err (1, min_stat, "gss_display_name");
+
+ fprintf (stderr, "%s `%.*s'\n", prefix,
+ (int)name_token.length,
+ (char *)name_token.value);
+
+ gss_release_buffer (&min_stat, &name_token);
+
+}
diff --git a/third_party/heimdal/appl/test/gss_common.h b/third_party/heimdal/appl/test/gss_common.h
new file mode 100644
index 0000000..eaab550
--- /dev/null
+++ b/third_party/heimdal/appl/test/gss_common.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 1997, 1998, 1999 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$ */
+
+void write_token (int sock, gss_buffer_t buf);
+void read_token (int sock, gss_buffer_t buf);
+
+void gss_print_errors (int min_stat);
+
+void gss_verr(int exitval, int status, const char *fmt, va_list ap)
+ __attribute__ ((format (printf, 3, 0)));
+
+void gss_err(int exitval, int status, const char *fmt, ...)
+ __attribute__ ((format (printf, 3, 4)));
+
+gss_OID select_mech(const char *);
+
+void print_gss_name(const char *, gss_name_t);
diff --git a/third_party/heimdal/appl/test/gssapi_client.c b/third_party/heimdal/appl/test/gssapi_client.c
new file mode 100644
index 0000000..13049c8
--- /dev/null
+++ b/third_party/heimdal/appl/test/gssapi_client.c
@@ -0,0 +1,307 @@
+/*
+ * Copyright (c) 1997 - 2000 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 "test_locl.h"
+#include <gssapi/gssapi.h>
+#include <gssapi/gssapi_krb5.h>
+#include <gssapi/gssapi_spnego.h>
+#include "gss_common.h"
+RCSID("$Id$");
+
+static int
+do_trans (int sock, gss_ctx_id_t context_hdl)
+{
+ OM_uint32 maj_stat, min_stat;
+ gss_buffer_desc real_input_token, real_output_token;
+ gss_buffer_t input_token = &real_input_token,
+ output_token = &real_output_token;
+ int conf_flag;
+
+ /* get_mic */
+
+ input_token->length = 3;
+ input_token->value = strdup("hej");
+
+ maj_stat = gss_get_mic(&min_stat,
+ context_hdl,
+ GSS_C_QOP_DEFAULT,
+ input_token,
+ output_token);
+ if (GSS_ERROR(maj_stat))
+ gss_err (1, min_stat, "gss_get_mic");
+
+ write_token (sock, input_token);
+ write_token (sock, output_token);
+
+ gss_release_buffer(&min_stat, output_token);
+
+ /* verify mic */
+
+ read_token (sock, input_token);
+ read_token (sock, output_token);
+
+ maj_stat = gss_verify_mic(&min_stat,
+ context_hdl,
+ input_token,
+ output_token,
+ NULL);
+ if (GSS_ERROR(maj_stat))
+ gss_err (1, min_stat, "gss_verify_mic");
+
+ gss_release_buffer (&min_stat, input_token);
+ gss_release_buffer (&min_stat, output_token);
+
+ /* wrap */
+
+ input_token->length = 7;
+ input_token->value = "hemligt";
+
+ maj_stat = gss_wrap (&min_stat,
+ context_hdl,
+ 0,
+ GSS_C_QOP_DEFAULT,
+ input_token,
+ NULL,
+ output_token);
+ if (GSS_ERROR(maj_stat))
+ gss_err (1, min_stat, "gss_wrap");
+
+ write_token (sock, output_token);
+
+ maj_stat = gss_wrap (&min_stat,
+ context_hdl,
+ 1,
+ GSS_C_QOP_DEFAULT,
+ input_token,
+ NULL,
+ output_token);
+ if (GSS_ERROR(maj_stat))
+ gss_err (1, min_stat, "gss_wrap");
+
+ write_token (sock, output_token);
+
+ read_token (sock, input_token);
+
+ maj_stat = gss_unwrap (&min_stat,
+ context_hdl,
+ input_token,
+ output_token,
+ &conf_flag,
+ NULL);
+ if(GSS_ERROR(maj_stat))
+ gss_err (1, min_stat, "gss_unwrap");
+
+ write_token (sock, output_token);
+
+ gss_release_buffer(&min_stat, output_token);
+
+ return 0;
+}
+
+extern char *password;
+
+static int
+proto (int sock, const char *hostname, const char *service)
+{
+ struct sockaddr_storage remote, local;
+ socklen_t addrlen;
+
+ int context_established = 0;
+ gss_ctx_id_t context_hdl = GSS_C_NO_CONTEXT;
+ gss_cred_id_t cred = GSS_C_NO_CREDENTIAL;
+ gss_buffer_desc real_input_token, real_output_token;
+ gss_buffer_t input_token = &real_input_token,
+ output_token = &real_output_token;
+ OM_uint32 maj_stat, min_stat;
+ gss_name_t server;
+ gss_buffer_desc name_token;
+ gss_OID mech_oid;
+ char *str;
+
+ mech_oid = select_mech(mech);
+
+ name_token.length = asprintf (&str,
+ "%s@%s", service, hostname);
+ if (str == NULL)
+ errx(1, "malloc - out of memory");
+ name_token.value = str;
+
+ maj_stat = gss_import_name (&min_stat,
+ &name_token,
+ GSS_C_NT_HOSTBASED_SERVICE,
+ &server);
+ if (GSS_ERROR(maj_stat))
+ gss_err (1, min_stat,
+ "Error importing name `%s@%s':\n", service, hostname);
+
+ if (password) {
+ gss_buffer_desc pw;
+
+ pw.value = password;
+ pw.length = strlen(password);
+
+ maj_stat = gss_acquire_cred_with_password(&min_stat,
+ GSS_C_NO_NAME,
+ &pw,
+ GSS_C_INDEFINITE,
+ GSS_C_NO_OID_SET,
+ GSS_C_INITIATE,
+ &cred,
+ NULL,
+ NULL);
+ if (GSS_ERROR(maj_stat))
+ gss_err (1, min_stat,
+ "Error acquiring default initiator credentials");
+ }
+
+ addrlen = sizeof(local);
+ if (getsockname (sock, (struct sockaddr *)&local, &addrlen) < 0
+ || addrlen > sizeof(local))
+ err (1, "getsockname(%s)", hostname);
+
+ addrlen = sizeof(remote);
+ if (getpeername (sock, (struct sockaddr *)&remote, &addrlen) < 0
+ || addrlen > sizeof(remote))
+ err (1, "getpeername(%s)", hostname);
+
+ input_token->length = 0;
+ output_token->length = 0;
+
+#if 0
+ struct gss_channel_bindings_struct input_chan_bindings;
+ u_char init_buf[4];
+ u_char acct_buf[4];
+
+ input_chan_bindings.initiator_addrtype = GSS_C_AF_INET;
+ input_chan_bindings.initiator_address.length = 4;
+ init_buf[0] = (local.sin_addr.s_addr >> 24) & 0xFF;
+ init_buf[1] = (local.sin_addr.s_addr >> 16) & 0xFF;
+ init_buf[2] = (local.sin_addr.s_addr >> 8) & 0xFF;
+ init_buf[3] = (local.sin_addr.s_addr >> 0) & 0xFF;
+ input_chan_bindings.initiator_address.value = init_buf;
+
+ input_chan_bindings.acceptor_addrtype = GSS_C_AF_INET;
+ input_chan_bindings.acceptor_address.length = 4;
+ acct_buf[0] = (remote.sin_addr.s_addr >> 24) & 0xFF;
+ acct_buf[1] = (remote.sin_addr.s_addr >> 16) & 0xFF;
+ acct_buf[2] = (remote.sin_addr.s_addr >> 8) & 0xFF;
+ acct_buf[3] = (remote.sin_addr.s_addr >> 0) & 0xFF;
+ input_chan_bindings.acceptor_address.value = acct_buf;
+
+ input_chan_bindings.application_data.value = emalloc(4);
+ * (unsigned short*)input_chan_bindings.application_data.value = local.sin_port;
+ * ((unsigned short *)input_chan_bindings.application_data.value + 1) = remote.sin_port;
+ input_chan_bindings.application_data.length = 4;
+
+ input_chan_bindings.application_data.length = 0;
+ input_chan_bindings.application_data.value = NULL;
+#endif
+
+ while(!context_established) {
+ maj_stat =
+ gss_init_sec_context(&min_stat,
+ cred,
+ &context_hdl,
+ server,
+ mech_oid,
+ GSS_C_MUTUAL_FLAG | GSS_C_SEQUENCE_FLAG,
+ 0,
+ NULL,
+ input_token,
+ NULL,
+ output_token,
+ NULL,
+ NULL);
+ if (GSS_ERROR(maj_stat))
+ gss_err (1, min_stat, "gss_init_sec_context");
+ if (output_token->length != 0)
+ write_token (sock, output_token);
+ if (GSS_ERROR(maj_stat)) {
+ if (context_hdl != GSS_C_NO_CONTEXT)
+ gss_delete_sec_context (&min_stat,
+ &context_hdl,
+ GSS_C_NO_BUFFER);
+ break;
+ }
+ if (maj_stat & GSS_S_CONTINUE_NEEDED) {
+ read_token (sock, input_token);
+ } else {
+ context_established = 1;
+ }
+
+ }
+ if (fork_flag) {
+ pid_t pid;
+ int pipefd[2];
+
+ if (pipe (pipefd) < 0)
+ err (1, "pipe");
+
+ pid = fork ();
+ if (pid < 0)
+ err (1, "fork");
+ if (pid != 0) {
+ gss_buffer_desc buf;
+
+ maj_stat = gss_export_sec_context (&min_stat,
+ &context_hdl,
+ &buf);
+ if (GSS_ERROR(maj_stat))
+ gss_err (1, min_stat, "gss_export_sec_context");
+ write_token (pipefd[1], &buf);
+ exit (0);
+ } else {
+ gss_ctx_id_t context_hdl;
+ gss_buffer_desc buf;
+
+ close (pipefd[1]);
+ read_token (pipefd[0], &buf);
+ close (pipefd[0]);
+ maj_stat = gss_import_sec_context (&min_stat, &buf, &context_hdl);
+ if (GSS_ERROR(maj_stat))
+ gss_err (1, min_stat, "gss_import_sec_context");
+ gss_release_buffer (&min_stat, &buf);
+ return do_trans (sock, context_hdl);
+ }
+ } else {
+ return do_trans (sock, context_hdl);
+ }
+}
+
+int
+main(int argc, char **argv)
+{
+ krb5_context context; /* XXX */
+ int port = client_setup(&context, &argc, argv);
+ return client_doit (argv[argc], port, service, proto);
+}
diff --git a/third_party/heimdal/appl/test/gssapi_server.c b/third_party/heimdal/appl/test/gssapi_server.c
new file mode 100644
index 0000000..74ceb3b
--- /dev/null
+++ b/third_party/heimdal/appl/test/gssapi_server.c
@@ -0,0 +1,404 @@
+/*
+ * Copyright (c) 1997 - 2000 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.
+ */
+
+/*
+ * A sample server that uses the GSSAPI.
+ */
+
+#include "test_locl.h"
+#include <gssapi/gssapi.h>
+#include <gssapi/gssapi_krb5.h>
+#include <gssapi/gssapi_spnego.h>
+#include "gss_common.h"
+
+static int
+process_it(int sock,
+ gss_ctx_id_t context_hdl,
+ gss_name_t client_name
+ )
+{
+ OM_uint32 maj_stat, min_stat;
+ gss_buffer_desc real_input_token, real_output_token;
+ gss_buffer_t input_token = &real_input_token,
+ output_token = &real_output_token;
+ gss_name_t server_name;
+ int conf_flag;
+
+ print_gss_name("User is", client_name);
+
+ maj_stat = gss_inquire_context(&min_stat,
+ context_hdl,
+ NULL,
+ &server_name,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ if (GSS_ERROR(maj_stat))
+ gss_err (1, min_stat, "gss_inquire_context");
+
+ print_gss_name("Server is", server_name);
+
+ maj_stat = gss_release_name(&min_stat, &server_name);
+ if (GSS_ERROR(maj_stat))
+ gss_err (1, min_stat, "gss_release_name");
+
+ /* gss_verify_mic */
+
+ read_token (sock, input_token);
+ read_token (sock, output_token);
+
+ maj_stat = gss_verify_mic (&min_stat,
+ context_hdl,
+ input_token,
+ output_token,
+ NULL);
+ if (GSS_ERROR(maj_stat))
+ gss_err (1, min_stat, "gss_verify_mic");
+
+ fprintf (stderr, "gss_verify_mic: %.*s\n", (int)input_token->length,
+ (char *)input_token->value);
+
+ gss_release_buffer (&min_stat, input_token);
+ gss_release_buffer (&min_stat, output_token);
+
+ /* create mic */
+
+ input_token->length = 6;
+ input_token->value = strdup("hejsan");
+
+ maj_stat = gss_get_mic(&min_stat,
+ context_hdl,
+ GSS_C_QOP_DEFAULT,
+ input_token,
+ output_token);
+ if (GSS_ERROR(maj_stat))
+ gss_err (1, min_stat, "gss_get_mic");
+
+ write_token (sock, input_token);
+ write_token (sock, output_token);
+
+ gss_release_buffer (&min_stat, output_token);
+
+ /* gss_unwrap */
+
+ read_token (sock, input_token);
+
+ maj_stat = gss_unwrap (&min_stat,
+ context_hdl,
+ input_token,
+ output_token,
+ &conf_flag,
+ NULL);
+ if(GSS_ERROR(maj_stat))
+ gss_err (1, min_stat, "gss_unwrap");
+
+ fprintf (stderr, "gss_unwrap: %.*s %s\n", (int)output_token->length,
+ (char *)output_token->value,
+ conf_flag ? "CONF" : "INT");
+
+ gss_release_buffer (&min_stat, input_token);
+ gss_release_buffer (&min_stat, output_token);
+
+ read_token (sock, input_token);
+
+ maj_stat = gss_unwrap (&min_stat,
+ context_hdl,
+ input_token,
+ output_token,
+ &conf_flag,
+ NULL);
+ if(GSS_ERROR(maj_stat))
+ gss_err (1, min_stat, "gss_unwrap");
+
+ fprintf (stderr, "gss_unwrap: %.*s %s\n", (int)output_token->length,
+ (char *)output_token->value,
+ conf_flag ? "CONF" : "INT");
+
+ gss_release_buffer (&min_stat, input_token);
+ gss_release_buffer (&min_stat, output_token);
+
+ input_token->value = "hejhej";
+ input_token->length = 6;
+
+ maj_stat = gss_wrap (&min_stat,
+ context_hdl,
+ 1,
+ GSS_C_QOP_DEFAULT,
+ input_token,
+ NULL,
+ output_token);
+ if (GSS_ERROR(maj_stat))
+ gss_err(1, min_stat, "gss_wrap");
+
+ write_token (sock, output_token);
+ gss_release_buffer (&min_stat, output_token);
+
+ read_token (sock, input_token);
+
+ if (input_token->length != 6 && memcmp(input_token->value, "hejhej", 6) != 0)
+ errx(1, "invalid reply");
+
+ return 0;
+}
+
+static int
+proto (int sock, const char *service)
+{
+ struct sockaddr_in remote, local;
+ socklen_t addrlen;
+ gss_ctx_id_t context_hdl = GSS_C_NO_CONTEXT;
+ gss_buffer_desc real_input_token, real_output_token;
+ gss_buffer_t input_token = &real_input_token,
+ output_token = &real_output_token;
+ OM_uint32 maj_stat, min_stat;
+ gss_name_t client_name;
+ struct gss_channel_bindings_struct input_chan_bindings;
+ gss_cred_id_t delegated_cred_handle = NULL;
+ krb5_ccache ccache = NULL;
+ u_char init_buf[4];
+ u_char acct_buf[4];
+ gss_OID mech_oid;
+ char *mech, *p;
+
+ memset(&remote, 0, sizeof(remote));
+ local = remote;
+
+ addrlen = sizeof(local);
+ if (getsockname (sock, (struct sockaddr *)&local, &addrlen) < 0
+ || addrlen != sizeof(local))
+ err (1, "getsockname)");
+
+ addrlen = sizeof(remote);
+ if (getpeername (sock, (struct sockaddr *)&remote, &addrlen) < 0
+ || addrlen != sizeof(remote))
+ err (1, "getpeername");
+
+ input_chan_bindings.initiator_addrtype = GSS_C_AF_INET;
+ input_chan_bindings.initiator_address.length = 4;
+ init_buf[0] = (remote.sin_addr.s_addr >> 24) & 0xFF;
+ init_buf[1] = (remote.sin_addr.s_addr >> 16) & 0xFF;
+ init_buf[2] = (remote.sin_addr.s_addr >> 8) & 0xFF;
+ init_buf[3] = (remote.sin_addr.s_addr >> 0) & 0xFF;
+
+ input_chan_bindings.initiator_address.value = init_buf;
+ input_chan_bindings.acceptor_addrtype = GSS_C_AF_INET;
+
+ input_chan_bindings.acceptor_address.length = 4;
+ acct_buf[0] = (local.sin_addr.s_addr >> 24) & 0xFF;
+ acct_buf[1] = (local.sin_addr.s_addr >> 16) & 0xFF;
+ acct_buf[2] = (local.sin_addr.s_addr >> 8) & 0xFF;
+ acct_buf[3] = (local.sin_addr.s_addr >> 0) & 0xFF;
+ input_chan_bindings.acceptor_address.value = acct_buf;
+ input_chan_bindings.application_data.value = emalloc(4);
+#if 0
+ * (unsigned short *)input_chan_bindings.application_data.value =
+ remote.sin_port;
+ * ((unsigned short *)input_chan_bindings.application_data.value + 1) =
+ local.sin_port;
+ input_chan_bindings.application_data.length = 4;
+#else
+ input_chan_bindings.application_data.length = 0;
+ input_chan_bindings.application_data.value = NULL;
+#endif
+
+ delegated_cred_handle = GSS_C_NO_CREDENTIAL;
+
+ do {
+ read_token (sock, input_token);
+ maj_stat =
+ gss_accept_sec_context (&min_stat,
+ &context_hdl,
+ GSS_C_NO_CREDENTIAL,
+ input_token,
+ &input_chan_bindings,
+ &client_name,
+ &mech_oid,
+ output_token,
+ NULL,
+ NULL,
+ &delegated_cred_handle);
+ if(GSS_ERROR(maj_stat))
+ gss_err (1, min_stat, "gss_accept_sec_context");
+ if (output_token->length != 0)
+ write_token (sock, output_token);
+ if (GSS_ERROR(maj_stat)) {
+ if (context_hdl != GSS_C_NO_CONTEXT)
+ gss_delete_sec_context (&min_stat,
+ &context_hdl,
+ GSS_C_NO_BUFFER);
+ break;
+ }
+ } while(maj_stat & GSS_S_CONTINUE_NEEDED);
+
+ p = (char *)mech_oid->elements;
+ if (mech_oid->length == GSS_KRB5_MECHANISM->length
+ && memcmp(p, GSS_KRB5_MECHANISM->elements, mech_oid->length) == 0)
+ mech = "Kerberos 5";
+ else if (mech_oid->length == GSS_SPNEGO_MECHANISM->length
+ && memcmp(p, GSS_SPNEGO_MECHANISM->elements, mech_oid->length) == 0)
+ mech = "SPNEGO"; /* XXX Silly, wont show up */
+ else
+ mech = "Unknown";
+
+ printf("Using mech: %s\n", mech);
+
+ if (delegated_cred_handle != GSS_C_NO_CREDENTIAL) {
+ krb5_context context = NULL;
+
+ printf("Delegated cred found\n");
+
+ min_stat = krb5_init_context(&context);
+ if (min_stat)
+ gss_err(1, min_stat, "krb5_init_context");
+ if (min_stat == 0)
+ min_stat = krb5_cc_resolve(context, "FILE:/tmp/krb5cc_test", &ccache);
+ if (min_stat == 0)
+ maj_stat = gss_krb5_copy_ccache(&min_stat,
+ delegated_cred_handle,
+ ccache);
+ else
+ maj_stat = GSS_S_FAILURE;
+ if (maj_stat == 0) {
+ krb5_principal p;
+ maj_stat = krb5_cc_get_principal(context, ccache, &p);
+ if (maj_stat == 0) {
+ char *name;
+ maj_stat = krb5_unparse_name(context, p, &name);
+ if (maj_stat == 0) {
+ printf("Delegated user is: `%s'\n", name);
+ free(name);
+ }
+ krb5_free_principal(context, p);
+ }
+ }
+ krb5_cc_close(context, ccache);
+ krb5_free_context(context);
+ gss_release_cred(&min_stat, &delegated_cred_handle);
+ }
+
+ if (fork_flag) {
+ pid_t pid;
+ int pipefd[2];
+
+ if (pipe (pipefd) < 0)
+ err (1, "pipe");
+
+ pid = fork ();
+ if (pid < 0)
+ err (1, "fork");
+ if (pid != 0) {
+ gss_buffer_desc buf;
+
+ maj_stat = gss_export_sec_context (&min_stat,
+ &context_hdl,
+ &buf);
+ if (GSS_ERROR(maj_stat))
+ gss_err (1, min_stat, "gss_export_sec_context");
+ write_token (pipefd[1], &buf);
+ exit (0);
+ } else {
+ gss_ctx_id_t context_hdl;
+ gss_buffer_desc buf;
+
+ close (pipefd[1]);
+ read_token (pipefd[0], &buf);
+ close (pipefd[0]);
+ maj_stat = gss_import_sec_context (&min_stat, &buf, &context_hdl);
+ if (GSS_ERROR(maj_stat))
+ gss_err (1, min_stat, "gss_import_sec_context");
+ gss_release_buffer (&min_stat, &buf);
+ return process_it (sock, context_hdl, client_name);
+ }
+ } else {
+ return process_it (sock, context_hdl, client_name);
+ }
+}
+
+static void
+loop (int port, const char *service)
+{
+ int sock, sock2;
+ struct sockaddr_in my_addr;
+ int one = 1;
+
+ if (keytab_str)
+ gsskrb5_register_acceptor_identity(keytab_str);
+
+ sock = socket (AF_INET, SOCK_STREAM, 0);
+ if (sock < 0)
+ err (1, "socket");
+
+ memset (&my_addr, 0, sizeof(my_addr));
+ my_addr.sin_family = AF_INET;
+ my_addr.sin_port = port;
+ my_addr.sin_addr.s_addr = INADDR_ANY;
+
+ if (setsockopt (sock, SOL_SOCKET, SO_REUSEADDR,
+ (void *)&one, sizeof(one)) < 0)
+ warn ("setsockopt SO_REUSEADDR");
+
+ if (bind (sock, (struct sockaddr *)&my_addr, sizeof(my_addr)) < 0)
+ err (1, "bind");
+
+ while (1) {
+ if (listen (sock, 1) < 0)
+ err (1, "listen");
+
+ sock2 = accept (sock, NULL, NULL);
+ if (sock2 < 0)
+ err (1, "accept");
+
+ proto (sock2, service);
+ }
+}
+
+/*
+ * Iterative server; process one connection at a time.
+ */
+int
+main(int argc, char **argv)
+{
+ krb5_context context = NULL; /* XXX */
+ krb5_error_code ret;
+ int port = server_setup(&context, argc, argv);
+
+ ret = krb5_kt_have_content(context, keytab);
+ if (ret)
+ krb5_err (context, 1, ret, "krb5_kt_have_content");
+
+ loop (port, service);
+ return 0;
+}
+
diff --git a/third_party/heimdal/appl/test/http_client.c b/third_party/heimdal/appl/test/http_client.c
new file mode 100644
index 0000000..88a8fee
--- /dev/null
+++ b/third_party/heimdal/appl/test/http_client.c
@@ -0,0 +1,517 @@
+/*
+ * Copyright (c) 2003 - 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 "test_locl.h"
+#include <gssapi/gssapi.h>
+#include <gssapi/gssapi_krb5.h>
+#include <gssapi/gssapi_spnego.h>
+#include "gss_common.h"
+#include <base64.h>
+
+RCSID("$Id$");
+
+/*
+ * A simplistic client implementing draft-brezak-spnego-http-04.txt
+ */
+
+static int
+do_connect (const char *hostname, const char *port)
+{
+ struct addrinfo *ai, *a;
+ struct addrinfo hints;
+ int error;
+ int s = -1;
+
+ memset (&hints, 0, sizeof(hints));
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = 0;
+
+ error = getaddrinfo (hostname, port, &hints, &ai);
+ if (error)
+ errx (1, "getaddrinfo(%s): %s", hostname, gai_strerror(error));
+
+ for (a = ai; a != NULL; a = a->ai_next) {
+ 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;
+ }
+ break;
+ }
+ freeaddrinfo (ai);
+ if (a == NULL)
+ errx (1, "failed to contact %s", hostname);
+
+ return s;
+}
+
+static void
+fdprintf(int s, const char *fmt, ...)
+{
+ size_t len;
+ ssize_t ret;
+ va_list ap;
+ char *str, *buf;
+
+ va_start(ap, fmt);
+ vasprintf(&str, fmt, ap);
+ va_end(ap);
+
+ if (str == NULL)
+ errx(1, "vasprintf");
+
+ buf = str;
+ len = strlen(buf);
+ while (len) {
+ ret = write(s, buf, len);
+ if (ret == 0)
+ err(1, "connection closed");
+ else if (ret < 0)
+ err(1, "error");
+ len -= ret;
+ buf += ret;
+ }
+ free(str);
+}
+
+static int help_flag;
+static int version_flag;
+static int verbose_flag;
+static int mutual_flag = 1;
+static int delegate_flag;
+static char *port_str = "http";
+static char *gss_service = "HTTP";
+
+static struct getargs http_args[] = {
+ { "verbose", 'v', arg_flag, &verbose_flag, "verbose logging", NULL },
+ { "port", 'p', arg_string, &port_str, "port to connect to", "port" },
+ { "delegate", 0, arg_flag, &delegate_flag, "gssapi delegate credential",
+ NULL },
+ { "gss-service", 's', arg_string, &gss_service, "gssapi service to use",
+ "service" },
+ { "mech", 'm', arg_string, &mech, "gssapi mech to use", "mech" },
+ { "mutual", 0, arg_negative_flag, &mutual_flag, "no gssapi mutual auth",
+ NULL },
+ { "help", 'h', arg_flag, &help_flag, NULL, NULL },
+ { "version", 0, arg_flag, &version_flag, NULL, NULL }
+};
+
+static int num_http_args = sizeof(http_args) / sizeof(http_args[0]);
+
+static void
+usage(int code)
+{
+ arg_printusage(http_args, num_http_args, NULL, "host [page]");
+ exit(code);
+}
+
+/*
+ *
+ */
+
+struct http_req {
+ char *response;
+ char **headers;
+ int num_headers;
+ void *body;
+ size_t body_size;
+};
+
+
+static void
+http_req_zero(struct http_req *req)
+{
+ req->response = NULL;
+ req->headers = NULL;
+ req->num_headers = 0;
+ req->body = NULL;
+ req->body_size = 0;
+}
+
+static void
+http_req_free(struct http_req *req)
+{
+ int i;
+
+ free(req->response);
+ for (i = 0; i < req->num_headers; i++)
+ free(req->headers[i]);
+ free(req->headers);
+ free(req->body);
+ http_req_zero(req);
+}
+
+static const char *
+http_find_header(struct http_req *req, const char *header)
+{
+ int i, len = strlen(header);
+
+ for (i = 0; i < req->num_headers; i++) {
+ if (strncasecmp(header, req->headers[i], len) == 0) {
+ return req->headers[i] + len + 1;
+ }
+ }
+ return NULL;
+}
+
+
+static int
+http_query(const char *host, const char *page,
+ char **headers, struct http_req *req)
+{
+ enum { RESPONSE, HEADER, BODY } state;
+ ssize_t ret;
+ char in_buf[1024], *in_ptr = in_buf;
+ size_t in_len = 0;
+ int s, i;
+
+ http_req_zero(req);
+
+ s = do_connect(host, port_str);
+ if (s < 0)
+ errx(1, "connection failed");
+
+ fdprintf(s, "GET %s HTTP/1.0\r\n", page);
+ for (i = 0; headers[i]; i++)
+ fdprintf(s, "%s\r\n", headers[i]);
+ fdprintf(s, "Host: %s\r\n\r\n", host);
+
+ state = RESPONSE;
+
+ while (1) {
+ ret = read (s, in_ptr, sizeof(in_buf) - in_len - 1);
+ if (ret == 0)
+ break;
+ else if (ret < 0)
+ err (1, "read: %lu", (unsigned long)ret);
+
+ in_buf[ret + in_len] = '\0';
+
+ if (state == HEADER || state == RESPONSE) {
+ char *p;
+
+ in_len += ret;
+ in_ptr += ret;
+
+ while (1) {
+ p = strstr(in_buf, "\r\n");
+
+ if (p == NULL) {
+ break;
+ } else if (p == in_buf) {
+ memmove(in_buf, in_buf + 2, sizeof(in_buf) - 2);
+ state = BODY;
+ in_len -= 2;
+ in_ptr -= 2;
+ break;
+ } else if (state == RESPONSE) {
+ req->response = emalloc(p - in_buf + 1);
+ memcpy(req->response, in_buf, p - in_buf);
+ req->response[p - in_buf] = '\0';
+ state = HEADER;
+ } else {
+ req->headers = realloc(req->headers,
+ (req->num_headers + 1) * sizeof(req->headers[0]));
+ req->headers[req->num_headers] = emalloc(p - in_buf + 1);
+ memcpy(req->headers[req->num_headers], in_buf, p - in_buf);
+ req->headers[req->num_headers][p - in_buf] = '\0';
+ if (req->headers[req->num_headers] == NULL)
+ errx(1, "strdup");
+ req->num_headers++;
+ }
+ memmove(in_buf, p + 2, sizeof(in_buf) - (p - in_buf) - 2);
+ in_len -= (p - in_buf) + 2;
+ in_ptr -= (p - in_buf) + 2;
+ }
+ }
+
+ if (state == BODY) {
+
+ req->body = erealloc(req->body, req->body_size + ret + 1);
+
+ memcpy((char *)req->body + req->body_size, in_buf, ret);
+ req->body_size += ret;
+ ((char *)req->body)[req->body_size] = '\0';
+
+ in_ptr = in_buf;
+ in_len = 0;
+ } else
+ abort();
+ }
+
+ if (verbose_flag) {
+ int i;
+ printf("response: %s\n", req->response);
+ for (i = 0; i < req->num_headers; i++)
+ printf("header[%d] %s\n", i, req->headers[i]);
+ printf("body: %.*s\n", (int)req->body_size, (char *)req->body);
+ }
+
+ close(s);
+ return 0;
+}
+
+
+int
+main(int argc, char **argv)
+{
+ struct http_req req;
+ const char *host, *page;
+ int i, done, print_body, gssapi_done, gssapi_started;
+ char *headers[10] = { 0 };
+ int num_headers = 0;
+ gss_ctx_id_t context_hdl = GSS_C_NO_CONTEXT;
+ gss_name_t server = GSS_C_NO_NAME;
+ int optind = 0;
+ gss_OID mech_oid;
+ OM_uint32 flags;
+
+ setprogname(argv[0]);
+
+ if(getarg(http_args, num_http_args, argc, argv, &optind))
+ usage(1);
+
+ if (help_flag)
+ usage (0);
+
+ if(version_flag) {
+ print_version(NULL);
+ exit(0);
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ memset(&req, 0, sizeof(req));
+ mech_oid = select_mech(mech);
+
+ if (argc != 1 && argc != 2)
+ errx(1, "usage: %s host [page]", getprogname());
+ host = argv[0];
+ if (argc == 2)
+ page = argv[1];
+ else
+ page = "/";
+
+ flags = 0;
+ if (delegate_flag)
+ flags |= GSS_C_DELEG_FLAG;
+ if (mutual_flag)
+ flags |= GSS_C_MUTUAL_FLAG;
+
+ done = 0;
+ num_headers = 0;
+ gssapi_done = 1;
+ gssapi_started = 0;
+ do {
+ print_body = 0;
+
+ http_query(host, page, headers, &req);
+ for (i = 0 ; headers[i]; i++) {
+ free(headers[i]);
+ headers[i] = NULL;
+ }
+ num_headers = 0;
+
+ if (req.response == NULL)
+ errx(1, "Got no response");
+
+ if (strstr(req.response, " 200 ") != NULL) {
+ print_body = 1;
+ done = 1;
+ } else if (strstr(req.response, " 401 ") != NULL) {
+ if (http_find_header(&req, "WWW-Authenticate:") == NULL)
+ errx(1, "Got %s but missed `WWW-Authenticate'", req.response);
+ gssapi_done = 0;
+ }
+
+ if (!gssapi_done) {
+ const char *h = http_find_header(&req, "WWW-Authenticate:");
+ if (h == NULL)
+ errx(1, "Got %s but missed `WWW-Authenticate'", req.response);
+
+ if (strncasecmp(h, "Negotiate", 9) == 0) {
+ OM_uint32 maj_stat, min_stat;
+ gss_buffer_desc input_token, output_token;
+
+ if (verbose_flag)
+ printf("Negotiate found\n");
+
+ if (server == GSS_C_NO_NAME) {
+ char *name;
+ asprintf(&name, "%s@%s", gss_service, host);
+ input_token.length = strlen(name);
+ input_token.value = name;
+
+ maj_stat = gss_import_name(&min_stat,
+ &input_token,
+ GSS_C_NT_HOSTBASED_SERVICE,
+ &server);
+ if (GSS_ERROR(maj_stat))
+ gss_err (1, min_stat, "gss_inport_name");
+ free(name);
+ input_token.length = 0;
+ input_token.value = NULL;
+ }
+
+ i = 9;
+ while(h[i] && isspace((unsigned char)h[i]))
+ i++;
+ if (h[i] != '\0') {
+ int len = strlen(&h[i]);
+ if (len == 0)
+ errx(1, "invalid Negotiate token");
+ input_token.value = emalloc(len);
+ len = rk_base64_decode(&h[i], input_token.value);
+ if (len < 0)
+ errx(1, "invalid base64 Negotiate token %s", &h[i]);
+ input_token.length = len;
+ } else {
+ if (gssapi_started)
+ errx(1, "Negotiate already started");
+ gssapi_started = 1;
+
+ input_token.length = 0;
+ input_token.value = NULL;
+ }
+
+ maj_stat =
+ gss_init_sec_context(&min_stat,
+ GSS_C_NO_CREDENTIAL,
+ &context_hdl,
+ server,
+ mech_oid,
+ flags,
+ 0,
+ GSS_C_NO_CHANNEL_BINDINGS,
+ &input_token,
+ NULL,
+ &output_token,
+ NULL,
+ NULL);
+ if (GSS_ERROR(maj_stat))
+ gss_err (1, min_stat, "gss_init_sec_context");
+ else if (maj_stat & GSS_S_CONTINUE_NEEDED)
+ gssapi_done = 0;
+ else {
+ gss_name_t targ_name, src_name;
+ gss_buffer_desc name_buffer;
+ gss_OID mech_type;
+
+ gssapi_done = 1;
+
+ printf("Negotiate done: %s\n", mech);
+
+ maj_stat = gss_inquire_context(&min_stat,
+ context_hdl,
+ &src_name,
+ &targ_name,
+ NULL,
+ &mech_type,
+ NULL,
+ NULL,
+ NULL);
+ if (GSS_ERROR(maj_stat))
+ gss_err (1, min_stat, "gss_inquire_context");
+
+ maj_stat = gss_display_name(&min_stat,
+ src_name,
+ &name_buffer,
+ NULL);
+ if (GSS_ERROR(maj_stat))
+ gss_err (1, min_stat, "gss_display_name");
+
+ printf("Source: %.*s\n",
+ (int)name_buffer.length,
+ (char *)name_buffer.value);
+
+ gss_release_buffer(&min_stat, &name_buffer);
+
+ maj_stat = gss_display_name(&min_stat,
+ targ_name,
+ &name_buffer,
+ NULL);
+ if (GSS_ERROR(maj_stat))
+ gss_err (1, min_stat, "gss_display_name");
+
+ printf("Target: %.*s\n",
+ (int)name_buffer.length,
+ (char *)name_buffer.value);
+
+ gss_release_name(&min_stat, &targ_name);
+ gss_release_buffer(&min_stat, &name_buffer);
+ }
+
+ if (output_token.length) {
+ char *neg_token;
+
+ rk_base64_encode(output_token.value,
+ output_token.length,
+ &neg_token);
+
+ asprintf(&headers[num_headers++], "Authorization: Negotiate %s",
+ neg_token);
+
+ free(neg_token);
+ gss_release_buffer(&min_stat, &output_token);
+ }
+ if (input_token.length)
+ free(input_token.value);
+
+ } else
+ done = 1;
+ } else
+ done = 1;
+
+ if (verbose_flag) {
+ printf("%s\n\n", req.response);
+
+ for (i = 0; i < req.num_headers; i++)
+ printf("%s\n", req.headers[i]);
+ printf("\n");
+ }
+ if (print_body || verbose_flag)
+ printf("%.*s\n", (int)req.body_size, (char *)req.body);
+
+ http_req_free(&req);
+ } while (!done);
+
+ if (gssapi_done == 0)
+ errx(1, "gssapi not done but http dance done");
+
+ return 0;
+}
diff --git a/third_party/heimdal/appl/test/jgssapi_server.java b/third_party/heimdal/appl/test/jgssapi_server.java
new file mode 100644
index 0000000..6a9e75e
--- /dev/null
+++ b/third_party/heimdal/appl/test/jgssapi_server.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2007 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.
+ */
+
+import org.ietf.jgss.*;
+import java.io.*;
+import java.net.Socket;
+import java.net.ServerSocket;
+
+public class jgssapi_server {
+
+ static byte [] getMessage(DataInputStream inStream)
+ throws IOException
+ {
+ byte[] token;
+ token = new byte[inStream.readInt()];
+ inStream.readFully(token);
+ return token;
+ }
+
+ static void putMessage(DataOutputStream outStream, byte [] token)
+ throws IOException
+ {
+ outStream.writeInt(token.length);
+ outStream.write(token);
+ }
+
+
+ public static void main(String[] args)
+ throws IOException, GSSException {
+
+ GSSManager manager = GSSManager.getInstance();
+
+ GSSContext context = manager.createContext((GSSCredential)null);
+
+ byte[] token = null;
+
+ int port = 4717;
+
+ System.out.println("listen on port " + port);
+
+ Socket s = new ServerSocket(port).accept();
+
+ DataInputStream inStream = new DataInputStream(s.getInputStream());
+ DataOutputStream outStream = new DataOutputStream(s.getOutputStream());
+
+ System.out.println("negotiate context");
+ while (!context.isEstablished()) {
+ token = getMessage(inStream);
+
+ token = context.acceptSecContext(token, 0, token.length);
+ if (token != null)
+ putMessage(outStream, token);
+ }
+
+ System.out.println("done");
+
+ /*
+ * mic
+ */
+ System.out.println("mic test");
+
+ System.out.println(" verify mic");
+
+ byte[] intoken = getMessage(inStream);
+ byte[] outtoken = getMessage(inStream);
+ byte[] bytes = null;
+
+ context.verifyMIC(outtoken, 0, outtoken.length,
+ intoken, 0, intoken.length, new MessageProp(0, false));
+
+ System.out.println(" create mic");
+
+ bytes = new byte[] { 0x66, 0x6f, 0x6f };
+
+ outtoken = context.getMIC(bytes, 0, bytes.length, new MessageProp(0, false));
+ putMessage(outStream, bytes);
+ putMessage(outStream, outtoken);
+
+ /*
+ * wrap int
+ */
+ System.out.println("warp int");
+
+ outtoken = getMessage(inStream);
+
+ bytes = context.unwrap(outtoken, 0, outtoken.length, new MessageProp(0, false));
+
+ if (bytes == null)
+ System.err.println("wrap int failed");
+
+ /*
+ * wrap conf
+ */
+ System.out.println("warp conf");
+
+ outtoken = getMessage(inStream);
+
+ bytes = context.unwrap(outtoken, 0, outtoken.length, new MessageProp(0, true));
+
+ if (bytes == null)
+ System.err.println("wrap conf failed");
+
+
+ /*
+ * wrap conf
+ */
+ System.out.println("warp conf");
+ intoken = new byte[] { 0x66, 0x6f, 0x6f };
+ outtoken = context.wrap(intoken, 0, intoken.length, new MessageProp(0, true));
+ putMessage(outStream, outtoken);
+ outtoken = getMessage(inStream);
+
+ context.dispose();
+
+ System.exit(0);
+ }
+}
+
diff --git a/third_party/heimdal/appl/test/nt_gss_client.c b/third_party/heimdal/appl/test/nt_gss_client.c
new file mode 100644
index 0000000..fc9ff3c
--- /dev/null
+++ b/third_party/heimdal/appl/test/nt_gss_client.c
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 1997 - 1999 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 "test_locl.h"
+#include <gssapi.h>
+#include "nt_gss_common.h"
+
+RCSID("$Id$");
+
+/*
+ * This program tries to act as a client for the sample in `Sample
+ * SSPI Code' in Windows 2000 RC1 SDK.
+ */
+
+static int
+proto (int sock, const char *hostname, const char *service)
+{
+ struct sockaddr_in remote, local;
+ socklen_t addrlen;
+
+ int context_established = 0;
+ gss_ctx_id_t context_hdl = GSS_C_NO_CONTEXT;
+ gss_buffer_t input_token, output_token;
+ gss_buffer_desc real_input_token, real_output_token;
+ OM_uint32 maj_stat, min_stat;
+ gss_name_t server;
+ gss_buffer_desc name_token;
+ char *str;
+
+ name_token.length = asprintf (&str,
+ "%s@%s", service, hostname);
+ if (str == NULL)
+ errx(1, "out of memory");
+ name_token.value = str;
+
+ maj_stat = gss_import_name (&min_stat,
+ &name_token,
+ GSS_C_NT_HOSTBASED_SERVICE,
+ &server);
+ if (GSS_ERROR(maj_stat))
+ gss_err (1, min_stat,
+ "Error importing name `%s@%s':\n", service, hostname);
+
+ addrlen = sizeof(local);
+ if (getsockname (sock, (struct sockaddr *)&local, &addrlen) < 0
+ || addrlen != sizeof(local))
+ err (1, "getsockname(%s)", hostname);
+
+ addrlen = sizeof(remote);
+ if (getpeername (sock, (struct sockaddr *)&remote, &addrlen) < 0
+ || addrlen != sizeof(remote))
+ err (1, "getpeername(%s)", hostname);
+
+ input_token = &real_input_token;
+ output_token = &real_output_token;
+
+ input_token->length = 0;
+ output_token->length = 0;
+
+ while(!context_established) {
+ maj_stat =
+ gss_init_sec_context(&min_stat,
+ GSS_C_NO_CREDENTIAL,
+ &context_hdl,
+ server,
+ GSS_C_NO_OID,
+ GSS_C_MUTUAL_FLAG | GSS_C_SEQUENCE_FLAG,
+ 0,
+ GSS_C_NO_CHANNEL_BINDINGS,
+ input_token,
+ NULL,
+ output_token,
+ NULL,
+ NULL);
+ if (GSS_ERROR(maj_stat))
+ gss_err (1, min_stat, "gss_init_sec_context");
+ if (output_token->length != 0)
+ nt_write_token (sock, output_token);
+ if (GSS_ERROR(maj_stat)) {
+ if (context_hdl != GSS_C_NO_CONTEXT)
+ gss_delete_sec_context (&min_stat,
+ &context_hdl,
+ GSS_C_NO_BUFFER);
+ break;
+ }
+ if (maj_stat & GSS_S_CONTINUE_NEEDED) {
+ nt_read_token (sock, input_token);
+ } else {
+ context_established = 1;
+ }
+
+ }
+
+ /* get_mic */
+
+ input_token->length = 3;
+ input_token->value = strdup("hej");
+
+ maj_stat = gss_get_mic(&min_stat,
+ context_hdl,
+ GSS_C_QOP_DEFAULT,
+ input_token,
+ output_token);
+ if (GSS_ERROR(maj_stat))
+ gss_err (1, min_stat, "gss_get_mic");
+
+ nt_write_token (sock, input_token);
+ nt_write_token (sock, output_token);
+
+ /* wrap */
+
+ input_token->length = 7;
+ input_token->value = "hemligt";
+
+
+ maj_stat = gss_wrap (&min_stat,
+ context_hdl,
+ 1,
+ GSS_C_QOP_DEFAULT,
+ input_token,
+ NULL,
+ output_token);
+ if (GSS_ERROR(maj_stat))
+ gss_err (1, min_stat, "gss_wrap");
+
+ nt_write_token (sock, output_token);
+
+ return 0;
+}
+
+int
+main(int argc, char **argv)
+{
+ krb5_context context; /* XXX */
+ int port = client_setup(&context, &argc, argv);
+ return client_doit (argv[argc], port, service, proto);
+}
diff --git a/third_party/heimdal/appl/test/nt_gss_common.c b/third_party/heimdal/appl/test/nt_gss_common.c
new file mode 100644
index 0000000..617c18a
--- /dev/null
+++ b/third_party/heimdal/appl/test/nt_gss_common.c
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 1997, 1998, 1999 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 "test_locl.h"
+#include <gssapi.h>
+#include "nt_gss_common.h"
+
+RCSID("$Id$");
+
+/*
+ * These are functions that are needed to interoperate with the
+ * `Sample SSPI Code' in Windows 2000 RC1 SDK.
+ */
+
+/*
+ * Write the `gss_buffer_t' in `buf' onto the fd `sock', but remember that
+ * the length is written in little-endian-order.
+ */
+
+void
+nt_write_token (int sock, gss_buffer_t buf)
+{
+ unsigned char net_len[4];
+ uint32_t len;
+ OM_uint32 min_stat;
+
+ len = buf->length;
+
+ net_len[0] = (len >> 0) & 0xFF;
+ net_len[1] = (len >> 8) & 0xFF;
+ net_len[2] = (len >> 16) & 0xFF;
+ net_len[3] = (len >> 24) & 0xFF;
+
+ if (write (sock, net_len, 4) != 4)
+ err (1, "write");
+ if (write (sock, buf->value, len) != len)
+ err (1, "write");
+
+ gss_release_buffer (&min_stat, buf);
+}
+
+/*
+ *
+ */
+
+void
+nt_read_token (int sock, gss_buffer_t buf)
+{
+ unsigned char net_len[4];
+ uint32_t len;
+
+ if (read(sock, net_len, 4) != 4)
+ err (1, "read");
+ len = (net_len[0] << 0)
+ | (net_len[1] << 8)
+ | (net_len[2] << 16)
+ | (net_len[3] << 24);
+
+ if (len > INT_MAX/16)
+ errx(1, "len too large");
+ buf->length = len;
+ buf->value = malloc(len);
+ if (read (sock, buf->value, len) != len)
+ err (1, "read");
+}
+
+void
+gss_print_errors (int min_stat)
+{
+ OM_uint32 new_stat;
+ OM_uint32 msg_ctx = 0;
+ gss_buffer_desc status_string;
+ OM_uint32 ret;
+
+ do {
+ ret = gss_display_status (&new_stat,
+ min_stat,
+ GSS_C_MECH_CODE,
+ GSS_C_NO_OID,
+ &msg_ctx,
+ &status_string);
+ fprintf (stderr, "%.*s\n",
+ (int)status_string.length,
+ (char *)status_string.value);
+ gss_release_buffer (&new_stat, &status_string);
+ } while (!GSS_ERROR(ret) && msg_ctx != 0);
+}
+
+void
+gss_verr(int exitval, int status, const char *fmt, va_list ap)
+{
+ vwarnx (fmt, ap);
+ gss_print_errors (status);
+ exit (exitval);
+}
+
+void
+gss_err(int exitval, int status, const char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ gss_verr (exitval, status, fmt, args);
+ va_end(args);
+}
diff --git a/third_party/heimdal/appl/test/nt_gss_common.h b/third_party/heimdal/appl/test/nt_gss_common.h
new file mode 100644
index 0000000..134afe3
--- /dev/null
+++ b/third_party/heimdal/appl/test/nt_gss_common.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 1997, 1998, 1999 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$ */
+
+void nt_write_token (int sock, gss_buffer_t buf);
+void nt_read_token (int sock, gss_buffer_t buf);
+
+void gss_print_errors (int min_stat);
+
+void gss_verr(int exitval, int status, const char *fmt, va_list ap)
+ __attribute__ ((format (printf, 3, 0)));
+
+void gss_err(int exitval, int status, const char *fmt, ...)
+ __attribute__ ((format (printf, 3, 4)));
diff --git a/third_party/heimdal/appl/test/nt_gss_server.c b/third_party/heimdal/appl/test/nt_gss_server.c
new file mode 100644
index 0000000..d6f7cc1
--- /dev/null
+++ b/third_party/heimdal/appl/test/nt_gss_server.c
@@ -0,0 +1,244 @@
+/*
+ * Copyright (c) 1997 - 2000 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 "test_locl.h"
+#include <gssapi/gssapi.h>
+#include <gssapi/gssapi_krb5.h>
+#include <gssapi/gssapi_spnego.h>
+#include <krb5.h>
+#include "nt_gss_common.h"
+
+RCSID("$Id$");
+
+/*
+ * This program tries to act as a server for the sample in `Sample
+ * SSPI Code' in Windows 2000 RC1 SDK.
+ *
+ * use --dump-auth to get a binary dump of the authorization data in the ticket
+ */
+
+static int help_flag;
+static int version_flag;
+static char *port_str;
+char *service = SERVICE;
+static char *auth_file;
+
+static struct getargs args[] = {
+ { "port", 'p', arg_string, &port_str, "port to listen to", "port" },
+ { "service", 's', arg_string, &service, "service to use", "service" },
+ { "dump-auth", 0, arg_string, &auth_file, "dump authorization data",
+ "file" },
+ { "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 int
+proto (int sock, const char *service)
+{
+ struct sockaddr_in remote, local;
+ socklen_t addrlen;
+ gss_ctx_id_t context_hdl = GSS_C_NO_CONTEXT;
+ gss_buffer_t input_token, output_token;
+ gss_buffer_desc real_input_token, real_output_token;
+ OM_uint32 maj_stat, min_stat;
+ gss_name_t client_name;
+ gss_buffer_desc name_token;
+
+ addrlen = sizeof(local);
+ if (getsockname (sock, (struct sockaddr *)&local, &addrlen) < 0
+ || addrlen != sizeof(local))
+ err (1, "getsockname)");
+
+ addrlen = sizeof(remote);
+ if (getpeername (sock, (struct sockaddr *)&remote, &addrlen) < 0
+ || addrlen != sizeof(remote))
+ err (1, "getpeername");
+
+ input_token = &real_input_token;
+ output_token = &real_output_token;
+
+ do {
+ nt_read_token (sock, input_token);
+ maj_stat =
+ gss_accept_sec_context (&min_stat,
+ &context_hdl,
+ GSS_C_NO_CREDENTIAL,
+ input_token,
+ GSS_C_NO_CHANNEL_BINDINGS,
+ &client_name,
+ NULL,
+ output_token,
+ NULL,
+ NULL,
+ NULL);
+ if(GSS_ERROR(maj_stat))
+ gss_err (1, min_stat, "gss_accept_sec_context");
+ if (output_token->length != 0)
+ nt_write_token (sock, output_token);
+ if (GSS_ERROR(maj_stat)) {
+ if (context_hdl != GSS_C_NO_CONTEXT)
+ gss_delete_sec_context (&min_stat,
+ &context_hdl,
+ GSS_C_NO_BUFFER);
+ break;
+ }
+ } while(maj_stat & GSS_S_CONTINUE_NEEDED);
+
+ if (auth_file != NULL) {
+ gss_buffer_desc data;
+
+ maj_stat = gsskrb5_extract_authz_data_from_sec_context(&min_stat,
+ context_hdl,
+ KRB5_AUTHDATA_WIN2K_PAC,
+ &data);
+ if (maj_stat == GSS_S_COMPLETE) {
+ rk_dumpdata(auth_file, data.value, data.length);
+ gss_release_buffer(&min_stat, &data);
+ }
+ }
+
+ maj_stat = gss_display_name (&min_stat,
+ client_name,
+ &name_token,
+ NULL);
+ if (GSS_ERROR(maj_stat))
+ gss_err (1, min_stat, "gss_display_name");
+
+ fprintf (stderr, "User is `%.*s'\n", (int)name_token.length,
+ (char *)name_token.value);
+
+ /* write something back */
+
+ output_token->value = strdup ("hejsan");
+ output_token->length = strlen (output_token->value) + 1;
+ nt_write_token (sock, output_token);
+
+ output_token->value = strdup ("hoppsan");
+ output_token->length = strlen (output_token->value) + 1;
+ nt_write_token (sock, output_token);
+
+ return 0;
+}
+
+static int
+doit (int port, const char *service)
+{
+ int sock, sock2;
+ struct sockaddr_in my_addr;
+ int one = 1;
+
+ sock = socket (AF_INET, SOCK_STREAM, 0);
+ if (sock < 0)
+ err (1, "socket");
+
+ memset (&my_addr, 0, sizeof(my_addr));
+ my_addr.sin_family = AF_INET;
+ my_addr.sin_port = port;
+ my_addr.sin_addr.s_addr = INADDR_ANY;
+
+ if (setsockopt (sock, SOL_SOCKET, SO_REUSEADDR,
+ (void *)&one, sizeof(one)) < 0)
+ warn ("setsockopt SO_REUSEADDR");
+
+ if (bind (sock, (struct sockaddr *)&my_addr, sizeof(my_addr)) < 0)
+ err (1, "bind");
+
+ if (listen (sock, 1) < 0)
+ err (1, "listen");
+
+ sock2 = accept (sock, NULL, NULL);
+ if (sock2 < 0)
+ err (1, "accept");
+
+ return proto (sock2, service);
+}
+
+static void
+usage(int code, struct getargs *args, int num_args)
+{
+ arg_printusage(args, num_args, NULL, "");
+ exit(code);
+}
+
+static int
+common_setup(krb5_context *context, int *argc, char **argv,
+ void (*usage)(int, struct getargs*, int))
+{
+ int port = 0;
+ *argc = krb5_program_setup(context, *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 (*context, PORT, "tcp", 4711);
+
+ return port;
+}
+
+static int
+setup(krb5_context *context, int argc, char **argv)
+{
+ int port = common_setup(context, &argc, argv, usage);
+ if(argv[argc] != NULL)
+ usage(1, args, num_args);
+ return port;
+}
+
+int
+main(int argc, char **argv)
+{
+ krb5_context context = NULL; /* XXX */
+ int port = setup(&context, argc, argv);
+ return doit (port, service);
+}
diff --git a/third_party/heimdal/appl/test/tcp_client.c b/third_party/heimdal/appl/test/tcp_client.c
new file mode 100644
index 0000000..2bbb068
--- /dev/null
+++ b/third_party/heimdal/appl/test/tcp_client.c
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 1997 - 1999 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 "test_locl.h"
+RCSID("$Id$");
+
+krb5_context context;
+
+static int
+proto (int sock, const char *hostname, const char *service)
+{
+ krb5_auth_context auth_context;
+ krb5_error_code status;
+ krb5_principal server;
+ krb5_data data;
+ krb5_data packet;
+ uint32_t len, net_len;
+
+ 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_setaddrs_from_fd");
+
+ status = krb5_sname_to_principal (context,
+ hostname,
+ service,
+ KRB5_NT_SRV_HST,
+ &server);
+ if (status)
+ krb5_err (context, 1, status, "krb5_sname_to_principal");
+
+ status = krb5_sendauth (context,
+ &auth_context,
+ &sock,
+ VERSION,
+ NULL,
+ server,
+ AP_OPTS_MUTUAL_REQUIRED,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ if (status)
+ krb5_err (context, 1, status, "krb5_sendauth");
+
+ data.data = "hej";
+ data.length = 3;
+
+ krb5_data_zero (&packet);
+
+ status = krb5_mk_safe (context,
+ auth_context,
+ &data,
+ &packet,
+ NULL);
+ if (status)
+ krb5_err (context, 1, status, "krb5_mk_safe");
+
+ len = packet.length;
+ net_len = htonl(len);
+
+ if (krb5_net_write (context, &sock, &net_len, 4) != 4)
+ err (1, "krb5_net_write");
+ if (krb5_net_write (context, &sock, packet.data, len) != len)
+ err (1, "krb5_net_write");
+
+ data.data = "hemligt";
+ data.length = 7;
+
+ krb5_data_free (&packet);
+
+ status = krb5_mk_priv (context,
+ auth_context,
+ &data,
+ &packet,
+ NULL);
+ if (status)
+ krb5_err (context, 1, status, "krb5_mk_priv");
+
+ len = packet.length;
+ net_len = htonl(len);
+
+ if (krb5_net_write (context, &sock, &net_len, 4) != 4)
+ err (1, "krb5_net_write");
+ if (krb5_net_write (context, &sock, packet.data, len) != len)
+ err (1, "krb5_net_write");
+ return 0;
+}
+
+int
+main(int argc, char **argv)
+{
+ int port = client_setup(&context, &argc, argv);
+ return client_doit (argv[argc], port, service, proto);
+}
diff --git a/third_party/heimdal/appl/test/tcp_server.c b/third_party/heimdal/appl/test/tcp_server.c
new file mode 100644
index 0000000..50d1bf4
--- /dev/null
+++ b/third_party/heimdal/appl/test/tcp_server.c
@@ -0,0 +1,205 @@
+/*
+ * Copyright (c) 1997 - 1999 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.
+ */
+
+/*
+ * A sample server that uses the Kerberos V5 API.
+ *
+ * See "Introduction to the Kerberos 5 API" in the Doxygen documentation
+ * for a walkthrough of this code.
+ */
+
+#include "test_locl.h"
+RCSID("$Id$");
+
+/* The API needs one Kerberos context per thread. */
+krb5_context context;
+
+static int
+proto (int sock, const char *service)
+{
+ krb5_auth_context auth_context;
+ krb5_error_code status;
+ krb5_principal server;
+ krb5_ticket *ticket;
+ char *name;
+ char hostname[MAXHOSTNAMELEN];
+ krb5_data packet;
+ krb5_data data;
+ uint32_t len, net_len;
+ ssize_t n;
+
+ /* Initialize the authentication context, to be used to authenticate the peer. */
+ status = krb5_auth_con_init (context, &auth_context);
+ if (status)
+ krb5_err (context, 1, status, "krb5_auth_con_init");
+
+ /* Extract the local and remote address from the socket into auth_context. */
+ status = krb5_auth_con_setaddrs_from_fd (context,
+ auth_context,
+ &sock);
+ if (status)
+ krb5_err (context, 1, status, "krb5_auth_con_setaddrs_from_fd");
+
+ if (gethostname (hostname, sizeof(hostname)) < 0)
+ krb5_err (context, 1, errno, "gethostname");
+
+ /* Create principal "server" for "service" on "hostname" (this host). */
+ status = krb5_sname_to_principal (context,
+ hostname,
+ service,
+ KRB5_NT_SRV_HST,
+ &server);
+ if (status)
+ krb5_err (context, 1, status, "krb5_sname_to_principal");
+
+ /*
+ * Perform the server side of the sendauth protocol. On success, "ticket"
+ * contains the authenticated credentials of the client.
+ */
+ status = krb5_recvauth (context,
+ &auth_context,
+ &sock,
+ VERSION,
+ server,
+ 0, /* flags */
+ keytab,
+ &ticket);
+ if (status)
+ krb5_err (context, 1, status, "krb5_recvauth");
+
+ /* Extract the client name as a string. */
+ status = krb5_unparse_name (context,
+ ticket->client,
+ &name);
+ if (status)
+ krb5_err (context, 1, status, "krb5_unparse_name");
+
+ fprintf (stderr, "User is `%s'\n", name);
+ free (name);
+
+ krb5_data_zero (&data);
+ krb5_data_zero (&packet);
+
+ /*
+ * Read the payload (encoded as length, value).
+ */
+ n = krb5_net_read (context, &sock, &net_len, 4);
+ if (n == 0)
+ krb5_errx (context, 1, "EOF in krb5_net_read");
+ if (n < 0)
+ krb5_err (context, 1, errno, "krb5_net_read");
+
+ len = ntohl(net_len);
+
+ krb5_data_alloc (&packet, len);
+
+ n = krb5_net_read (context, &sock, packet.data, len);
+ if (n == 0)
+ krb5_errx (context, 1, "EOF in krb5_net_read");
+ if (n < 0)
+ krb5_err (context, 1, errno, "krb5_net_read");
+
+ /*
+ * Expect a KRB_SAFE message (authenticated, not encrypted)
+ */
+ status = krb5_rd_safe (context,
+ auth_context,
+ &packet,
+ &data,
+ NULL);
+ if (status)
+ krb5_err (context, 1, status, "krb5_rd_safe");
+
+ fprintf (stderr, "safe packet: %.*s\n", (int)data.length,
+ (char *)data.data);
+
+ /*
+ * Read the payload (encoded as length, value).
+ */
+ n = krb5_net_read (context, &sock, &net_len, 4);
+ if (n == 0)
+ krb5_errx (context, 1, "EOF in krb5_net_read");
+ if (n < 0)
+ krb5_err (context, 1, errno, "krb5_net_read");
+
+ len = ntohl(net_len);
+
+ krb5_data_alloc (&packet, len);
+
+ n = krb5_net_read (context, &sock, packet.data, len);
+ if (n == 0)
+ krb5_errx (context, 1, "EOF in krb5_net_read");
+ if (n < 0)
+ krb5_err (context, 1, errno, "krb5_net_read");
+
+ /*
+ * Expect a KRB_PRIV message (authenticated and encrypted)
+ */
+ status = krb5_rd_priv (context,
+ auth_context,
+ &packet,
+ &data,
+ NULL);
+ if (status)
+ krb5_err (context, 1, status, "krb5_rd_priv");
+
+ fprintf (stderr, "priv packet: %.*s\n", (int)data.length,
+ (char *)data.data);
+
+ return 0;
+}
+
+static int
+doit (int port, const char *service)
+{
+ /* Block waiting for a connection. */
+ mini_inetd (port, NULL);
+
+ return proto (STDIN_FILENO, service);
+}
+
+/*
+ * Process only one connection and then exit.
+ */
+int
+main(int argc, char **argv)
+{
+ int port = server_setup(&context, argc, argv);
+ krb5_error_code ret;
+
+ ret = krb5_kt_have_content(context, keytab);
+ if (ret)
+ krb5_err (context, 1, ret, "krb5_kt_have_content");
+
+ return doit (port, service);
+}
diff --git a/third_party/heimdal/appl/test/test_locl.h b/third_party/heimdal/appl/test/test_locl.h
new file mode 100644
index 0000000..dba2bba
--- /dev/null
+++ b/third_party/heimdal/appl/test/test_locl.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 1997 - 2000 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 SERVICE "test"
+
+#define PORT "test"
+
+extern char *service;
+extern char *mech;
+extern char *keytab_str;
+extern krb5_keytab keytab;
+extern int fork_flag;
+int server_setup(krb5_context*, int, char**);
+int client_setup(krb5_context*, int*, char**);
+int client_doit (const char *hostname, int port, const char *service,
+ int (*func)(int, const char *hostname, const char *service));
diff --git a/third_party/heimdal/appl/test/uu_client.c b/third_party/heimdal/appl/test/uu_client.c
new file mode 100644
index 0000000..15e7899
--- /dev/null
+++ b/third_party/heimdal/appl/test/uu_client.c
@@ -0,0 +1,192 @@
+/*
+ * Copyright (c) 1997 - 2000 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 "test_locl.h"
+RCSID("$Id$");
+
+krb5_context context;
+
+static int
+proto (int sock, const char *hostname, const char *service)
+{
+ struct sockaddr_storage remote, local;
+ socklen_t addrlen;
+ krb5_address remote_addr, local_addr;
+ krb5_context context;
+ krb5_ccache ccache;
+ krb5_auth_context auth_context;
+ krb5_error_code status;
+ krb5_principal client;
+ krb5_data data;
+ krb5_data packet;
+ krb5_creds mcred, cred;
+ krb5_ticket *ticket;
+
+ addrlen = sizeof(local);
+ if (getsockname (sock, (struct sockaddr *)&local, &addrlen) < 0
+ || addrlen > sizeof(local))
+ err (1, "getsockname(%s)", hostname);
+
+ addrlen = sizeof(remote);
+ if (getpeername (sock, (struct sockaddr *)&remote, &addrlen) < 0
+ || addrlen > sizeof(remote))
+ err (1, "getpeername(%s)", hostname);
+
+ status = krb5_init_context(&context);
+ if (status)
+ errx(1, "krb5_init_context failed: %d", status);
+
+ status = krb5_cc_default (context, &ccache);
+ if (status)
+ krb5_err(context, 1, status, "krb5_cc_default");
+
+ status = krb5_auth_con_init (context, &auth_context);
+ if (status)
+ krb5_err(context, 1, status, "krb5_auth_con_init");
+
+ status = krb5_sockaddr2address (context, (struct sockaddr *)&local, &local_addr);
+ if (status)
+ krb5_err(context, 1, status, "krb5_sockaddr2address(local)");
+ status = krb5_sockaddr2address (context, (struct sockaddr *)&remote, &remote_addr);
+ if (status)
+ krb5_err(context, 1, status, "krb5_sockaddr2address(remote)");
+
+ status = krb5_auth_con_setaddrs (context,
+ auth_context,
+ &local_addr,
+ &remote_addr);
+ if (status)
+ krb5_err(context, 1, status, "krb5_auth_con_setaddr");
+
+ krb5_cc_clear_mcred(&mcred);
+
+ status = krb5_cc_get_principal(context, ccache, &client);
+ if(status)
+ krb5_err(context, 1, status, "krb5_cc_get_principal");
+ status = krb5_make_principal(context, &mcred.server,
+ krb5_principal_get_realm(context, client),
+ "krbtgt",
+ krb5_principal_get_realm(context, client),
+ NULL);
+ if(status)
+ krb5_err(context, 1, status, "krb5_make_principal");
+ mcred.client = client;
+
+ status = krb5_cc_retrieve_cred(context, ccache, 0, &mcred, &cred);
+ if(status)
+ krb5_err(context, 1, status, "krb5_cc_retrieve_cred");
+
+ {
+ char *client_name;
+ krb5_data data;
+ status = krb5_unparse_name(context, cred.client, &client_name);
+ if(status)
+ krb5_err(context, 1, status, "krb5_unparse_name");
+ data.data = client_name;
+ data.length = strlen(client_name) + 1;
+ status = krb5_write_message(context, &sock, &data);
+ if(status)
+ krb5_err(context, 1, status, "krb5_write_message");
+ free(client_name);
+ }
+
+ status = krb5_write_message(context, &sock, &cred.ticket);
+ if(status)
+ krb5_err(context, 1, status, "krb5_write_message");
+
+ status = krb5_auth_con_setuserkey(context, auth_context, &cred.session);
+ if(status)
+ krb5_err(context, 1, status, "krb5_auth_con_setuserkey");
+
+ status = krb5_recvauth(context, &auth_context, &sock,
+ VERSION, client, 0, NULL, &ticket);
+
+ if (status)
+ krb5_err(context, 1, status, "krb5_recvauth");
+
+ if (ticket->ticket.authorization_data) {
+ AuthorizationData *authz;
+ int i;
+
+ printf("Authorization data:\n");
+
+ authz = ticket->ticket.authorization_data;
+ for (i = 0; i < authz->len; i++) {
+ printf("\ttype %d, length %lu\n",
+ authz->val[i].ad_type,
+ (unsigned long)authz->val[i].ad_data.length);
+ }
+ }
+
+ data.data = "hej";
+ data.length = 3;
+
+ krb5_data_zero (&packet);
+
+ status = krb5_mk_safe (context,
+ auth_context,
+ &data,
+ &packet,
+ NULL);
+ if (status)
+ krb5_err(context, 1, status, "krb5_mk_safe");
+
+ status = krb5_write_message(context, &sock, &packet);
+ if(status)
+ krb5_err(context, 1, status, "krb5_write_message");
+
+ data.data = "hemligt";
+ data.length = 7;
+
+ krb5_data_free (&packet);
+
+ status = krb5_mk_priv (context,
+ auth_context,
+ &data,
+ &packet,
+ NULL);
+ if (status)
+ krb5_err(context, 1, status, "krb5_mk_priv");
+
+ status = krb5_write_message(context, &sock, &packet);
+ if(status)
+ krb5_err(context, 1, status, "krb5_write_message");
+ return 0;
+}
+
+int
+main(int argc, char **argv)
+{
+ int port = client_setup(&context, &argc, argv);
+ return client_doit (argv[argc], port, service, proto);
+}
diff --git a/third_party/heimdal/appl/test/uu_server.c b/third_party/heimdal/appl/test/uu_server.c
new file mode 100644
index 0000000..6e04699
--- /dev/null
+++ b/third_party/heimdal/appl/test/uu_server.c
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 1997 - 2000, 2007 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 "test_locl.h"
+RCSID("$Id$");
+
+krb5_context context;
+
+static int
+proto (int sock, const char *service)
+{
+ struct sockaddr_storage remote, local;
+ socklen_t addrlen;
+ krb5_address remote_addr, local_addr;
+ krb5_ccache ccache;
+ krb5_auth_context auth_context;
+ krb5_error_code status;
+ krb5_data packet;
+ krb5_data data;
+ krb5_data client_name;
+ krb5_creds in_creds, *out_creds;
+
+ addrlen = sizeof(local);
+ if (getsockname (sock, (struct sockaddr *)&local, &addrlen) < 0
+ || addrlen > sizeof(local))
+ err (1, "getsockname)");
+
+ addrlen = sizeof(remote);
+ if (getpeername (sock, (struct sockaddr *)&remote, &addrlen) < 0
+ || addrlen > sizeof(remote))
+ err (1, "getpeername");
+
+ status = krb5_auth_con_init (context, &auth_context);
+ if (status)
+ krb5_err(context, 1, status, "krb5_auth_con_init");
+
+ status = krb5_sockaddr2address (context, (struct sockaddr *)&local, &local_addr);
+ if (status)
+ krb5_err(context, 1, status, "krb5_sockaddr2address(local)");
+ status = krb5_sockaddr2address (context, (struct sockaddr *)&remote, &remote_addr);
+ if (status)
+ krb5_err(context, 1, status, "krb5_sockaddr2address(remote)");
+
+ status = krb5_auth_con_setaddrs (context,
+ auth_context,
+ &local_addr,
+ &remote_addr);
+ if (status)
+ krb5_err(context, 1, status, "krb5_auth_con_setaddr");
+
+ status = krb5_read_message(context, &sock, &client_name);
+ if(status)
+ krb5_err(context, 1, status, "krb5_read_message");
+
+ memset(&in_creds, 0, sizeof(in_creds));
+ status = krb5_cc_default(context, &ccache);
+ if(status)
+ krb5_err(context, 1, status, "krb5_cc_default");
+ status = krb5_cc_get_principal(context, ccache, &in_creds.client);
+ if(status)
+ krb5_err(context, 1, status, "krb5_cc_get_principal");
+
+ status = krb5_read_message(context, &sock, &in_creds.second_ticket);
+ if(status)
+ krb5_err(context, 1, status, "krb5_read_message");
+
+ status = krb5_parse_name(context, client_name.data, &in_creds.server);
+ if(status)
+ krb5_err(context, 1, status, "krb5_parse_name");
+
+ status = krb5_get_credentials(context, KRB5_GC_USER_USER, ccache,
+ &in_creds, &out_creds);
+ if(status)
+ krb5_err(context, 1, status, "krb5_get_credentials");
+ krb5_cc_close(context, ccache);
+ ccache = NULL;
+
+ status = krb5_cc_default(context, &ccache);
+ if(status)
+ krb5_err(context, 1, status, "krb5_cc_default");
+
+ status = krb5_sendauth(context,
+ &auth_context,
+ &sock,
+ VERSION,
+ in_creds.client,
+ in_creds.server,
+ AP_OPTS_USE_SESSION_KEY,
+ NULL,
+ out_creds,
+ ccache,
+ NULL,
+ NULL,
+ NULL);
+ krb5_cc_close(context, ccache);
+ ccache = NULL;
+
+ if (status)
+ krb5_err(context, 1, status, "krb5_sendauth");
+
+ {
+ char *str;
+ krb5_unparse_name(context, in_creds.server, &str);
+ printf ("User is `%s'\n", str);
+ free(str);
+ krb5_unparse_name(context, in_creds.client, &str);
+ printf ("Server is `%s'\n", str);
+ free(str);
+ }
+
+ krb5_free_principal(context, in_creds.client);
+ krb5_free_principal(context, in_creds.server);
+
+ krb5_data_zero (&data);
+ krb5_data_zero (&packet);
+
+ status = krb5_read_message(context, &sock, &packet);
+ if(status)
+ krb5_err(context, 1, status, "krb5_read_message");
+
+ status = krb5_rd_safe (context,
+ auth_context,
+ &packet,
+ &data,
+ NULL);
+ if (status)
+ krb5_err(context, 1, status, "krb5_rd_safe");
+
+ printf ("safe packet: %.*s\n", (int)data.length,
+ (char *)data.data);
+
+ status = krb5_read_message(context, &sock, &packet);
+ if(status)
+ krb5_err(context, 1, status, "krb5_read_message");
+
+ status = krb5_rd_priv (context,
+ auth_context,
+ &packet,
+ &data,
+ NULL);
+ if (status)
+ krb5_err(context, 1, status, "krb5_rd_priv");
+
+ printf ("priv packet: %.*s\n", (int)data.length,
+ (char *)data.data);
+
+ return 0;
+}
+
+static int
+doit (int port, const char *service)
+{
+ rk_socket_t sock;
+
+ mini_inetd(port, &sock);
+
+ return proto(sock, service);
+}
+
+int
+main(int argc, char **argv)
+{
+ int port = server_setup(&context, argc, argv);
+ return doit (port, service);
+}