[Chilli] Bug in password handling - Rev 257 PATCH

Alberto Bellettato albesvs at yahoo.it
Tue Dec 15 12:46:42 UTC 2009


Long passwords still did not work with the latest svn rev. 257, so I dug into the code and I found a real problem.

In 3 code's rows, the length of the password string is calculated through strlen(), that considers the first NUL as the end of the string, as you surely know.

But in function redir_hextochar() (redir.c row 78), sscanf() is used to transform the password from hex string to char (row 87).

And here is the big problem:
the hex password string is the result of the md5() encryption so it _can_ contain the hex '00', that will be converted to NUL by sscanf().

You can easily test it with this example:

--------------------------------------------
#include <stdio.h> 

main () {
  char x[3];
  int y;
  char ds[7];

  x[0] = '0';
  x[1] = '0';
  x[2] = 0;
  if (sscanf(x, "%2x", &y) != 1) 
    printf("\nError\n");
  ds[0]='s';
  ds[1]='t';
  ds[2]='r';
  ds[3]=(char)y;
  ds[4]='n';
  ds[5]='g';
  ds[6]='\0';
  printf("\n%s\n",ds);
}
----------------------------------------------

The output will be 'str' and NOT 'str0ng' !!

Obviously this problem shows more frequently as the password's length increase because the probability of finding a HEX '00' increases with it.

So I patched the code to remove all the strlen() use with password strings, and I optimized some parts too.
I tested it with Rev 257 configured with --enable-chilliredir and it works fine with every password length.
NOTE: if password's length (sent by UAM service) is more than 128 chars (RFC2865 maximum length) it is truncated to the first 128 chars.

Here is the patch for Rev 257:

Index: src/redir.c
===================================================================
--- src/redir.c	(revisione 257)
+++ src/redir.c	(copia locale)
@@ -85,10 +85,8 @@
     x[1] = src[n*2+1];
     x[2] = 0;
     if (sscanf(x, "%2x", &y) != 1) {
-      /*log_err(0, "HEX conversion failed!");
-	return -1;*/
-      dst[n] = 0;
-      break;
+      log_err(0, "HEX conversion failed!");
+      return -1;
     }
     dst[n] = (unsigned char) y;
   }
@@ -405,7 +403,7 @@
   
   hex[0]=0;
   for (i=0; i<16; i++)
-    sprintf(hex+strlen(hex), "%.2X", cksum[i]);
+    sprintf(hex+2*i, "%.2X", cksum[i]);
   
   bcatcstr(str, amp);
   bcatcstr(str, "md=");
@@ -1570,8 +1568,11 @@
 	conn->password[0] = 0;
       }
       else if (!redir_getparam(redir, httpreq->qs, "password", bt)) {
-	redir_hextochar(bt->data, conn->password, RADIUS_PWSIZE);
-	conn->password[RADIUS_PWSIZE-1]=0;
+	conn->password_len = bt->slen/2;
+	log_dbg("Password length: %d",conn->password_len);
+	if (conn->password_len > RADIUS_PWSIZE)
+	  conn->password_len = RADIUS_PWSIZE;
+	redir_hextochar(bt->data, conn->password, conn->password_len);
 	conn->chap = 0;
 	conn->chappassword[0] = 0;
       } else {
@@ -1798,7 +1799,7 @@
       for (n=0; n < REDIR_MD5LEN; m++, n++)
 	user_password[m] = conn->password[m] ^ chap_challenge[n];
     
-    user_password[strlen((char *)conn->password)] = 0;
+    user_password[conn->password_len] = 0;
 
 #ifdef HAVE_OPENSSL
     if (_options.mschapv2) {
@@ -1810,7 +1811,7 @@
       
       GenerateNTResponse(chap_challenge, /*peer*/chap_challenge,
 			 conn->s_state.redir.username, strlen(conn->s_state.redir.username),
-			 user_password, strlen(user_password),
+			 user_password, conn->password_len,
 			 ntresponse);
       
       /* peer challenge - same as auth challenge */
@@ -1831,7 +1832,7 @@
 #endif
       
       radius_addattr(radius, &radius_pack, RADIUS_ATTR_USER_PASSWORD, 0, 0, 0,
-		     user_password, strlen((char*)user_password));
+		     user_password, conn->password_len);
 
 #ifdef HAVE_OPENSSL
     }
Index: src/redir.h
===================================================================
--- src/redir.h	(revisione 257)
+++ src/redir.h	(copia locale)
@@ -79,6 +79,7 @@
   int response; /* 0: No radius response yet; 1:Reject; 2:Accept; 3:Timeout */
   uint8_t chappassword[RADIUS_CHAPSIZE];
   uint8_t password[RADIUS_PWSIZE];
+  int password_len;
   uint8_t chap_ident;
   
   /* 
Index: src/radius.c
===================================================================
--- src/radius.c	(revisione 257)
+++ src/radius.c	(copia locale)
@@ -1064,7 +1064,7 @@
     *dstlen = srclen;                 /* No padding */
 
   /* Is dstsize too small ? */
-  if (dstsize <= *dstlen) {
+  if (dstsize < *dstlen) {
     *dstlen = 0;
     return -1;
   }





More information about the Chilli mailing list