X-Git-Url: https://git.decadent.org.uk/gitweb/?p=nfs-utils.git;a=blobdiff_plain;f=utils%2Fgssd%2Fcontext_lucid.c;h=badbe88d82ec5c8c957aa880758f9ac51381f5ee;hp=35507629ae46b1476fe1d67926bd5b6c49b9cf31;hb=051eb4863cf880f0349a1de44517f9c99a9c5bd4;hpb=27b9c1633398fe605d35da74318f96731506059e diff --git a/utils/gssd/context_lucid.c b/utils/gssd/context_lucid.c index 3550762..badbe88 100644 --- a/utils/gssd/context_lucid.c +++ b/utils/gssd/context_lucid.c @@ -28,7 +28,9 @@ * SUCH DAMAGES. */ -#include "config.h" +#ifdef HAVE_CONFIG_H +#include +#endif /* HAVE_CONFIG_H */ #ifdef HAVE_LUCID_CONTEXT_SUPPORT @@ -40,17 +42,18 @@ #include #include #include +#include + +#include + #include "gss_util.h" #include "gss_oids.h" #include "err_util.h" #include "context.h" -#include -#include #ifndef OM_uint64 typedef uint64_t OM_uint64; #endif -#include static int write_lucid_keyblock(char **p, char *end, gss_krb5_lucid_key_t *key) @@ -66,16 +69,18 @@ write_lucid_keyblock(char **p, char *end, gss_krb5_lucid_key_t *key) static int prepare_krb5_rfc1964_buffer(gss_krb5_lucid_context_v1_t *lctx, - gss_buffer_desc *buf) + gss_buffer_desc *buf, int32_t *endtime) { +#define FAKESEED_SIZE 16 char *p, *end; static int constant_zero = 0; - unsigned char fakeseed[16]; + unsigned char fakeseed[FAKESEED_SIZE]; uint32_t word_send_seq; gss_krb5_lucid_key_t enc_key; - int i; + uint32_t i; char *skd, *dkd; gss_buffer_desc fakeoid; + int err; /* * The new Kerberos interface to get the gss context @@ -86,6 +91,7 @@ prepare_krb5_rfc1964_buffer(gss_krb5_lucid_context_v1_t *lctx, */ memset(&enc_key, 0, sizeof(enc_key)); memset(&fakeoid, 0, sizeof(fakeoid)); + memset(fakeseed, 0, FAKESEED_SIZE); if (!(buf->value = calloc(1, MAX_CTX_LEN))) goto out_err; @@ -96,11 +102,13 @@ prepare_krb5_rfc1964_buffer(gss_krb5_lucid_context_v1_t *lctx, /* 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, &fakeseed, FAKESEED_SIZE)) 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; + if (endtime) + *endtime = lctx->endtime; 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_oid(&p, end, &krb5oid)) goto out_err; @@ -113,15 +121,13 @@ prepare_krb5_rfc1964_buffer(gss_krb5_lucid_context_v1_t *lctx, * Note that the rfc1964 version only supports DES enctypes. */ if (lctx->rfc1964_kd.ctx_key.type != 4) { - printerr(1, "prepare_krb5_rfc1964_buffer: " - "overriding heimdal keytype (%d => %d)\n", - lctx->rfc1964_kd.ctx_key.type, 4); + printerr(2, "%s: overriding heimdal keytype (%d => %d)\n", + __FUNCTION__, lctx->rfc1964_kd.ctx_key.type, 4); lctx->rfc1964_kd.ctx_key.type = 4; } #endif - printerr(2, "prepare_krb5_rfc1964_buffer: serializing keys with " - "enctype %d and length %d\n", - lctx->rfc1964_kd.ctx_key.type, + printerr(2, "%s: serializing keys with enctype %d and length %d\n", + __FUNCTION__, lctx->rfc1964_kd.ctx_key.type, lctx->rfc1964_kd.ctx_key.length); /* derive the encryption key and copy it into buffer */ @@ -133,11 +139,10 @@ prepare_krb5_rfc1964_buffer(gss_krb5_lucid_context_v1_t *lctx, 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; - } + err = write_lucid_keyblock(&p, end, &enc_key); free(enc_key.data); + if (err) + goto out_err; if (write_lucid_keyblock(&p, end, &lctx->rfc1964_kd.ctx_key)) goto out_err; @@ -148,21 +153,111 @@ 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; } +/* Flags for version 2 context flags */ +#define KRB5_CTX_FLAG_INITIATOR 0x00000001 +#define KRB5_CTX_FLAG_CFX 0x00000002 +#define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY 0x00000004 + +/* + * Prepare a new-style buffer, as defined in rfc4121 (a.k.a. cfx), + * to send to the kernel for newer encryption types -- or for DES3. + * + * The new format is: + * + * u32 flags; + * #define KRB5_CTX_FLAG_INITIATOR 0x00000001 + * #define KRB5_CTX_FLAG_CFX 0x00000002 + * #define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY 0x00000004 + * s32 endtime; + * u64 seq_send; + * u32 enctype; ( encrption type of key ) + * raw key; ( raw key bytes (kernel will derive)) + * + */ static int -prepare_krb5_rfc_cfx_buffer(gss_krb5_lucid_context_v1_t *lctx, - gss_buffer_desc *buf) +prepare_krb5_rfc4121_buffer(gss_krb5_lucid_context_v1_t *lctx, + gss_buffer_desc *buf, int32_t *endtime) { - printerr(0, "ERROR: prepare_krb5_rfc_cfx_buffer: not implemented\n"); + char *p, *end; + uint32_t v2_flags = 0; + uint32_t enctype; + uint32_t keysize; + + if (!(buf->value = calloc(1, MAX_CTX_LEN))) + goto out_err; + p = buf->value; + end = buf->value + MAX_CTX_LEN; + + /* Version 2 */ + if (lctx->initiate) + v2_flags |= KRB5_CTX_FLAG_INITIATOR; + if (lctx->protocol != 0) + v2_flags |= KRB5_CTX_FLAG_CFX; + if (lctx->protocol != 0 && lctx->cfx_kd.have_acceptor_subkey == 1) + v2_flags |= KRB5_CTX_FLAG_ACCEPTOR_SUBKEY; + + if (WRITE_BYTES(&p, end, v2_flags)) goto out_err; + if (WRITE_BYTES(&p, end, lctx->endtime)) goto out_err; + if (endtime) + *endtime = lctx->endtime; + if (WRITE_BYTES(&p, end, lctx->send_seq)) goto out_err; + + /* Protocol 0 here implies DES3 or RC4 */ + printerr(2, "%s: protocol %d\n", __FUNCTION__, lctx->protocol); + if (lctx->protocol == 0) { + enctype = lctx->rfc1964_kd.ctx_key.type; + keysize = lctx->rfc1964_kd.ctx_key.length; + } else { + if (lctx->cfx_kd.have_acceptor_subkey) { + enctype = lctx->cfx_kd.acceptor_subkey.type; + keysize = lctx->cfx_kd.acceptor_subkey.length; + } else { + enctype = lctx->cfx_kd.ctx_key.type; + keysize = lctx->cfx_kd.ctx_key.length; + } + } + printerr(2, "%s: serializing key with enctype %d and size %d\n", + __FUNCTION__, enctype, keysize); + + if (WRITE_BYTES(&p, end, enctype)) goto out_err; + + if (lctx->protocol == 0) { + if (write_bytes(&p, end, lctx->rfc1964_kd.ctx_key.data, + lctx->rfc1964_kd.ctx_key.length)) + goto out_err; + } else { + if (lctx->cfx_kd.have_acceptor_subkey) { + if (write_bytes(&p, end, + lctx->cfx_kd.acceptor_subkey.data, + lctx->cfx_kd.acceptor_subkey.length)) + goto out_err; + } else { + if (write_bytes(&p, end, lctx->cfx_kd.ctx_key.data, + lctx->cfx_kd.ctx_key.length)) + goto out_err; + } + } + + buf->length = p - (char *)buf->value; + return 0; + +out_err: + printerr(0, "ERROR: %s: failed serializing krb5 context for kernel\n", + __FUNCTION__); + if (buf->value) { + free(buf->value); + buf->value = NULL; + } + buf->length = 0; return -1; } int -serialize_krb5_ctx(gss_ctx_id_t ctx, gss_buffer_desc *buf) +serialize_krb5_ctx(gss_ctx_id_t *ctx, gss_buffer_desc *buf, int32_t *endtime) { OM_uint32 maj_stat, min_stat; void *return_ctx = 0; @@ -170,8 +265,8 @@ serialize_krb5_ctx(gss_ctx_id_t ctx, gss_buffer_desc *buf) gss_krb5_lucid_context_v1_t *lctx = 0; int retcode = 0; - printerr(2, "DEBUG: serialize_krb5_ctx: lucid version!\n"); - maj_stat = gss_export_lucid_sec_context(&min_stat, &ctx, + printerr(2, "DEBUG: %s: lucid version!\n", __FUNCTION__); + maj_stat = gss_export_lucid_sec_context(&min_stat, ctx, 1, &return_ctx); if (maj_stat != GSS_S_COMPLETE) { pgsserr("gss_export_lucid_sec_context", @@ -192,22 +287,31 @@ serialize_krb5_ctx(gss_ctx_id_t ctx, gss_buffer_desc *buf) 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); + /* + * Now lctx points to a lucid context that we can send down to kernel + * + * Note: we send down different information to the kernel depending + * on the protocol version and the enctyption type. + * For protocol version 0 with all enctypes besides DES3, we use + * the original format. For protocol version != 0 or DES3, we + * send down the new style information. + */ + + if (lctx->protocol == 0 && lctx->rfc1964_kd.ctx_key.type <= 4) + retcode = prepare_krb5_rfc1964_buffer(lctx, buf, endtime); else - retcode = prepare_krb5_rfc_cfx_buffer(lctx, buf); + retcode = prepare_krb5_rfc4121_buffer(lctx, buf, endtime); maj_stat = gss_free_lucid_sec_context(&min_stat, ctx, return_ctx); if (maj_stat != GSS_S_COMPLETE) { - pgsserr("gss_export_lucid_sec_context", + pgsserr("gss_free_lucid_sec_context", maj_stat, min_stat, &krb5oid); printerr(0, "WARN: failed to free lucid sec context\n"); } if (retcode) { - printerr(1, "serialize_krb5_ctx: prepare_krb5_*_buffer " - "failed (retcode = %d)\n", retcode); + printerr(1, "%s: prepare_krb5_*_buffer failed (retcode = %d)\n", + __FUNCTION__, retcode); goto out_err; } @@ -217,4 +321,7 @@ out_err: printerr(0, "ERROR: failed serializing krb5 context for kernel\n"); return -1; } + + + #endif /* HAVE_LUCID_CONTEXT_SUPPORT */