Whamcloud - gitweb
LU-6020 kerberos: checksum errors when using kerberos 76/13076/2
authorAndrew Perepechko <andrew.perepechko@seagate.com>
Mon, 15 Dec 2014 21:54:34 +0000 (00:54 +0300)
committerOleg Drokin <oleg.drokin@intel.com>
Fri, 16 Jan 2015 17:48:41 +0000 (17:48 +0000)
derive_key_lucid() uses krb5int_derive_key() to
construct the requested key. However, in the
end it copies the key from kout keyblock, whereas
the derive function puts it into key_out. The
original code contains the invalid assumption
that krb5_k_create_key() binds the newly created
key to the keyblock which was used to create it.

Xyratex-bug-id: SNT-15
Signed-off-by: Andrew Perepechko <andrew.perepechko@seagate.com>
Change-Id: Id2f28b4a9ca3909861a703f2ce07ed860087e809
Reviewed-on: http://review.whamcloud.com/13076
Tested-by: Jenkins
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: Andreas Dilger <andreas.dilger@intel.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
lustre/utils/gss/context_lucid.c

index ef07dff..c5241cc 100644 (file)
@@ -223,19 +223,30 @@ key_lucid_to_krb5(const gss_krb5_lucid_key_t *lin, krb5_keyblock *kout)
 #endif
 }
 
 #endif
 }
 
-static void
+static int
 key_krb5_to_lucid(const krb5_keyblock *kin, gss_krb5_lucid_key_t *lout)
 {
        memset(lout, 0, sizeof(*lout));
 key_krb5_to_lucid(const krb5_keyblock *kin, gss_krb5_lucid_key_t *lout)
 {
        memset(lout, 0, sizeof(*lout));
+
 #ifdef HAVE_KRB5
 #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->type = kin->enctype;
        lout->length = kin->length;
-       lout->data = kin->contents;
+       memcpy(lout->data, kin->contents, kin->length);
 #else
 #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
        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 */
 }
 
 /* XXX Hack alert! XXX  Do NOT submit upstream! XXX */
@@ -253,17 +264,19 @@ derive_key_lucid(const gss_krb5_lucid_key_t *in, gss_krb5_lucid_key_t *out,
        unsigned char constant_data[K5CLENGTH];
        krb5_data datain;
        int keylength;
        unsigned char constant_data[K5CLENGTH];
        krb5_data datain;
        int keylength;
+#ifdef HAVE_KRB5
        void *enc;
        void *enc;
-       krb5_keyblock kin, kout;  /* must send krb5_keyblock, not lucid! */
+#endif
+       krb5_keyblock kin;  /* must send krb5_keyblock, not lucid! */
 #if defined(HAVE_HEIMDAL) || HAVE_KRB5INT_DERIVE_KEY
        krb5_context kcontext;
 #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
 #endif
 #if HAVE_KRB5INT_DERIVE_KEY
        krb5_key key_in, key_out;
 #endif
-#ifdef HAVE_HEIMDAL
-       krb5_keyblock *outkey;
-#endif
 
        /*
         * XXX Hack alert.  We don't have "legal" access to these
 
        /*
         * XXX Hack alert.  We don't have "legal" access to these
@@ -296,17 +309,8 @@ derive_key_lucid(const gss_krb5_lucid_key_t *in, gss_krb5_lucid_key_t *out,
                goto out;
        }
 
                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);
        /* 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;
 
        datain.data = (char *) constant_data;
        datain.length = K5CLENGTH;
@@ -318,52 +322,57 @@ derive_key_lucid(const gss_krb5_lucid_key_t *in, gss_krb5_lucid_key_t *out,
 
        ((char *)(datain.data))[4] = (char) extra;
 
 
        ((char *)(datain.data))[4] = (char) extra;
 
-#ifdef HAVE_KRB5
-#if HAVE_KRB5INT_DERIVE_KEY
+       /* 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);
        code = krb5_init_context(&kcontext);
-       if (code) {
-               free(out->data);
-               out->data = NULL;
+       if (code)
                goto out;
                goto out;
-       }
+#endif
+
+       /* Step 2: Get the derived key */
+#ifdef HAVE_KRB5
+#if HAVE_KRB5INT_DERIVE_KEY
        code = krb5_k_create_key(kcontext, &kin, &key_in);
        code = krb5_k_create_key(kcontext, &kin, &key_in);
-       if (code) {
-               free(out->data);
-               out->data = NULL;
-               goto out;
-       }
-       code = krb5_k_create_key(kcontext, &kout, &key_out);
-       if (code) {
-               free(out->data);
-               out->data = NULL;
+       if (code)
                goto out;
                goto out;
-       }
+
        code = krb5int_derive_key(enc, key_in, &key_out, &datain,
                                  DERIVE_RFC3961);
        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 */
 #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(enc, &kin, &kout, &datain);
 #endif /* HAVE_KRB5INT_DERIVE_KEY */
 #else  /* !defined(HAVE_KRB5) */
-       if ((code = krb5_init_context(&kcontext))) {
-       }
        code = krb5_derive_key(kcontext, &kin, in->type, constant_data, K5CLENGTH, &outkey);
 #endif /* defined(HAVE_KRB5) */
        code = krb5_derive_key(kcontext, &kin, in->type, constant_data, K5CLENGTH, &outkey);
 #endif /* defined(HAVE_KRB5) */
-       if (code) {
-               free(out->data);
-               out->data = NULL;
+
+       if (code)
                goto out;
                goto out;
-       }
-#ifdef HAVE_KRB5
-       key_krb5_to_lucid(&kout, out);
-#if HAVE_KRB5INT_DERIVE_KEY
-       krb5_free_context(kcontext);
-#endif /* HAVE_KRB5INT_DERIVE_KEY */
-#else  /* !defined(HAVE_KRB5) */
-       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);
        krb5_free_keyblock(kcontext, outkey);
-       krb5_free_context(kcontext);
+#else  /* !defined(HAVE_KRB5) */
+       code = key_krb5_to_lucid(&kout, out);
 #endif /* defined(HAVE_KRB5) */
 
 #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)
                printerr(0, "ERROR: %s: returning error %d (%s)\n",
   out:
        if (code)
                printerr(0, "ERROR: %s: returning error %d (%s)\n",