diff options
Diffstat (limited to 'third_party/heimdal/appl/test')
18 files changed, 3237 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..baf13ec --- /dev/null +++ b/third_party/heimdal/appl/test/gssapi_server.c @@ -0,0 +1,401 @@ +/* + * 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; + + 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..24c4e6e --- /dev/null +++ b/third_party/heimdal/appl/test/http_client.c @@ -0,0 +1,513 @@ +/* + * 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; + + 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 (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); +} |