Parcourir la source

RADIUS DAS: Check Disconnect-Request attributes

Reject Disconnect-Request if it includes unsupported attributes.

Signed-hostap: Jouni Malinen <j@w1.fi>
Jouni Malinen il y a 12 ans
Parent
commit
fc2a924a8c
3 fichiers modifiés avec 68 ajouts et 7 suppressions
  1. 21 0
      src/radius/radius.c
  2. 2 0
      src/radius/radius.h
  3. 45 7
      src/radius/radius_das.c

+ 21 - 0
src/radius/radius.c

@@ -1552,3 +1552,24 @@ int radius_copy_class(struct radius_class_data *dst,
 
 	return 0;
 }
+
+
+u8 radius_msg_find_unlisted_attr(struct radius_msg *msg, u8 *attrs)
+{
+	size_t i, j;
+	struct radius_attr_hdr *attr;
+
+	for (i = 0; i < msg->attr_used; i++) {
+		attr = radius_get_attr_hdr(msg, i);
+
+		for (j = 0; attrs[j]; j++) {
+			if (attr->type == attrs[j])
+				break;
+		}
+
+		if (attrs[j] == 0)
+			return attr->type; /* unlisted attr */
+	}
+
+	return 0;
+}

+ 2 - 0
src/radius/radius.h

@@ -282,4 +282,6 @@ void radius_free_class(struct radius_class_data *c);
 int radius_copy_class(struct radius_class_data *dst,
 		      const struct radius_class_data *src);
 
+u8 radius_msg_find_unlisted_attr(struct radius_msg *msg, u8 *attrs);
+
 #endif /* RADIUS_H */

+ 45 - 7
src/radius/radius_das.c

@@ -29,6 +29,50 @@ struct radius_das_data {
 };
 
 
+static struct radius_msg * radius_das_disconnect(struct radius_das_data *das,
+						 struct radius_msg *msg,
+						 const char *abuf,
+						 int from_port)
+{
+	struct radius_hdr *hdr;
+	struct radius_msg *reply;
+	u8 allowed[] = {
+		RADIUS_ATTR_USER_NAME,
+		RADIUS_ATTR_CALLING_STATION_ID,
+		RADIUS_ATTR_ACCT_SESSION_ID,
+		RADIUS_ATTR_EVENT_TIMESTAMP,
+		RADIUS_ATTR_MESSAGE_AUTHENTICATOR,
+		RADIUS_ATTR_CHARGEABLE_USER_IDENTITY,
+		0
+	};
+	int error = 405;
+	u8 attr;
+
+	hdr = radius_msg_get_hdr(msg);
+
+	attr = radius_msg_find_unlisted_attr(msg, allowed);
+	if (attr) {
+		wpa_printf(MSG_INFO, "DAS: Unsupported attribute %u in "
+			   "Disconnect-Request from %s:%d", attr,
+			   abuf, from_port);
+		error = 401;
+		goto fail;
+	}
+
+	/* TODO */
+
+	goto fail;
+
+fail:
+	reply = radius_msg_new(RADIUS_CODE_DISCONNECT_NAK, hdr->identifier);
+	if (reply == NULL)
+		return NULL;
+
+	radius_msg_add_attr_int32(reply, RADIUS_ATTR_ERROR_CAUSE, error);
+	return reply;
+}
+
+
 static void radius_das_receive(int sock, void *eloop_ctx, void *sock_ctx)
 {
 	struct radius_das_data *das = eloop_ctx;
@@ -110,13 +154,7 @@ static void radius_das_receive(int sock, void *eloop_ctx, void *sock_ctx)
 
 	switch (hdr->code) {
 	case RADIUS_CODE_DISCONNECT_REQUEST:
-		/* TODO */
-		reply = radius_msg_new(RADIUS_CODE_DISCONNECT_NAK,
-				       hdr->identifier);
-		if (reply == NULL)
-			break;
-
-		radius_msg_add_attr_int32(reply, RADIUS_ATTR_ERROR_CAUSE, 405);
+		reply = radius_das_disconnect(das, msg, abuf, from_port);
 		break;
 	case RADIUS_CODE_COA_REQUEST:
 		/* TODO */