diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 17:20:00 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 17:20:00 +0000 |
commit | 8daa83a594a2e98f39d764422bfbdbc62c9efd44 (patch) | |
tree | 4099e8021376c7d8c05bdf8503093d80e9c7bad0 /third_party/heimdal/appl/gssmask | |
parent | Initial commit. (diff) | |
download | samba-8daa83a594a2e98f39d764422bfbdbc62c9efd44.tar.xz samba-8daa83a594a2e98f39d764422bfbdbc62c9efd44.zip |
Adding upstream version 2:4.20.0+dfsg.upstream/2%4.20.0+dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | third_party/heimdal/appl/gssmask/Makefile.am | 13 | ||||
-rw-r--r-- | third_party/heimdal/appl/gssmask/NTMakefile | 35 | ||||
-rw-r--r-- | third_party/heimdal/appl/gssmask/common.c | 97 | ||||
-rw-r--r-- | third_party/heimdal/appl/gssmask/common.h | 114 | ||||
-rw-r--r-- | third_party/heimdal/appl/gssmask/gssmaestro.c | 962 | ||||
-rw-r--r-- | third_party/heimdal/appl/gssmask/gssmask.c | 1272 | ||||
-rw-r--r-- | third_party/heimdal/appl/gssmask/protocol.h | 317 |
7 files changed, 2810 insertions, 0 deletions
diff --git a/third_party/heimdal/appl/gssmask/Makefile.am b/third_party/heimdal/appl/gssmask/Makefile.am new file mode 100644 index 0000000..55673a0 --- /dev/null +++ b/third_party/heimdal/appl/gssmask/Makefile.am @@ -0,0 +1,13 @@ +# $Id$ + +include $(top_srcdir)/Makefile.am.common + +noinst_PROGRAMS = gssmask gssmaestro + +gssmask_SOURCES = gssmask.c common.c common.h protocol.h + +gssmaestro_SOURCES = gssmaestro.c common.c common.h protocol.h + +LDADD = $(top_builddir)/lib/gssapi/libgssapi.la $(LIB_roken) $(top_builddir)/lib/krb5/libkrb5.la + +EXTRA_DIST = NTMakefile diff --git a/third_party/heimdal/appl/gssmask/NTMakefile b/third_party/heimdal/appl/gssmask/NTMakefile new file mode 100644 index 0000000..4ad1dc4 --- /dev/null +++ b/third_party/heimdal/appl/gssmask/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\gssmask + +!include ../../windows/NTMakefile.w32 + diff --git a/third_party/heimdal/appl/gssmask/common.c b/third_party/heimdal/appl/gssmask/common.c new file mode 100644 index 0000000..733db90 --- /dev/null +++ b/third_party/heimdal/appl/gssmask/common.c @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2006 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 KTH 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 KTH AND ITS 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 KTH OR ITS 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 <common.h> +RCSID("$Id$"); + +krb5_error_code +store_string(krb5_storage *sp, const char *str) +{ + size_t len = strlen(str) + 1; + krb5_error_code ret; + + ret = krb5_store_int32(sp, len); + if (ret) + return ret; + ret = krb5_storage_write(sp, str, len); + if (ret != len) + return EINVAL; + return 0; +} + +static void +add_list(char ****list, size_t *listlen, char **str, size_t len) +{ + size_t i; + *list = erealloc(*list, sizeof(**list) * (*listlen + 1)); + + (*list)[*listlen] = ecalloc(len, sizeof(***list)); + for (i = 0; i < len; i++) + (*list)[*listlen][i] = str[i]; + (*listlen)++; +} + +static void +permute(char ****list, size_t *listlen, + char **str, const int start, const int len) +{ + int i, j; + +#define SWAP(s,i,j) { char *t = str[i]; str[i] = str[j]; str[j] = t; } + + for (i = start; i < len - 1; i++) { + for (j = i+1; j < len; j++) { + SWAP(str,i,j); + permute(list, listlen, str, i+1, len); + SWAP(str,i,j); + } + } + add_list(list, listlen, str, len); +} + +char *** +permutate_all(struct getarg_strings *strings, size_t *size) +{ + char **list, ***all = NULL; + int i; + + *size = 0; + + list = ecalloc(strings->num_strings, sizeof(*list)); + for (i = 0; i < strings->num_strings; i++) + list[i] = strings->strings[i]; + + permute(&all, size, list, 0, strings->num_strings); + free(list); + return all; +} diff --git a/third_party/heimdal/appl/gssmask/common.h b/third_party/heimdal/appl/gssmask/common.h new file mode 100644 index 0000000..96d10ff --- /dev/null +++ b/third_party/heimdal/appl/gssmask/common.h @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2006 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 KTH 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 KTH AND ITS 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 KTH OR ITS 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 <sys/param.h> +#ifdef HAVE_SYS_UTSNAME_H +#include <sys/utsname.h> +#endif + +#ifdef HAVE_SYS_WAIT_H +#include <sys/wait.h> +#endif + +#include <assert.h> +#include <krb5.h> +#include <gssapi/gssapi.h> +#include <gssapi/gssapi_krb5.h> +#include <gssapi/gssapi_spnego.h> +#include <unistd.h> + +#include <roken.h> +#include <getarg.h> + +#include "protocol.h" + +/* + * pthread support is disable because the pthread + * test have no "application pthread libflags" variable, + * when this is fixed pthread support can be enabled again. + */ +#undef ENABLE_PTHREAD_SUPPORT + +krb5_error_code store_string(krb5_storage *, const char *); + + +#define ret16(_client, num) \ + do { \ + if (krb5_ret_int16((_client)->sock, &(num)) != 0) \ + errx(1, "krb5_ret_int16 " #num); \ + } while(0) + +#define ret32(_client, num) \ + do { \ + if (krb5_ret_int32((_client)->sock, &(num)) != 0) \ + errx(1, "krb5_ret_int32 " #num); \ + } while(0) + +#define retdata(_client, data) \ + do { \ + if (krb5_ret_data((_client)->sock, &(data)) != 0) \ + errx(1, "krb5_ret_data " #data); \ + } while(0) + +#define retstring(_client, data) \ + do { \ + if (krb5_ret_string((_client)->sock, &(data)) != 0) \ + errx(1, "krb5_ret_data " #data); \ + } while(0) + + +#define put32(_client, num) \ + do { \ + if (krb5_store_int32((_client)->sock, num) != 0) \ + errx(1, "krb5_store_int32 " #num); \ + } while(0) + +#define putdata(_client, data) \ + do { \ + if (krb5_store_data((_client)->sock, data) != 0) \ + errx(1, "krb5_store_data " #data); \ + } while(0) + +#define putstring(_client, str) \ + do { \ + if (store_string((_client)->sock, str) != 0) \ + errx(1, "krb5_store_str " #str); \ + } while(0) + +char *** permutate_all(struct getarg_strings *, size_t *); diff --git a/third_party/heimdal/appl/gssmask/gssmaestro.c b/third_party/heimdal/appl/gssmask/gssmaestro.c new file mode 100644 index 0000000..9ccf1de --- /dev/null +++ b/third_party/heimdal/appl/gssmask/gssmaestro.c @@ -0,0 +1,962 @@ +/* + * Copyright (c) 2006 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 KTH 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 KTH AND ITS 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 KTH OR ITS 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 <common.h> +RCSID("$Id$"); + +static FILE *logfile; + +/* + * + */ + +struct client { + char *name; + struct sockaddr *sa; + socklen_t salen; + krb5_storage *sock; + int32_t capabilities; + char *target_name; + char *moniker; + krb5_storage *logsock; + int have_log; +#ifdef ENABLE_PTHREAD_SUPPORT + pthread_t thr; +#else + pid_t child; +#endif +}; + +static struct client **clients; +static int num_clients; + +static int +init_sec_context(struct client *client, + int32_t *hContext, int32_t *hCred, + int32_t flags, + const char *targetname, + const krb5_data *itoken, krb5_data *otoken) +{ + int32_t val; + krb5_data_zero(otoken); + put32(client, eInitContext); + put32(client, *hContext); + put32(client, *hCred); + put32(client, flags); + putstring(client, targetname); + putdata(client, *itoken); + ret32(client, *hContext); + ret32(client, val); + retdata(client, *otoken); + return val; +} + +static int +accept_sec_context(struct client *client, + int32_t *hContext, + int32_t flags, + const krb5_data *itoken, + krb5_data *otoken, + int32_t *hDelegCred) +{ + int32_t val; + krb5_data_zero(otoken); + put32(client, eAcceptContext); + put32(client, *hContext); + put32(client, flags); + putdata(client, *itoken); + ret32(client, *hContext); + ret32(client, val); + retdata(client, *otoken); + ret32(client, *hDelegCred); + return val; +} + +static int +acquire_cred(struct client *client, + const char *username, + const char *password, + int32_t flags, + int32_t *hCred) +{ + int32_t val; + put32(client, eAcquireCreds); + putstring(client, username); + putstring(client, password); + put32(client, flags); + ret32(client, val); + ret32(client, *hCred); + return val; +} + +static int +toast_resource(struct client *client, + int32_t hCred) +{ + int32_t val; + put32(client, eToastResource); + put32(client, hCred); + ret32(client, val); + return val; +} + +static int +goodbye(struct client *client) +{ + put32(client, eGoodBye); + return GSMERR_OK; +} + +static int +get_targetname(struct client *client, + char **target) +{ + put32(client, eGetTargetName); + retstring(client, *target); + return GSMERR_OK; +} + +static int32_t +encrypt_token(struct client *client, int32_t hContext, int32_t flags, + krb5_data *in, krb5_data *out) +{ + int32_t val; + put32(client, eEncrypt); + put32(client, hContext); + put32(client, flags); + put32(client, 0); + putdata(client, *in); + ret32(client, val); + retdata(client, *out); + return val; +} + +static int32_t +decrypt_token(struct client *client, int32_t hContext, int flags, + krb5_data *in, krb5_data *out) +{ + int32_t val; + put32(client, eDecrypt); + put32(client, hContext); + put32(client, flags); + put32(client, 0); + putdata(client, *in); + ret32(client, val); + retdata(client, *out); + return val; +} + +static int32_t +wrap_token_ext(struct client *client, int32_t hContext, int32_t flags, + int32_t bflags, krb5_data *header, krb5_data *in, krb5_data *trailer, + krb5_data *out) +{ + int32_t val; + put32(client, eWrapExt); + put32(client, hContext); + put32(client, flags); + put32(client, bflags); + putdata(client, *header); + putdata(client, *in); + putdata(client, *trailer); + ret32(client, val); + retdata(client, *out); + return val; +} + +static int32_t +unwrap_token_ext(struct client *client, int32_t hContext, int32_t flags, + int32_t bflags, krb5_data *header, krb5_data *in, krb5_data *trailer, + krb5_data *out) +{ + int32_t val; + put32(client, eUnwrapExt); + put32(client, hContext); + put32(client, flags); + put32(client, bflags); + putdata(client, *header); + putdata(client, *in); + putdata(client, *trailer); + ret32(client, val); + retdata(client, *out); + return val; +} + +static int32_t +get_mic(struct client *client, int32_t hContext, + krb5_data *in, krb5_data *mic) +{ + int32_t val; + put32(client, eSign); + put32(client, hContext); + put32(client, 0); + put32(client, 0); + putdata(client, *in); + ret32(client, val); + retdata(client, *mic); + return val; +} + +static int32_t +verify_mic(struct client *client, int32_t hContext, + krb5_data *in, krb5_data *mic) +{ + int32_t val; + put32(client, eVerify); + put32(client, hContext); + put32(client, 0); + put32(client, 0); + putdata(client, *in); + putdata(client, *mic); + ret32(client, val); + return val; +} + + +static int32_t +get_version_capa(struct client *client, + int32_t *version, int32_t *capa, + char **version_str) +{ + put32(client, eGetVersionAndCapabilities); + ret32(client, *version); + ret32(client, *capa); + retstring(client, *version_str); + return GSMERR_OK; +} + +static int32_t +get_moniker(struct client *client, + char **moniker) +{ + put32(client, eGetMoniker); + retstring(client, *moniker); + return GSMERR_OK; +} + +static int +wait_log(struct client *c) +{ + int32_t port; + struct sockaddr_storage sast; + socklen_t salen = sizeof(sast); + krb5_socket_t sock, sock2; + int ret; + + memset(&sast, 0, sizeof(sast)); + + assert(sizeof(sast) >= c->salen); + + sock = socket(c->sa->sa_family, SOCK_STREAM, 0); + if (sock == rk_INVALID_SOCKET) + err(1, "failed to build socket for %s's logging port", c->moniker); + + sast.ss_family = c->sa->sa_family; + ret = bind(sock, (struct sockaddr *)&sast, c->salen); + if (ret < 0) + err(1, "failed to bind %s's logging port", c->moniker); + + if (listen(sock, SOMAXCONN) < 0) + err(1, "failed to listen %s's logging port", c->moniker); + + salen = sizeof(sast); + ret = getsockname(sock, (struct sockaddr *)&sast, &salen); + if (ret < 0) + err(1, "failed to get address of local socket for %s", c->moniker); + + port = socket_get_port((struct sockaddr *)&sast); + + put32(c, eSetLoggingSocket); + put32(c, ntohs(port)); + + salen = sizeof(sast); + sock2 = accept(sock, (struct sockaddr *)&sast, &salen); + if (sock2 == rk_INVALID_SOCKET) + err(1, "failed to accept local socket for %s", c->moniker); + rk_closesocket(sock); + + return sock2; +} + + + + +static int +build_context(struct client *ipeer, struct client *apeer, + int32_t flags, int32_t hCred, + int32_t *iContext, int32_t *aContext, int32_t *hDelegCred) +{ + int32_t val = GSMERR_ERROR, ic = 0, ac = 0, deleg = 0; + krb5_data itoken, otoken; + int iDone = 0, aDone = 0; + int step = 0; + int first_call = 0x80; + + if (apeer->target_name == NULL) + errx(1, "apeer %s have no target name", apeer->name); + + krb5_data_zero(&itoken); + + while (!iDone || !aDone) { + + if (iDone) { + warnx("iPeer already done, aPeer want extra rtt"); + val = GSMERR_ERROR; + goto out; + } + + val = init_sec_context(ipeer, &ic, &hCred, flags|first_call, + apeer->target_name, &itoken, &otoken); + step++; + switch(val) { + case GSMERR_OK: + iDone = 1; + if (aDone) + continue; + break; + case GSMERR_CONTINUE_NEEDED: + break; + default: + warnx("iPeer %s failed with %d (step %d)", + ipeer->name, (int)val, step); + goto out; + } + + if (aDone) { + warnx("aPeer already done, iPeer want extra rtt"); + val = GSMERR_ERROR; + goto out; + } + + val = accept_sec_context(apeer, &ac, flags|first_call, + &otoken, &itoken, &deleg); + step++; + switch(val) { + case GSMERR_OK: + aDone = 1; + if (iDone) + continue; + break; + case GSMERR_CONTINUE_NEEDED: + break; + default: + warnx("aPeer %s failed with %d (step %d)", + apeer->name, (int)val, step); + val = GSMERR_ERROR; + goto out; + } + first_call = 0; + val = GSMERR_OK; + } + + if (iContext == NULL || val != GSMERR_OK) { + if (ic) + toast_resource(ipeer, ic); + if (iContext) + *iContext = 0; + } else + *iContext = ic; + + if (aContext == NULL || val != GSMERR_OK) { + if (ac) + toast_resource(apeer, ac); + if (aContext) + *aContext = 0; + } else + *aContext = ac; + + if (hDelegCred == NULL || val != GSMERR_OK) { + if (deleg) + toast_resource(apeer, deleg); + if (hDelegCred) + *hDelegCred = 0; + } else + *hDelegCred = deleg; + +out: + return val; +} + +static void +test_mic(struct client *c1, int32_t hc1, struct client *c2, int32_t hc2) +{ + krb5_data msg, mic; + int32_t val; + + msg.data = "foo"; + msg.length = 3; + + krb5_data_zero(&mic); + + val = get_mic(c1, hc1, &msg, &mic); + if (val) + errx(1, "get_mic failed to host: %s", c1->moniker); + val = verify_mic(c2, hc2, &msg, &mic); + if (val) + errx(1, "verify_mic failed to host: %s", c2->moniker); + + krb5_data_free(&mic); +} + +static int32_t +test_wrap(struct client *c1, int32_t hc1, struct client *c2, int32_t hc2, + int conf) +{ + krb5_data msg, wrapped, out; + int32_t val; + + msg.data = "foo"; + msg.length = 3; + + krb5_data_zero(&wrapped); + krb5_data_zero(&out); + + val = encrypt_token(c1, hc1, conf, &msg, &wrapped); + if (val) { + warnx("encrypt_token failed to host: %s", c1->moniker); + return val; + } + val = decrypt_token(c2, hc2, conf, &wrapped, &out); + if (val) { + krb5_data_free(&wrapped); + warnx("decrypt_token failed to host: %s", c2->moniker); + return val; + } + + if (msg.length != out.length) { + warnx("decrypted'ed token have wrong length (%lu != %lu)", + (unsigned long)msg.length, (unsigned long)out.length); + val = GSMERR_ERROR; + } else if (memcmp(msg.data, out.data, msg.length) != 0) { + warnx("decryptd'ed token have wrong data"); + val = GSMERR_ERROR; + } + + krb5_data_free(&wrapped); + krb5_data_free(&out); + return val; +} + +static int32_t +test_wrap_ext(struct client *c1, int32_t hc1, struct client *c2, int32_t hc2, + int conf, int bflags) +{ + krb5_data header, msg, trailer, wrapped, out; + int32_t val; + + header.data = "header"; + header.length = sizeof("header") - 1; + + msg.data = "0123456789abcdef"; /* padded for most enctypes */ + msg.length = sizeof("0123456789abcdef") - 1; + + trailer.data = "trailer"; + trailer.length = 7; + + krb5_data_zero(&wrapped); + krb5_data_zero(&out); + + val = wrap_token_ext(c1, hc1, conf, bflags, &header, &msg, &trailer, &wrapped); + if (val) { + warnx("encrypt_token failed to host: %s", c1->moniker); + return val; + } + val = unwrap_token_ext(c2, hc2, conf, bflags, &header, &wrapped, &trailer, &out); + if (val) { + krb5_data_free(&wrapped); + warnx("decrypt_token failed to host: %s", c2->moniker); + return val; + } + + if (msg.length != out.length) { + warnx("decrypted'ed token have wrong length (%lu != %lu)", + (unsigned long)msg.length, (unsigned long)out.length); + val = GSMERR_ERROR; + } else if (memcmp(msg.data, out.data, msg.length) != 0) { + warnx("decryptd'ed token have wrong data"); + val = GSMERR_ERROR; + } + + krb5_data_free(&wrapped); + krb5_data_free(&out); + return val; +} + + +static int32_t +test_token(struct client *c1, int32_t hc1, struct client *c2, int32_t hc2, int wrap_ext) +{ + int32_t val; + int i; + + for (i = 0; i < 10; i++) { + /* mic */ + test_mic(c1, hc1, c2, hc2); + test_mic(c2, hc2, c1, hc1); + + /* wrap */ + val = test_wrap(c1, hc1, c2, hc2, 0); + if (val) return val; + val = test_wrap(c2, hc2, c1, hc1, 0); + if (val) return val; + + val = test_wrap(c1, hc1, c2, hc2, 1); + if (val) return val; + val = test_wrap(c2, hc2, c1, hc1, 1); + if (val) return val; + + if (wrap_ext) { + /* wrap ext */ + val = test_wrap_ext(c1, hc1, c2, hc2, 1, 0); + if (val) return val; + val = test_wrap_ext(c2, hc2, c1, hc1, 1, 0); + if (val) return val; + + val = test_wrap_ext(c1, hc1, c2, hc2, 1, 1); + if (val) return val; + val = test_wrap_ext(c2, hc2, c1, hc1, 1, 1); + if (val) return val; + + val = test_wrap_ext(c1, hc1, c2, hc2, 0, 0); + if (val) return val; + val = test_wrap_ext(c2, hc2, c1, hc1, 0, 0); + if (val) return val; + + val = test_wrap_ext(c1, hc1, c2, hc2, 0, 1); + if (val) return val; + val = test_wrap_ext(c2, hc2, c1, hc1, 0, 1); + if (val) return val; + } + } + return GSMERR_OK; +} + +static int +log_function(void *ptr) +{ + struct client *c = ptr; + int32_t cmd, line; + char *file = NULL, *string = NULL; + + while (1) { + if (krb5_ret_int32(c->logsock, &cmd)) + goto out; + + switch (cmd) { + case eLogSetMoniker: + if (krb5_ret_string(c->logsock, &file)) + goto out; + break; + case eLogInfo: + case eLogFailure: + if (krb5_ret_string(c->logsock, &file)) + goto out; + if (krb5_ret_int32(c->logsock, &line)) + goto out; + if (krb5_ret_string(c->logsock, &string)) + goto out; + printf("%s:%lu: %s\n", + file, (unsigned long)line, string); + fprintf(logfile, "%s:%lu: %s\n", + file, (unsigned long)line, string); + fflush(logfile); + if (krb5_store_int32(c->logsock, 0)) + goto out; + break; + default: + errx(1, "client send bad log command: %d", (int)cmd); + } + } +out: + free(file); + free(string); + + return 0; +} + +static void +connect_client(const char *slave) +{ + char *name, *port; + struct client *c = ecalloc(1, sizeof(*c)); + struct addrinfo hints, *res0, *res; + int ret; + krb5_socket_t sock; + + name = estrdup(slave); + port = strchr(name, ':'); + if (port == NULL) + errx(1, "port missing from %s", name); + *port++ = 0; + + c->name = estrdup(slave); + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + + ret = getaddrinfo(name, port, &hints, &res0); + if (ret) + errx(1, "error resolving %s", name); + + for (res = res0, sock = rk_INVALID_SOCKET; res; res = res->ai_next) { + sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + if (sock == rk_INVALID_SOCKET) + continue; + if (connect(sock, res->ai_addr, res->ai_addrlen) < 0) { + rk_closesocket(sock); + sock = rk_INVALID_SOCKET; + continue; + } + c->sa = ecalloc(1, res->ai_addrlen); + memcpy(c->sa, res->ai_addr, res->ai_addrlen); + c->salen = res->ai_addrlen; + break; /* okay we got one */ + } + if (sock == rk_INVALID_SOCKET) + err(1, "connect to host: %s", name); + freeaddrinfo(res0); + + c->sock = krb5_storage_from_socket(sock); + rk_closesocket(sock); + if (c->sock == NULL) + errx(1, "krb5_storage_from_fd"); + + { + int32_t version; + char *str = NULL; + get_version_capa(c, &version, &c->capabilities, &str); + if (str) { + free(str); + } + if (c->capabilities & HAS_MONIKER) + get_moniker(c, &c->moniker); + else + c->moniker = c->name; + if (c->capabilities & ISSERVER) + get_targetname(c, &c->target_name); + } + + if (logfile) { + printf("starting log socket to client %s\n", c->moniker); + + sock = wait_log(c); + + c->logsock = krb5_storage_from_socket(sock); + rk_closesocket(sock); + if (c->logsock == NULL) + errx(1, "failed to create log krb5_storage"); +#ifdef ENABLE_PTHREAD_SUPPORT + pthread_create(&c->thr, NULL, log_function, c); +#else + c->child = fork(); + if (c->child == -1) + errx(1, "failed to fork"); + else if (c->child == 0) { + log_function(c); + fclose(logfile); + exit(0); + } +#endif + } + + + clients = erealloc(clients, (num_clients + 1) * sizeof(*clients)); + + clients[num_clients] = c; + num_clients++; + + free(name); +} + +static struct client * +get_client(const char *slave) +{ + size_t i; + for (i = 0; i < num_clients; i++) + if (strcmp(slave, clients[i]->name) == 0) + return clients[i]; + errx(1, "failed to find client %s", slave); +} + +/* + * + */ + +static int version_flag; +static int help_flag; +static int wrap_ext = 0; +static char *logfile_str; +static getarg_strings principals; +static getarg_strings slaves; + +struct getargs args[] = { + { "principals", 0, arg_strings, &principals, "Test principal", + NULL }, + { "slaves", 0, arg_strings, &slaves, "Slaves", + NULL }, + { "log-file", 0, arg_string, &logfile_str, "Logfile", + NULL }, + { "wrap-ext", 0, arg_flag, &wrap_ext, "test wrap extended", + NULL }, + { "version", 0, arg_flag, &version_flag, "Print version", + NULL }, + { "help", 0, arg_flag, &help_flag, NULL, + NULL } +}; + +static void +usage(int ret) +{ + arg_printusage (args, + sizeof(args) / sizeof(args[0]), + NULL, + ""); + exit (ret); +} + +int +main(int argc, char **argv) +{ + int optidx= 0; + char *user; + char *password; + char ***list, **p; + size_t num_list, i, j, k; + int failed = 0; + + setprogname (argv[0]); + + if (getarg (args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx)) + usage (1); + + if (help_flag) + usage (0); + + if (version_flag) { + print_version (NULL); + return 0; + } + + if (optidx != argc) + usage (1); + + if (principals.num_strings == 0) + errx(1, "no principals"); + + user = estrdup(principals.strings[0]); + password = strchr(user, ':'); + if (password == NULL) + errx(1, "password missing from %s", user); + *password++ = 0; + + if (slaves.num_strings == 0) + errx(1, "no principals"); + + if (logfile_str) { + printf("open logfile %s\n", logfile_str); + logfile = fopen(logfile_str, "w+"); + if (logfile == NULL) + err(1, "failed to open: %s", logfile_str); + } + + /* + * + */ + + list = permutate_all(&slaves, &num_list); + + /* + * Set up connection to all clients + */ + + printf("Connecting to slaves\n"); + for (i = 0; i < slaves.num_strings; i++) + connect_client(slaves.strings[i]); + + /* + * Test acquire credentials + */ + + printf("Test acquire credentials\n"); + for (i = 0; i < slaves.num_strings; i++) { + int32_t hCred, val; + + val = acquire_cred(clients[i], user, password, 1, &hCred); + if (val != GSMERR_OK) { + warnx("Failed to acquire_cred on host %s: %d", + clients[i]->moniker, (int)val); + failed = 1; + } else + toast_resource(clients[i], hCred); + } + + if (failed) + goto out; + + /* + * First test if all slaves can build context to them-self. + */ + + printf("Self context tests\n"); + for (i = 0; i < num_clients; i++) { + int32_t hCred, val, delegCred; + int32_t clientC, serverC; + struct client *c = clients[i]; + + if (c->target_name == NULL) + continue; + + printf("%s connects to self using %s\n", + c->moniker, c->target_name); + + val = acquire_cred(c, user, password, 1, &hCred); + if (val != GSMERR_OK) + errx(1, "failed to acquire_cred: %d", (int)val); + + val = build_context(c, c, + GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG| + GSS_C_INTEG_FLAG|GSS_C_CONF_FLAG| + GSS_C_DELEG_FLAG|GSS_C_MUTUAL_FLAG, + hCred, &clientC, &serverC, &delegCred); + if (val == GSMERR_OK) { + test_token(c, clientC, c, serverC, wrap_ext); + toast_resource(c, clientC); + toast_resource(c, serverC); + if (delegCred) + toast_resource(c, delegCred); + } else { + warnx("build_context failed: %d", (int)val); + } + /* + * + */ + + val = build_context(c, c, + GSS_C_INTEG_FLAG|GSS_C_CONF_FLAG, + hCred, &clientC, &serverC, &delegCred); + if (val == GSMERR_OK) { + test_token(c, clientC, c, serverC, wrap_ext); + toast_resource(c, clientC); + toast_resource(c, serverC); + if (delegCred) + toast_resource(c, delegCred); + } else { + warnx("build_context failed: %d", (int)val); + } + + toast_resource(c, hCred); + } + /* + * Build contexts though all entries in each lists, including the + * step from the last entry to the first, ie treat the list as a + * circle. + * + * Only follow the delegated credential, but test "all" + * flags. (XXX only do deleg|mutual right now. + */ + + printf("\"All\" permutation tests\n"); + + for (i = 0; i < num_list; i++) { + int32_t hCred, val, delegCred = 0; + int32_t clientC = 0, serverC = 0; + struct client *client, *server; + + p = list[i]; + + client = get_client(p[0]); + + val = acquire_cred(client, user, password, 1, &hCred); + if (val != GSMERR_OK) + errx(1, "failed to acquire_cred: %d", (int)val); + + for (j = 1; j < num_clients + 1; j++) { + server = get_client(p[j % num_clients]); + + if (server->target_name == NULL) + break; + + for (k = 1; k < j; k++) + printf("\t"); + printf("%s -> %s\n", client->moniker, server->moniker); + + val = build_context(client, server, + GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG| + GSS_C_INTEG_FLAG|GSS_C_CONF_FLAG| + GSS_C_DELEG_FLAG|GSS_C_MUTUAL_FLAG, + hCred, &clientC, &serverC, &delegCred); + if (val != GSMERR_OK) { + warnx("build_context failed: %d", (int)val); + break; + } + + val = test_token(client, clientC, server, serverC, wrap_ext); + if (val) + break; + + toast_resource(client, clientC); + toast_resource(server, serverC); + if (!delegCred) { + warnx("no delegated cred on %s", server->moniker); + break; + } + toast_resource(client, hCred); + hCred = delegCred; + client = server; + } + if (hCred) + toast_resource(client, hCred); + } + + /* + * Close all connections to clients + */ + +out: + printf("sending goodbye and waiting for log sockets\n"); + for (i = 0; i < num_clients; i++) { + goodbye(clients[i]); + if (clients[i]->logsock) { +#ifdef ENABLE_PTHREAD_SUPPORT + pthread_join(&clients[i]->thr, NULL); +#else + waitpid(clients[i]->child, NULL, 0); +#endif + } + } + + printf("done\n"); + + return 0; +} diff --git a/third_party/heimdal/appl/gssmask/gssmask.c b/third_party/heimdal/appl/gssmask/gssmask.c new file mode 100644 index 0000000..86a6713 --- /dev/null +++ b/third_party/heimdal/appl/gssmask/gssmask.c @@ -0,0 +1,1272 @@ +/* + * Copyright (c) 2006 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 KTH 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 KTH AND ITS 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 KTH OR ITS 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 "common.h" +RCSID("$Id$"); + +/* + * + */ + +enum handle_type { handle_context, handle_cred }; + +struct handle { + int32_t idx; + enum handle_type type; + void *ptr; + struct handle *next; +}; + +struct client { + krb5_storage *sock; + krb5_storage *logging; + char *moniker; + int32_t nHandle; + struct handle *handles; + struct sockaddr_storage sa; + socklen_t salen; + char servername[MAXHOSTNAMELEN]; +}; + +FILE *logfile; +static char *targetname; +krb5_context context; + +/* + * + */ + +static void +logmessage(struct client *c, const char *file, unsigned int lineno, + int level, const char *fmt, ...) +{ + char *message; + va_list ap; + int32_t ackid; + int ret; + + va_start(ap, fmt); + ret = vasprintf(&message, fmt, ap); + va_end(ap); + if (ret == -1) + errx(1, "out of memory"); + + if (logfile) + fprintf(logfile, "%s:%u: %d %s\n", file, lineno, level, message); + + if (c->logging) { + if (krb5_store_int32(c->logging, eLogInfo) != 0) + errx(1, "krb5_store_int32: log level"); + if (krb5_store_string(c->logging, file) != 0) + errx(1, "krb5_store_string: filename"); + if (krb5_store_int32(c->logging, lineno) != 0) + errx(1, "krb5_store_string: filename"); + if (krb5_store_string(c->logging, message) != 0) + errx(1, "krb5_store_string: message"); + if (krb5_ret_int32(c->logging, &ackid) != 0) + errx(1, "krb5_ret_int32: ackid"); + } + free(message); +} + +/* + * + */ + +static int32_t +add_handle(struct client *c, enum handle_type type, void *data) +{ + struct handle *h; + + h = ecalloc(1, sizeof(*h)); + + h->idx = ++c->nHandle; + h->type = type; + h->ptr = data; + h->next = c->handles; + c->handles = h; + + return h->idx; +} + +static void +del_handle(struct handle **h, int32_t idx) +{ + OM_uint32 min_stat; + + if (idx == 0) + return; + + while (*h) { + if ((*h)->idx == idx) { + struct handle *p = *h; + *h = (*h)->next; + switch(p->type) { + case handle_context: { + gss_ctx_id_t c = p->ptr; + gss_delete_sec_context(&min_stat, &c, NULL); + break; } + case handle_cred: { + gss_cred_id_t c = p->ptr; + gss_release_cred(&min_stat, &c); + break; } + } + free(p); + return; + } + h = &((*h)->next); + } + errx(1, "tried to delete an unexisting handle"); +} + +static void * +find_handle(struct handle *h, int32_t idx, enum handle_type type) +{ + if (idx == 0) + return NULL; + + while (h) { + if (h->idx == idx) { + if (type == h->type) + return h->ptr; + errx(1, "monger switched type on handle!"); + } + h = h->next; + } + return NULL; +} + + +static int32_t +convert_gss_to_gsm(OM_uint32 maj_stat) +{ + switch(maj_stat) { + case 0: + return GSMERR_OK; + case GSS_S_CONTINUE_NEEDED: + return GSMERR_CONTINUE_NEEDED; + case GSS_S_DEFECTIVE_TOKEN: + return GSMERR_INVALID_TOKEN; + case GSS_S_BAD_MIC: + return GSMERR_AP_MODIFIED; + default: + return GSMERR_ERROR; + } +} + +static int32_t +convert_krb5_to_gsm(krb5_error_code ret) +{ + switch(ret) { + case 0: + return GSMERR_OK; + default: + return GSMERR_ERROR; + } +} + +/* + * + */ + +static int32_t +acquire_cred(struct client *c, + krb5_principal principal, + krb5_get_init_creds_opt *opt, + int32_t *handle) +{ + krb5_error_code ret; + krb5_creds cred; + krb5_ccache id; + gss_cred_id_t gcred; + OM_uint32 maj_stat, min_stat; + + *handle = 0; + + krb5_get_init_creds_opt_set_forwardable (opt, 1); + krb5_get_init_creds_opt_set_renew_life (opt, 3600 * 24 * 30); + + memset(&cred, 0, sizeof(cred)); + + ret = krb5_get_init_creds_password (context, + &cred, + principal, + NULL, + NULL, + NULL, + 0, + NULL, + opt); + if (ret) { + logmessage(c, __FILE__, __LINE__, 0, + "krb5_get_init_creds failed: %d", ret); + return convert_krb5_to_gsm(ret); + } + + ret = krb5_cc_new_unique(context, "MEMORY", NULL, &id); + if (ret) + krb5_err (context, 1, ret, "krb5_cc_initialize"); + + ret = krb5_cc_initialize (context, id, cred.client); + if (ret) + krb5_err (context, 1, ret, "krb5_cc_initialize"); + + ret = krb5_cc_store_cred (context, id, &cred); + if (ret) + krb5_err (context, 1, ret, "krb5_cc_store_cred"); + + krb5_free_cred_contents (context, &cred); + + maj_stat = gss_krb5_import_cred(&min_stat, + id, + NULL, + NULL, + &gcred); + krb5_cc_close(context, id); + if (maj_stat) { + logmessage(c, __FILE__, __LINE__, 0, + "krb5 import creds failed with: %d", maj_stat); + return convert_gss_to_gsm(maj_stat); + } + + *handle = add_handle(c, handle_cred, gcred); + + return 0; +} + + +/* + * + */ + +#define HandleOP(h) \ +handle##h(enum gssMaggotOp op, struct client *c) + +/* + * + */ + +static int +HandleOP(GetVersionInfo) +{ + put32(c, GSSMAGGOTPROTOCOL); + errx(1, "GetVersionInfo"); +} + +static int +HandleOP(GoodBye) +{ + struct handle *h = c->handles; + unsigned int i = 0; + + while (h) { + h = h->next; + i++; + } + + if (i) + logmessage(c, __FILE__, __LINE__, 0, + "Did not toast all resources: %d", i); + return 1; +} + +static int +HandleOP(InitContext) +{ + OM_uint32 maj_stat, min_stat, ret_flags; + int32_t hContext, hCred, flags; + krb5_data target_name, in_token; + int32_t new_context_id = 0, gsm_error = 0; + krb5_data out_token = { 0 , NULL }; + + gss_ctx_id_t ctx; + gss_cred_id_t creds; + gss_name_t gss_target_name; + gss_buffer_desc input_token; + gss_buffer_desc output_token = {0, 0}; + gss_OID oid = GSS_C_NO_OID; + gss_buffer_t input_token_ptr = GSS_C_NO_BUFFER; + + ret32(c, hContext); + ret32(c, hCred); + ret32(c, flags); + retdata(c, target_name); + retdata(c, in_token); + + logmessage(c, __FILE__, __LINE__, 0, + "targetname: <%.*s>", (int)target_name.length, + (char *)target_name.data); + + ctx = find_handle(c->handles, hContext, handle_context); + if (ctx == NULL) + hContext = 0; + creds = find_handle(c->handles, hCred, handle_cred); + if (creds == NULL) + abort(); + + input_token.length = target_name.length; + input_token.value = target_name.data; + + maj_stat = gss_import_name(&min_stat, + &input_token, + GSS_KRB5_NT_PRINCIPAL_NAME, + &gss_target_name); + if (GSS_ERROR(maj_stat)) { + logmessage(c, __FILE__, __LINE__, 0, + "import name creds failed with: %d", maj_stat); + gsm_error = convert_gss_to_gsm(maj_stat); + goto out; + } + + /* oid from flags */ + + if (in_token.length) { + input_token.length = in_token.length; + input_token.value = in_token.data; + input_token_ptr = &input_token; + if (ctx == NULL) + krb5_errx(context, 1, "initcreds, context NULL, but not first req"); + } else { + input_token.length = 0; + input_token.value = NULL; + if (ctx) + krb5_errx(context, 1, "initcreds, context not NULL, but first req"); + } + + if ((flags & GSS_C_DELEG_FLAG) != 0) + logmessage(c, __FILE__, __LINE__, 0, "init_sec_context delegating"); + if ((flags & GSS_C_DCE_STYLE) != 0) + logmessage(c, __FILE__, __LINE__, 0, "init_sec_context dce-style"); + + maj_stat = gss_init_sec_context(&min_stat, + creds, + &ctx, + gss_target_name, + oid, + flags & 0x7f, + 0, + NULL, + input_token_ptr, + NULL, + &output_token, + &ret_flags, + NULL); + if (GSS_ERROR(maj_stat)) { + if (hContext != 0) + del_handle(&c->handles, hContext); + new_context_id = 0; + logmessage(c, __FILE__, __LINE__, 0, + "gss_init_sec_context returns code: %d/%d", + maj_stat, min_stat); + } else { + if (input_token.length == 0) + new_context_id = add_handle(c, handle_context, ctx); + else + new_context_id = hContext; + } + + gsm_error = convert_gss_to_gsm(maj_stat); + + if (output_token.length) { + out_token.data = output_token.value; + out_token.length = output_token.length; + } + +out: + logmessage(c, __FILE__, __LINE__, 0, + "InitContext return code: %d", gsm_error); + + put32(c, new_context_id); + put32(c, gsm_error); + putdata(c, out_token); + + gss_release_name(&min_stat, &gss_target_name); + if (output_token.length) + gss_release_buffer(&min_stat, &output_token); + krb5_data_free(&in_token); + krb5_data_free(&target_name); + + return 0; +} + +static int +HandleOP(AcceptContext) +{ + OM_uint32 maj_stat, min_stat, ret_flags; + int32_t hContext, deleg_hcred, flags; + krb5_data in_token; + int32_t new_context_id = 0, gsm_error = 0; + krb5_data out_token = { 0 , NULL }; + + gss_ctx_id_t ctx; + gss_cred_id_t deleg_cred = GSS_C_NO_CREDENTIAL; + gss_buffer_desc input_token, output_token; + + ret32(c, hContext); + ret32(c, flags); + retdata(c, in_token); + + ctx = find_handle(c->handles, hContext, handle_context); + if (ctx == NULL) + hContext = 0; + + if (in_token.length) { + input_token.length = in_token.length; + input_token.value = in_token.data; + } else { + input_token.length = 0; + input_token.value = NULL; + } + + maj_stat = gss_accept_sec_context(&min_stat, + &ctx, + GSS_C_NO_CREDENTIAL, + &input_token, + GSS_C_NO_CHANNEL_BINDINGS, + NULL, + NULL, + &output_token, + &ret_flags, + NULL, + &deleg_cred); + if (GSS_ERROR(maj_stat)) { + if (hContext != 0) + del_handle(&c->handles, hContext); + logmessage(c, __FILE__, __LINE__, 0, + "gss_accept_sec_context returns code: %d/%d", + maj_stat, min_stat); + new_context_id = 0; + } else { + if (hContext == 0) + new_context_id = add_handle(c, handle_context, ctx); + else + new_context_id = hContext; + } + if (output_token.length) { + out_token.data = output_token.value; + out_token.length = output_token.length; + } + if ((ret_flags & GSS_C_DCE_STYLE) != 0) + logmessage(c, __FILE__, __LINE__, 0, "accept_sec_context dce-style"); + if ((ret_flags & GSS_C_DELEG_FLAG) != 0) { + deleg_hcred = add_handle(c, handle_cred, deleg_cred); + logmessage(c, __FILE__, __LINE__, 0, + "accept_context delegated handle: %d", deleg_hcred); + } else { + gss_release_cred(&min_stat, &deleg_cred); + deleg_hcred = 0; + } + + + gsm_error = convert_gss_to_gsm(maj_stat); + + put32(c, new_context_id); + put32(c, gsm_error); + putdata(c, out_token); + put32(c, deleg_hcred); + + if (output_token.length) + gss_release_buffer(&min_stat, &output_token); + krb5_data_free(&in_token); + + return 0; +} + +static int +HandleOP(ToastResource) +{ + int32_t handle; + + ret32(c, handle); + logmessage(c, __FILE__, __LINE__, 0, "toasting %d", handle); + del_handle(&c->handles, handle); + put32(c, GSMERR_OK); + + return 0; +} + +static int +HandleOP(AcquireCreds) +{ + char *name, *password; + int32_t gsm_error, flags, handle = 0; + krb5_principal principal = NULL; + krb5_get_init_creds_opt *opt = NULL; + krb5_error_code ret; + + retstring(c, name); + retstring(c, password); + ret32(c, flags); + + logmessage(c, __FILE__, __LINE__, 0, + "username: %s password: %s", name, password); + + ret = krb5_parse_name(context, name, &principal); + if (ret) { + gsm_error = convert_krb5_to_gsm(ret); + goto out; + } + + ret = krb5_get_init_creds_opt_alloc (context, &opt); + if (ret) + krb5_err(context, 1, ret, "krb5_get_init_creds_opt_alloc"); + + krb5_get_init_creds_opt_set_pa_password(context, opt, password, NULL); + + gsm_error = acquire_cred(c, principal, opt, &handle); + +out: + logmessage(c, __FILE__, __LINE__, 0, + "AcquireCreds handle: %d return code: %d", handle, gsm_error); + + if (opt) + krb5_get_init_creds_opt_free (context, opt); + if (principal) + krb5_free_principal(context, principal); + free(name); + free(password); + + put32(c, gsm_error); + put32(c, handle); + + return 0; +} + +static int +HandleOP(Sign) +{ + OM_uint32 maj_stat, min_stat; + int32_t hContext, flags, seqno; + krb5_data token; + gss_ctx_id_t ctx; + gss_buffer_desc input_token, output_token; + + ret32(c, hContext); + ret32(c, flags); + ret32(c, seqno); + retdata(c, token); + + ctx = find_handle(c->handles, hContext, handle_context); + if (ctx == NULL) + errx(1, "sign: reference to unknown context"); + + input_token.length = token.length; + input_token.value = token.data; + + maj_stat = gss_get_mic(&min_stat, ctx, 0, &input_token, + &output_token); + if (maj_stat != GSS_S_COMPLETE) + errx(1, "gss_get_mic failed"); + + krb5_data_free(&token); + + token.data = output_token.value; + token.length = output_token.length; + + put32(c, 0); /* XXX fix gsm_error */ + putdata(c, token); + + gss_release_buffer(&min_stat, &output_token); + + return 0; +} + +static int +HandleOP(Verify) +{ + OM_uint32 maj_stat, min_stat; + int32_t hContext, flags, seqno; + krb5_data msg, mic; + gss_ctx_id_t ctx; + gss_buffer_desc msg_token, mic_token; + gss_qop_t qop; + + ret32(c, hContext); + + ctx = find_handle(c->handles, hContext, handle_context); + if (ctx == NULL) + errx(1, "verify: reference to unknown context"); + + ret32(c, flags); + ret32(c, seqno); + retdata(c, msg); + + msg_token.length = msg.length; + msg_token.value = msg.data; + + retdata(c, mic); + + mic_token.length = mic.length; + mic_token.value = mic.data; + + maj_stat = gss_verify_mic(&min_stat, ctx, &msg_token, + &mic_token, &qop); + if (maj_stat != GSS_S_COMPLETE) + errx(1, "gss_verify_mic failed"); + + krb5_data_free(&mic); + krb5_data_free(&msg); + + put32(c, 0); /* XXX fix gsm_error */ + + return 0; +} + +static int +HandleOP(GetVersionAndCapabilities) +{ + int32_t cap = HAS_MONIKER; + char *name = NULL, *str = NULL; + int ret; + + if (targetname) + cap |= ISSERVER; /* is server */ + +#ifdef HAVE_UNAME + { + struct utsname ut; + if (uname(&ut) == 0) { + if (asprintf(&name, "%s-%s-%s", + ut.sysname, ut.version, ut.machine) == -1) { + errx(1, "out of memory"); + } + } + } +#endif + + ret = asprintf(&str, "gssmask %s %s", PACKAGE_STRING, + name ? name : "unknown"); + if (ret == -1) + errx(1, "out of memory"); + + put32(c, GSSMAGGOTPROTOCOL); + put32(c, cap); + putstring(c, str); + free(str); + free(name); + + return 0; +} + +static int +HandleOP(GetTargetName) +{ + if (targetname) + putstring(c, targetname); + else + putstring(c, ""); + return 0; +} + +static int +HandleOP(SetLoggingSocket) +{ + int32_t portnum; + krb5_socket_t sock; + int ret; + + ret32(c, portnum); + + logmessage(c, __FILE__, __LINE__, 0, + "logging port on peer is: %d", (int)portnum); + + socket_set_port((struct sockaddr *)(&c->sa), htons(portnum)); + + sock = socket(((struct sockaddr *)&c->sa)->sa_family, SOCK_STREAM, 0); + if (sock == rk_INVALID_SOCKET) + return 0; + + ret = connect(sock, (struct sockaddr *)&c->sa, c->salen); + if (ret < 0) { + logmessage(c, __FILE__, __LINE__, 0, "failed connect to log port: %s", + strerror(errno)); + rk_closesocket(sock); + return 0; + } + + if (c->logging) + krb5_storage_free(c->logging); + c->logging = krb5_storage_from_socket(sock); + rk_closesocket(sock); + + krb5_store_int32(c->logging, eLogSetMoniker); + store_string(c->logging, c->moniker); + + logmessage(c, __FILE__, __LINE__, 0, "logging turned on"); + + return 0; +} + + +static int +HandleOP(ChangePassword) +{ + errx(1, "ChangePassword"); +} + +static int +HandleOP(SetPasswordSelf) +{ + errx(1, "SetPasswordSelf"); +} + +static int +HandleOP(Wrap) +{ + OM_uint32 maj_stat, min_stat; + int32_t hContext, flags, seqno; + krb5_data token; + gss_ctx_id_t ctx; + gss_buffer_desc input_token, output_token; + int conf_state; + + ret32(c, hContext); + ret32(c, flags); + ret32(c, seqno); + retdata(c, token); + + ctx = find_handle(c->handles, hContext, handle_context); + if (ctx == NULL) + errx(1, "wrap: reference to unknown context"); + + input_token.length = token.length; + input_token.value = token.data; + + maj_stat = gss_wrap(&min_stat, ctx, flags, 0, &input_token, + &conf_state, &output_token); + if (maj_stat != GSS_S_COMPLETE) + errx(1, "gss_wrap failed"); + + krb5_data_free(&token); + + token.data = output_token.value; + token.length = output_token.length; + + put32(c, 0); /* XXX fix gsm_error */ + putdata(c, token); + + gss_release_buffer(&min_stat, &output_token); + + return 0; +} + + +static int +HandleOP(Unwrap) +{ + OM_uint32 maj_stat, min_stat; + int32_t hContext, flags, seqno; + krb5_data token; + gss_ctx_id_t ctx; + gss_buffer_desc input_token, output_token; + int conf_state; + gss_qop_t qop_state; + + ret32(c, hContext); + ret32(c, flags); + ret32(c, seqno); + retdata(c, token); + + ctx = find_handle(c->handles, hContext, handle_context); + if (ctx == NULL) + errx(1, "unwrap: reference to unknown context"); + + input_token.length = token.length; + input_token.value = token.data; + + maj_stat = gss_unwrap(&min_stat, ctx, &input_token, + &output_token, &conf_state, &qop_state); + + if (maj_stat != GSS_S_COMPLETE) + errx(1, "gss_unwrap failed: %d/%d", maj_stat, min_stat); + + krb5_data_free(&token); + if (maj_stat == GSS_S_COMPLETE) { + token.data = output_token.value; + token.length = output_token.length; + } else { + token.data = NULL; + token.length = 0; + } + put32(c, 0); /* XXX fix gsm_error */ + putdata(c, token); + + if (maj_stat == GSS_S_COMPLETE) + gss_release_buffer(&min_stat, &output_token); + + return 0; +} + +static int +HandleOP(Encrypt) +{ + return handleWrap(op, c); +} + +static int +HandleOP(Decrypt) +{ + return handleUnwrap(op, c); +} + +static int +HandleOP(ConnectLoggingService2) +{ + errx(1, "ConnectLoggingService2"); +} + +static int +HandleOP(GetMoniker) +{ + putstring(c, c->moniker); + return 0; +} + +static int +HandleOP(CallExtension) +{ + errx(1, "CallExtension"); +} + +static int +HandleOP(AcquirePKInitCreds) +{ + int32_t flags; + krb5_data pfxdata; + char fn[] = "FILE:/tmp/pkcs12-creds-XXXXXXX"; + int fd; + + ret32(c, flags); + retdata(c, pfxdata); + + fd = mkstemp(fn + 5); + if (fd < 0) + errx(1, "mkstemp"); + + net_write(fd, pfxdata.data, pfxdata.length); + krb5_data_free(&pfxdata); + close(fd); + + put32(c, -1); /* hResource */ + put32(c, GSMERR_NOT_SUPPORTED); + return 0; +} + +static int +HandleOP(WrapExt) +{ + OM_uint32 maj_stat, min_stat; + int32_t hContext, flags, bflags; + krb5_data token, header, trailer; + gss_ctx_id_t ctx; + unsigned char *p; + int conf_state, iov_len; + gss_iov_buffer_desc iov[6]; + + ret32(c, hContext); + ret32(c, flags); + ret32(c, bflags); + retdata(c, header); + retdata(c, token); + retdata(c, trailer); + + ctx = find_handle(c->handles, hContext, handle_context); + if (ctx == NULL) + errx(1, "wrap: reference to unknown context"); + + memset(&iov, 0, sizeof(iov)); + + iov_len = sizeof(iov)/sizeof(iov[0]); + + if (bflags & WRAP_EXP_ONLY_HEADER) + iov_len -= 2; /* skip trailer and padding, aka dce-style */ + + iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER | GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATE; + if (header.length != 0) { + iov[1].type = GSS_IOV_BUFFER_TYPE_SIGN_ONLY; + iov[1].buffer.length = header.length; + iov[1].buffer.value = header.data; + } else { + iov[1].type = GSS_IOV_BUFFER_TYPE_EMPTY; + } + iov[2].type = GSS_IOV_BUFFER_TYPE_DATA; + iov[2].buffer.length = token.length; + iov[2].buffer.value = token.data; + if (trailer.length != 0) { + iov[3].type = GSS_IOV_BUFFER_TYPE_SIGN_ONLY; + iov[3].buffer.length = trailer.length; + iov[3].buffer.value = trailer.data; + } else { + iov[3].type = GSS_IOV_BUFFER_TYPE_EMPTY; + } + iov[4].type = GSS_IOV_BUFFER_TYPE_PADDING | GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATE; + iov[5].type = GSS_IOV_BUFFER_TYPE_TRAILER | GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATE; + + maj_stat = gss_wrap_iov_length(&min_stat, ctx, flags, 0, &conf_state, + iov, iov_len); + if (maj_stat != GSS_S_COMPLETE) + errx(1, "gss_wrap_iov_length failed"); + + maj_stat = gss_wrap_iov(&min_stat, ctx, flags, 0, &conf_state, + iov, iov_len); + if (maj_stat != GSS_S_COMPLETE) + errx(1, "gss_wrap_iov failed"); + + krb5_data_free(&token); + + token.length = iov[0].buffer.length + iov[2].buffer.length + iov[4].buffer.length + iov[5].buffer.length; + token.data = malloc(token.length); + + p = token.data; + memcpy(p, iov[0].buffer.value, iov[0].buffer.length); + p += iov[0].buffer.length; + memcpy(p, iov[2].buffer.value, iov[2].buffer.length); + p += iov[2].buffer.length; + memcpy(p, iov[4].buffer.value, iov[4].buffer.length); + p += iov[4].buffer.length; + memcpy(p, iov[5].buffer.value, iov[5].buffer.length); +#if 0 /* Would be needed to keep going, but presently unused */ + p += iov[5].buffer.length; +#endif + + gss_release_iov_buffer(NULL, iov, iov_len); + + put32(c, 0); /* XXX fix gsm_error */ + putdata(c, token); + + free(token.data); + + return 0; +} + + +static int +HandleOP(UnwrapExt) +{ + OM_uint32 maj_stat, min_stat; + int32_t hContext, flags, bflags; + krb5_data token, header, trailer; + gss_ctx_id_t ctx; + gss_iov_buffer_desc iov[3]; + int conf_state, iov_len; + gss_qop_t qop_state; + + ret32(c, hContext); + ret32(c, flags); + ret32(c, bflags); + retdata(c, header); + retdata(c, token); + retdata(c, trailer); + + iov_len = sizeof(iov)/sizeof(iov[0]); + + if (bflags & WRAP_EXP_ONLY_HEADER) + iov_len -= 1; /* skip trailer and padding, aka dce-style */ + + ctx = find_handle(c->handles, hContext, handle_context); + if (ctx == NULL) + errx(1, "unwrap: reference to unknown context"); + + if (header.length != 0) { + iov[0].type = GSS_IOV_BUFFER_TYPE_SIGN_ONLY; + iov[0].buffer.length = header.length; + iov[0].buffer.value = header.data; + } else { + iov[0].type = GSS_IOV_BUFFER_TYPE_EMPTY; + } + iov[1].type = GSS_IOV_BUFFER_TYPE_DATA; + iov[1].buffer.length = token.length; + iov[1].buffer.value = token.data; + + if (trailer.length != 0) { + iov[2].type = GSS_IOV_BUFFER_TYPE_SIGN_ONLY; + iov[2].buffer.length = trailer.length; + iov[2].buffer.value = trailer.data; + } else { + iov[2].type = GSS_IOV_BUFFER_TYPE_EMPTY; + } + + maj_stat = gss_unwrap_iov(&min_stat, ctx, &conf_state, &qop_state, + iov, iov_len); + + if (maj_stat != GSS_S_COMPLETE) + errx(1, "gss_unwrap failed: %d/%d", maj_stat, min_stat); + + if (maj_stat == GSS_S_COMPLETE) { + token.data = iov[1].buffer.value; + token.length = iov[1].buffer.length; + } else { + token.data = NULL; + token.length = 0; + } + put32(c, 0); /* XXX fix gsm_error */ + putdata(c, token); + + return 0; +} + +/* + * + */ + +struct handler { + enum gssMaggotOp op; + const char *name; + int (*func)(enum gssMaggotOp, struct client *); +}; + +#define S(a) { e##a, #a, handle##a } + +struct handler handlers[] = { + S(GetVersionInfo), + S(GoodBye), + S(InitContext), + S(AcceptContext), + S(ToastResource), + S(AcquireCreds), + S(Encrypt), + S(Decrypt), + S(Sign), + S(Verify), + S(GetVersionAndCapabilities), + S(GetTargetName), + S(SetLoggingSocket), + S(ChangePassword), + S(SetPasswordSelf), + S(Wrap), + S(Unwrap), + S(ConnectLoggingService2), + S(GetMoniker), + S(CallExtension), + S(AcquirePKInitCreds), + S(WrapExt), + S(UnwrapExt), +}; + +#undef S + +/* + * + */ + +static struct handler * +find_op(int32_t op) +{ + int i; + + for (i = 0; i < sizeof(handlers)/sizeof(handlers[0]); i++) + if (handlers[i].op == op) + return &handlers[i]; + return NULL; +} + +static struct client * +create_client(krb5_socket_t sock, int port, const char *moniker) +{ + struct client *c; + int ret; + + c = ecalloc(1, sizeof(*c)); + + if (moniker) { + c->moniker = estrdup(moniker); + } else { + char hostname[MAXHOSTNAMELEN]; + gethostname(hostname, sizeof(hostname)); + ret = asprintf(&c->moniker, "gssmask: %s:%d", hostname, port); + if (ret == -1) + c->moniker = NULL; + } + + if (!c->moniker) + errx(1, "out of memory"); + + { + c->salen = sizeof(c->sa); + getpeername(sock, (struct sockaddr *)&c->sa, &c->salen); + + getnameinfo((struct sockaddr *)&c->sa, c->salen, + c->servername, sizeof(c->servername), + NULL, 0, NI_NUMERICHOST); + } + + c->sock = krb5_storage_from_socket(sock); + if (c->sock == NULL) + errx(1, "krb5_storage_from_socket"); + + rk_closesocket(sock); + + return c; +} + +static void +free_client(struct client *c) +{ + while(c->handles) + del_handle(&c->handles, c->handles->idx); + + free(c->moniker); + krb5_storage_free(c->sock); + if (c->logging) + krb5_storage_free(c->logging); + free(c); +} + + +static void * +handleServer(void *ptr) +{ + struct handler *handler; + struct client *c; + int32_t op; + + c = (struct client *)ptr; + + + while(1) { + ret32(c, op); + + handler = find_op(op); + if (handler == NULL) { + logmessage(c, __FILE__, __LINE__, 0, + "op %d not supported", (int)op); + exit(1); + } + + logmessage(c, __FILE__, __LINE__, 0, + "---> Got op %s from server %s", + handler->name, c->servername); + + if ((handler->func)(handler->op, c)) + break; + } + + return NULL; +} + + +static char *port_str; +static int version_flag; +static int help_flag; +static char *logfile_str; +static char *moniker_str; + +static int port = 4711; + +struct getargs args[] = { + { "spn", 0, arg_string, &targetname, "This host's SPN", + "service/host@REALM" }, + { "port", 'p', arg_string, &port_str, "Use this port", + "number-of-service" }, + { "logfile", 0, arg_string, &logfile_str, "logfile", + "number-of-service" }, + { "moniker", 0, arg_string, &moniker_str, "nickname", + "name" }, + { "version", 0, arg_flag, &version_flag, "Print version", + NULL }, + { "help", 0, arg_flag, &help_flag, NULL, + NULL } +}; + +static void +usage(int ret) +{ + arg_printusage (args, + sizeof(args) / sizeof(args[0]), + NULL, + ""); + exit (ret); +} + +int +main(int argc, char **argv) +{ + int optidx = 0; + krb5_error_code ret; + + setprogname (argv[0]); + + if (getarg (args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx)) + usage (1); + + if (help_flag) + usage (0); + + if (version_flag) { + print_version (NULL); + return 0; + } + + if (optidx != argc) + usage (1); + + if (port_str) { + char *ptr; + + port = strtol (port_str, &ptr, 10); + if (port == 0 && ptr == port_str) + errx (1, "Bad port `%s'", port_str); + } + + ret = krb5_init_context(&context); + if (ret) + errx(1, "Error initializing kerberos: %d", ret); + + { + const char *lf = logfile_str; + if (lf == NULL) + lf = "/dev/tty"; + + logfile = fopen(lf, "w"); + if (logfile == NULL) + err(1, "error opening %s", lf); + } + + mini_inetd(htons(port), NULL); + fprintf(logfile, "connected\n"); + + { + struct client *c; + + c = create_client(0, port, moniker_str); + /* close(0); */ + + handleServer(c); + + free_client(c); + } + + krb5_free_context(context); + + return 0; +} diff --git a/third_party/heimdal/appl/gssmask/protocol.h b/third_party/heimdal/appl/gssmask/protocol.h new file mode 100644 index 0000000..1e1f141 --- /dev/null +++ b/third_party/heimdal/appl/gssmask/protocol.h @@ -0,0 +1,317 @@ +/* + * Copyright (c) 2006 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 KTH 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 KTH AND ITS 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 KTH OR ITS 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$ + */ + +/* missing from tests: + * - export context + * - import context + */ + +/* + * wire encodings: + * int16: number, 2 bytes, in network order + * int32: number, 4 bytes, in network order + * length-encoded: [int32 length, data of length bytes] + * string: [int32 length, string of length + 1 bytes, includes trailing '\0' ] + */ + +enum gssMaggotErrorCodes { + GSMERR_OK = 0, + GSMERR_ERROR, + GSMERR_CONTINUE_NEEDED, + GSMERR_INVALID_TOKEN, + GSMERR_AP_MODIFIED, + GSMERR_TEST_ISSUE, + GSMERR_NOT_SUPPORTED +}; + +/* + * input: + * int32: message OP (enum gssMaggotProtocol) + * ... + * + * return: -- on error + * int32: not support (GSMERR_NOT_SUPPORTED) + * + * return: -- on existing message OP + * int32: support (GSMERR_OK) -- only sent for extensions + * ... + */ + +#define GSSMAGGOTPROTOCOL 14 + +enum gssMaggotOp { + eGetVersionInfo = 0, + /* + * input: + * none + * return: + * int32: last version handled + */ + eGoodBye, + /* + * input: + * none + * return: + * close socket + */ + eInitContext, + /* + * input: + * int32: hContext + * int32: hCred + * int32: Flags + * the lowest 0x7f flags maps directly to GSS-API flags + * DELEGATE 0x001 + * MUTUAL_AUTH 0x002 + * REPLAY_DETECT 0x004 + * SEQUENCE_DETECT 0x008 + * CONFIDENTIALITY 0x010 + * INTEGRITY 0x020 + * ANONYMOUS 0x040 + * + * FIRST_CALL 0x080 + * + * NTLM 0x100 + * SPNEGO 0x200 + * length-encoded: targetname + * length-encoded: token + * return: + * int32: hNewContextId + * int32: gssapi status val + * length-encoded: output token + */ + eAcceptContext, + /* + * input: + * int32: hContext + * int32: Flags -- unused ? + * flags are same as flags for eInitContext + * length-encoded: token + * return: + * int32: hNewContextId + * int32: gssapi status val + * length-encoded: output token + * int32: delegation cred id + */ + eToastResource, + /* + * input: + * int32: hResource + * return: + * int32: gsm status val + */ + eAcquireCreds, + /* + * input: + * string: principal name + * string: password + * int32: flags + * FORWARDABLE 0x001 + * DEFAULT_CREDS 0x002 + * + * NTLM 0x100 + * SPNEGO 0x200 + * return: + * int32: gsm status val + * int32: hCred + */ + eEncrypt, + /* + * input: + * int32: hContext + * int32: flags + * int32: seqno -- unused + * length-encode: plaintext + * return: + * int32: gsm status val + * length-encode: ciphertext + */ + eDecrypt, + /* + * input: + * int32: hContext + * int32: flags + * int32: seqno -- unused + * length-encode: ciphertext + * return: + * int32: gsm status val + * length-encode: plaintext + */ + eSign, + /* message same as eEncrypt */ + eVerify, + /* + * input: + * int32: hContext + * int32: flags + * int32: seqno -- unused + * length-encode: message + * length-encode: signature + * return: + * int32: gsm status val + */ + eGetVersionAndCapabilities, + /* + * return: + * int32: protocol version + * int32: capability flags */ +#define ISSERVER 0x01 +#define ISKDC 0x02 +#define MS_KERBEROS 0x04 +#define LOGSERVER 0x08 +#define HAS_MONIKER 0x10 + /* string: version string + */ + eGetTargetName, + /* + * return: + * string: target principal name + */ + eSetLoggingSocket, + /* + * input: + * int32: hostPort + * return to the port on the host: + * int32: opcode - for example eLogSetMoniker + */ + eChangePassword, + /* here ended version 7 of the protocol */ + /* + * input: + * string: principal name + * string: old password + * string: new password + * return: + * int32: gsm status val + */ + eSetPasswordSelf, + /* same as eChangePassword */ + eWrap, + /* message same as eEncrypt */ + eUnwrap, + /* message same as eDecrypt */ + eConnectLoggingService2, + /* + * return1: + * int16: log port number + * int32: master log prototocol version (0) + * + * wait for master to connect on the master log socket + * + * return2: + * int32: gsm connection status + * int32: maggot log prototocol version (2) + */ + eGetMoniker, + /* + * return: + * string: moniker (Nickname the master can refer to maggot) + */ + eCallExtension, + /* + * input: + * string: extension name + * int32: message id + * return: + * int32: gsm status val + */ + eAcquirePKInitCreds, + /* + * input: + * int32: flags + * length-encode: certificate (pkcs12 data) + * return: + * int32: hResource + * int32: gsm status val (GSMERR_NOT_SUPPORTED) + */ + /* here ended version 7 of the protocol */ + eWrapExt, + /* + * input: + * int32: hContext + * int32: flags + * int32: bflags + * length-encode: protocol header + * length-encode: plaintext + * length-encode: protocol trailer + * return: + * int32: gsm status val + * length-encode: ciphertext + */ + eUnwrapExt, + /* + * input: + * int32: hContext + * int32: flags + * int32: bflags + * length-encode: protocol header + * length-encode: ciphertext + * length-encode: protocol trailer + * return: + * int32: gsm status val + * length-encode: plaintext + */ + /* here ended version 8 of the protocol */ + + eLastProtocolMessage +}; + +/* bflags */ +#define WRAP_EXP_ONLY_HEADER 1 + +enum gssMaggotLogOp{ + eLogInfo = 0, + /* + string: File + int32: Line + string: message + reply: + int32: ackid + */ + eLogFailure, + /* + string: File + int32: Line + string: message + reply: + int32: ackid + */ + eLogSetMoniker + /* + string: moniker + */ +}; |