]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
HS 2.0: Terms and Conditions testing feature in authentication server
authorJouni Malinen <jouni@codeaurora.org>
Wed, 25 Apr 2018 21:57:44 +0000 (00:57 +0300)
committerJouni Malinen <j@w1.fi>
Thu, 26 Apr 2018 14:56:22 +0000 (17:56 +0300)
Allow hostapd RADIUS authentication server with SQLite EAP user DB to be
used for testing Terms and Conditions functionality. This could be used
for the HO AAA part of functionality (merging HO AAA and SP AAA into a
single component to avoid separate RADIUS proxy in testing setup).

A T&C server with HTTPS processing is needed to allow this to be used
for full over-the-air testing. This commit adds sufficient functionality
to allow hwsim test cases to cover the RADIUS server part.

Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
hostapd/hostapd.eap_user_sqlite
src/ap/ap_config.h
src/ap/authsrv.c
src/ap/eap_user_db.c
src/eap_server/eap.h
src/radius/radius_server.c

index 826db349cfc2a1f23612efbd75458808ed02592e..1ee18432849a0579adfe16667d7c9895ed08e0d2 100644 (file)
@@ -3,7 +3,8 @@ CREATE TABLE users(
        methods TEXT,
        password TEXT,
        remediation TEXT,
-       phase2 INTEGER
+       phase2 INTEGER,
+       t_c_timestamp INTEGER
 );
 
 CREATE TABLE wildcards(
index 7f24e6f68888e0dc725d9c1ac2d1dbeae299e3cb..35ccd21e60690b51443a861d0a8ed82396ed6ded 100644 (file)
@@ -169,6 +169,7 @@ struct hostapd_eap_user {
        unsigned int macacl:1;
        int ttls_auth; /* EAP_TTLS_AUTH_* bitfield */
        struct hostapd_radius_attr *accept_attr;
+       u32 t_c_timestamp;
 };
 
 struct hostapd_radius_attr {
index a20f49f2824626ed856abdf22ce441e9ccae622d..be69d83b257293f21e09ec93bada945051ae6707 100644 (file)
@@ -83,6 +83,7 @@ static int hostapd_radius_get_eap_user(void *ctx, const u8 *identity,
        user->ttls_auth = eap_user->ttls_auth;
        user->remediation = eap_user->remediation;
        user->accept_attr = eap_user->accept_attr;
+       user->t_c_timestamp = eap_user->t_c_timestamp;
        rv = 0;
 
 out:
index 082d0f53175e197f518783945c57ebc222543997..fab307f7a8bd9bbe0142b61aacf479072c699f4e 100644 (file)
@@ -91,6 +91,8 @@ static int get_user_cb(void *ctx, int argc, char *argv[], char *col[])
                        set_user_methods(user, argv[i]);
                } else if (os_strcmp(col[i], "remediation") == 0 && argv[i]) {
                        user->remediation = strlen(argv[i]) > 0;
+               } else if (os_strcmp(col[i], "t_c_timestamp") == 0 && argv[i]) {
+                       user->t_c_timestamp = strtol(argv[i], 0, 10);
                }
        }
 
index c67fa82f63b07366ba668486ff745385041076f5..f9ee7619fffc5f52994a5bb13840a48f43249d59 100644 (file)
@@ -38,6 +38,7 @@ struct eap_user {
        int ttls_auth; /* bitfield of
                        * EAP_TTLS_AUTH_{PAP,CHAP,MSCHAP,MSCHAPV2} */
        struct hostapd_radius_attr *accept_attr;
+       u32 t_c_timestamp;
 };
 
 struct eap_eapol_interface {
index 0a8f448e7558e20387817aaaede9661bb8b97cd0..cc77204774a9e307793764bc2d2ed9677b7d89e5 100644 (file)
@@ -92,8 +92,11 @@ struct radius_session {
 
        unsigned int remediation:1;
        unsigned int macacl:1;
+       unsigned int t_c_filtering:1;
 
        struct hostapd_radius_attr *accept_attr;
+
+       u32 t_c_timestamp; /* Last read T&C timestamp from user DB */
 };
 
 /**
@@ -821,6 +824,16 @@ radius_server_encapsulate_eap(struct radius_server_data *data,
                        RADIUS_DEBUG("Failed to add WFA-HS20-SubscrRem");
                }
        }
+
+       if (code == RADIUS_CODE_ACCESS_ACCEPT && sess->t_c_filtering) {
+               u8 buf[4] = { 0x01, 0x00, 0x00, 0x00 }; /* E=1 */
+
+               if (!radius_msg_add_wfa(
+                           msg, RADIUS_VENDOR_ATTR_WFA_HS20_T_C_FILTERING,
+                           buf, sizeof(buf))) {
+                       RADIUS_DEBUG("Failed to add WFA-HS20-T-C-Filtering");
+               }
+       }
 #endif /* CONFIG_HS20 */
 
        if (radius_msg_copy_attr(msg, request, RADIUS_ATTR_PROXY_STATE) < 0) {
@@ -1003,6 +1016,51 @@ static int radius_server_reject(struct radius_server_data *data,
 }
 
 
+static void radius_server_hs20_t_c_check(struct radius_session *sess,
+                                        struct radius_msg *msg)
+{
+#ifdef CONFIG_HS20
+       u8 *buf, *pos, *end, type, sublen, *timestamp = NULL;
+       size_t len;
+
+       buf = NULL;
+       for (;;) {
+               if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_VENDOR_SPECIFIC,
+                                           &buf, &len, buf) < 0)
+                       break;
+               if (len < 6)
+                       continue;
+               pos = buf;
+               end = buf + len;
+               if (WPA_GET_BE32(pos) != RADIUS_VENDOR_ID_WFA)
+                       continue;
+               pos += 4;
+
+               type = *pos++;
+               sublen = *pos++;
+               if (sublen < 2)
+                       continue; /* invalid length */
+               sublen -= 2; /* skip header */
+               if (pos + sublen > end)
+                       continue; /* invalid WFA VSA */
+
+               if (type == RADIUS_VENDOR_ATTR_WFA_HS20_TIMESTAMP && len >= 4) {
+                       timestamp = pos;
+                       break;
+               }
+       }
+
+       if (!timestamp)
+               return;
+       RADIUS_DEBUG("HS20-Timestamp: %u", WPA_GET_BE32(timestamp));
+       if (sess->t_c_timestamp != WPA_GET_BE32(timestamp)) {
+               RADIUS_DEBUG("Last read T&C timestamp does not match HS20-Timestamp --> require filtering");
+               sess->t_c_filtering = 1;
+       }
+#endif /* CONFIG_HS20 */
+}
+
+
 static int radius_server_request(struct radius_server_data *data,
                                 struct radius_msg *msg,
                                 struct sockaddr *from, socklen_t fromlen,
@@ -1138,6 +1196,9 @@ static int radius_server_request(struct radius_server_data *data,
        else if (sess->eap_if->eapSuccess)
                srv_log(sess, "EAP authentication succeeded");
 
+       if (sess->eap_if->eapSuccess)
+               radius_server_hs20_t_c_check(sess, msg);
+
        reply = radius_server_encapsulate_eap(data, client, sess, msg);
 
 send_reply:
@@ -2059,6 +2120,7 @@ static int radius_server_get_eap_user(void *ctx, const u8 *identity,
                sess->accept_attr = user->accept_attr;
                sess->remediation = user->remediation;
                sess->macacl = user->macacl;
+               sess->t_c_timestamp = user->t_c_timestamp;
        }
 
        if (ret) {