summaryrefslogtreecommitdiffstats
path: root/utils/gssd/context_heimdal.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 06:03:02 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 06:03:02 +0000
commit4897093455a2bf08f3db3a1132cc2f6f5484d77c (patch)
tree9e6373544263f003139431fb4b08f9766e1ed530 /utils/gssd/context_heimdal.c
parentInitial commit. (diff)
downloadnfs-utils-upstream.tar.xz
nfs-utils-upstream.zip
Adding upstream version 1:2.6.4.upstream/1%2.6.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'utils/gssd/context_heimdal.c')
-rw-r--r--utils/gssd/context_heimdal.c275
1 files changed, 275 insertions, 0 deletions
diff --git a/utils/gssd/context_heimdal.c b/utils/gssd/context_heimdal.c
new file mode 100644
index 0000000..d07103b
--- /dev/null
+++ b/utils/gssd/context_heimdal.c
@@ -0,0 +1,275 @@
+/*
+ Copyright (c) 2004-2006 The Regents of the University of Michigan.
+ 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 University 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 ``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 REGENTS 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.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#ifndef HAVE_LUCID_CONTEXT_SUPPORT
+#ifdef HAVE_HEIMDAL
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <syslog.h>
+#include <string.h>
+#include <errno.h>
+#include <krb5.h>
+#include <gssapi.h> /* Must use the heimdal copy! */
+#ifdef HAVE_COM_ERR_H
+#include <com_err.h>
+#endif
+#include "err_util.h"
+#include "gss_oids.h"
+#include "write_bytes.h"
+
+int write_heimdal_keyblock(char **p, char *end, krb5_keyblock *key)
+{
+ gss_buffer_desc tmp;
+ int code = -1;
+
+ if (WRITE_BYTES(p, end, key->keytype)) goto out_err;
+ tmp.length = key->keyvalue.length;
+ tmp.value = key->keyvalue.data;
+ if (write_buffer(p, end, &tmp)) goto out_err;
+ code = 0;
+ out_err:
+ return(code);
+}
+
+int write_heimdal_enc_key(char **p, char *end, gss_ctx_id_t ctx)
+{
+ krb5_keyblock enc_key, *key;
+ krb5_context context;
+ krb5_error_code ret;
+ int i;
+ char *skd, *dkd, *k5err = NULL;
+ int code = -1;
+
+ if ((ret = krb5_init_context(&context))) {
+ k5err = gssd_k5_err_msg(NULL, ret);
+ printerr(0, "ERROR: initializing krb5_context: %s\n", k5err);
+ goto out_err;
+ }
+
+ if ((ret = krb5_auth_con_getlocalsubkey(context,
+ ctx->auth_context, &key))){
+ k5err = gssd_k5_err_msg(context, ret);
+ printerr(0, "ERROR: getting auth_context key: %s\n", k5err);
+ goto out_err_free_context;
+ }
+
+ memset(&enc_key, 0, sizeof(enc_key));
+ enc_key.keytype = key->keytype;
+ /* XXX current kernel code only handles des-cbc-raw (4) */
+ if (enc_key.keytype != 4) {
+ printerr(1, "WARN: write_heimdal_enc_key: "
+ "overriding heimdal keytype (%d => %d)\n",
+ enc_key.keytype, 4);
+ enc_key.keytype = 4;
+ }
+ enc_key.keyvalue.length = key->keyvalue.length;
+ if ((enc_key.keyvalue.data =
+ calloc(1, enc_key.keyvalue.length)) == NULL) {
+ k5err = gssd_k5_err_msg(context, ENOMEM);
+ printerr(0, "ERROR: allocating memory for enc key: %s\n",
+ k5err);
+ goto out_err_free_key;
+ }
+ skd = (char *) key->keyvalue.data;
+ dkd = (char *) enc_key.keyvalue.data;
+ for (i = 0; i < enc_key.keyvalue.length; i++)
+ dkd[i] = skd[i] ^ 0xf0;
+ if (write_heimdal_keyblock(p, end, &enc_key)) {
+ goto out_err_free_enckey;
+ }
+
+ code = 0;
+
+ out_err_free_enckey:
+ krb5_free_keyblock_contents(context, &enc_key);
+ out_err_free_key:
+ krb5_free_keyblock(context, key);
+ out_err_free_context:
+ krb5_free_context(context);
+ out_err:
+ free(k5err);
+ printerr(2, "write_heimdal_enc_key: %s\n", code ? "FAILED" : "SUCCESS");
+ return(code);
+}
+
+int write_heimdal_seq_key(char **p, char *end, gss_ctx_id_t ctx)
+{
+ krb5_keyblock *key;
+ krb5_context context;
+ krb5_error_code ret;
+ char *k5err = NULL;
+ int code = -1;
+
+ if ((ret = krb5_init_context(&context))) {
+ k5err = gssd_k5_err_msg(NULL, ret);
+ printerr(0, "ERROR: initializing krb5_context: %s\n", k5err);
+ goto out_err;
+ }
+
+ if ((ret = krb5_auth_con_getlocalsubkey(context,
+ ctx->auth_context, &key))){
+ k5err = gssd_k5_err_msg(context, ret);
+ printerr(0, "ERROR: getting auth_context key: %s\n", k5err);
+ goto out_err_free_context;
+ }
+
+ /* XXX current kernel code only handles des-cbc-raw (4) */
+ if (key->keytype != 4) {
+ printerr(1, "WARN: write_heimdal_seq_key: "
+ "overriding heimdal keytype (%d => %d)\n",
+ key->keytype, 4);
+ key->keytype = 4;
+ }
+
+ if (write_heimdal_keyblock(p, end, key)) {
+ goto out_err_free_key;
+ }
+
+ code = 0;
+
+ out_err_free_key:
+ krb5_free_keyblock(context, key);
+ out_err_free_context:
+ krb5_free_context(context);
+ out_err:
+ free(k5err);
+ printerr(2, "write_heimdal_seq_key: %s\n", code ? "FAILED" : "SUCCESS");
+ return(code);
+}
+
+/*
+ * The following is the kernel structure that we are filling in:
+ *
+ * struct krb5_ctx {
+ * int initiate;
+ * int seed_init;
+ * unsigned char seed[16];
+ * int signalg;
+ * int sealalg;
+ * struct crypto_tfm *enc;
+ * struct crypto_tfm *seq;
+ * s32 endtime;
+ * u32 seq_send;
+ * struct xdr_netobj mech_used;
+ * };
+ *
+ * However, note that we do not send the data fields in the
+ * order they appear in the structure. The order they are
+ * sent down in is:
+ *
+ * initiate
+ * seed_init
+ * seed
+ * signalg
+ * sealalg
+ * endtime
+ * seq_send
+ * mech_used
+ * enc key
+ * seq key
+ *
+ */
+
+int
+serialize_krb5_ctx(gss_ctx_id_t *_ctx, gss_buffer_desc *buf, int32_t *endtime)
+{
+ gss_ctx_id_t ctx = *_ctx;
+ char *p, *end;
+ static int constant_one = 1;
+ static int constant_zero = 0;
+ unsigned char fakeseed[16];
+ uint32_t algorithm;
+
+ if (!(buf->value = calloc(1, MAX_CTX_LEN)))
+ goto out_err;
+ p = buf->value;
+ end = buf->value + MAX_CTX_LEN;
+
+
+ /* initiate: 1 => initiating 0 => accepting */
+ if (ctx->more_flags & LOCAL) {
+ if (WRITE_BYTES(&p, end, constant_one)) goto out_err;
+ }
+ else {
+ if (WRITE_BYTES(&p, end, constant_zero)) goto out_err;
+ }
+
+ /* seed_init: not used by kernel code */
+ if (WRITE_BYTES(&p, end, constant_zero)) goto out_err;
+
+ /* seed: not used by kernel code */
+ memset(&fakeseed, 0, sizeof(fakeseed));
+ if (write_bytes(&p, end, &fakeseed, 16)) goto out_err;
+
+ /* signalg */
+ algorithm = 0; /* SGN_ALG_DES_MAC_MD5 XXX */
+ if (WRITE_BYTES(&p, end, algorithm)) goto out_err;
+
+ /* sealalg */
+ algorithm = 0; /* SEAL_ALG_DES XXX */
+ if (WRITE_BYTES(&p, end, algorithm)) goto out_err;
+
+ /* endtime */
+ if (WRITE_BYTES(&p, end, ctx->lifetime)) goto out_err;
+
+ if (endtime)
+ *endtime = ctx->lifetime;
+
+ /* seq_send */
+ if (WRITE_BYTES(&p, end, ctx->auth_context->local_seqnumber))
+ goto out_err;
+ /* mech_used */
+ if (write_buffer(&p, end, (gss_buffer_desc*)&krb5oid)) goto out_err;
+
+ /* enc: derive the encryption key and copy it into buffer */
+ if (write_heimdal_enc_key(&p, end, ctx)) goto out_err;
+
+ /* seq: get the sequence number key and copy it into buffer */
+ if (write_heimdal_seq_key(&p, end, ctx)) goto out_err;
+
+ buf->length = p - (char *)buf->value;
+ printerr(4, "serialize_krb5_ctx: returning buffer "
+ "with %d bytes\n", buf->length);
+
+ return 0;
+out_err:
+ printerr(0, "ERROR: failed exporting Heimdal krb5 ctx to kernel\n");
+ if (buf->value) free(buf->value);
+ buf->length = 0;
+ return -1;
+}
+
+#endif /* HAVE_HEIMDAL */
+#endif /* HAVE_LUCID_CONTEXT_SUPPORT */