aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/lib/gssapi/mechglue/g_glue.c20
-rw-r--r--src/tests/gssapi/t_invalid.c57
2 files changed, 66 insertions, 11 deletions
diff --git a/src/lib/gssapi/mechglue/g_glue.c b/src/lib/gssapi/mechglue/g_glue.c
index 4aa3591..4cd2e8f 100644
--- a/src/lib/gssapi/mechglue/g_glue.c
+++ b/src/lib/gssapi/mechglue/g_glue.c
@@ -189,7 +189,7 @@ OM_uint32 gssint_get_mech_type_oid(OID, token)
gss_buffer_t token;
{
unsigned char * buffer_ptr;
- int length;
+ size_t buflen, lenbytes, length, oidlen;
/*
* This routine reads the prefix of "token" in order to determine
@@ -223,25 +223,33 @@ OM_uint32 gssint_get_mech_type_oid(OID, token)
/* Skip past the APP/Sequnce byte and the token length */
buffer_ptr = (unsigned char *) token->value;
+ buflen = token->length;
- if (*(buffer_ptr++) != 0x60)
+ if (buflen < 2 || *buffer_ptr++ != 0x60)
return (GSS_S_DEFECTIVE_TOKEN);
length = *buffer_ptr++;
+ buflen -= 2;
/* check if token length is null */
if (length == 0)
return (GSS_S_DEFECTIVE_TOKEN);
if (length & 0x80) {
- if ((length & 0x7f) > 4)
+ lenbytes = length & 0x7f;
+ if (lenbytes > 4 || lenbytes > buflen)
return (GSS_S_DEFECTIVE_TOKEN);
- buffer_ptr += length & 0x7f;
+ buffer_ptr += lenbytes;
+ buflen -= lenbytes;
}
- if (*(buffer_ptr++) != 0x06)
+ if (buflen < 2 || *buffer_ptr++ != 0x06)
+ return (GSS_S_DEFECTIVE_TOKEN);
+ oidlen = *buffer_ptr++;
+ buflen -= 2;
+ if (oidlen > 0x7f || oidlen > buflen)
return (GSS_S_DEFECTIVE_TOKEN);
- OID->length = (OM_uint32) *(buffer_ptr++);
+ OID->length = oidlen;
OID->elements = (void *) buffer_ptr;
return (GSS_S_COMPLETE);
}
diff --git a/src/tests/gssapi/t_invalid.c b/src/tests/gssapi/t_invalid.c
index 5c8ddac..2a332a8 100644
--- a/src/tests/gssapi/t_invalid.c
+++ b/src/tests/gssapi/t_invalid.c
@@ -31,8 +31,8 @@
*/
/*
- * This file contains regression tests for some GSSAPI krb5 invalid per-message
- * token vulnerabilities.
+ * This file contains regression tests for some GSSAPI invalid token
+ * vulnerabilities.
*
* 1. A pre-CFX wrap or MIC token processed with a CFX-only context causes a
* null pointer dereference. (The token must use SEAL_ALG_NONE or it will
@@ -54,10 +54,13 @@
* causes an integer underflow when computing the original message length,
* leading to an allocation error.
*
+ * 5. In the mechglue, truncated encapsulation in the initial context token can
+ * cause input buffer overruns in gss_accept_sec_context().
+ *
* Vulnerabilities #1 and #2 also apply to IOV unwrap, although tokens with
- * fewer than 16 bytes after the ASN.1 header will be rejected. Vulnerability
- * #2 can only be robustly detected using a memory-checking environment such as
- * valgrind.
+ * fewer than 16 bytes after the ASN.1 header will be rejected.
+ * Vulnerabilities #2 and #5 can only be robustly detected using a
+ * memory-checking environment such as valgrind.
*/
#include "k5-int.h"
@@ -406,6 +409,48 @@ test_bad_pad(gss_ctx_id_t ctx, const struct test *test)
(void)gss_release_buffer(&minor, &out);
}
+static void
+try_accept(void *value, size_t len)
+{
+ OM_uint32 minor;
+ gss_buffer_desc in, out;
+ gss_ctx_id_t ctx = GSS_C_NO_CONTEXT;
+
+ /* Copy the provided value to make input overruns more obvious. */
+ in.value = malloc(len);
+ if (in.value == NULL)
+ abort();
+ memcpy(in.value, value, len);
+ in.length = len;
+ (void)gss_accept_sec_context(&minor, &ctx, GSS_C_NO_CREDENTIAL, &in,
+ GSS_C_NO_CHANNEL_BINDINGS, NULL, NULL,
+ &out, NULL, NULL, NULL);
+ gss_release_buffer(&minor, &out);
+ gss_delete_sec_context(&minor, &ctx, GSS_C_NO_BUFFER);
+ free(in.value);
+}
+
+/* Accept contexts using superficially valid but truncated encapsulations. */
+static void
+test_short_encapsulation()
+{
+ /* Include just the initial application tag, to see if we overrun reading
+ * the sequence length. */
+ try_accept("\x60", 1);
+
+ /* Indicate four additional sequence length bytes, to see if we overrun
+ * reading them (or skipping them and reading the next byte). */
+ try_accept("\x60\x84", 2);
+
+ /* Include an object identifier tag but no length, to see if we overrun
+ * reading the length. */
+ try_accept("\x60\x40\x06", 3);
+
+ /* Include an object identifier tag with a length matching the krb5 mech,
+ * but no OID bytes, to see if we overrun comparing against mechs. */
+ try_accept("\x60\x40\x06\x09", 4);
+}
+
int
main(int argc, char **argv)
{
@@ -425,5 +470,7 @@ main(int argc, char **argv)
free_fake_context(ctx);
}
+ test_short_encapsulation();
+
return 0;
}