add missing files from previous update
authorneilbrown <neilbrown>
Tue, 28 Mar 2006 00:47:06 +0000 (00:47 +0000)
committerneilbrown <neilbrown>
Tue, 28 Mar 2006 00:47:06 +0000 (00:47 +0000)
utils/gssd/context_mit.c [new file with mode: 0644]
utils/gssd/context_spkm3.c [new file with mode: 0644]

diff --git a/utils/gssd/context_mit.c b/utils/gssd/context_mit.c
new file mode 100644 (file)
index 0000000..0af92a3
--- /dev/null
@@ -0,0 +1,335 @@
+/*
+  Copyright (c) 2004 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.
+*/
+
+#include "config.h"
+#include <stdio.h>
+#include <syslog.h>
+#include <string.h>
+#include <gssapi/gssapi.h>
+#include <rpc/rpc.h>
+#include <rpc/auth_gss.h>
+#include "gss_util.h"
+#include "gss_oids.h"
+#include "err_util.h"
+#include "context.h"
+
+#ifdef HAVE_KRB5
+#include <krb5.h>
+
+/* XXX spkm3 seems to actually want it this big, yipes. */
+#define MAX_CTX_LEN 4096
+
+#ifdef HAVE_LUCID_CONTEXT_SUPPORT
+
+/* Don't use the private structure, use the exported lucid structure */
+#include <gssapi/gssapi_krb5.h>
+
+#elif (KRB5_VERSION > 131)
+/* XXX argggg, there's gotta be a better way than just duplicating this
+ * whole struct.  Unfortunately, this is in a "private" header file,
+ * so this is our best choice at this point :-/
+ *
+ * XXX Does this match the Heimdal definition?  */
+
+typedef struct _krb5_gss_ctx_id_rec {
+   unsigned int initiate : 1;   /* nonzero if initiating, zero if accepting */
+   unsigned int established : 1;
+   unsigned int big_endian : 1;
+   unsigned int have_acceptor_subkey : 1;
+   unsigned int seed_init : 1;  /* XXX tested but never actually set */
+#ifdef CFX_EXERCISE
+   unsigned int testing_unknown_tokid : 1; /* for testing only */
+#endif
+   OM_uint32 gss_flags;
+   unsigned char seed[16];
+   krb5_principal here;
+   krb5_principal there;
+   krb5_keyblock *subkey;
+   int signalg;
+   size_t cksum_size;
+   int sealalg;
+   krb5_keyblock *enc;
+   krb5_keyblock *seq;
+   krb5_timestamp endtime;
+   krb5_flags krb_flags;
+   /* XXX these used to be signed.  the old spec is inspecific, and
+      the new spec specifies unsigned.  I don't believe that the change
+      affects the wire encoding. */
+   uint64_t seq_send;          /* gssint_uint64 */
+   uint64_t seq_recv;          /* gssint_uint64 */
+   void *seqstate;
+   krb5_auth_context auth_context;
+   gss_buffer_desc *mech_used; /* gss_OID_desc */
+    /* Protocol spec revision
+       0 => RFC 1964 with 3DES and RC4 enhancements
+       1 => draft-ietf-krb-wg-gssapi-cfx-01
+       No others defined so far.  */
+   int proto;
+   krb5_cksumtype cksumtype;    /* for "main" subkey */
+   krb5_keyblock *acceptor_subkey; /* CFX only */
+   krb5_cksumtype acceptor_subkey_cksumtype;
+#ifdef CFX_EXERCISE
+    gss_buffer_desc init_token;
+#endif
+} krb5_gss_ctx_id_rec, *krb5_gss_ctx_id_t;
+
+#else  /* KRB5_VERSION > 131 */
+
+typedef struct _krb5_gss_ctx_id_rec {
+       int initiate;
+       u_int32_t gss_flags;
+       int seed_init;
+       unsigned char seed[16];
+       krb5_principal here;
+       krb5_principal there;
+       krb5_keyblock *subkey;
+       int signalg;
+       int cksum_size;
+       int sealalg;
+       krb5_keyblock *enc;
+       krb5_keyblock *seq;
+       krb5_timestamp endtime;
+       krb5_flags krb_flags;
+       krb5_ui_4 seq_send;
+       krb5_ui_4 seq_recv;
+       void *seqstate;
+       int established;
+       int big_endian;
+       krb5_auth_context auth_context;
+       gss_buffer_desc *mech_used;
+       int nctypes;
+       krb5_cksumtype *ctypes;
+} krb5_gss_ctx_id_rec, *krb5_gss_ctx_id_t;
+
+#endif /* KRB5_VERSION */
+
+
+#ifdef HAVE_LUCID_CONTEXT_SUPPORT /* Lucid context support */
+static int
+write_lucid_keyblock(char **p, char *end, gss_krb5_lucid_key_t *key)
+{
+       gss_buffer_desc tmp;
+
+       if (WRITE_BYTES(p, end, key->type)) return -1;
+       tmp.length = key->length;
+       tmp.value = key->data;
+       if (write_buffer(p, end, &tmp)) return -1;
+       return 0;
+}
+
+static int
+prepare_krb5_rfc1964_buffer(gss_krb5_lucid_context_v1_t *lctx,
+       gss_buffer_desc *buf)
+{
+       char *p, *end;
+       static int constant_zero = 0;
+       unsigned char fakeseed[16];
+       uint32_t word_send_seq;
+       gss_krb5_lucid_key_t enc_key;
+       int i;
+       char *skd, *dkd;
+       gss_buffer_desc fakeoid;
+
+       /*
+        * The new Kerberos interface to get the gss context
+        * does not include the seed or seed_init fields
+        * because we never really use them.  But for now,
+        * send down a fake buffer so we can use the same
+        * interface to the kernel.
+        */
+       memset(&enc_key, 0, sizeof(enc_key));
+       memset(&fakeoid, 0, sizeof(fakeoid));
+
+       if (!(buf->value = calloc(1, MAX_CTX_LEN)))
+               goto out_err;
+       p = buf->value;
+       end = buf->value + MAX_CTX_LEN;
+
+       if (WRITE_BYTES(&p, end, lctx->initiate)) goto out_err;
+
+       /* seed_init and seed not used by kernel anyway */
+       if (WRITE_BYTES(&p, end, constant_zero)) goto out_err;
+       if (write_bytes(&p, end, &fakeseed, 16)) goto out_err;
+
+       if (WRITE_BYTES(&p, end, lctx->rfc1964_kd.sign_alg)) goto out_err;
+       if (WRITE_BYTES(&p, end, lctx->rfc1964_kd.seal_alg)) goto out_err;
+       if (WRITE_BYTES(&p, end, lctx->endtime)) goto out_err;
+       word_send_seq = lctx->send_seq; /* XXX send_seq is 64-bit */
+       if (WRITE_BYTES(&p, end, word_send_seq)) goto out_err;
+       if (write_buffer(&p, end, (gss_buffer_desc*)&krb5oid)) goto out_err;
+
+       /* derive the encryption key and copy it into buffer */
+       enc_key.type = lctx->rfc1964_kd.ctx_key.type;
+       enc_key.length = lctx->rfc1964_kd.ctx_key.length;
+       if ((enc_key.data = calloc(1, enc_key.length)) == NULL)
+               goto out_err;
+       skd = (char *) lctx->rfc1964_kd.ctx_key.data;
+       dkd = (char *) enc_key.data;
+       for (i = 0; i < enc_key.length; i++)
+               dkd[i] = skd[i] ^ 0xf0;
+       if (write_lucid_keyblock(&p, end, &enc_key)) {
+               free(enc_key.data);
+               goto out_err;
+       }
+       free(enc_key.data);
+
+       if (write_lucid_keyblock(&p, end, &lctx->rfc1964_kd.ctx_key))
+               goto out_err;
+
+       buf->length = p - (char *)buf->value;
+       return 0;
+out_err:
+       printerr(0, "ERROR: failed serializing krb5 context for kernel\n");
+       if (buf->value) free(buf->value);
+       buf->length = 0;
+       if (enc_key.data) free(enc_key.data);
+       return -1;
+}
+
+static int
+prepare_krb5_rfc_cfx_buffer(gss_krb5_lucid_context_v1_t *lctx,
+       gss_buffer_desc *buf)
+{
+       printerr(0, "ERROR: prepare_krb5_rfc_cfx_buffer: not implemented\n");
+       return -1;
+}
+
+
+int
+serialize_krb5_ctx(gss_ctx_id_t ctx, gss_buffer_desc *buf)
+{
+       OM_uint32 maj_stat, min_stat;
+       void *return_ctx = 0;
+       OM_uint32 vers;
+       gss_krb5_lucid_context_v1_t *lctx = 0;
+       int retcode = 0;
+
+       printerr(2, "DEBUG: serialize_krb5_ctx: lucid version!\n");
+       maj_stat = gss_krb5_export_lucid_sec_context(&min_stat, &ctx,
+                                                       1, &return_ctx);
+       if (maj_stat != GSS_S_COMPLETE)
+               goto out_err;
+
+       /* Check the version returned, we only support v1 right now */
+       vers = ((gss_krb5_lucid_context_version_t *)return_ctx)->version;
+       switch (vers) {
+       case 1:
+               lctx = (gss_krb5_lucid_context_v1_t *) return_ctx;
+               break;
+       default:
+               printerr(0, "ERROR: unsupported lucid sec context version %d\n",
+                       vers);
+               goto out_err;
+               break;
+       }
+
+       /* Now lctx points to a lucid context that we can send down to kernel */
+       if (lctx->protocol == 0)
+               retcode = prepare_krb5_rfc1964_buffer(lctx, buf);
+       else
+               retcode = prepare_krb5_rfc_cfx_buffer(lctx, buf);
+
+       maj_stat = gss_krb5_free_lucid_sec_context(&min_stat,
+                                                  (void *)lctx);
+       if (maj_stat != GSS_S_COMPLETE)
+               printerr(0, "WARN: failed to free lucid sec context\n");
+       if (retcode)
+               goto out_err;
+
+       return 0;
+
+out_err:
+       printerr(0, "ERROR: failed serializing krb5 context for kernel\n");
+       return -1;
+}
+
+
+#else /* HAVE_LUCID_CONTEXT_SUPPORT */
+
+static int
+write_keyblock(char **p, char *end, struct _krb5_keyblock *arg)
+{
+       gss_buffer_desc tmp;
+
+       if (WRITE_BYTES(p, end, arg->enctype)) return -1;
+       tmp.length = arg->length;
+       tmp.value = arg->contents;
+       if (write_buffer(p, end, &tmp)) return -1;
+       return 0;
+}
+
+int
+serialize_krb5_ctx(gss_ctx_id_t ctx, gss_buffer_desc *buf)
+{
+       krb5_gss_ctx_id_t       kctx = (krb5_gss_ctx_id_t)ctx;
+       char *p, *end;
+       static int constant_one = 1;
+       static int constant_zero = 0;
+       uint32_t word_seq_send;
+
+       if (!(buf->value = calloc(1, MAX_CTX_LEN)))
+               goto out_err;
+       p = buf->value;
+       end = buf->value + MAX_CTX_LEN;
+
+       if (kctx->initiate) {
+               if (WRITE_BYTES(&p, end, constant_one)) goto out_err;
+       }
+       else {
+               if (WRITE_BYTES(&p, end, constant_zero)) goto out_err;
+       }
+       if (kctx->seed_init) {
+               if (WRITE_BYTES(&p, end, constant_one)) goto out_err;
+       }
+       else {
+               if (WRITE_BYTES(&p, end, constant_zero)) goto out_err;
+       }
+       if (write_bytes(&p, end, &kctx->seed, sizeof(kctx->seed)))
+               goto out_err;
+       if (WRITE_BYTES(&p, end, kctx->signalg)) goto out_err;
+       if (WRITE_BYTES(&p, end, kctx->sealalg)) goto out_err;
+       if (WRITE_BYTES(&p, end, kctx->endtime)) goto out_err;
+       word_seq_send = kctx->seq_send;
+       if (WRITE_BYTES(&p, end, word_seq_send)) goto out_err;
+       if (write_buffer(&p, end, kctx->mech_used)) goto out_err;
+       if (write_keyblock(&p, end, kctx->enc)) goto out_err;
+       if (write_keyblock(&p, end, kctx->seq)) goto out_err;
+
+       buf->length = p - (char *)buf->value;
+       return 0;
+out_err:
+       printerr(0, "ERROR: failed serializing krb5 context for kernel\n");
+       if (buf->value) free(buf->value);
+       buf->length = 0;
+       return -1;
+}
+#endif /* HAVE_LUCID_CONTEXT_SUPPORT */
+
+#endif /* HAVE_KRB5 */
diff --git a/utils/gssd/context_spkm3.c b/utils/gssd/context_spkm3.c
new file mode 100644 (file)
index 0000000..90dc05c
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+  Copyright (c) 2004 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.
+*/
+
+#include "config.h"
+#include <stdio.h>
+#include <syslog.h>
+#include <string.h>
+#include <gssapi/gssapi.h>
+#include <rpc/rpc.h>
+#include <rpc/auth_gss.h>
+#include "gss_util.h"
+#include "gss_oids.h"
+#include "err_util.h"
+#include "context.h"
+
+#ifdef HAVE_SPKM3_H
+
+#include <spkm3.h>
+
+/*
+ * Function: prepare_spkm3_ctx_buffer()
+ *
+ * Prepare spkm3 lucid context for the kernel
+ *
+ *     buf->length should be:
+ *
+ *     ctx_id 4 + 12
+ *     qop 4
+ *     mech_used 4 + 7
+ *     ret_fl  4
+ *     req_fl  4
+ *      share   4 + key_len
+ *      conf_alg 4 + oid_len
+ *      d_conf_key 4 + key_len
+ *      intg_alg 4 + oid_len
+ *      d_intg_key 4 + key_len
+ *      kyestb 4 + oid_len
+ *      owl alg 4 + oid_len
+*/
+static int
+prepare_spkm3_ctx_buffer(gss_spkm3_lucid_ctx_t *lctx, gss_buffer_desc *buf)
+{
+       char *p, *end;
+       unsigned int buf_size = 0;
+
+       buf_size = lctx->ctx_id.length +
+               sizeof(lctx->ctx_id.length) + sizeof(lctx->qop) +
+               sizeof(lctx->mech_used.length) + lctx->mech_used.length +
+               sizeof(lctx->ret_flags) + sizeof(lctx->req_flags) +
+               sizeof(lctx->share_key.length) + lctx->share_key.length +
+               sizeof(lctx->conf_alg.length) + lctx->conf_alg.length +
+               sizeof(lctx->derived_conf_key.length) +
+               lctx->derived_conf_key.length +
+               sizeof(lctx->intg_alg.length) + lctx->intg_alg.length +
+               sizeof(lctx->derived_integ_key.length) +
+               lctx->derived_integ_key.length +
+               sizeof(lctx->keyestb_alg.length) + lctx->keyestb_alg.length +
+               sizeof(lctx->owf_alg.length) + lctx->owf_alg.length;
+
+       if (!(buf->value = calloc(1, buf_size)))
+               goto out_err;
+       p = buf->value;
+       end = buf->value + buf_size;
+
+       if (write_buffer(&p, end, &lctx->ctx_id))
+               goto out_err;
+
+       if (WRITE_BYTES(&p, end, lctx->qop))
+               goto out_err;
+
+       if (write_buffer(&p, end, &lctx->mech_used))
+               goto out_err;
+
+       if (WRITE_BYTES(&p, end, lctx->ret_flags))
+               goto out_err;
+
+       if (WRITE_BYTES(&p, end, lctx->req_flags))
+               goto out_err;
+
+       if (write_buffer(&p, end, &lctx->share_key))
+               goto out_err;
+
+       if (write_buffer(&p, end, &lctx->conf_alg))
+               goto out_err;
+
+       if (write_buffer(&p, end, &lctx->derived_conf_key))
+               goto out_err;
+
+       if (write_buffer(&p, end, &lctx->intg_alg))
+               goto out_err;
+
+       if (write_buffer(&p, end, &lctx->derived_integ_key))
+               goto out_err;
+
+       if (write_buffer(&p, end, &lctx->keyestb_alg))
+               goto out_err;
+
+       if (write_buffer(&p, end, &lctx->owf_alg))
+               goto out_err;
+
+       buf->length = p - (char *)buf->value;
+       return 0;
+out_err:
+       printerr(0, "ERROR: failed serializing spkm3 context for kernel\n");
+       if (buf->value) free(buf->value);
+       buf->length = 0;
+
+       return -1;
+}
+
+/* ANDROS: need to determine which fields of the spkm3_gss_ctx_id_desc_t
+ * are needed in the kernel for get_mic, validate, wrap, unwrap, and destroy
+ * and only export those fields to the kernel.
+ */
+int
+serialize_spkm3_ctx(gss_ctx_id_t ctx, gss_buffer_desc *buf)
+{
+       OM_uint32 vers, ret, maj_stat, min_stat;
+       void *ret_ctx = 0;
+       gss_spkm3_lucid_ctx_t     *lctx;
+
+       printerr(1, "serialize_spkm3_ctx called\n");
+
+       printerr(2, "DEBUG: serialize_spkm3_ctx: lucid version!\n");
+       maj_stat = gss_export_lucid_sec_context(&min_stat, ctx, 1, &ret_ctx);
+       if (maj_stat != GSS_S_COMPLETE)
+               goto out_err;
+
+       lctx = (gss_spkm3_lucid_ctx_t *)ret_ctx;
+
+       vers = lctx->version;
+       if (vers != 1) {
+               printerr(0, "ERROR: unsupported spkm3 context version %d\n",
+                       vers);
+               goto out_err;
+       }
+       ret = prepare_spkm3_ctx_buffer(lctx, buf);
+
+       maj_stat = gss_free_lucid_sec_context(&min_stat, ctx, ret_ctx);
+
+       if (maj_stat != GSS_S_COMPLETE)
+               printerr(0, "WARN: failed to free lucid sec context\n");
+       if (ret)
+               goto out_err;
+       printerr(2, "DEBUG: serialize_spkm3_ctx: success\n");
+       return 0;
+
+out_err:
+       printerr(2, "DEBUG: serialize_spkm3_ctx: failed\n");
+       return -1;
+}
+#endif /* HAVE_SPKM3_H */