/*
- * COPYRIGHT (c) 2006
- * The Regents of the University of Michigan
+ * COPYRIGHT (c) 2006 The Regents of the University of Michigan
* ALL RIGHTS RESERVED
*
+ * Copyright (c) 2012, 2014, Intel Corporation.
+ *
* Permission is granted to use, copy, create derivative works
* and redistribute this software and such derivative works
* for any purpose, so long as the name of The University of
#endif
#include <gssapi/gssapi_krb5.h>
-#include "gss_util.h"
-#include "gss_oids.h"
-#include "err_util.h"
+#ifdef _NEW_BUILD_
+# include "lgss_utils.h"
+#else
+# include "gss_util.h"
+# include "gss_oids.h"
+# include "err_util.h"
+#endif
+#include "write_bytes.h"
#include "context.h"
+
static int
write_lucid_keyblock(char **p, char *end, gss_krb5_lucid_key_t *key)
{
{
char *p, *end;
static int constant_zero = 0;
- unsigned char fakeseed[16];
+ 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
* 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;
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);
+ if (write_lucid_keyblock(&p, end, &enc_key))
goto out_err;
- }
- free(enc_key.data);
-
if (write_lucid_keyblock(&p, end, &lctx->rfc1964_kd.ctx_key))
goto out_err;
+ free(enc_key.data);
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);
+ if (buf->value) {
+ free(buf->value);
+ buf->value = NULL;
+ }
buf->length = 0;
if (enc_key.data) free(enc_key.data);
return -1;
* We don't have "legal" access to these MIT-only
* structures located in libk5crypto
*/
-extern void krb5int_enc_arcfour;
-extern void krb5int_enc_des3;
-extern void krb5int_enc_aes128;
-extern void krb5int_enc_aes256;
-extern int krb5_derive_key();
+extern void *krb5int_enc_arcfour;
+extern void *krb5int_enc_des3;
+extern void *krb5int_enc_aes128;
+extern void *krb5int_enc_aes256;
static void
key_lucid_to_krb5(const gss_krb5_lucid_key_t *lin, krb5_keyblock *kout)
{
- memset(kout, '\0', sizeof(kout));
+ memset(kout, 0, sizeof(*kout));
#ifdef HAVE_KRB5
kout->enctype = lin->type;
kout->length = lin->length;
#endif
}
-static void
+static int
key_krb5_to_lucid(const krb5_keyblock *kin, gss_krb5_lucid_key_t *lout)
{
- memset(lout, '\0', sizeof(lout));
+ memset(lout, 0, sizeof(*lout));
+
#ifdef HAVE_KRB5
+ lout->data = malloc(kin->length);
+ if (lout->data == NULL)
+ return KRB5_CC_NOMEM;
+
lout->type = kin->enctype;
lout->length = kin->length;
- lout->data = kin->contents;
+ memcpy(lout->data, kin->contents, kin->length);
#else
+ lout->data = malloc(kin->keyvalue.length);
+ if (lout->data == NULL)
+ return KRB5_CC_NOMEM;
+
lout->type = kin->keytype;
lout->length = kin->keyvalue.length;
memcpy(lout->data, kin->keyvalue.data, kin->keyvalue.length);
#endif
+
+ return 0;
}
/* XXX Hack alert! XXX Do NOT submit upstream! XXX */
krb5_error_code code;
unsigned char constant_data[K5CLENGTH];
krb5_data datain;
- int keylength;
+ int keylength __attribute__ ((unused));
+#ifdef HAVE_KRB5
void *enc;
- krb5_keyblock kin, kout; /* must send krb5_keyblock, not lucid! */
-#ifdef HAVE_HEIMDAL
+#endif
+ krb5_keyblock kin; /* must send krb5_keyblock, not lucid! */
+#if defined(HAVE_HEIMDAL) || HAVE_KRB5INT_DERIVE_KEY
krb5_context kcontext;
krb5_keyblock *outkey;
+#else
+ krb5_keyblock kout;
+#endif
+#if HAVE_KRB5INT_DERIVE_KEY
+ krb5_key key_in, key_out;
#endif
/*
goto out;
}
- /* allocate memory for output key */
- if ((out->data = malloc(keylength)) == NULL) {
- code = ENOMEM;
- goto out;
- }
- out->length = keylength;
- out->type = in->type;
-
/* Convert to correct format for call to krb5_derive_key */
key_lucid_to_krb5(in, &kin);
- key_lucid_to_krb5(out, &kout);
datain.data = (char *) constant_data;
datain.length = K5CLENGTH;
((char *)(datain.data))[4] = (char) extra;
+ /* Step 1: Init context */
+ /* Heimdal and newer MIT Kerberos require kcontext */
+#if defined(HAVE_KRB5INT_DERIVE_KEY) || defined(HAVE_HEIMDAL)
+ code = krb5_init_context(&kcontext);
+ if (code)
+ goto out;
+#endif
+
+ /* Step 2: Get the derived key */
#ifdef HAVE_KRB5
- code = krb5_derive_key(enc, &kin, &kout, &datain);
-#else
- if ((code = krb5_init_context(&kcontext))) {
+#if HAVE_KRB5INT_DERIVE_KEY
+ code = krb5_k_create_key(kcontext, &kin, &key_in);
+ if (code)
+ goto out;
+
+ code = krb5int_derive_key(enc, key_in, &key_out, &datain,
+ DERIVE_RFC3961);
+
+ krb5_k_free_key(kcontext, key_in);
+ if (code == 0) {
+ krb5_k_key_keyblock(kcontext, key_out, &outkey);
+ krb5_k_free_key(kcontext, key_out);
}
+#else /* !HAVE_KRB5INT_DERIVE_KEY */
+ out->length = keylength;
+ out->type = in->type;
+
+ key_lucid_to_krb5(out, &kout);
+
+ code = krb5_derive_key(enc, &kin, &kout, &datain);
+#endif /* HAVE_KRB5INT_DERIVE_KEY */
+#else /* !defined(HAVE_KRB5) */
code = krb5_derive_key(kcontext, &kin, in->type, constant_data, K5CLENGTH, &outkey);
-#endif
- if (code) {
- free(out->data);
- out->data = NULL;
+#endif /* defined(HAVE_KRB5) */
+
+ if (code)
goto out;
- }
-#ifdef HAVE_KRB5
- key_krb5_to_lucid(&kout, out);
-#else
- key_krb5_to_lucid(outkey, out);
+
+ /* Step 3: Copy the key to out */
+#if defined(HAVE_KRB5INT_DERIVE_KEY) || defined(HAVE_HEIMDAL)
+ code = key_krb5_to_lucid(outkey, out);
krb5_free_keyblock(kcontext, outkey);
+#else /* !defined(HAVE_KRB5) */
+ code = key_krb5_to_lucid(&kout, out);
+#endif /* defined(HAVE_KRB5) */
+
+ /* Step 4: Free the context */
+#if defined(HAVE_KRB5INT_DERIVE_KEY) || defined(HAVE_HEIMDAL)
krb5_free_context(kcontext);
#endif
out:
- if (code)
+ if (code)
printerr(0, "ERROR: %s: returning error %d (%s)\n",
__FUNCTION__, code, error_message(code));
return (code);
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);
+ printerr(3, "protocol %d\n", lctx->protocol);
if (lctx->protocol == 0) {
enctype = lctx->rfc1964_kd.ctx_key.type;
#ifdef HAVE_HEIMDAL
}
numkeys = 3;
}
- printerr(2, "%s: serializing %d keys with enctype %d and size %d\n",
- __FUNCTION__, numkeys, enctype, keysize);
+ printerr(3, "serializing %d keys with enctype %d and size %d\n",
+ numkeys, enctype, keysize);
if (WRITE_BYTES(&p, end, enctype)) goto out_err;
if (WRITE_BYTES(&p, end, keysize)) goto out_err;
if (WRITE_BYTES(&p, end, numkeys)) goto out_err;
else
keyptr = &lctx->cfx_kd.ctx_key;
-#if 0
- if (lctx->initiate == 1) {
- sign_usage = KG_USAGE_INITIATOR_SIGN;
- seal_usage = KG_USAGE_INITIATOR_SEAL;
- } else {
- sign_usage = KG_USAGE_ACCEPTOR_SIGN;
- seal_usage = KG_USAGE_ACCEPTOR_SEAL;
- }
-#else
/* FIXME
- * These are from rfc4142, but I don't understand: if we supply
- * different 'usage' value for client & server, then the peers
- * will have different derived keys. How could this work?
+ * These are from rfc4142, but I don't understand:
+ * if we supply different 'usage' value for client &
+ * server, then the peers will have different derived
+ * keys. How could this work?
*
- * Here we simply use old SIGN/SEAL values until we find the
- * answer. --ericm
+ * Here we simply use old SIGN/SEAL values until we
+ * find the answer. --ericm
* FIXME
*/
sign_usage = KG_USAGE_SIGN;
seal_usage = KG_USAGE_SEAL;
-#endif
/* derive and send down: Ke, Ki, and Kc */
gss_krb5_lucid_context_v1_t *lctx = 0;
int retcode = 0;
- printerr(2, "DEBUG: %s: lucid version!\n", __FUNCTION__);
- maj_stat = gss_export_lucid_sec_context(&min_stat, &ctx,
+ printerr(3, "lucid version!\n");
+ maj_stat = gss_krb5_export_lucid_sec_context(&min_stat, &ctx,
1, &return_ctx);
if (maj_stat != GSS_S_COMPLETE) {
- pgsserr("gss_export_lucid_sec_context",
+ pgsserr("gss_krb5_export_lucid_sec_context",
maj_stat, min_stat, &krb5oid);
goto out_err;
}
else
retcode = prepare_krb5_rfc4121_buffer(lctx, buf);
- maj_stat = gss_free_lucid_sec_context(&min_stat, ctx, return_ctx);
+ maj_stat = gss_krb5_free_lucid_sec_context(&min_stat, return_ctx);
if (maj_stat != GSS_S_COMPLETE) {
- pgsserr("gss_export_lucid_sec_context",
+ pgsserr("gss_krb5_export_lucid_sec_context",
maj_stat, min_stat, &krb5oid);
printerr(0, "WARN: failed to free lucid sec context\n");
}