$NetBSD: patch-CVE-2014-4341,v 1.1 2014/08/28 22:23:05 tez Exp $

Fix for CVE-2014-4341 & CVE-2014-4342 from:
https://github.com/krb5/krb5/commit/e6ae703ae597d798e310368d52b8f38ee11c6a73


--- lib/gssapi/krb5/k5unseal.c
+++ lib/gssapi/krb5/k5unseal.c
@@ -74,6 +74,7 @@
     int conflen = 0;
     int signalg;
     int sealalg;
+    int bad_pad = 0;
     gss_buffer_desc token;
     krb5_checksum cksum;
     krb5_checksum md5cksum;
@@ -86,6 +87,7 @@
     krb5_ui_4 seqnum;
     OM_uint32 retval;
     size_t sumlen;
+    size_t padlen;
     krb5_keyusage sign_usage = KG_USAGE_SIGN;
 
     if (toktype == KG_TOK_SEAL_MSG) {
@@ -93,18 +95,23 @@
         message_buffer->value = NULL;
     }
 
-    /* get the sign and seal algorithms */
-
-    signalg = ptr[0] + (ptr[1]<<8);
-    sealalg = ptr[2] + (ptr[3]<<8);
-
     /* Sanity checks */
 
-    if ((ptr[4] != 0xff) || (ptr[5] != 0xff)) {
+    if (ctx->seq == NULL) {
+        /* ctx was established using a newer enctype, and cannot process RFC
+         * 1964 tokens. */
         *minor_status = 0;
         return GSS_S_DEFECTIVE_TOKEN;
     }
 
+    if ((bodysize < 22) || (ptr[4] != 0xff) || (ptr[5] != 0xff)) {
+        *minor_status = 0;
+        return GSS_S_DEFECTIVE_TOKEN;
+    }
+
+    signalg = ptr[0] + (ptr[1]<<8);
+    sealalg = ptr[2] + (ptr[3]<<8);
+
     if ((toktype != KG_TOK_SEAL_MSG) &&
         (sealalg != 0xffff)) {
         *minor_status = 0;
@@ -153,6 +160,11 @@
         return GSS_S_DEFECTIVE_TOKEN;
     }
 
+    if ((size_t)bodysize < 14 + cksum_len) {
+        *minor_status = 0;
+        return GSS_S_DEFECTIVE_TOKEN;
+    }
+
     /* get the token parameters */
 
     if ((code = kg_get_seq_num(context, ctx->seq, ptr+14, ptr+6, &direction,
@@ -210,7 +222,20 @@
             token.length = tmsglen;
         } else {
             conflen = kg_confounder_size(context, ctx->enc->keyblock.enctype);
-            token.length = tmsglen - conflen - plain[tmsglen-1];
+            if (tmsglen < conflen) {
+                if (sealalg != 0xffff)
+                    xfree(plain);
+                *minor_status = 0;
+                return(GSS_S_DEFECTIVE_TOKEN);
+            }
+            padlen = plain[tmsglen - 1];
+            if (tmsglen - conflen < padlen) {
+                /* Don't error out yet, to avoid padding oracle attacks.  We will
+                 * treat this as a checksum failure later on. */
+                padlen = 0;
+                bad_pad = 1;
+            }
+            token.length = tmsglen - conflen - padlen;
         }
 
         if (token.length) {
@@ -423,7 +448,7 @@
 
     /* compare the computed checksum against the transmitted checksum */
 
-    if (code) {
+    if (code || bad_pad) {
         if (toktype == KG_TOK_SEAL_MSG)
             gssalloc_free(token.value);
         *minor_status = 0;

--- lib/gssapi/krb5/k5unsealiov.c
+++ lib/gssapi/krb5/k5unsealiov.c
@@ -69,7 +69,14 @@ kg_unseal_v1_iov(krb5_context context,
         return GSS_S_DEFECTIVE_TOKEN;
     }
 
-    if (header->buffer.length < token_wrapper_len + 14) {
+    if (ctx->seq == NULL) {
+        /* ctx was established using a newer enctype, and cannot process RFC
+         * 1964 tokens. */
+        *minor_status = 0;
+        return GSS_S_DEFECTIVE_TOKEN;
+    }
+
+    if (header->buffer.length < token_wrapper_len + 22) {
         *minor_status = 0;
         return GSS_S_DEFECTIVE_TOKEN;
     }
