Re: Failure to relay Access-Challenge

Sergey Poznyakoff <[email protected]> Fri, 23 Aug 2002 13:52:11 +0300
Newsgroups gmane.comp.gnu.radius.bugs
Organization Farlep-Internet
Message-ID <[email protected]>
Hi Gayatri

The thing was a bit more difficult to solve than I thought. Please
find enclosed a patch for version 0.96.4. Theoretically it should
work for 0.96.3 too, with a fuzz factor of about -6 lines.

In case you are unable to apply the patch, you will find the prepared
tarball at anonymous:

 ftp://mirddin.farlep.net/pub/radius/alpha/gnu-radius-0.96.4-20020823.tar.gz

md5sum of the tarball is:
d6849c7a3d98792cfa1554d67c74bbd5  gnu-radius-0.96.4-20020823.tar.gz

Note also that in order for this to work, you will have to mark State
attribute with a proxy-propagate flag (P) in your raddb/dictionary.

Regards,
Sergey
0.96.4.diff (text/plain, 6.6 KB)
Index: raddb/dictionary
===================================================================
RCS file: /cvsroot/radius/radius/raddb/dictionary,v
retrieving revision 1.24.2.4
diff -p -u -w -b -r1.24.2.4 dictionary
--- raddb/dictionary	14 Aug 2002 14:32:19 -0000	1.24.2.4
+++ raddb/dictionary	23 Aug 2002 10:42:31 -0000
@@ -45,7 +45,7 @@ ATTRIBUTE	Callback-Number		19	string	- [
 ATTRIBUTE	Callback-Id		20	string	- [-R----]=	
 ATTRIBUTE	Framed-Route		22	string	- [-R----]=
 ATTRIBUTE	Framed-IPX-Network	23	ipaddr	- [-R----]=
-ATTRIBUTE	State			24	string	- [LRLRLR]
+ATTRIBUTE	State			24	string	- [LRLRLR]P
 ATTRIBUTE	Class			25	string	- [LRLRLR]
 ATTRIBUTE	Vendor-Specific		26	string	- [LR-R-R]
 ATTRIBUTE	Session-Timeout		27	integer	- [-R----]=P
Index: radiusd/auth.c
===================================================================
RCS file: /cvsroot/radius/radius/radiusd/auth.c,v
retrieving revision 1.47.2.8
diff -p -u -w -b -r1.47.2.8 auth.c
--- radiusd/auth.c	17 Aug 2002 09:10:22 -0000	1.47.2.8
+++ radiusd/auth.c	23 Aug 2002 10:42:35 -0000
@@ -517,7 +517,7 @@ enum auth_state {
 	as_ipaddr, 
 	as_exec_wait, 
 	as_cleanup_cbkid, 
-	as_menu,
+	as_menu_challenge,
 	as_ack, 
 	as_exec_nowait, 
 	as_stop, 
@@ -565,6 +565,7 @@ static void sfn_ipaddr(AUTH_MACH*);
 static void sfn_exec_wait(AUTH_MACH*);
 static void sfn_cleanup_cbkid(AUTH_MACH*);
 static void sfn_menu(AUTH_MACH*);
+static void sfn_menu_challenge(AUTH_MACH*);
 static void sfn_ack(AUTH_MACH*);
 static void sfn_exec_nowait(AUTH_MACH*);
 static void sfn_reject(AUTH_MACH*);
@@ -617,11 +618,11 @@ struct auth_state_s states[] = {
 	as_exec_wait,    as_cleanup_cbkid,
 	                 DA_EXEC_PROGRAM_WAIT, L_reply, sfn_exec_wait,
 	
-	as_cleanup_cbkid,as_menu,
+	as_cleanup_cbkid,as_menu_challenge,
 	                 DA_CALLBACK_ID,  L_reply, sfn_cleanup_cbkid,
 	
-	as_menu,         as_ack,
-	                 DA_MENU,         L_reply, sfn_menu,
+	as_menu_challenge,         as_ack,
+	                 DA_MENU,         L_reply, sfn_menu_challenge,
 	
 	as_ack,          as_exec_nowait,
 	                 0,               L_null, sfn_ack,
@@ -752,23 +753,9 @@ rad_authenticate(radreq, activefd)
 	enum auth_state oldstate;
 	struct auth_state_s *sp;
 	struct auth_mach m;
-#ifdef USE_LIVINGSTON_MENUS
-	VALUE_PAIR *pair_ptr;
-#endif
 
 	log_open(L_AUTH);
 	
-#ifdef USE_LIVINGSTON_MENUS
-	/*
-	 * If the request is processing a menu, service it here.
-	 */
-	if ((pair_ptr = avl_find(radreq->request, DA_STATE)) != NULL &&
-	    strncmp(pair_ptr->strvalue, "MENU=", 5) == 0) {
-	    process_menu(radreq, activefd);
-	    return 0;
-	}
-#endif
-
 	m.req = radreq;
 	m.activefd = activefd;
 	m.user_check = NULL;
@@ -845,26 +832,50 @@ sfn_init(m)
 	RADIUS_REQ *radreq = m->req;
 	VALUE_PAIR *pair_ptr;
 	
+	switch (radreq->server_code) {
+	case RT_AUTHENTICATION_REJECT:
+		m->user_check = avp_create(DA_AUTH_TYPE, 0,
+					   NULL, DV_AUTH_TYPE_REJECT);
+		break;
+
+	case RT_AUTHENTICATION_ACK:
+		m->user_check = avp_create(DA_AUTH_TYPE, 0,
+					   NULL, DV_AUTH_TYPE_ACCEPT);
+		break;
+
+	case 0:
+		break;
+
+	default:
+		rad_send_reply(radreq->server_code,
+			       radreq,
+			       radreq->server_reply,
+			       NULL,
+			       m->activefd);
+		newstate(as_stop);
+		return;
+	}
+	
+#ifdef USE_LIVINGSTON_MENUS
 	/*
-	 *	Move the proxy_state A/V pairs somewhere else.
+	 * If the request is processing a menu, service it here.
 	 */
-	avl_move_attr(&m->proxy_pairs, &radreq->request, DA_PROXY_STATE);
+	if (radreq->server_code == 0
+	    && (pair_ptr = avl_find(m->req->request, DA_STATE)) != NULL
+	    && strncmp(pair_ptr->strvalue, "MENU=", 5) == 0) {
+	    process_menu(m->req, m->activefd);
+	    newstate(as_stop);
+	    return;
+	}
+#endif
 
 	/*
-	 * If this request got proxied to another server, we need
-	 * to add an initial Auth-Type: Auth-Accept for success,
-	 * Auth-Reject for fail. We also need to add the reply
-	 * pairs from the server to the initial reply.
+	 *	Move the proxy_state A/V pairs somewhere else.
 	 */
-	if (radreq->server_code == RT_AUTHENTICATION_REJECT ||
-	    radreq->server_code == RT_AUTHENTICATION_ACK) {
-		m->user_check = avp_create(DA_AUTH_TYPE, 0, NULL, 0);
-		proxied = 1;
-	}
-	if (radreq->server_code == RT_AUTHENTICATION_REJECT)
-		m->user_check->lvalue = DV_AUTH_TYPE_REJECT;
-	if (radreq->server_code == RT_AUTHENTICATION_ACK)
-		m->user_check->lvalue = DV_AUTH_TYPE_ACCEPT;
+	avl_move_attr(&m->proxy_pairs, &radreq->request, DA_PROXY_STATE);
+
+	/* If this request was proxied to another server, we need
+	   to add the reply pairs from the server to the initial reply. */
 
 	if (radreq->server_reply) {
 		m->user_reply = radreq->server_reply;
@@ -881,7 +892,7 @@ sfn_init(m)
 	 */
 	if (user_find(m->namepair->strvalue, radreq,
 		      &m->user_check, &m->user_reply) != 0
-	    && !proxied) {
+	    && !radreq->server_code) {
 
 		if (is_log_mode(m, RLOG_AUTH)) 
 			auth_log(m, _("Invalid user"), NULL, NULL, NULL);
@@ -1245,7 +1256,7 @@ sfn_cleanup_cbkid(m)
 }
 
 void
-sfn_menu(m)
+sfn_menu_challenge(m)
 	AUTH_MACH *m;
 {
 #ifdef USE_LIVINGSTON_MENUS
Index: radiusd/radius.c
===================================================================
RCS file: /cvsroot/radius/radius/radiusd/radius.c,v
retrieving revision 1.20.2.1
diff -p -u -w -b -r1.20.2.1 radius.c
--- radiusd/radius.c	2 Jul 2002 20:54:53 -0000	1.20.2.1
+++ radiusd/radius.c	23 Aug 2002 10:42:35 -0000
@@ -159,8 +159,8 @@ rad_send_reply(code, radreq, oreply, msg
 				reply->strlength = strlen(reply->strvalue);
 
 			len = reply->strlength;
-			if (len >= AUTH_STRING_LEN) {
-				len = AUTH_STRING_LEN - 1;
+			if (len > AUTH_STRING_LEN) {
+				len = AUTH_STRING_LEN;
 			}
 			if (total_length + len + 2 >= SEND_BUFFER_SIZE)
 				goto err;
@@ -415,7 +415,7 @@ radrecv(host, udp_port, buffer, length)
 
 		if ((attr = attr_number_to_dict(attribute)) == NULL) {
 			debug(1, ("Received unknown attribute %d", attribute));
-		} else if ( attrlen >= AUTH_STRING_LEN ) {
+		} else if ( attrlen > AUTH_STRING_LEN ) {
 			debug(1, ("attribute %d too long, %d >= %d", attribute,
 				attrlen, AUTH_STRING_LEN));
 		} else if ( attrlen > length ) {
Index: radiusd/radiusd.c
===================================================================
RCS file: /cvsroot/radius/radius/radiusd/radiusd.c,v
retrieving revision 1.55.2.5
diff -p -u -w -b -r1.55.2.5 radiusd.c
--- radiusd/radiusd.c	16 Aug 2002 12:31:27 -0000	1.55.2.5
+++ radiusd/radiusd.c	23 Aug 2002 10:42:39 -0000
@@ -964,6 +964,7 @@ radrespond(radreq, activefd)
 	case RT_AUTHENTICATION_ACK:
 	case RT_AUTHENTICATION_REJECT:
 	case RT_ACCOUNTING_RESPONSE:
+	case RT_ACCESS_CHALLENGE:
 		if (proxy_receive(radreq, activefd) < 0) {
 			radreq_free(radreq);
 			return 0;