Browse Source

eapol_test: Add a universal way of adding extra RADIUS attributes

This change replaces -I and -i options (Chargeable-User-Identity) with a
new -N option that can add any RADIUS attribute into the Access-Request
messages without having to modify eapol_test for each new attribute.
Tomasz Wolniewicz 16 years ago
parent
commit
db803a3607
1 changed files with 127 additions and 30 deletions
  1. 127 30
      wpa_supplicant/eapol_test.c

+ 127 - 30
wpa_supplicant/eapol_test.c

@@ -38,6 +38,13 @@ extern int wpa_debug_show_keys;
 struct wpa_driver_ops *wpa_supplicant_drivers[] = { NULL };
 
 
+struct extra_radius_attr {
+	u8 type;
+	char syntax;
+	char *data;
+	struct extra_radius_attr *next;
+};
+
 struct eapol_test_data {
 	struct wpa_supplicant *wpa_s;
 
@@ -66,8 +73,7 @@ struct eapol_test_data {
 
 	char *connect_info;
 	u8 own_addr[ETH_ALEN];
-	int cui_flag;
-	char *cui_str;
+	struct extra_radius_attr *extra_attrs;
 };
 
 static struct eapol_test_data eapol_test;
@@ -87,6 +93,69 @@ static void hostapd_logger_cb(void *ctx, const u8 *addr, unsigned int module,
 }
 
 
+static int add_extra_attr(struct radius_msg *msg,
+			  struct extra_radius_attr *attr)
+{
+	size_t len;
+	char *pos;
+	u32 val;
+	char buf[128];
+
+	switch (attr->syntax) {
+	case 's':
+		os_snprintf(buf, sizeof(buf), "%s", attr->data);
+		len = os_strlen(buf);
+		break;
+	case 'n':
+		buf[0] = '\0';
+		len = 1;
+		break;
+	case 'x':
+		pos = attr->data;
+		if (pos[0] == '0' && pos[1] == 'x')
+			pos += 2;
+		len = os_strlen(pos);
+		if ((len & 1) || (len / 2) > sizeof(buf)) {
+			printf("Invalid extra attribute hexstring\n");
+			return -1;
+		}
+		len /= 2;
+		if (hexstr2bin(pos, (u8 *) buf, len) < 0) {
+			printf("Invalid extra attribute hexstring\n");
+			return -1;
+		}
+		break;
+	case 'd':
+		val = htonl(atoi(attr->data));
+		os_memcpy(buf, &val, 4);
+		len = 4;
+		break;
+	default:
+		printf("Incorrect extra attribute syntax specification\n");
+		return -1;
+	}
+
+	if (!radius_msg_add_attr(msg, attr->type, (u8 *) buf, len)) {
+		printf("Could not add attribute %d\n", attr->type);
+		return -1;
+	}
+
+	return 0;
+}
+
+
+static int add_extra_attrs(struct radius_msg *msg,
+			   struct extra_radius_attr *attrs)
+{
+	struct extra_radius_attr *p;
+	for (p = attrs; p; p = p->next) {
+		if (add_extra_attr(msg, p) < 0)
+			return -1;
+	}
+	return 0;
+}
+
+
 static void ieee802_1x_encapsulate_radius(struct eapol_test_data *e,
 					  const u8 *eap, size_t len)
 {
@@ -166,22 +235,8 @@ static void ieee802_1x_encapsulate_radius(struct eapol_test_data *e,
 		goto fail;
 	}
 
-	if (e->cui_flag) {
-		int l = 0;
-		if (e->cui_flag == 1) {
-			l = 1;
-			buf[0] = '\0';
-		} else if (e->cui_flag == 2) {
-			os_snprintf(buf, sizeof(buf), "%s", e->cui_str);
-			l = os_strlen(buf);
-		}
-		if (!radius_msg_add_attr(msg,
-					 RADIUS_ATTR_CHARGEABLE_USER_IDENTITY,
-					 (u8 *) buf, l)) {
-			printf("Could not add Chargeable-User-Identity\n");
-			goto fail;
-		}
-	}
+	if (add_extra_attrs(msg, e->extra_attrs) < 0)
+		goto fail;
 
 	if (eap && !radius_msg_add_eap(msg, eap, len)) {
 		printf("Could not add EAP-Message\n");
@@ -365,6 +420,8 @@ static int test_eapol(struct eapol_test_data *e, struct wpa_supplicant *wpa_s,
 static void test_eapol_clean(struct eapol_test_data *e,
 			     struct wpa_supplicant *wpa_s)
 {
+	struct extra_radius_attr *p, *prev;
+
 	radius_client_deinit(e->radius);
 	os_free(e->last_eap_radius);
 	if (e->last_recv_radius) {
@@ -387,6 +444,13 @@ static void test_eapol_clean(struct eapol_test_data *e,
 		wpa_s->ctrl_iface = NULL;
 	}
 	wpa_config_free(wpa_s->conf);
+
+	p = e->extra_attrs;
+	while (p) {
+		prev = p;
+		p = p->next;
+		os_free(prev);
+	}
 }
 
 
@@ -889,7 +953,8 @@ static void usage(void)
 	       "[-s<AS secret>]\\\n"
 	       "           [-r<count>] [-t<timeout>] [-C<Connect-Info>] \\\n"
 	       "           [-M<client MAC address>] \\\n"
-	       "           [-I<CUI>] [-i] [-A<client IP>]\n"
+	       "           [-N<attr spec>] \\\n"
+	       "           [-A<client IP>]\n"
 	       "eapol_test scard\n"
 	       "eapol_test sim <PIN> <num triplets> [debug]\n"
 	       "\n");
@@ -913,9 +978,18 @@ static void usage(void)
 	       "  -M<client MAC address> = Set own MAC address "
 	       "(Calling-Station-Id,\n"
 	       "                           default: 02:00:00:00:00:01)\n"
-	       "  -I<CUI> = send Chargeable-User-Identity containing the "
-	       "value of CUI\n"
-	       "  -i = send NUL value in Chargeable-User-Identity\n");
+	       "  -N<attr spec> = send arbitrary attribute specified by:\n"
+	       "                  attr_id:syntax:value or attr_id\n"
+	       "                  attr_id - number id of the attribute\n"
+	       "                  syntax - one of: s, d, x\n"
+	       "                     s = string\n"
+	       "                     d = integer\n"
+	       "                     x = octet string\n"
+	       "                  value - attribute value.\n"
+	       "       When only attr_id is specified, NULL will be used as "
+	       "value.\n"
+	       "       Multiple attributes can be specified by using the "
+	       "option several times.\n");
 }
 
 
@@ -929,6 +1003,8 @@ int main(int argc, char *argv[])
 	char *cli_addr = NULL;
 	char *conf = NULL;
 	int timeout = 30;
+	char *pos;
+	struct extra_radius_attr *p = NULL, *p1;
 
 	if (os_program_init())
 		return -1;
@@ -943,7 +1019,7 @@ int main(int argc, char *argv[])
 	wpa_debug_show_keys = 1;
 
 	for (;;) {
-		c = getopt(argc, argv, "a:A:c:C:iI:M:np:r:s:St:W");
+		c = getopt(argc, argv, "a:A:c:C:M:nN:p:r:s:St:W");
 		if (c < 0)
 			break;
 		switch (c) {
@@ -959,13 +1035,6 @@ int main(int argc, char *argv[])
 		case 'C':
 			eapol_test.connect_info = optarg;
 			break;
-		case 'i':
-			eapol_test.cui_flag = 1;
-			break;
-		case 'I':
-			eapol_test.cui_flag = 2;
-			eapol_test.cui_str = optarg;
-			break;
 		case 'M':
 			if (hwaddr_aton(optarg, eapol_test.own_addr)) {
 				usage();
@@ -993,6 +1062,34 @@ int main(int argc, char *argv[])
 		case 'W':
 			wait_for_monitor++;
 			break;
+		case 'N':
+			p1 = os_zalloc(sizeof(p1));
+			if (p1 == NULL)
+				break;
+			if (!p)
+				eapol_test.extra_attrs = p1;
+			else
+				p->next = p1;
+			p = p1;
+
+			p->type = atoi(optarg);
+			pos = os_strchr(optarg, ':');
+			if (pos == NULL) {
+				p->syntax = 'n';
+				p->data = NULL;
+				break;
+			}
+
+			pos++;
+			if (pos[0] == '\0' || pos[1] != ':') {
+				printf("Incorrect format of attribute "
+				       "specification\n");
+				break;
+			}
+
+			p->syntax = pos[0];
+			p->data = pos + 2;
+			break;
 		default:
 			usage();
 			return -1;