diff -ur freeradius-1.1.3-orig/share/dictionary freeradius-1.1.3/share/dictionary
--- freeradius-1.1.3-orig/share/dictionary	2006-07-27 01:00:19.000000000 +0200
+++ freeradius-1.1.3/share/dictionary	2006-09-18 08:00:43.000000000 +0200
@@ -159,9 +159,8 @@
 #
 ATTRIBUTE	Originating-Line-Info			94	string
 
-#  As defined in draft-sterman-aaa-sip-00.txt
-ATTRIBUTE	Digest-Response				206	string
-ATTRIBUTE	Digest-Attributes			207	octets	# stupid format
+#  As defined in rfc 4590
+$INCLUDE dictionary.digest
 
 #
 #	Integer Translations
diff -ur freeradius-1.1.3-orig/share/dictionary.digest freeradius-1.1.3/share/dictionary.digest
--- freeradius-1.1.3-orig/share/dictionary.digest	2005-11-30 23:17:23.000000000 +0100
+++ freeradius-1.1.3/share/dictionary.digest	2006-09-20 08:02:47.000000000 +0200
@@ -1,16 +1,41 @@
-#  As defined in draft-sterman-aaa-sip-00.txt
-ATTRIBUTE	Digest-Response				206	string
-ATTRIBUTE	Digest-Attributes			207	octets	# stupid format
-
-BEGIN-SUB-ATTR Digest-Attributes
-ATTRIBUTE	Digest-Realm				1	string
-ATTRIBUTE	Digest-Nonce				2	string
-ATTRIBUTE	Digest-Method				3	string
-ATTRIBUTE	Digest-URI				4	string
-ATTRIBUTE	Digest-QOP				5	string
-ATTRIBUTE	Digest-Algorithm			6	string
-ATTRIBUTE	Digest-Body-Digest			7	string
-ATTRIBUTE	Digest-CNonce				8	string
-ATTRIBUTE	Digest-Nonce-Count			9	string
-ATTRIBUTE	Digest-User-Name			10	string
-END-SUB-ATTR
+#  As defined in rfc 4590
+ATTRIBUTE	Digest-Realm				104	string
+ATTRIBUTE	Digest-Nonce				105	string
+ATTRIBUTE	Digest-Response				106	string
+ATTRIBUTE	Digest-Nextonce				107	string
+ATTRIBUTE	Digest-Method				108	string
+ATTRIBUTE	Digest-URI				109	string
+ATTRIBUTE	Digest-QOP				110	string
+ATTRIBUTE	Digest-Algorithm			111	string
+ATTRIBUTE	Digest-Body-Digest			112	string
+ATTRIBUTE	Digest-CNonce				113	string
+ATTRIBUTE	Digest-Nonce-Count			114	string
+ATTRIBUTE	Digest-User-Name			115	string
+ATTRIBUTE	Digest-Opaque				116	string
+ATTRIBUTE	Digest-Auth-Param			117	string
+ATTRIBUTE	Digest-AKA-Auts				118	string
+ATTRIBUTE	Digest-Domain				119	string
+ATTRIBUTE	Digest-Stale				120	string
+ATTRIBUTE	Digest-HA1				121	string
+ATTRIBUTE	SIP-AOR					122	string
+
+#draft-00 format to avoid regression of freeradius
+ATTRIBUTE       Digest-Obselete-Response                         206     string
+ATTRIBUTE       Digest-Obselete-Attributes                       207     octets  # stupid format
+
+ATTRIBUTE	Digest-Obselete-Realm				1063	string
+ATTRIBUTE	Digest-Obselete-Nonce				1064	string
+ATTRIBUTE	Digest-Obselete-Method			1065	string
+ATTRIBUTE	Digest-Obselete-URI					1066	string
+ATTRIBUTE	Digest-Obselete-QOP					1067	string
+ATTRIBUTE	Digest-Obselete-Algorithm		1068	string
+ATTRIBUTE	Digest-Obselete-Body-Digest	1069	string
+ATTRIBUTE	Digest-Obselete-CNonce			1070	string
+ATTRIBUTE	Digest-Obselete-Nonce-Count	1071	string
+ATTRIBUTE	Digest-Obselete-User-Name		1072	string
+ATTRIBUTE	Digest-Obselete-HA1					1081	string
+
+
+
+
+
diff -ur freeradius-1.1.3-orig/share/dictionary.freeradius.internal freeradius-1.1.3/share/dictionary.freeradius.internal
--- freeradius-1.1.3-orig/share/dictionary.freeradius.internal	2006-03-07 19:10:09.000000000 +0100
+++ freeradius-1.1.3/share/dictionary.freeradius.internal	2006-09-15 08:42:39.000000000 +0200
@@ -89,16 +89,6 @@
 ATTRIBUTE	SMB-Account-CTRL			1059	integer
 ATTRIBUTE	SMB-Account-CTRL-TEXT			1061	string
 ATTRIBUTE	User-Profile				1062	string
-ATTRIBUTE	Digest-Realm				1063	string
-ATTRIBUTE	Digest-Nonce				1064	string
-ATTRIBUTE	Digest-Method				1065	string
-ATTRIBUTE	Digest-URI				1066	string
-ATTRIBUTE	Digest-QOP				1067	string
-ATTRIBUTE	Digest-Algorithm			1068	string
-ATTRIBUTE	Digest-Body-Digest			1069	string
-ATTRIBUTE	Digest-CNonce				1070	string
-ATTRIBUTE	Digest-Nonce-Count			1071	string
-ATTRIBUTE	Digest-User-Name			1072	string
 ATTRIBUTE	Pool-Name				1073	string
 ATTRIBUTE	Ldap-Group				1074	string
 ATTRIBUTE	Module-Success-Message			1075	string
@@ -107,7 +97,6 @@
 ATTRIBUTE	Rewrite-Rule				1078	string
 ATTRIBUTE	Sql-Group				1079	string
 ATTRIBUTE	Response-Packet-Type			1080	integer
-ATTRIBUTE	Digest-HA1				1081	string
 ATTRIBUTE	MS-CHAP-Use-NTLM-Auth			1082	integer
 ATTRIBUTE	NTLM-User-Name				1083	string
 ATTRIBUTE	Packet-Src-IP-Address			1084	ipaddr
diff -ur freeradius-1.1.3-orig/src/include/radius.h freeradius-1.1.3/src/include/radius.h
--- freeradius-1.1.3-orig/src/include/radius.h	2006-03-07 19:10:08.000000000 +0100
+++ freeradius-1.1.3/src/include/radius.h	2006-09-20 08:06:12.000000000 +0200
@@ -113,8 +113,12 @@
 #define PW_FRAMED_POOL			88
 #define PW_NAS_IPV6_ADDRESS		95
 
-#define PW_DIGEST_RESPONSE		206
-#define PW_DIGEST_ATTRIBUTES		207
+#define PW_DIGEST_RESPONSE		106
+
+/* Draft version of digest to avoid regression of freeradius*/ 
+#define PW_DIGEST_OBSELETE_RESPONSE              206
+#define PW_DIGEST_OBSELETE_ATTRIBUTES            207
+
 
 #define PW_FALL_THROUGH			500
 #define PW_ADD_PORT_TO_IP_ADDRESS	501
@@ -166,16 +170,44 @@
 #define PW_SMB_ACCOUNT_CTRL		1059
 #define PW_SMB_ACCOUNT_CTRL_TEXT	1061
 #define PW_USER_PROFILE			1062
-#define PW_DIGEST_REALM			1063
-#define PW_DIGEST_NONCE			1064
-#define PW_DIGEST_METHOD		1065
-#define PW_DIGEST_URI			1066
-#define PW_DIGEST_QOP			1067
-#define PW_DIGEST_ALGORITHM		1068
-#define PW_DIGEST_BODY_DIGEST		1069
-#define PW_DIGEST_CNONCE		1070
-#define PW_DIGEST_NONCE_COUNT		1071
-#define PW_DIGEST_USER_NAME		1072
+
+
+#define PW_DIGEST_REALM			104
+#define PW_DIGEST_NONCE			105
+#define PW_DIGEST_METHOD		108
+#define PW_DIGEST_URI			109
+#define PW_DIGEST_QOP			110
+#define PW_DIGEST_ALGORITHM		111
+#define PW_DIGEST_BODY_DIGEST		112
+#define PW_DIGEST_CNONCE		113
+#define PW_DIGEST_NONCE_COUNT		114
+#define PW_DIGEST_USER_NAME		115
+#define PW_DIGEST_HA1     121
+
+/* Draft version of digest to avoid regression of freeradius */ 
+#define PW_DIGEST_OBSELETE_REALM                 1
+#define PW_DIGEST_OBSELETE_NONCE                 2
+#define PW_DIGEST_OBSELETE_METHOD                3
+#define PW_DIGEST_OBSELETE_URI                   4
+#define PW_DIGEST_OBSELETE_QOP                   5
+#define PW_DIGEST_OBSELETE_ALGORITHM             6
+#define PW_DIGEST_OBSELETE_BODY_DIGEST           7
+#define PW_DIGEST_OBSELETE_CNONCE                8
+#define PW_DIGEST_OBSELETE_NONCE_COUNT           9
+#define PW_DIGEST_OBSELETE_USER_NAME             10
+
+#define PW_DIGEST_OBSELETE_INTERNAL_REALM                 1063
+#define PW_DIGEST_OBSELETE_INTERNAL_NONCE                 1064
+#define PW_DIGEST_OBSELETE_INTERNAL_METHOD                1065
+#define PW_DIGEST_OBSELETE_INTERNAL_URI                   1066
+#define PW_DIGEST_OBSELETE_INTERNAL_QOP                   1067
+#define PW_DIGEST_OBSELETE_INTERNAL_ALGORITHM             1068
+#define PW_DIGEST_OBSELETE_INTERNAL_BODY_DIGEST           1069
+#define PW_DIGEST_OBSELETE_INTERNAL_CNONCE                1070
+#define PW_DIGEST_OBSELETE_INTERNAL_NONCE_COUNT           1071
+#define PW_DIGEST_OBSELETE_INTERNAL_USER_NAME             1072
+
+
 #define PW_POOL_NAME			1073
 #define PW_LDAP_GROUP			1074
 #define PW_MODULE_SUCCESS_MESSAGE	1075
@@ -186,7 +218,6 @@
 #define PW_REWRITE_RULE			1078
 #define PW_SQL_GROUP			1079
 #define PW_RESPONSE_PACKET_TYPE		1080
-#define PW_DIGEST_HA1			1081
 #define PW_MS_CHAP_USE_NTLM_AUTH	1082
 #define PW_PACKET_SRC_IP_ADDRESS	1084
 #define PW_PACKET_DST_IP_ADDRESS	1085
diff -ur freeradius-1.1.3-orig/src/main/radclient.c freeradius-1.1.3/src/main/radclient.c
--- freeradius-1.1.3-orig/src/main/radclient.c	2006-05-16 20:26:08.000000000 +0200
+++ freeradius-1.1.3/src/main/radclient.c	2006-09-20 12:54:14.000000000 +0200
@@ -230,13 +230,11 @@
 		}
 
 		/*
-		 *  Fix up Digest-Attributes issues
+		 *  Fix up the old style Digest-Attributes issues
 		 */
 		for (vp = radclient->request->vps; vp != NULL; vp = vp->next) {
+      int attrib = 0;
 			switch (vp->attribute) {
-			default:
-				break;
-
 				/*
 				 *	Allow it to set the packet type in
 				 *	the attributes read from the file.
@@ -244,29 +242,51 @@
 			case PW_PACKET_TYPE:
 				radclient->request->code = vp->lvalue;
 				break;
-
 			case PW_PACKET_DST_PORT:
 				radclient->request->dst_port = (vp->lvalue & 0xffff);
 				break;
 
-			case PW_DIGEST_REALM:
-			case PW_DIGEST_NONCE:
-			case PW_DIGEST_METHOD:
-			case PW_DIGEST_URI:
-			case PW_DIGEST_QOP:
-			case PW_DIGEST_ALGORITHM:
-			case PW_DIGEST_BODY_DIGEST:
-			case PW_DIGEST_CNONCE:
-			case PW_DIGEST_NONCE_COUNT:
-			case PW_DIGEST_USER_NAME:
-				/* overlapping! */
-				memmove(&vp->strvalue[2], &vp->strvalue[0], vp->length);
-				vp->strvalue[0] = vp->attribute - PW_DIGEST_REALM + 1;
-				vp->length += 2;
-				vp->strvalue[1] = vp->length;
-				vp->attribute = PW_DIGEST_ATTRIBUTES;
+			case PW_DIGEST_OBSELETE_INTERNAL_REALM:
+        attrib = PW_DIGEST_OBSELETE_REALM;
+        break;
+			case PW_DIGEST_OBSELETE_INTERNAL_NONCE:
+        attrib = PW_DIGEST_OBSELETE_NONCE;
+        break;
+      case PW_DIGEST_OBSELETE_INTERNAL_METHOD:
+        attrib = PW_DIGEST_OBSELETE_METHOD;
+        break;
+			case PW_DIGEST_OBSELETE_INTERNAL_URI:
+        attrib = PW_DIGEST_OBSELETE_URI;
+        break;
+			case PW_DIGEST_OBSELETE_INTERNAL_QOP:
+        attrib = PW_DIGEST_OBSELETE_QOP;
+        break;
+			case PW_DIGEST_OBSELETE_INTERNAL_ALGORITHM:
+        attrib = PW_DIGEST_OBSELETE_ALGORITHM;
+        break;
+			case PW_DIGEST_OBSELETE_INTERNAL_BODY_DIGEST:
+        attrib = PW_DIGEST_OBSELETE_BODY_DIGEST;
+        break;
+			case PW_DIGEST_OBSELETE_INTERNAL_CNONCE:
+        attrib = PW_DIGEST_OBSELETE_CNONCE;
+        break;
+			case PW_DIGEST_OBSELETE_INTERNAL_NONCE_COUNT:
+        attrib = PW_DIGEST_OBSELETE_NONCE_COUNT;
+        break;
+			case PW_DIGEST_OBSELETE_INTERNAL_USER_NAME:
+				attrib = PW_DIGEST_OBSELETE_USER_NAME;
 				break;
+        
+      default:
+        break;
 			}
+      if (attrib != 0) {      
+        memmove(&vp->strvalue[2], &vp->strvalue[0], vp->length);
+        vp->strvalue[0] = attrib;
+        vp->length += 2;
+        vp->strvalue[1] = vp->length;
+        vp->attribute = PW_DIGEST_OBSELETE_ATTRIBUTES;
+      }
 		} /* loop over the VP's we read in */
 
 		if (!start) {
diff -ur freeradius-1.1.3-orig/src/modules/rlm_digest/rlm_digest.c freeradius-1.1.3/src/modules/rlm_digest/rlm_digest.c
--- freeradius-1.1.3-orig/src/modules/rlm_digest/rlm_digest.c	2006-04-29 01:44:31.000000000 +0200
+++ freeradius-1.1.3/src/modules/rlm_digest/rlm_digest.c	2006-09-20 12:42:50.000000000 +0200
@@ -36,33 +36,179 @@
 static int digest_authorize(void *instance, REQUEST *request)
 {
 	VALUE_PAIR *vp;
-
-	/* quiet the compiler */
+  
+  /* quiet the compiler */
 	instance = instance;
-
-	/*
-	 *	We need both of these attributes to do the authentication.
-	 */
-	vp = pairfind(request->packet->vps, PW_DIGEST_RESPONSE);
-	if (vp == NULL) {
-		return RLM_MODULE_NOOP;
-	}
-
-	/*
-	 *	Check the sanity of the attribute.
-	 */
-	if (vp->length != 32) {
-		DEBUG("ERROR: Received invalid Digest-Response attribute (length %d should be 32)", vp->length);
-		return RLM_MODULE_INVALID;
-	}
-
-	/*
-	 *	We need these, too.
-	 */
-	vp = pairfind(request->packet->vps, PW_DIGEST_ATTRIBUTES);
-	if (vp == NULL) {
-		DEBUG("ERROR: Received Digest-Response without Digest-Attributes");
-		return RLM_MODULE_INVALID;
+  
+  /* 
+   * Even though RFC 4590 replaces the old draft style attributes, 
+   * we handle these to avoid regression
+   */
+  
+  DEBUG("    rlm_digest: Looking for old style attributes to convert");
+  vp = pairfind(request->packet->vps, PW_DIGEST_OBSELETE_RESPONSE);
+  if (vp) {
+    DEBUG("    rlm_digest: Converting old style response");
+    VALUE_PAIR *resp;
+    resp = paircopy(vp);
+    resp->attribute = PW_DIGEST_RESPONSE;
+    pairadd(&request->packet->vps, resp);    
+  }
+  
+  vp = pairfind(request->packet->vps, PW_DIGEST_OBSELETE_ATTRIBUTES);
+  while (vp) {
+    int length = vp->length;
+    int attrlen;
+    uint8_t *p = &vp->strvalue[0];
+    VALUE_PAIR *sub;
+
+    while (length > 0) {
+      /* Valid sub-attribute? */
+      if ((p[0] == 0) || (p[0] > 10)) {
+        DEBUG("ERROR: Received Digest-Attributes with invalid sub-attribute %d", p[0]);
+        return RLM_MODULE_INVALID;
+      }
+
+      attrlen = p[1];
+
+      /* Sanity check on subattribute length */
+      if (attrlen < 3 || attrlen > length) {
+        DEBUG("ERROR: Received Digest-Attributes with sub-attribute %d, of length %d. This is wrong.", p[0], attrlen);
+        return RLM_MODULE_INVALID;
+      }
+
+      DEBUG("    rlm_digest: Converting an old style attribute!");      
+      /*  Create a new attribute, broken out of the old style subattribute. */
+      switch(p[0]) {
+        case PW_DIGEST_OBSELETE_REALM:
+          sub = paircreate(PW_DIGEST_REALM,
+           PW_TYPE_STRING);
+           break;
+        case PW_DIGEST_OBSELETE_NONCE:
+          sub = paircreate(PW_DIGEST_NONCE,
+           PW_TYPE_STRING);
+           break;
+        case PW_DIGEST_OBSELETE_METHOD:
+          sub = paircreate(PW_DIGEST_METHOD,
+           PW_TYPE_STRING);
+           break;
+        case PW_DIGEST_OBSELETE_URI:
+          sub = paircreate(PW_DIGEST_URI,
+           PW_TYPE_STRING);
+           break;
+        case PW_DIGEST_OBSELETE_QOP:
+          sub = paircreate(PW_DIGEST_QOP,
+           PW_TYPE_STRING);
+           break;
+        case PW_DIGEST_OBSELETE_ALGORITHM:
+          sub = paircreate(PW_DIGEST_ALGORITHM,
+           PW_TYPE_STRING);
+           break;
+        case PW_DIGEST_OBSELETE_BODY_DIGEST:
+          sub = paircreate(PW_DIGEST_BODY_DIGEST,
+           PW_TYPE_STRING);
+           break;
+        case PW_DIGEST_OBSELETE_CNONCE:
+          sub = paircreate(PW_DIGEST_CNONCE,
+           PW_TYPE_STRING);
+           break;
+        case PW_DIGEST_OBSELETE_NONCE_COUNT:
+          sub = paircreate(PW_DIGEST_NONCE_COUNT,
+           PW_TYPE_STRING);
+           break;
+        case PW_DIGEST_OBSELETE_USER_NAME:
+          sub = paircreate(PW_DIGEST_USER_NAME,
+           PW_TYPE_STRING);
+           break;
+        default:
+          return RLM_MODULE_FAIL;
+      }
+      
+      if (!sub) {
+        return RLM_MODULE_FAIL; /* out of memory */
+      }
+      /* Copy the subattribute data to the new flat attribute */
+      memcpy(&sub->strvalue[0], &p[2], attrlen - 2);
+      sub->strvalue[attrlen - 2] = '\0';
+      sub->length = attrlen - 2;
+
+      if (debug_flag) {
+        putchar('\t');
+        vp_print(stdout, sub);
+        putchar('\n');
+      }
+  
+      /* Add the created new-style attribute to package */
+      pairadd(&request->packet->vps, sub);
+
+      length -= attrlen;
+      p += attrlen;
+    } /* loop over this one attribute */
+  /* Next obselete attribute (if any) */
+  vp = pairfind(vp->next, PW_DIGEST_OBSELETE_ATTRIBUTES);
+  }
+  
+  
+
+
+	/*
+	 *	These attributes must always be present
+	 */
+	if (!pairfind(request->packet->vps, PW_DIGEST_METHOD)) {
+    DEBUG("ERROR: Received Digest-Response without Digest-Method");
+    return RLM_MODULE_INVALID;
+  }
+  if (!pairfind(request->packet->vps, PW_DIGEST_URI)) {
+    DEBUG("ERROR: Received Digest-Response without Digest-URI");
+    return RLM_MODULE_INVALID;
+  }
+
+  /* At this point (having a Method and URI) we look for a nonce. 
+   * If there is no nonce, we should create one and reply with a challange!
+   */   
+  if (!pairfind(request->packet->vps, PW_DIGEST_NONCE)) {
+    DEBUG("ERROR: Challange should be created, but it is not implemented!");
+    
+    return RLM_MODULE_INVALID;
+  } 
+  
+  /*
+   *  Ok, so this package has a nonce (see prev comment)
+   *  Make sure the rest of the required attribs are there...  
+   */
+  vp = pairfind(request->packet->vps, PW_DIGEST_RESPONSE);
+  if (vp == NULL) {
+    DEBUG("ERROR: There is no Digest-Response");
+    return RLM_MODULE_NOOP;
+  }
+
+  /*
+   *  Check the sanity of the attribute.
+   */
+  if (vp->length != 32) {
+    DEBUG("ERROR: Received invalid Digest-Response attribute (length %d should be 32)", vp->length);
+    return RLM_MODULE_INVALID;
+  }
+  if (!pairfind(request->packet->vps, PW_DIGEST_REALM)) {
+		DEBUG("ERROR: Received Digest-Response without Digest-Realm");
+		return RLM_MODULE_INVALID;
+	}
+	if (!pairfind(request->packet->vps, PW_DIGEST_USER_NAME)) {
+		DEBUG("ERROR: Received Digest-Response without Digest-Username");
+		return RLM_MODULE_INVALID;
+	}
+	if (!pairfind(request->packet->vps, PW_DIGEST_QOP)) {
+		DEBUG("ERROR: Received Digest-Response without Digest-Qop");
+		return RLM_MODULE_INVALID;
+	}
+	/*
+	 * If QoP = auth-int then digest-body-digest is required
+	 */
+	if (strncmp("auth-int", vp->strvalue, strlen(vp->strvalue)) == 0) {
+	  if (!pairfind(request->packet->vps, PW_DIGEST_BODY_DIGEST)) {
+	    DEBUG("ERROR: Received Digest-Response with QoP = auth-int without Digest-Body-Digest");
+	    return RLM_MODULE_INVALID;
+	  }
 	}
 
 	/*
@@ -82,423 +228,285 @@
  */
 static int digest_authenticate(void *instance, REQUEST *request)
 {
-	int i;
-	size_t a1_len, a2_len, kd_len;
+  int i;
+  
+	size_t a1_len, a2_len, response_len;
 	uint8_t a1[(MAX_STRING_LEN + 1) * 5]; /* can be 5 attributes */
+  uint8_t ha1[32];
 	uint8_t a2[(MAX_STRING_LEN + 1) * 3]; /* can be 3 attributes */
-	uint8_t kd[(MAX_STRING_LEN + 1) * 5];
+	uint8_t ha2[32];
+  uint8_t response[(MAX_STRING_LEN + 1) * 5];
+  
 	uint8_t hash[16];	/* MD5 output */
-	VALUE_PAIR *vp, *passwd, *algo;
-	VALUE_PAIR *qop, *nonce;
+  
+	VALUE_PAIR *resp, *digestha1, *algo;
+  VALUE_PAIR *method, *uri;
+	VALUE_PAIR *nonce, *ncount, *cnonce, *qop;
 
 	instance = instance;	/* -Wunused */
 
+  
 	/*
-	 *	We require access to the plain-text password.
+	 *	We require access to the plain-text password or the Digest-HA1
 	 */
-	passwd = pairfind(request->config_items, PW_DIGEST_HA1);
-	if (passwd) {
-		if (passwd->length != 32) {
+	digestha1 = pairfind(request->config_items, PW_DIGEST_HA1);
+	if (digestha1) {
+    /* Sanity check */
+		if (digestha1->length != 32) {
 			radlog(L_AUTH, "rlm_digest: Digest-HA1 has invalid length, authentication failed.");
 			return RLM_MODULE_INVALID;
 		}
+    
+    memcpy(ha1, digestha1->strvalue, 32);
+    DEBUG2("A1 = (using pre-hashed Digest-HA1)");
 	} else {
-		passwd = pairfind(request->config_items, PW_PASSWORD);
-	}
-	if (!passwd) {
-		radlog(L_AUTH, "rlm_digest: Configuration item \"User-Password\" or Digest-HA1 is required for authentication.");
-		return RLM_MODULE_INVALID;
-	}
-
-	/*
-	 *	We need these, too.
-	 */
-	vp = pairfind(request->packet->vps, PW_DIGEST_ATTRIBUTES);
-	if (vp == NULL) {
-		DEBUG("ERROR: You set 'Auth-Type = Digest' for a request that did not contain any digest attributes!");
-		return RLM_MODULE_INVALID;
-	}
-
-	/*
-	 *	Loop through the Digest-Attributes, sanity checking them.
-	 */
-	DEBUG("    rlm_digest: Converting Digest-Attributes to something sane...");
-	while (vp) {
-		int length = vp->length;
-		int attrlen;
-		uint8_t *p = &vp->strvalue[0];
-		VALUE_PAIR *sub;
-
-		/*
-		 *	Until this stupidly encoded attribure is exhausted.
-		 */
-		while (length > 0) {
-			/*
-			 *	The attribute type must be valid
-			 */
-			if ((p[0] == 0) || (p[0] > 10)) {
-				DEBUG("ERROR: Received Digest-Attributes with invalid sub-attribute %d", p[0]);
-				return RLM_MODULE_INVALID;
-			}
-
-			attrlen = p[1];	/* stupid VSA format */
-
-			/*
-			 *	Too short.
-			 */
-			if (attrlen < 3) {
-				DEBUG("ERROR: Received Digest-Attributes with short sub-attribute %d, of length %d", p[0], attrlen);
-				return RLM_MODULE_INVALID;
-			}
-
-			/*
-			 *	Too long.
-			 */
-			if (attrlen > length) {
-				DEBUG("ERROR: Received Digest-Attributes with long sub-attribute %d, of length %d", p[0], attrlen);
-				return RLM_MODULE_INVALID;
-			}
-
-			/*
-			 *	Create a new attribute, broken out of
-			 *	the stupid sub-attribute crap.
-			 *
-			 *	Didn't they know that VSA's exist?
-			 */
-			sub = paircreate(PW_DIGEST_REALM - 1 + p[0],
-					 PW_TYPE_STRING);
-			if (!sub) {
-				return RLM_MODULE_FAIL; /* out of memory */
-			}
-			memcpy(&sub->strvalue[0], &p[2], attrlen - 2);
-			sub->strvalue[attrlen - 2] = '\0';
-			sub->length = attrlen - 2;
-
-			if (debug_flag) {
-			  putchar('\t');
-			  vp_print(stdout, sub);
-			  putchar('\n');
-			}
-
-			/*
-			 *	And add it to the request pairs.
-			 */
-			pairadd(&request->packet->vps, sub);
-
-			/*
-			 *	FIXME: Check for the existence
-			 *	of the necessary attributes!
-			 */
-
-			length -= attrlen;
-			p += attrlen;
-		} /* loop over this one attribute */
-
-		/*
-		 *	Find the next one, if it exists.
-		 */
-		vp = pairfind(vp->next, PW_DIGEST_ATTRIBUTES);
-	}
-
-	/*
-	 *	We require access to the Digest-Nonce-Value
-	 */
-	nonce = pairfind(request->packet->vps, PW_DIGEST_NONCE);
-	if (!nonce) {
-		DEBUG("ERROR: No Digest-Nonce: Cannot perform Digest authentication");
-		return RLM_MODULE_INVALID;
-	}
-
-	/*
-	 *	A1 = Digest-User-Name ":" Realm ":" Password
-	 */
-	vp = pairfind(request->packet->vps, PW_DIGEST_USER_NAME);
-	if (!vp) {
-		DEBUG("ERROR: No Digest-User-Name: Cannot perform Digest authentication");
-		return RLM_MODULE_INVALID;
-	}
-	memcpy(&a1[0], &vp->strvalue[0], vp->length);
-	a1_len = vp->length;
-
-	a1[a1_len] = ':';
-	a1_len++;
-
-	vp = pairfind(request->packet->vps, PW_DIGEST_REALM);
-	if (!vp) {
-		DEBUG("ERROR: No Digest-Realm: Cannot perform Digest authentication");
-		return RLM_MODULE_INVALID;
-	}
-	memcpy(&a1[a1_len], &vp->strvalue[0], vp->length);
-	a1_len += vp->length;
-
-	a1[a1_len] = ':';
-	a1_len++;
-
-	if (passwd->attribute == PW_USER_PASSWORD) {
-		memcpy(&a1[a1_len], &passwd->strvalue[0], passwd->length);
-		a1_len += passwd->length;
-		a1[a1_len] = '\0';
-		DEBUG2("A1 = %s", a1);
-	} else {
-		a1[a1_len] = '\0';
-		DEBUG2("A1 = %s (using Digest-HA1)", a1);
-		a1_len = 16;
-	}
-
-	/*
-	 *	See which variant we calculate.
-	 *	Assume MD5 if no Digest-Algorithm attribute received
-	 */
-	algo = pairfind(request->packet->vps, PW_DIGEST_ALGORITHM);
-	if ((algo == NULL) || 
-	    (strcasecmp(algo->strvalue, "MD5") == 0)) {
-		/*
-		 *	Set A1 to Digest-HA1 if no User-Password found
-		 */
-		if (passwd->attribute == PW_DIGEST_HA1) {
-			lrad_hex2bin(passwd->strvalue, &a1[0], 16);
-		}
-
-	} else if (strcasecmp(algo->strvalue, "MD5-sess") == 0) {
-		/*
-		 *	K1 = H(A1) : Digest-Nonce ... : H(A2)
-		 *
-		 *	If we find Digest-HA1, we assume it contains
-		 *	H(A1).
-		 */
-		if (passwd->attribute == PW_USER_PASSWORD) {
-			librad_md5_calc(hash, &a1[0], a1_len);
-			lrad_bin2hex(hash, &a1[0], 16);
-		} else {	/* MUST be Digest-HA1 */
-			memcpy(&a1[0], passwd->strvalue, 32);
-		}
-		a1_len = 32;
-
-		a1[a1_len] = ':';
-		a1_len++;
-
-		/*
-		 *	Tack on the Digest-Nonce. Length must be even
-		 */
-		if ((nonce->length & 1) != 0) {
-			DEBUG("ERROR: Received Digest-Nonce hex string with invalid length: Cannot perform Digest authentication");
-			return RLM_MODULE_INVALID;
-		}
-		memcpy(&a1[a1_len], &nonce->strvalue[0], nonce->length);
-		a1_len += nonce->length;
-
-		a1[a1_len] = ':';
-		a1_len++;
-
-		vp = pairfind(request->packet->vps, PW_DIGEST_CNONCE);
-		if (!vp) {
-			DEBUG("ERROR: No Digest-CNonce: Cannot perform Digest authentication");
-			return RLM_MODULE_INVALID;
-		}
-
-		/*
-		 *      Digest-CNonce length must be even
-		 */
-		if ((vp->length & 1) != 0) {
-			DEBUG("ERROR: Received Digest-CNonce hex string with invalid length: Cannot perform Digest authentication");
-			return RLM_MODULE_INVALID;
-		}
-		memcpy(&a1[a1_len], &vp->strvalue[0], vp->length);
-		a1_len += vp->length;
-
-	} else if ((algo != NULL) &&
-		   (strcasecmp(algo->strvalue, "MD5") != 0)) {
-		/*
-		 *	We check for "MD5-sess" and "MD5".
-		 *	Anything else is an error.
-		 */
-		DEBUG("ERROR: Unknown Digest-Algorithm \"%s\": Cannot perform Digest authentication", vp->strvalue);
-		return RLM_MODULE_INVALID;
-	}
-
-	/*
-	 *	A2 = Digest-Method ":" Digest-URI
-	 */
-	vp = pairfind(request->packet->vps, PW_DIGEST_METHOD);
-	if (!vp) {
-		DEBUG("ERROR: No Digest-Method: Cannot perform Digest authentication");
-		return RLM_MODULE_INVALID;
-	}
-	memcpy(&a2[0], &vp->strvalue[0], vp->length);
-	a2_len = vp->length;
-
-	a2[a2_len] = ':';
-	a2_len++;
-
-	vp = pairfind(request->packet->vps, PW_DIGEST_URI);
-	if (!vp) {
-		DEBUG("ERROR: No Digest-URI: Cannot perform Digest authentication");
-		return RLM_MODULE_INVALID;
-	}
-	memcpy(&a2[a2_len], &vp->strvalue[0], vp->length);
-	a2_len += vp->length;
-
-	/*
-	 *  QOP is "auth-int", tack on ": Digest-Body-Digest"
-	 */
-	qop = pairfind(request->packet->vps, PW_DIGEST_QOP);
-	if ((qop != NULL) &&
-	    (strcasecmp(qop->strvalue, "auth-int") == 0)) {
-		VALUE_PAIR *body;
-
-		/*
-		 *	Add in Digest-Body-Digest
-		 */
-		a2[a2_len] = ':';
-		a2_len++;
-
-		/*
-		 *  Must be a hex representation of an MD5 digest.
-		 */
-		body = pairfind(request->packet->vps, PW_DIGEST_BODY_DIGEST);
-		if (!body) {
-			DEBUG("ERROR: No Digest-Body-Digest: Cannot perform Digest authentication");
-			return RLM_MODULE_INVALID;
-		}
-
-		if ((a2_len + body->length) > sizeof(a2)) {
-			DEBUG("ERROR: Digest-Body-Digest is too long");
-			return RLM_MODULE_INVALID;
-		}
-
-		memcpy(a2 + a2_len, body->strvalue, body->length);
-		a2_len += body->length;
-
-	} else if ((qop != NULL) &&
-		   (strcasecmp(qop->strvalue, "auth") != 0)) {
-		DEBUG("ERROR: Unknown Digest-QOP \"%s\": Cannot perform Digest authentication", qop->strvalue);
-		return RLM_MODULE_INVALID;
-	}
-
-	a2[a2_len] = '\0';
-	DEBUG2("A2 = %s", a2);
-
-	/*
-	 *     KD = H(A1) : Digest-Nonce ... : H(A2).
-	 *     Compute MD5 if Digest-Algorithm == "MD5-Sess",
-	 *     or if we found a User-Password.
-	 */
-	if (((algo != NULL) && 
-	     (strcasecmp(algo->strvalue, "MD5-Sess") == 0)) ||
-	    (passwd->attribute == PW_USER_PASSWORD)) {
-	  a1[a1_len] = '\0';
-		librad_md5_calc(&hash[0], &a1[0], a1_len);
-	} else {
-		memcpy(&hash[0], &a1[0], a1_len);
-	}
-	lrad_bin2hex(hash, kd, sizeof(hash));
-
-#ifndef NDEBUG
-	if (debug_flag) {
-		printf("H(A1) = ");
-		for (i = 0; i < 16; i++) {
-			printf("%02x", hash[i]);
-		}
-		printf("\n");
-	}
-#endif
-	kd_len = 32;
-
-	kd[kd_len] = ':';
-	kd_len++;
-
-	memcpy(&kd[kd_len], nonce->strvalue, nonce->length);
-	kd_len += nonce->length;
+    /* No HA1, create one from the clear text password */
+		VALUE_PAIR *passwd;
+    VALUE_PAIR *user_name;
+    VALUE_PAIR *realm;
+    
+    passwd = pairfind(request->config_items, PW_PASSWORD);
+    user_name = pairfind(request->packet->vps, PW_DIGEST_USER_NAME);
+    realm = pairfind(request->packet->vps, PW_DIGEST_REALM);
+    
+    /* Make sure we got all of them */
+    if (!user_name) {
+      DEBUG("ERROR: No Digest-User-Name: Cannot perform Digest authentication");
+      return RLM_MODULE_INVALID;
+    }
+    if (!realm) {
+      DEBUG("ERROR: No Digest-Realm: Cannot perform Digest authentication");
+      return RLM_MODULE_INVALID;
+    }
+    if (!passwd) {
+      DEBUG("ERROR: No Clear text Password: Cannot perform Digest authentication");
+      return RLM_MODULE_INVALID;
+    }
+
+    /* Copy first part of A1 (user name)*/        
+    memcpy(&a1[0], &user_name->strvalue[0], user_name->length);
+    a1_len = user_name->length;
+
+    a1[a1_len] = ':';
+    a1_len++;
+    
+    /* Copy second part of A1 (realm)*/
+    memcpy(&a1[a1_len], &realm->strvalue[0], realm->length);
+    a1_len += realm->length;
+
+    a1[a1_len] = ':';
+    a1_len++;
+    /* Copy last part of A1 (passwd) */
+    memcpy(&a1[a1_len], passwd->strvalue, passwd->length);
+    a1_len += passwd->length;
+    a1[a1_len] = '\0';
+
+    DEBUG2("A1 = %s", a1);
+    
+    librad_md5_calc(hash, a1, a1_len);
+    lrad_bin2hex(hash, ha1, sizeof(hash));
+	}
+  
+  /*
+   *  See which variant we calculate.
+   *  Assume MD5 if no Digest-Algorithm attribute received
+   */
+  algo = pairfind(request->packet->vps, PW_DIGEST_ALGORITHM);
+  if (!algo || (strcasecmp(algo->strvalue, "MD5") == 0)) {
+    
+  } else if (strcasecmp(algo->strvalue, "MD5-sess") == 0) {
+    /* A1 = HA1:nonce:cnonce */
+    
+    nonce = pairfind(request->packet->vps, PW_DIGEST_NONCE);
+    cnonce = pairfind(request->packet->vps, PW_DIGEST_CNONCE);
+    
+    if (!nonce || !cnonce) {
+      DEBUG("ERROR: nonce or cnonce missing");
+      return RLM_MODULE_INVALID;
+    }
+    
+    memcpy(a1, ha1, 32);
+    a1_len = 32;
+
+    a1[a1_len] = ':';
+    a1_len++;
+
+    /*
+     *  Tack on the Digest-Nonce.
+     */
+    memcpy(&a1[a1_len], &nonce->strvalue[0], nonce->length);
+    a1_len += nonce->length;
+
+    a1[a1_len] = ':';
+    a1_len++;
+
+    /*
+     *  Tack on the Digest-CNonce.
+     */
+    memcpy(&a1[a1_len], &cnonce->strvalue[0], cnonce->length);
+    a1_len += cnonce->length;
+    
+    librad_md5_calc(hash, a1, a1_len);
+    lrad_bin2hex(hash, ha1, sizeof(hash));
+    
+  } else if (strcasecmp(algo->strvalue, "MD5") != 0) {
+    /*
+     *  We check for "MD5-sess" and "MD5".
+     *  Anything else is an error.
+     */
+    DEBUG("ERROR: Unknown Digest-Algorithm \"%s\": Cannot perform Digest authentication", algo->strvalue);
+    return RLM_MODULE_INVALID;
+  }
+  
+  
+  /*
+   *  Create ha2
+   *  A2 = Digest-Method ":" Digest-URI
+   */
+   
+   method = pairfind(request->packet->vps, PW_DIGEST_METHOD);
+   uri = pairfind(request->packet->vps, PW_DIGEST_URI); 
+  
+  if (!method) {
+    DEBUG("ERROR: No Digest-Method: Cannot perform Digest authentication");
+    return RLM_MODULE_INVALID;
+  }
+  if (!uri) {
+    DEBUG("ERROR: No Digest-URI: Cannot perform Digest authentication");
+    return RLM_MODULE_INVALID;
+  }
+  
+  /* Copy first attrib to a2 (method) */
+  memcpy(&a2[0], &method->strvalue[0], method->length);
+  a2_len = method->length;
+
+  a2[a2_len] = ':';
+  a2_len++;
+
+  /* Copy second attrib to a2 (uri) */
+  memcpy(&a2[a2_len], &uri->strvalue[0], uri->length);
+  a2_len += uri->length;
+
+  /*
+   *  QOP is "auth-int", tack on ": Digest-Body-Digest"
+   */
+  qop = pairfind(request->packet->vps, PW_DIGEST_QOP);
+  if (qop && (strcasecmp(qop->strvalue, "auth-int") == 0)) {
+    VALUE_PAIR *body;
+
+    body = pairfind(request->packet->vps, PW_DIGEST_BODY_DIGEST);
+    if (!body) {
+      DEBUG("ERROR: No Digest-Body-Digest: Cannot perform Digest authentication");
+      return RLM_MODULE_INVALID;
+    }
+    if (body->length != 32) {
+      DEBUG("ERROR: Digest-Body-Digest is wrong size");
+      return RLM_MODULE_INVALID;
+    }
+
+    /* Add the body-digest to a2 */
+    a2[a2_len] = ':';
+    a2_len++;
+    
+    memcpy(a2 + a2_len, body->strvalue, body->length);
+    a2_len += body->length;
+
+  } else if (qop && (strcasecmp(qop->strvalue, "auth") != 0)) {
+    DEBUG("ERROR: Unknown Digest-QOP \"%s\": Cannot perform Digest authentication", qop->strvalue);
+    return RLM_MODULE_INVALID;
+  }
+
+  a2[a2_len] = '\0';
+  DEBUG2("A2 = %s", a2);
+  
+  librad_md5_calc(hash, &a2[0], a2_len);
+  lrad_bin2hex(hash, ha2, sizeof(hash));
+  
+	/* Now create response from HA1, HA2 and a little more	*/
+
+  nonce = pairfind(request->packet->vps, PW_DIGEST_NONCE);
+  ncount = pairfind(request->packet->vps, PW_DIGEST_NONCE_COUNT);
+  cnonce = pairfind(request->packet->vps, PW_DIGEST_CNONCE);
+  qop = pairfind(request->packet->vps, PW_DIGEST_QOP);
+  
+  if (!nonce || !ncount || !cnonce) {
+    DEBUG("ERROR: Digest-Nonce or Digest-Nonce-Count or Digest-CNonce Missing");
+    return RLM_MODULE_INVALID;
+  }
+
+
+  /* First part of kd (HA1) */
+	memcpy(response, ha1, 32);
+  response_len = 32;
+
+  response[response_len] = ':';
+  response_len++;
+  
+  /* Second part of kd (nonce) */
+	memcpy(&response[response_len], nonce->strvalue, nonce->length);
+	response_len += nonce->length;
 
 	/*
-	 *	No QOP defined.  Do RFC 2069 compatibility.
+	 *	Skip this if no QOP defined (RFC 2069 compatibility)
 	 */
-	if (!qop) {
-		/*
-		 *	Do nothing here.
-		 */
-
-	} else {		/* Digest-QOP MUST be "auth" or "auth-int" */
+	if (qop) {		/* Digest-QOP MUST be "auth" or "auth-int" */
 		/*
 		 *	Tack on ":" Digest-Nonce-Count ":" Digest-CNonce
 		 *	       ":" Digest-QOP
 		 */
-		kd[kd_len] = ':';
-		kd_len++;
+		response[response_len] = ':';
+		response_len++;
 
-		vp = pairfind(request->packet->vps, PW_DIGEST_NONCE_COUNT);
-		if (!vp) {
-			DEBUG("ERROR: No Digest-Nonce-Count: Cannot perform Digest authentication");
-			return RLM_MODULE_INVALID;
-		}
-		memcpy(&kd[kd_len], &vp->strvalue[0], vp->length);
-		kd_len += vp->length;
-
-		kd[kd_len] = ':';
-		kd_len++;
+		memcpy(&response[response_len], &ncount->strvalue[0], ncount->length);
+		response_len += ncount->length;
 
-		vp = pairfind(request->packet->vps, PW_DIGEST_CNONCE);
-		if (!vp) {
-			DEBUG("ERROR: No Digest-CNonce: Cannot perform Digest authentication");
-			return RLM_MODULE_INVALID;
-		}
-		memcpy(&kd[kd_len], &vp->strvalue[0], vp->length);
-		kd_len += vp->length;
+		response[response_len] = ':';
+		response_len++;
+		
+		memcpy(&response[response_len], &cnonce->strvalue[0], cnonce->length);
+		response_len += cnonce->length;
 
-		kd[kd_len] = ':';
-		kd_len++;
+		response[response_len] = ':';
+		response_len++;
 
-		memcpy(&kd[kd_len], &qop->strvalue[0], qop->length);
-		kd_len += qop->length;
+		memcpy(&response[response_len], &qop->strvalue[0], qop->length);
+		response_len += qop->length;
 	}
 
 	/*
-	 *	Tack on ":" H(A2)
+	 *	Last part of kd (HA2)
 	 */
-	kd[kd_len] = ':';
-	kd_len++;
+	response[response_len] = ':';
+	response_len++;
 
-	librad_md5_calc(&hash[0], &a2[0], a2_len);
-
-	lrad_bin2hex(hash, kd + kd_len, sizeof(hash));
-
-#ifndef NDEBUG
-	if (debug_flag) {
-		printf("H(A2) = ");
-		for (i = 0; i < 16; i++) {
-			printf("%02x", hash[i]);
-		}
-		printf("\n");
-	}
-#endif
-	kd_len += 32;
+  memcpy(&response[response_len], ha2, 32);
 
-	kd[kd_len] = 0;
+	response_len += 32;
+	response[response_len] = 0;
 
-	DEBUG2("KD = %s\n", &kd[0]);
+	DEBUG2("KD = %s\n", &response[0]);
 
 	/*
 	 *	Take the hash of KD.
 	 */
-	librad_md5_calc(&hash[0], &kd[0], kd_len);
-	memcpy(&kd[0], &hash[0], 16);
+	librad_md5_calc(&hash[0], &response[0], response_len);
+	memcpy(&response[0], &hash[0], 16);
 
 	/*
 	 *	Get the binary value of Digest-Response
 	 */
-	vp = pairfind(request->packet->vps, PW_DIGEST_RESPONSE);
-	if (!vp) {
+	resp = pairfind(request->packet->vps, PW_DIGEST_RESPONSE);
+	if (!resp) {
 		DEBUG("ERROR: No Digest-Response attribute in the request.  Cannot perform digest authentication");
 		return RLM_MODULE_INVALID;
 	}
 
-	lrad_hex2bin(&vp->strvalue[0], &hash[0], vp->length >> 1);
+	lrad_hex2bin(&resp->strvalue[0], &hash[0], resp->length >> 1);
 
-#ifndef NDEBUG
 	if (debug_flag) {
 		printf("EXPECTED ");
 		for (i = 0; i < 16; i++) {
-			printf("%02x", kd[i]);
+			printf("%02x", response[i]);
 		}
 		printf("\n");
 
@@ -508,12 +516,11 @@
 		}
 		printf("\n");
 	}
-#endif
 
 	/*
 	 *  And finally, compare the digest in the packet with KD.
 	 */
-	if (memcmp(&kd[0], &hash[0], 16) == 0) {
+	if (memcmp(&response[0], &hash[0], 16) == 0) {
 		return RLM_MODULE_OK;
 	}
 
diff -ur freeradius-1.1.3-orig/src/modules/rlm_eap/radeapclient.c freeradius-1.1.3/src/modules/rlm_eap/radeapclient.c
--- freeradius-1.1.3-orig/src/modules/rlm_eap/radeapclient.c	2006-05-19 16:22:23.000000000 +0200
+++ freeradius-1.1.3/src/modules/rlm_eap/radeapclient.c	2006-09-20 11:50:49.000000000 +0200
@@ -815,9 +815,9 @@
 	map_eap_types(rep);
 
 	/*
-	 *  Fix up Digest-Attributes issues
+	 *  Fix up Digest-Attributes issues (Should this be removed now?)
 	 */
-	for (vp = rep->vps; vp != NULL; vp = vp->next) {
+	/*for (vp = rep->vps; vp != NULL; vp = vp->next) {
 		switch (vp->attribute) {
 		default:
 			break;
@@ -832,15 +832,14 @@
 		case PW_DIGEST_CNONCE:
 		case PW_DIGEST_NONCE_COUNT:
 		case PW_DIGEST_USER_NAME:
-			/* overlapping! */
 			memmove(&vp->strvalue[2], &vp->strvalue[0], vp->length);
 			vp->strvalue[0] = vp->attribute - PW_DIGEST_REALM + 1;
 			vp->length += 2;
 			vp->strvalue[1] = vp->length;
-			vp->attribute = PW_DIGEST_ATTRIBUTES;
+			vp->attribute = PW_DIGEST_OBSELETE_ATTRIBUTES;
 			break;
 		}
-	}
+	}*/
 
 	/*
 	 *	If we've already sent a packet, free up the old
