svn rev #22248: branches/krb5-1-7/src/lib/gssapi/spnego/

tlyu@MIT.EDU tlyu at MIT.EDU
Wed Apr 15 16:07:30 EDT 2009


http://src.mit.edu/fisheye/changelog/krb5/?cs=22248
Commit By: tlyu
Log Message:
ticket: 6443
version_fixed: 1.7

pull up r22174 from trunk

 ------------------------------------------------------------------------
 r22174 | tlyu | 2009-04-07 17:22:17 -0400 (Tue, 07 Apr 2009) | 11 lines
 Changed paths:
    M /trunk/src/lib/gssapi/spnego/spnego_mech.c

 ticket: 6443
 subject: CVE-2009-0844 SPNEGO can read beyond buffer end
 tags: pullup
 target_version: 1.7

 SPNEGO can read beyond the end of a buffer if the claimed DER length
 exceeds the number of bytes in the input buffer. This can lead to
 crash or information disclosure.

 Thanks to Apple for reporting this vulnerability and providing
 patches.


Changed Files:
U   branches/krb5-1-7/src/lib/gssapi/spnego/spnego_mech.c
Modified: branches/krb5-1-7/src/lib/gssapi/spnego/spnego_mech.c
===================================================================
--- branches/krb5-1-7/src/lib/gssapi/spnego/spnego_mech.c	2009-04-15 20:07:26 UTC (rev 22247)
+++ branches/krb5-1-7/src/lib/gssapi/spnego/spnego_mech.c	2009-04-15 20:07:30 UTC (rev 22248)
@@ -83,8 +83,8 @@
 
 /* der routines defined in libgss */
 extern unsigned int gssint_der_length_size(OM_uint32);
-extern int gssint_get_der_length(unsigned char **, OM_uint32, OM_uint32*);
-extern int gssint_put_der_length(OM_uint32, unsigned char **, OM_uint32);
+extern int gssint_get_der_length(unsigned char **, OM_uint32, unsigned int*);
+extern int gssint_put_der_length(OM_uint32, unsigned char **, unsigned int);
 
 
 /* private routines for spnego_mechanism */
@@ -2390,22 +2390,16 @@
 get_input_token(unsigned char **buff_in, unsigned int buff_length)
 {
 	gss_buffer_t input_token;
-	unsigned int bytes;
+	unsigned int len;
 
-	if (**buff_in != OCTET_STRING)
+	if (g_get_tag_and_length(buff_in, OCTET_STRING, buff_length, &len) < 0)
 		return (NULL);
 
-	(*buff_in)++;
 	input_token = (gss_buffer_t)malloc(sizeof (gss_buffer_desc));
-
 	if (input_token == NULL)
 		return (NULL);
 
-	input_token->length = gssint_get_der_length(buff_in, buff_length, &bytes);
-	if ((int)input_token->length == -1) {
-		free(input_token);
-		return (NULL);
-	}
+	input_token->length = len;
 	input_token->value = malloc(input_token->length);
 
 	if (input_token->value == NULL) {
@@ -2457,8 +2451,8 @@
 {
 	gss_OID_set returned_mechSet;
 	OM_uint32 major_status;
-	OM_uint32 length;
-	OM_uint32 bytes;
+	int length;
+	unsigned int bytes;
 	OM_uint32 set_length;
 	unsigned char		*start;
 	int i;
@@ -2470,23 +2464,26 @@
 	(*buff_in)++;
 
 	length = gssint_get_der_length(buff_in, buff_length, &bytes);
+	if (length < 0 || buff_length - bytes < (unsigned int)length)
+		return NULL;
 
 	major_status = gss_create_empty_oid_set(minor_status,
 						&returned_mechSet);
 	if (major_status != GSS_S_COMPLETE)
 		return (NULL);
 
-	for (set_length = 0, i = 0; set_length < length; i++) {
+	for (set_length = 0, i = 0; set_length < (unsigned int)length; i++) {
 		gss_OID_desc *temp = get_mech_oid(minor_status, buff_in,
 			buff_length - (*buff_in - start));
-		if (temp != NULL) {
-		    major_status = gss_add_oid_set_member(minor_status,
-					temp, &returned_mechSet);
-		    if (major_status == GSS_S_COMPLETE) {
+		if (temp == NULL)
+			break;
+
+		major_status = gss_add_oid_set_member(minor_status,
+						      temp, &returned_mechSet);
+		if (major_status == GSS_S_COMPLETE) {
 			set_length += returned_mechSet->elements[i].length +2;
 			if (generic_gss_release_oid(minor_status, &temp))
-			    map_errcode(minor_status);
-		    }
+				map_errcode(minor_status);
 		}
 	}
 
@@ -2665,7 +2662,7 @@
 		return GSS_S_DEFECTIVE_TOKEN;
 	if (*ptr++ == SEQUENCE) {
 		tmplen = gssint_get_der_length(&ptr, REMAIN, &bytes);
-		if (tmplen < 0)
+		if (tmplen < 0 || REMAIN < (unsigned int)tmplen)
 			return GSS_S_DEFECTIVE_TOKEN;
 	}
 	if (REMAIN < 1)
@@ -2675,7 +2672,7 @@
 
 	if (tag == CONTEXT) {
 		tmplen = gssint_get_der_length(&ptr, REMAIN, &bytes);
-		if (tmplen < 0)
+		if (tmplen < 0 || REMAIN < (unsigned int)tmplen)
 			return GSS_S_DEFECTIVE_TOKEN;
 
 		if (g_get_tag_and_length(&ptr, ENUMERATED,
@@ -2696,7 +2693,7 @@
 	}
 	if (tag == (CONTEXT | 0x01)) {
 		tmplen = gssint_get_der_length(&ptr, REMAIN, &bytes);
-		if (tmplen < 0)
+		if (tmplen < 0 || REMAIN < (unsigned int)tmplen)
 			return GSS_S_DEFECTIVE_TOKEN;
 
 		*supportedMech = get_mech_oid(minor_status, &ptr, REMAIN);
@@ -2710,7 +2707,7 @@
 	}
 	if (tag == (CONTEXT | 0x02)) {
 		tmplen = gssint_get_der_length(&ptr, REMAIN, &bytes);
-		if (tmplen < 0)
+		if (tmplen < 0 || REMAIN < (unsigned int)tmplen)
 			return GSS_S_DEFECTIVE_TOKEN;
 
 		*responseToken = get_input_token(&ptr, REMAIN);
@@ -2724,7 +2721,7 @@
 	}
 	if (tag == (CONTEXT | 0x03)) {
 		tmplen = gssint_get_der_length(&ptr, REMAIN, &bytes);
-		if (tmplen < 0)
+		if (tmplen < 0 || REMAIN < (unsigned int)tmplen)
 			return GSS_S_DEFECTIVE_TOKEN;
 
 		*mechListMIC = get_input_token(&ptr, REMAIN);
@@ -3269,7 +3266,7 @@
 	unsigned char *ptr = *buf;
 	int ret = -1; /* pessimists, assume failure ! */
 	unsigned int encoded_len;
-	unsigned int tmplen = 0;
+	int tmplen = 0;
 
 	*outlen = 0;
 	if (buflen > 1 && *ptr == tag) {
@@ -3278,7 +3275,7 @@
 						&encoded_len);
 		if (tmplen < 0) {
 			ret = -1;
-		} else if (tmplen > buflen - (ptr - *buf)) {
+		} else if ((unsigned int)tmplen > buflen - (ptr - *buf)) {
 			ret = -1;
 		} else
 			ret = 0;




More information about the cvs-krb5 mailing list