Esempio n. 1
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] = { 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;
}
Esempio n. 2
0
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;
}