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] = { 0 }; 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_oid(&p, end, &krb5oid)) goto out_err; #ifdef HAVE_HEIMDAL /* * The kernel gss code expects des-cbc-raw for all flavors of des. * The keytype from MIT has this type, but Heimdal does not. * Force the Heimdal keytype to 4 (des-cbc-raw). * Note that the rfc1964 version only supports DES enctypes. */ if (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, "%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 */ 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; }
int serialize_krb5_ctx(gss_ctx_id_t *ctx, gss_buffer_desc *buf, int32_t *endtime) { krb5_gss_ctx_id_t kctx = ((gss_union_ctx_id_t)(*ctx))->internal_ctx_id; char *p, *end; static int constant_zero = 0; static int constant_one = 1; static int constant_two = 2; uint32_t word_seq_send; u_int64_t seq_send_64bit; uint32_t v2_flags = 0; if (!(buf->value = calloc(1, MAX_CTX_LEN))) goto out_err; p = buf->value; end = buf->value + MAX_CTX_LEN; switch (kctx->enc->enctype) { case ENCTYPE_DES_CBC_CRC: case ENCTYPE_DES_CBC_MD4: case ENCTYPE_DES_CBC_MD5: case ENCTYPE_DES_CBC_RAW: /* Old format of context to the kernel */ 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; if (endtime) *endtime = kctx->endtime; word_seq_send = kctx->seq_send; if (WRITE_BYTES(&p, end, word_seq_send)) goto out_err; if (write_oid(&p, end, kctx->mech_used)) goto out_err; printerr(2, "serialize_krb5_ctx: serializing keys with " "enctype %d and length %d\n", kctx->enc->enctype, kctx->enc->length); if (write_keyblock(&p, end, kctx->enc)) goto out_err; if (write_keyblock(&p, end, kctx->seq)) goto out_err; break; case ENCTYPE_DES3_CBC_RAW: case ENCTYPE_DES3_CBC_SHA1: case ENCTYPE_ARCFOUR_HMAC: case ENCTYPE_ARCFOUR_HMAC_EXP: case ENCTYPE_AES128_CTS_HMAC_SHA1_96: case ENCTYPE_AES256_CTS_HMAC_SHA1_96: /* New format of context to the kernel */ /* 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; * rawkey data */ if (kctx->initiate) v2_flags |= KRB5_CTX_FLAG_INITIATOR; if (kctx->proto == 1) v2_flags |= KRB5_CTX_FLAG_CFX; if (kctx->have_acceptor_subkey) v2_flags |= KRB5_CTX_FLAG_ACCEPTOR_SUBKEY; if (WRITE_BYTES(&p, end, v2_flags)) goto out_err; if (WRITE_BYTES(&p, end, kctx->endtime)) goto out_err; seq_send_64bit = kctx->seq_send; if (WRITE_BYTES(&p, end, seq_send_64bit)) goto out_err; if (kctx->have_acceptor_subkey) { if (WRITE_BYTES(&p, end, kctx->acceptor_subkey->enctype)) goto out_err; printerr(2, "serialize_krb5_ctx: serializing subkey " "with enctype %d and size %d\n", kctx->acceptor_subkey->enctype, kctx->acceptor_subkey->length); if (write_bytes(&p, end, kctx->acceptor_subkey->contents, kctx->acceptor_subkey->length)) goto out_err; } else { if (WRITE_BYTES(&p, end, kctx->enc->enctype)) goto out_err; printerr(2, "serialize_krb5_ctx: serializing key " "with enctype %d and size %d\n", kctx->enc->enctype, kctx->enc->length); if (write_bytes(&p, end, kctx->enc->contents, kctx->enc->length)) goto out_err; } break; default: printerr(0, "ERROR: serialize_krb5_ctx: unsupported encryption " "algorithm %d\n", kctx->enc->enctype); 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->value = NULL; buf->length = 0; return -1; }