From: neilbrown Date: Tue, 28 Mar 2006 00:45:33 +0000 (+0000) Subject: Separate out context handling code for MIT Kerberos and SPKM3 X-Git-Tag: nfs-utils-1-0-8~19 X-Git-Url: https://git.decadent.org.uk/gitweb/?a=commitdiff_plain;h=43e5f4e81d522a5355ff9f88c8c4ced0087c754c;p=nfs-utils.git Separate out context handling code for MIT Kerberos and SPKM3 into their own file. (Really this time) --- diff --git a/ChangeLog b/ChangeLog index ebccf8b..2b5ae8a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2006-03-28 kwc@citi.umich.edu + + Separate out context handling code for MIT Kerberos and SPKM3 + into their own file. + (Really this time) + 2006-03-28 Kevin Coffman User-selectable idmapping cache lifetime diff --git a/utils/gssd/Makefile.am b/utils/gssd/Makefile.am index b29bf1a..d152525 100644 --- a/utils/gssd/Makefile.am +++ b/utils/gssd/Makefile.am @@ -14,7 +14,9 @@ EXTRA_DIST = \ COMMON_SRCS = \ context.c \ + context_mit.c \ context_heimdal.c \ + context_spkm3.c \ gss_util.c \ gss_oids.c \ err_util.c \ diff --git a/utils/gssd/context.c b/utils/gssd/context.c index 8f2f359..02d162f 100644 --- a/utils/gssd/context.c +++ b/utils/gssd/context.c @@ -32,9 +32,7 @@ #include #include #include -#ifdef HAVE_KRB5 -#include -#endif +#include #include #include #include "gss_util.h" @@ -42,453 +40,6 @@ #include "err_util.h" #include "context.h" -#ifdef HAVE_SPKM3_H -#include -#endif - -/* spkm3 seems to actually want it this big, yipes. */ -#define MAX_CTX_LEN 4096 - -#ifdef HAVE_KRB5 /* MIT Kerberos */ - -#ifdef HAVE_LUCID_CONTEXT_SUPPORT - -/* Don't use the private structure, use the exported lucid structure */ -#include -#include - -#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 */ - -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 */ -#endif /* HAVE_KRB5 */ - -/* adapted from mit kerberos 5 ../lib/gssapi/mechglue/mglueP.h - * this is what gets passed around when the mechglue code is enabled : */ -typedef struct gss_union_ctx_id_t { - gss_OID mech_type; - gss_ctx_id_t internal_ctx_id; -} gss_union_ctx_id_desc, *gss_union_ctx_id_t; - -#ifdef HAVE_KRB5 /* MIT Kerberos */ -#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; -} - -#else /* 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; -} -#endif /* lucid context support */ -#endif /* HAVE_KRB5 */ - -#ifdef HAVE_KRB5 -#ifdef HAVE_LUCID_CONTEXT_SUPPORT /* Lucid context support */ -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; -} - - -static 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 /* lucid context support */ - -static 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 /* lucid context support */ -#endif /* HAVE_KRB5 */ - - -#ifdef HAVE_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. - */ -static 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 */ - int serialize_context_for_kernel(gss_ctx_id_t ctx, gss_buffer_desc *buf) { diff --git a/utils/gssd/context.h b/utils/gssd/context.h index d896bd0..b296539 100644 --- a/utils/gssd/context.h +++ b/utils/gssd/context.h @@ -34,5 +34,7 @@ #include int serialize_context_for_kernel(gss_ctx_id_t ctx, gss_buffer_desc *buf); +int serialize_spkm3_ctx(gss_ctx_id_t ctx, gss_buffer_desc *buf); +int serialize_krb5_ctx(gss_ctx_id_t ctx, gss_buffer_desc *buf); #endif /* _CONTEXT_H_ */