]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
Allow arbitrary RADIUS attributes to be added into Access-Accept
authorJouni Malinen <jouni@qca.qualcomm.com>
Fri, 7 Mar 2014 21:19:52 +0000 (23:19 +0200)
committerJouni Malinen <j@w1.fi>
Sat, 8 Mar 2014 09:35:08 +0000 (11:35 +0200)
This extends the design already available for Access-Request packets to
the RADIUS server and Access-Accept messages. Each user entry can be
configured to add arbitrary RADIUS attributes.

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
hostapd/config_file.c
hostapd/hostapd.eap_user
src/ap/ap_config.c
src/ap/ap_config.h
src/ap/authsrv.c
src/eap_server/eap.h
src/radius/radius_server.c

index bd66474392dc8a32141a589d01034a44badc7911..949a9d171d6db543a394d07a315d827b5dc33f20 100644 (file)
 #include "config_file.h"
 
 
+#ifndef CONFIG_NO_RADIUS
+#ifdef EAP_SERVER
+static struct hostapd_radius_attr *
+hostapd_parse_radius_attr(const char *value);
+#endif /* EAP_SERVER */
+#endif /* CONFIG_NO_RADIUS */
+
+
 #ifndef CONFIG_NO_VLAN
 static int hostapd_config_read_vlan_file(struct hostapd_bss_config *bss,
                                         const char *fname)
@@ -208,7 +216,7 @@ static int hostapd_config_read_eap_user(const char *fname,
        FILE *f;
        char buf[512], *pos, *start, *pos2;
        int line = 0, ret = 0, num_methods;
-       struct hostapd_eap_user *user, *tail = NULL;
+       struct hostapd_eap_user *user = NULL, *tail = NULL;
 
        if (!fname)
                return 0;
@@ -242,6 +250,27 @@ static int hostapd_config_read_eap_user(const char *fname,
                if (buf[0] == '\0')
                        continue;
 
+#ifndef CONFIG_NO_RADIUS
+               if (user && os_strncmp(buf, "radius_accept_attr=", 19) == 0) {
+                       struct hostapd_radius_attr *attr, *a;
+                       attr = hostapd_parse_radius_attr(buf + 19);
+                       if (attr == NULL) {
+                               wpa_printf(MSG_ERROR, "Invalid radius_auth_req_attr: %s",
+                                          buf + 19);
+                               goto failed;
+                       }
+                       if (user->accept_attr == NULL) {
+                               user->accept_attr = attr;
+                       } else {
+                               a = user->accept_attr;
+                               while (a->next)
+                                       a = a->next;
+                               a->next = attr;
+                       }
+                       continue;
+               }
+#endif /* CONFIG_NO_RADIUS */
+
                user = NULL;
 
                if (buf[0] != '"' && buf[0] != '*') {
@@ -468,11 +497,8 @@ static int hostapd_config_read_eap_user(const char *fname,
                continue;
 
        failed:
-               if (user) {
-                       os_free(user->password);
-                       os_free(user->identity);
-                       os_free(user);
-               }
+               if (user)
+                       hostapd_config_free_eap_user(user);
                ret = -1;
                break;
        }
index 12a2c61296d7fb8b3863203083e596bca15b8ce3..00edc95af5cd0f3a6b9cb6dd0dd9e453c84b71f6 100644 (file)
 # TTLS-CHAP, TTLS-MSCHAP, TTLS-MSCHAPV2. TTLS-PAP and TTLS-CHAP require a
 # plaintext password while TTLS-MSCHAP and TTLS-MSCHAPV2 can use NT password
 # hash.
+#
+# Arbitrary RADIUS attributes can be added into Access-Accept packets similarly
+# to the way radius_auth_req_attr is used for Access-Request packet in
+# hostapd.conf. For EAP server, this is configured separately for each user
+# entry with radius_accept_attr=<value> line(s) following the main user entry
+# line.
 
 # Phase 1 users
 "user"         MD5     "password"
index b995892cdad813e9e97c1b5794f9bf9ce4190ca5..f744985a00c57c6003945371355c7672df15e443 100644 (file)
@@ -388,8 +388,9 @@ static void hostapd_config_free_radius_attr(struct hostapd_radius_attr *attr)
 }
 
 
-static void hostapd_config_free_eap_user(struct hostapd_eap_user *user)
+void hostapd_config_free_eap_user(struct hostapd_eap_user *user)
 {
+       hostapd_config_free_radius_attr(user->accept_attr);
        os_free(user->identity);
        os_free(user->password);
        os_free(user);
index e1e34e2d512b93fb8b230f181a6caeaedfc8d452..f6ca8b1f9a75b68a52983ae927fd6c8da6406b5c 100644 (file)
@@ -128,6 +128,7 @@ struct hostapd_eap_user {
                                       * nt_password_hash() */
        unsigned int remediation:1;
        int ttls_auth; /* EAP_TTLS_AUTH_* bitfield */
+       struct hostapd_radius_attr *accept_attr;
 };
 
 struct hostapd_radius_attr {
@@ -601,6 +602,7 @@ int hostapd_mac_comp(const void *a, const void *b);
 int hostapd_mac_comp_empty(const void *a);
 struct hostapd_config * hostapd_config_defaults(void);
 void hostapd_config_defaults_bss(struct hostapd_bss_config *bss);
+void hostapd_config_free_eap_user(struct hostapd_eap_user *user);
 void hostapd_config_free_bss(struct hostapd_bss_config *conf);
 void hostapd_config_free(struct hostapd_config *conf);
 int hostapd_maclist_found(struct mac_acl_entry *list, int num_entries,
index 7691012fe41b00470b7192b1fc21355c24369758..8b922ec2175dbeb4cd485dbff1930e0ab1d21e90 100644 (file)
@@ -81,6 +81,7 @@ static int hostapd_radius_get_eap_user(void *ctx, const u8 *identity,
        user->force_version = eap_user->force_version;
        user->ttls_auth = eap_user->ttls_auth;
        user->remediation = eap_user->remediation;
+       user->accept_attr = eap_user->accept_attr;
 
        return 0;
 }
index 197b232ff295ba2f86b51f59e2e0a2ad05a57d09..25347baa4d25cafa6d0d44e0e5a87e3e56d3c795 100644 (file)
@@ -35,6 +35,7 @@ struct eap_user {
        unsigned int remediation:1;
        int ttls_auth; /* bitfield of
                        * EAP_TTLS_AUTH_{PAP,CHAP,MSCHAP,MSCHAPV2} */
+       struct hostapd_radius_attr *accept_attr;
 };
 
 struct eap_eapol_interface {
index 6b86932ac8b7736233fda441932b114768624016..dd96b592a01ad1498fb96559501fe4b8a99d3305 100644 (file)
@@ -13,6 +13,7 @@
 #include "radius.h"
 #include "eloop.h"
 #include "eap_server/eap.h"
+#include "ap/ap_config.h"
 #include "radius_server.h"
 
 /**
@@ -79,6 +80,8 @@ struct radius_session {
        u8 last_authenticator[16];
 
        unsigned int remediation:1;
+
+       struct hostapd_radius_attr *accept_attr;
 };
 
 /**
@@ -483,6 +486,7 @@ radius_server_get_new_session(struct radius_server_data *data,
        int res;
        struct radius_session *sess;
        struct eap_config eap_conf;
+       struct eap_user tmp;
 
        RADIUS_DEBUG("Creating a new session");
 
@@ -499,7 +503,9 @@ radius_server_get_new_session(struct radius_server_data *data,
        user_len = res;
        RADIUS_DUMP_ASCII("User-Name", user, user_len);
 
-       res = data->get_eap_user(data->conf_ctx, user, user_len, 0, NULL);
+       os_memset(&tmp, 0, sizeof(tmp));
+       res = data->get_eap_user(data->conf_ctx, user, user_len, 0, &tmp);
+       os_free(tmp.password);
        os_free(user);
 
        if (res == 0) {
@@ -509,6 +515,7 @@ radius_server_get_new_session(struct radius_server_data *data,
                        RADIUS_DEBUG("Failed to create a new session");
                        return NULL;
                }
+               sess->accept_attr = tmp.accept_attr;
        } else {
                RADIUS_DEBUG("User-Name not found from user database");
                return NULL;
@@ -661,6 +668,19 @@ radius_server_encapsulate_eap(struct radius_server_data *data,
                return NULL;
        }
 
+       if (code == RADIUS_CODE_ACCESS_ACCEPT) {
+               struct hostapd_radius_attr *attr;
+               for (attr = sess->accept_attr; attr; attr = attr->next) {
+                       if (!radius_msg_add_attr(msg, attr->type,
+                                                wpabuf_head(attr->val),
+                                                wpabuf_len(attr->val))) {
+                               wpa_printf(MSG_ERROR, "Could not add RADIUS attribute");
+                               radius_msg_free(msg);
+                               return NULL;
+                       }
+               }
+       }
+
        if (radius_msg_finish_srv(msg, (u8 *) client->shared_secret,
                                  client->shared_secret_len,
                                  hdr->authenticator) < 0) {
@@ -1725,8 +1745,10 @@ static int radius_server_get_eap_user(void *ctx, const u8 *identity,
 
        ret = data->get_eap_user(data->conf_ctx, identity, identity_len,
                                 phase2, user);
-       if (ret == 0 && user)
+       if (ret == 0 && user) {
+               sess->accept_attr = user->accept_attr;
                sess->remediation = user->remediation;
+       }
        return ret;
 }