Subject: [radext] Fwd: I-D Action: draft-chen-radext-identifier-attr-01.txt

From: Enke Chen <[email-masked]>
Date: Tue, 25 Apr 2017 10:24:57 -0700

Hi, Folks:

This revised version includes the following changes:

   o Renamed the attribute as "Extended Identifier Attribute".

   o Removed the specification for the optional "Extended Code" as Alan
     suggested.

   o Relaxed the use of the two parameters "Identifier" and "Extended
     Identifier", from "OR" to "AND" for more flexible implementation.

Finally, "no ID changes" according to Alan's definition :-)

Regards,  -- Enke

-------- Forwarded Message --------
Subject: I-D Action: draft-chen-radext-identifier-attr-01.txt
Date: Tue, 25 Apr 2017 10:11:19 -0700
From: [email-masked]
Reply-To: [email-masked]
To: [email-masked]

A New Internet-Draft is available from the on-line Internet-Drafts directories.

        Title           : RADIUS Extended Identifier Attribute
        Authors         : Enke Chen
                          Naiming Shen
	Filename        : draft-chen-radext-identifier-attr-01.txt
	Pages           : 7
	Date            : 2017-04-25

Abstract:
   The limitation with the one-octet "Identifier" field in the RADIUS
   packet is well known. In this document we propose extensions to the
   RADIUS protocol to address this fundamental limitation, and thus
   allowing for more efficient and more scalable implementations.

The IETF datatracker status page for this draft is:
https://datatracker.ietf.org/doc/draft-chen-radext-identifier-attr/

There are also htmlized versions available at:
https://tools.ietf.org/html/draft-chen-radext-identifier-attr-01
https://datatracker.ietf.org/doc/html/draft-chen-radext-identifier-attr-01

A diff from the previous version is available at:
https://www.ietf.org/rfcdiff?url2=draft-chen-radext-identifier-attr-01

Please note that it may take a couple of minutes from the time of submission
until the htmlized version and diff are available at tools.ietf.org.

Internet-Drafts are also available by anonymous FTP at:
ftp://ftp.ietf.org/internet-drafts/

_______________________________________________
I-D-Announce mailing list
[email-masked]
https://www.ietf.org/mailman/listinfo/i-d-announce
Internet-Draft directories: http://www.ietf.org/shadow.html
or ftp://ftp.ietf.org/ietf/1shadow-sites.txt

---

From: Alan DeKok <[email-masked]>
Date: Wed, 26 Apr 2017 08:15:00 -0400

> On Apr 25, 2017, at 1:24 PM, Enke Chen <[email-masked]> wrote:
> 
> Hi, Folks:
> 

  It looks reasonable.

  I'd like to see more text on how this proposal affects clients and servers.  Also, how it affects proxies.  I also need to add more text to my draft for proxies, too.

  i.e. it's best to describe not only the changes, but how those changes affect existing systems.

  Alan DeKok.

---

From: "Naiming Shen (naiming)" <[email-masked]>
Date: Fri, 28 Apr 2017 00:24:51 +0000

Hi,

Enclosed are two files of implementation on freeradius code
base with this draft: draft-chen-radext-identifier-attr-01.txt.
One is the patch and the other is the testing results of
cases with multiple combinations of client, server, proxy,
home-server support this feature. The diff is about 190 lines
including the radtest file changes.

Please take a look.

Regards,
- Naiming

 (1) the patch implements the spec of draft-chen-radext-identifier-attr-01,
     patch code base using freeradius 3.1.12

 (2) due to the freeradius way of coding the attributes using the
     RFC include files. the patch temporarily creates a fake rfc9000 for
     this ID-Attr feature for the patch, this patch uses the radius
     attribute of '192' (PW_EXTENDED_ID) for testing

 (3) new commandline parameters on client side(for patch testing
     purpose). on both 'radtest' and 'radclient' programs, new
     parameter '-I' to indicate the client<->server radius message
     using the ID-Attr feature, and the '-S' to indicate client using
     'status-server' to query the server support of this ID-Attr feature

 (4) since this ID-Attr uses the 'status-server' message to query
     the server side support of this feature. In this patch, two
     different ways of doing 'status-server' query:

     - client to server
       radclient to use '-S' to query the server to make sure it
       support this ID-Attr feature; then it can use '-I' for
       any communication with ID-Attr encoding

     - proxy to home-server
       if the proxy server is configured to allow ID-Attr feature,
       when the proxy receives a message from client which is the
       first time to the home-server, it will convert it to the
       'status-server' message to query this ID-Attr support; This
       first message will be dropped and the client will resend after
       timeout. The second and the later messages from the proxy to
       the home-server will use the ID-Attr encoding if the home-server
       supports that.
       This is sort of analogous to the ICMP PING the first time, if
       the ARP address is not resolved, the first PING might be lost.
       But the mechanism can be improved with different implementations.

 (5) if the ID-Attr is supported, the 'ext-id' starts with 256 in this
     patch, is allocated sequentially.  The ID wrapping is handled.

----------------------------------------------------------------
lenovo:~/radius/fr-3.0.12$ git diff --stat
 share/dictionary         |  1 +
 share/dictionary.rfc9000 |  6 ++++
 src/include/libradius.h  |  6 ++++
 src/include/radius.h     |  1 +
 src/include/realms.h     |  2 ++
 src/lib/packet.c         | 27 ++++++++++++++--
 src/lib/radius.c         | 82 +++++++++++++++++++++++++++++++++++++++++++++---
 src/main/listen.c        |  5 +++
 src/main/process.c       | 25 +++++++++++++--
 src/main/radclient.c     | 16 ++++++++--
 src/main/radtest         | 18 ++++++++++-
 11 files changed, 178 insertions(+), 11 deletions(-)
----------------------------------------------------------------
diff --git a/share/dictionary b/share/dictionary
index 1b34cce..60a9ba5 100644
--- a/share/dictionary
+++ b/share/dictionary
@@ -114,6 +114,7 @@ $INCLUDE dictionary.rfc7055
 $INCLUDE dictionary.rfc7155
 $INCLUDE dictionary.rfc7268
 $INCLUDE dictionary.rfc7499
+$INCLUDE dictionary.rfc9000
 
 #
 #	Mostly values which have been allocated by IANA under
diff --git a/share/dictionary.rfc9000 b/share/dictionary.rfc9000
index e69de29..4ea97ca 100644
--- a/share/dictionary.rfc9000
+++ b/share/dictionary.rfc9000
@@ -0,0 +1,6 @@
+# -*- text -*-
+# Copyright (C) 2017 The FreeRADIUS Server project and contributors
+#	Temp to use RFC9000 for code testing. Attribute defined in draft:
+#	https://tools.ietf.org/html/draft-chen-radext-identifier-attr-01.txt
+
+ATTRIBUTE	EXTENDED-ID				192	octets
diff --git a/src/include/libradius.h b/src/include/libradius.h
index a3c8f58..b461cec 100644
--- a/src/include/libradius.h
+++ b/src/include/libradius.h
@@ -130,6 +130,8 @@ typedef void (*sig_t)(int);
 #define MAX_STRING_LEN		254	/* RFC2138: string 0-253 octets */
 #define FR_MAX_VENDOR		(1 << 24) /* RFC limitations */
 
+#define MAX_EXT_ID_VALUE	0x3fffffff
+#define EXTID_STATUS_MASK	0xc0000000
 #ifdef _LIBRADIUS
 #  define RADIUS_HDR_LEN	20
 #  define VENDORPEC_USR		429
@@ -398,6 +400,10 @@ typedef struct radius_packet {
 	size_t			data_len;
 	VALUE_PAIR		*vps;
 	ssize_t			offset;
+	uint8_t			use_extended_id;	// use extID in pkt
+	uint8_t			hdr_id;			// save orig ID
+	uint8_t			client_extid_request;	// has sent query
+	uint8_t			server_extid_reply;	// server support extID
 #ifdef WITH_TCP
 	size_t			partial;
 	int			proto;
diff --git a/src/include/radius.h b/src/include/radius.h
index 44a2c13..ca74e4d 100644
--- a/src/include/radius.h
+++ b/src/include/radius.h
@@ -109,6 +109,7 @@ typedef enum {
 #include <freeradius-devel/rfc7055.h>
 #include <freeradius-devel/rfc7155.h>
 #include <freeradius-devel/rfc7268.h>
+#include <freeradius-devel/rfc9000.h>
 
 /*
  *	All internal attributes are now defined in this file.
diff --git a/src/include/realms.h b/src/include/realms.h
index d857115..dc0d3c7 100644
--- a/src/include/realms.h
+++ b/src/include/realms.h
@@ -105,6 +105,8 @@ typedef struct home_server {
 	char const		*ping_user_name;
 	char const		*ping_user_password;
 
+	uint8_t			sent_status_server;	// Sent query to server
+	uint8_t			support_extid;		// Home Server supports
 	uint32_t		ping_interval;
 	uint32_t		num_pings_to_alive;
 	uint32_t		num_sent_pings;
diff --git a/src/lib/packet.c b/src/lib/packet.c
index c258c60..458ce55 100644
--- a/src/lib/packet.c
+++ b/src/lib/packet.c
@@ -249,10 +249,13 @@ typedef struct fr_packet_socket_t {
 	int		proto;
 #endif
 
+	uint32_t	extended_id;
+	bool		server_support_extid;
 	uint8_t		id[32];
 } fr_packet_socket_t;

+#define MAX_HDR_ID (255)
 #define FNV_MAGIC_PRIME (0x01000193)
 #define MAX_SOCKETS (256)
 #define SOCKOFFSET_MASK (MAX_SOCKETS - 1)
@@ -430,6 +433,7 @@ bool fr_packet_list_socket_add(fr_packet_list_t *pl, int sockfd, int proto,
 	 *	As the last step before returning.
 	 */
 	ps->sockfd = sockfd;
+	ps->extended_id = MAX_HDR_ID + 1;
 	pl->num_sockets++;
 
 	return true;
@@ -760,6 +764,18 @@ bool fr_packet_list_id_alloc(fr_packet_list_t *pl, int proto,
 		 *	Otherwise, this socket is OK to use.
 		 */
 
+		if (request->use_extended_id &&
+		    (request->code != PW_CODE_STATUS_SERVER)) {
+			ps->extended_id++;
+			if (ps->extended_id > MAX_EXT_ID_VALUE) {
+				ps->extended_id = MAX_HDR_ID + 1;
+			}
+			id = ps->extended_id;
+			fd = i;
+			request->hdr_id = MAX_HDR_ID;
+			break;
+		}
+
 		/*
 		 *	Look for a free Id, starting from a random number.
 		 */
@@ -819,7 +835,9 @@ bool fr_packet_list_id_alloc(fr_packet_list_t *pl, int proto,
 	 *	Mark the ID as free.  This is the one line from
 	 *	id_free() that we care about here.
 	 */
-	ps->id[(request->id >> 3) & 0x1f] &= ~(1 << (request->id & 0x07));
+	if (request->id <= MAX_HDR_ID) {
+		ps->id[(request->id >> 3) & 0x1f] &= ~(1 << (request->id & 0x07));
+	}
 
 	request->id = -1;
 	request->sockfd = -1;
@@ -853,7 +871,12 @@ bool fr_packet_list_id_free(fr_packet_list_t *pl,
 	}
 #endif
 
-	ps->id[(request->id >> 3) & 0x1f] &= ~(1 << (request->id & 0x07));
+	if (request->id <= MAX_HDR_ID) {
+		ps->id[(request->id >> 3) & 0x1f] &= ~(1 << (request->id & 0x07));
+	}
+	if (request->server_extid_reply) {
+		ps->server_support_extid = true;
+	}
 
 	ps->num_outgoing--;
 	pl->num_outgoing--;
diff --git a/src/lib/radius.c b/src/lib/radius.c
index 53d45e2..f28a7b0 100644
--- a/src/lib/radius.c
+++ b/src/lib/radius.c
@@ -86,6 +86,16 @@ typedef struct radius_packet_t {
   uint8_t	data[1];
 } radius_packet_t;
 
+typedef struct CC_HINT(__packed__) radius_extid_t {
+	uint16_t	id_code_length;		// attr code and length
+	uint32_t	status_extid;		// status and ext-id fields
+} radius_extid_t;
+
+#define PW_EXTID_CODELEN	(PW_EXTENDED_ID << 8) + sizeof(radius_extid_t)
+#define RADIUS_HDR_AND_EXTID_LEN	RADIUS_HDR_LEN + sizeof(radius_extid_t)
+#define EXTID_REQUEST			htonl(1 << 30)
+#define EXTID_RESPOND_ACK		htonl(2 << 30)
+#define EXTID_RESPOND_NAK		htonl(3 << 30)
 static fr_randctx fr_rand_pool;	/* across multiple calls */
 static int fr_rand_initialized = 0;
 static unsigned int salt_offset = 0;
@@ -1745,6 +1755,8 @@ int rad_encode(RADIUS_PACKET *packet, RADIUS_PACKET const *original,
 	 *	A 4K packet, aligned on 64-bits.
 	 */
 	uint64_t	data[MAX_PACKET_LEN / sizeof(uint64_t)];
+	radius_extid_t		extid;
+	bool			status_server_extid = false;
 
 	/*
 	 *	Double-check some things based on packet code.
@@ -1782,16 +1794,50 @@ int rad_encode(RADIUS_PACKET *packet, RADIUS_PACKET const *original,
 	 *	Build standard header
 	 */
 	hdr->code = packet->code;
-	hdr->id = packet->id;
+	if (!packet->use_extended_id) {
+		hdr->id = packet->id;
+		if (original && (original->code == PW_CODE_STATUS_SERVER) &&
+		    (original->data_len >= RADIUS_HDR_AND_EXTID_LEN)) {
+			memcpy(&extid, &original->data[RADIUS_HDR_LEN],
+			       sizeof(extid));
+			if ((extid.id_code_length ==
+			     htons(PW_EXTID_CODELEN)) &&
+			    (extid.status_extid == EXTID_REQUEST)) {
+				radius_extid_t *new_extid;
+				new_extid = (radius_extid_t *)&hdr->data[0];
+				new_extid->id_code_length =
+					htons(PW_EXTID_CODELEN);
+				new_extid->status_extid = EXTID_RESPOND_ACK;
+				status_server_extid = true;
+			}
+		}
+	} else {
+		memset(&extid, 0, sizeof(extid));
+		if (packet->code == PW_CODE_STATUS_SERVER) {
+			hdr->id = packet->id;
+			packet->client_extid_request = 1;
+			extid.status_extid = EXTID_REQUEST;
+		} else {
+			hdr->id = packet->hdr_id;
+			extid.status_extid = htonl(packet->id &
+						   MAX_EXT_ID_VALUE);
+		}
+		extid.id_code_length = htons(PW_EXTID_CODELEN);
+		memcpy(&hdr->data[0], &extid, sizeof(extid));
+	}
 
 	memcpy(hdr->vector, packet->vector, sizeof(hdr->vector));
 
-	total_length = RADIUS_HDR_LEN;
+	total_length = (!packet->use_extended_id && !status_server_extid) ?
+		RADIUS_HDR_LEN : RADIUS_HDR_LEN + sizeof(extid);
 
 	/*
 	 *	Load up the configuration values for the user
 	 */
 	ptr = hdr->data;
+	if (packet->use_extended_id || status_server_extid) {
+		ptr += sizeof(extid);
+	}
 	packet->offset = 0;
 
 	/*
@@ -1850,6 +1896,12 @@ int rad_encode(RADIUS_PACKET *packet, RADIUS_PACKET const *original,
 			}
 		}
 
+		if ((reply->vp_length == 4) &&
+		    (reply->da->attr == PW_EXTENDED_ID)) {
+			reply = reply->next;
+			continue;
+		}
+
 		/*
 		 *	Set the Message-Authenticator to the correct
 		 *	length and initial value.
@@ -2344,6 +2396,7 @@ bool rad_packet_ok(RADIUS_PACKET *packet, int flags, decode_fail_t *reason)
 	bool			seen_ma = false;
 	uint32_t		num_attributes;
 	decode_fail_t		failure = DECODE_FAIL_NONE;
+	radius_extid_t	        *extid;
 
 	/*
 	 *	Check for packets smaller than the packet header.
@@ -2543,7 +2596,14 @@ bool rad_packet_ok(RADIUS_PACKET *packet, int flags, decode_fail_t *reason)
 		default:	/* don't do anything by default */
 			break;
 
-			/*
+		  case PW_EXTENDED_ID:
+		    extid = (radius_extid_t *)&attr[0];
+		    if (extid->status_extid == EXTID_RESPOND_ACK) {
+			    packet->server_extid_reply = 1;
+		    }
+		    break;
+
+		    /*
 			 *	If there's an EAP-Message, we require
 			 *	a Message-Authenticator.
 			 */
@@ -2630,7 +2690,21 @@ bool rad_packet_ok(RADIUS_PACKET *packet, int flags, decode_fail_t *reason)
 	 *	Fill RADIUS header fields
 	 */
 	packet->code = hdr->code;
-	packet->id = hdr->id;
+	extid = (radius_extid_t *) &packet->data[RADIUS_HDR_LEN];
+	if ((packet->data_len >= RADIUS_HDR_AND_EXTID_LEN) &&
+	    (hdr->code != PW_CODE_STATUS_SERVER) &&
+	    (extid->id_code_length == htons(PW_EXTID_CODELEN))) {
+		if (!(ntohl(extid->status_extid) & EXTID_STATUS_MASK)) {
+			packet->id = ntohl(extid->status_extid) &
+				MAX_EXT_ID_VALUE;
+			packet->hdr_id = hdr->id;
+			packet->use_extended_id = 1;
+		} else {
+			packet->id = hdr->id;
+		}
+	} else {
+		packet->id = hdr->id;
+	}
 	memcpy(packet->vector, hdr->vector, AUTH_VECTOR_LEN);

diff --git a/src/main/listen.c b/src/main/listen.c
index 65e5c8b..65ca735 100644
--- a/src/main/listen.c
+++ b/src/main/listen.c
@@ -2167,6 +2167,11 @@ static int client_socket_decode(UNUSED rad_listen_t *listener, REQUEST *request)
 #ifdef WITH_PROXY
 static int proxy_socket_encode(UNUSED rad_listen_t *listener, REQUEST *request)
 {
+	if ((request->packet->code == PW_CODE_ACCESS_REQUEST) &&
+	    !request->home_server->sent_status_server) {
+		request->proxy->code = PW_CODE_STATUS_SERVER;
+		request->proxy->use_extended_id = 1;
+	}
 	if (rad_encode(request->proxy, NULL, request->home_server->secret) < 0) {
 		RERROR("Failed encoding proxied packet: %s", fr_strerror());
 
diff --git a/src/main/process.c b/src/main/process.c
index 5ec16e6..cac5648 100644
--- a/src/main/process.c
+++ b/src/main/process.c
@@ -1441,6 +1441,10 @@ static void request_finish(REQUEST *request, int action)
 #endif
 	}
 
+	if (request->proxy && (request->proxy->code == PW_CODE_STATUS_SERVER)) {
+		request_cleanup_delay_init(request);
+		return;
+	}
 	/*
 	 *	Send the reply.
 	 */
@@ -1874,6 +1878,8 @@ static REQUEST *request_setup(TALLOC_CTX *ctx, rad_listen_t *listener, RADIUS_PA
 	request->reply->src_port = request->packet->dst_port;
 	request->reply->id = request->packet->id;
 	request->reply->code = 0; /* UNKNOWN code */
+	request->reply->use_extended_id = request->packet->use_extended_id;
+	request->reply->hdr_id = request->packet->hdr_id;
 	memcpy(request->reply->vector, request->packet->vector,
 	       sizeof(request->reply->vector));
 	request->reply->vps = NULL;
@@ -2172,6 +2178,10 @@ static int insert_into_proxy_hash(REQUEST *request)
 	request->num_proxied_requests = 1;
 	request->num_proxied_responses = 0;
 
+	if (request->home_server->support_extid) {
+		request->proxy->use_extended_id = 1;
+	}
+
 	for (tries = 0; tries < 2; tries++) {
 		rad_listen_t *this;
 		listen_socket_t *sock;
@@ -2435,6 +2445,13 @@ static void mark_home_server_alive(REQUEST *request, home_server_t *home)
 
 	fr_event_delete(el, &home->ev);
 
+	if (request->proxy->code == PW_CODE_STATUS_SERVER) {
+		home->sent_status_server = true;
+		if (request->proxy_reply->server_extid_reply) {
+			home->support_extid = 1;
+			RDEBUG("Home Server %s supports ID Attribute", home->name);
+		}
+	}
 	RPROXY("Marking home server %s port %d alive",
 	       inet_ntop(request->proxy->dst_ipaddr.af,
 			 &request->proxy->dst_ipaddr.ipaddr,
@@ -3982,8 +3999,12 @@ static void proxy_wait_for_reply(REQUEST *request, int action)
 		 *	We received a new reply.  Go process it.
 		 */
 	case FR_ACTION_PROXY_REPLY:
-		request_queue_or_run(request, proxy_running);
-		break;
+	  if (request->proxy->code == PW_CODE_STATUS_SERVER) {
+		  request_queue_or_run(request, proxy_no_reply);
+	  } else {
+		  request_queue_or_run(request, proxy_running);
+	  }
+	  break;
 
 	default:
 		RDEBUG3("%s: Ignoring action %s", __FUNCTION__, action_codes[action]);
diff --git a/src/main/radclient.c b/src/main/radclient.c
index 7594ed4..e431bd4 100644
--- a/src/main/radclient.c
+++ b/src/main/radclient.c
@@ -1074,7 +1074,6 @@ static int recv_one_packet(int wait_time)
 		RDEBUG("%s response code %d", request->files->packets, reply->code);
 	}
 
-	deallocate_id(request);
 	request->reply = reply;
 	reply = NULL;
 
@@ -1140,11 +1139,18 @@ static int recv_one_packet(int wait_time)
 		}
 	}
 
+	if (request->packet->client_extid_request &&
+	    request->reply->server_extid_reply) {
+		request->packet->server_extid_reply = 1;
+		RDEBUG("Server supports ID Attribute");
+	}
+
 	if (request->resend == resend_count) {
 		request->done = true;
 	}
 
 packet_done:
+	deallocate_id(request);
 	rad_free(&request->reply);
 	rad_free(&reply);	/* may be NULL */
 
@@ -1163,6 +1169,7 @@ int main(int argc, char **argv)
 	int		parallel = 1;
 	rc_request_t	*this;
 	int		force_af = AF_UNSPEC;
+	int		use_extended_id = 0;
 
 	/*
 	 *	It's easier having two sets of flags to set the
@@ -1188,7 +1195,7 @@ int main(int argc, char **argv)
 		exit(1);
 	}
 
-	while ((c = getopt(argc, argv, "46c:d:D:f:Fhi:n:p:qr:sS:t:vx"
+	while ((c = getopt(argc, argv, "46c:d:D:f:Fhi:I:n:p:qr:sS:t:vx"
 #ifdef WITH_TCP
 		"P:"
 #endif
@@ -1249,6 +1256,10 @@ int main(int argc, char **argv)
 			}
 			break;
 
+		case 'I':	/* Use ID-Attribute */
+			use_extended_id = 1;
+			break;
+
 		case 'n':
 			persec = atoi(optarg);
 			if (persec <= 0) usage();
@@ -1478,6 +1489,7 @@ int main(int argc, char **argv)
 	for (this = request_head; this != NULL; this = this->next) {
 		this->packet->src_ipaddr = client_ipaddr;
 		this->packet->src_port = client_port;
+		this->packet->use_extended_id = use_extended_id;
 		if (radclient_sane(this) != 0) {
 			exit(1);
 		}
diff --git a/src/main/radtest b/src/main/radtest
index 621bd5e..cc3ed62 100755
--- a/src/main/radtest
+++ b/src/main/radtest
@@ -34,6 +34,7 @@ radeapclient=$bindir/radeapclient
 OPTIONS=
 PASSWORD="User-Password"
 NAS_ADDR_ATTR="NAS-IP-Address"
+SERVICE="auth"
 
 #  We need at LEAST these many options
 if [ $# -lt 5 ]
@@ -67,6 +68,15 @@ do
 		OPTIONS="$OPTIONS -x"
 		shift
 		;;
+	-I)
+		OPTIONS="$OPTIONS -I -x"
+		shift
+		;;
+	-S)
+		OPTIONS="$OPTIONS -I -x"
+		SERVICE="status"
+		shift
+		;;
 
 	-t)
 		shift;
@@ -116,6 +126,8 @@ else
 fi
 
 (
+    if [ "$SERVICE" != "status" ]
+       then
 	echo "User-Name = \"$1\""
 	echo "$PASSWORD = \"$2\""
 	echo "$NAS_ADDR_ATTR = $nas"
@@ -130,6 +142,10 @@ fi
 	then
 		echo "Framed-Protocol = PPP"
 	fi
-) | $radclient $OPTIONS -x $3 auth "$5"
+    else
+	echo "Message-Authenticator = 0x00"
+#	echo "User-Name = \"$1\""
+	fi
+) | $radclient $OPTIONS -x $3 $SERVICE "$5"
 
 exit $?