]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
HS 2.0: Move Terms and Conditions Server URL generation from AP to AS
authorJouni Malinen <jouni@codeaurora.org>
Thu, 21 Jun 2018 17:50:54 +0000 (20:50 +0300)
committerJouni Malinen <j@w1.fi>
Thu, 21 Jun 2018 17:50:54 +0000 (20:50 +0300)
This makes it more convenient to generate the URL in a way that
interoperates between different vendors. The AP is simply copying the
already constructed URL as-is from Access-Accept to WNM-Notification.
This means that the HO AAA can generate the URL in a manner that works
for the associated T&C Server without having to coordinate with each AP.

Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
hostapd/hostapd.conf
src/ap/authsrv.c
src/ap/hs20.c
src/ap/hs20.h
src/ap/ieee802_1x.c
src/ap/sta_info.c
src/ap/sta_info.h
src/radius/radius.h
src/radius/radius_server.c
src/radius/radius_server.h

index 64dd8c28b637b29604b5c5a34bd7f763cec99092..8834ccfbf59d36690d30fa08f9a5ebdaa64ccacc 100644 (file)
@@ -2191,7 +2191,8 @@ own_ip_addr=127.0.0.1
 #
 # hs20_t_c_server_url contains a template for the Terms and Conditions server
 # URL. This template is used to generate the URL for a STA that needs to
-# acknowledge Terms and Conditions.
+# acknowledge Terms and Conditions. Unlike the other hs20_t_c_* parameters, this
+# parameter is used on the authentication server, not the AP.
 # Macros:
 # @1@ = MAC address of the STA (colon separated hex octets)
 #hs20_t_c_server_url=https://example.com/t_and_c?addr=@1@&ap=123
index 315c30bbeb31e3d8225404f7c1efe7ed70c79da8..66d255c749943299b29bebd3b596a0208e6983a2 100644 (file)
@@ -136,6 +136,7 @@ static int hostapd_setup_radius_srv(struct hostapd_data *hapd)
 #ifdef CONFIG_HS20
        srv.subscr_remediation_url = conf->subscr_remediation_url;
        srv.subscr_remediation_method = conf->subscr_remediation_method;
+       srv.t_c_server_url = conf->t_c_server_url;
 #endif /* CONFIG_HS20 */
        srv.erp = conf->eap_server_erp;
        srv.erp_domain = conf->erp_domain;
index 9770c34d2509cf59f7210892adc17730c94c569d..98d016d96287c9fec7a4c10ec78717d55874e610 100644 (file)
@@ -180,20 +180,24 @@ int hs20_send_wnm_notification_deauth_req(struct hostapd_data *hapd,
 
 
 int hs20_send_wnm_notification_t_c(struct hostapd_data *hapd,
-                                  const u8 *addr)
+                                  const u8 *addr, const char *url)
 {
        struct wpabuf *buf;
        int ret;
-       const char *url = hapd->conf->t_c_server_url, *pos;
-       size_t url_len;
+       size_t url_len = os_strlen(url);
 
-       if (!url)
+       if (!url) {
+               wpa_printf(MSG_INFO, "HS 2.0: No T&C Server URL available");
                return -1;
-       pos = os_strstr(url, "@1@");
-       if (!pos)
+       }
+
+       if (5 + url_len > 255) {
+               wpa_printf(MSG_INFO,
+                          "HS 2.0: Too long T&C Server URL for WNM-Notification: '%s'",
+                          url);
                return -1;
+       }
 
-       url_len = os_strlen(url) + ETH_ALEN * 3 - 1 - 3;
        buf = wpabuf_alloc(4 + 7 + url_len);
        if (!buf)
                return -1;
@@ -209,9 +213,7 @@ int hs20_send_wnm_notification_t_c(struct hostapd_data *hapd,
        wpabuf_put_be24(buf, OUI_WFA);
        wpabuf_put_u8(buf, HS20_WNM_T_C_ACCEPTANCE);
        wpabuf_put_u8(buf, url_len);
-       wpabuf_put_data(buf, url, pos - url);
-       wpabuf_printf(buf, MACSTR, MAC2STR(addr));
-       wpabuf_put_str(buf, pos + 3);
+       wpabuf_put_str(buf, url);
 
        ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr,
                                      wpabuf_head(buf), wpabuf_len(buf));
index bf3980628fce9929dbbac00451399b3b5141149d..e99e26e911587fa1ad1f2fbc57f42a40e398e0a2 100644 (file)
@@ -19,7 +19,7 @@ int hs20_send_wnm_notification_deauth_req(struct hostapd_data *hapd,
                                          const u8 *addr,
                                          const struct wpabuf *payload);
 int hs20_send_wnm_notification_t_c(struct hostapd_data *hapd,
-                                  const u8 *addr);
+                                  const u8 *addr, const char *url);
 void hs20_t_c_filtering(struct hostapd_data *hapd, struct sta_info *sta,
                        int enabled);
 
index c7d15a5264a6e42ed7874ce3535877557eb3896f..985f8b787b0cb9d55ab22512c689015b532e73fa 100644 (file)
@@ -1635,6 +1635,20 @@ static void ieee802_1x_hs20_t_c_filtering(struct hostapd_data *hapd,
        hs20_t_c_filtering(hapd, sta, pos[0] & BIT(0));
 }
 
+
+static void ieee802_1x_hs20_t_c_url(struct hostapd_data *hapd,
+                                   struct sta_info *sta, u8 *pos, size_t len)
+{
+       os_free(sta->t_c_url);
+       sta->t_c_url = os_malloc(len + 1);
+       if (!sta->t_c_url)
+               return;
+       os_memcpy(sta->t_c_url, pos, len);
+       sta->t_c_url[len] = '\0';
+       wpa_printf(MSG_DEBUG,
+                  "HS 2.0: Terms and Conditions URL %s", sta->t_c_url);
+}
+
 #endif /* CONFIG_HS20 */
 
 
@@ -1685,6 +1699,9 @@ static void ieee802_1x_check_hs20(struct hostapd_data *hapd,
                case RADIUS_VENDOR_ATTR_WFA_HS20_T_C_FILTERING:
                        ieee802_1x_hs20_t_c_filtering(hapd, sta, pos, sublen);
                        break;
+               case RADIUS_VENDOR_ATTR_WFA_HS20_T_C_URL:
+                       ieee802_1x_hs20_t_c_url(hapd, sta, pos, sublen);
+                       break;
                }
        }
 #endif /* CONFIG_HS20 */
@@ -2767,7 +2784,9 @@ static void ieee802_1x_wnm_notif_send(void *eloop_ctx, void *timeout_ctx)
                wpa_printf(MSG_DEBUG, "HS 2.0: Send WNM-Notification to "
                           MACSTR " to indicate Terms and Conditions filtering",
                           MAC2STR(sta->addr));
-               hs20_send_wnm_notification_t_c(hapd, sta->addr);
+               hs20_send_wnm_notification_t_c(hapd, sta->addr, sta->t_c_url);
+               os_free(sta->t_c_url);
+               sta->t_c_url = NULL;
        }
 }
 #endif /* CONFIG_HS20 */
index 5e2f055d3b36ad4c6732daa47cf60e3560a8a05b..179cf43b60b17c267d9fe9622370c3c82fad9e4b 100644 (file)
@@ -332,6 +332,7 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
        os_free(sta->identity);
        os_free(sta->radius_cui);
        os_free(sta->remediation_url);
+       os_free(sta->t_c_url);
        wpabuf_free(sta->hs20_deauth_req);
        os_free(sta->hs20_session_info_url);
 
index 0459549ebc6be17a4e9cf2b51360dc92da417175..9cac6f157f68f4b1b9dc9d7f617541b51def71c9 100644 (file)
@@ -187,6 +187,7 @@ struct sta_info {
        struct wpabuf *roaming_consortium;
        u8 remediation_method;
        char *remediation_url; /* HS 2.0 Subscription Remediation Server URL */
+       char *t_c_url; /* HS 2.0 Terms and Conditions Server URL */
        struct wpabuf *hs20_deauth_req;
        char *hs20_session_info_url;
        int hs20_disassoc_timer;
index 55185dfb32288968cd47f7b8e23f6f7a33d86af2..630c0f9d0bc5bd1e48ab7ded17c5ec11b215a711 100644 (file)
@@ -202,6 +202,7 @@ enum {
        RADIUS_VENDOR_ATTR_WFA_HS20_T_C_FILENAME = 7,
        RADIUS_VENDOR_ATTR_WFA_HS20_TIMESTAMP = 8,
        RADIUS_VENDOR_ATTR_WFA_HS20_T_C_FILTERING = 9,
+       RADIUS_VENDOR_ATTR_WFA_HS20_T_C_URL = 10,
 };
 
 #ifdef _MSC_VER
index 17c90878dd83219eccd34f74895214d4d8716825..27e2050c10e70236dd121535d53a72a8033de0bc 100644 (file)
@@ -350,6 +350,8 @@ struct radius_server_data {
        char *subscr_remediation_url;
        u8 subscr_remediation_method;
 
+       char *t_c_server_url;
+
 #ifdef CONFIG_SQLITE
        sqlite3 *db;
 #endif /* CONFIG_SQLITE */
@@ -884,12 +886,56 @@ radius_server_encapsulate_eap(struct radius_server_data *data,
 
        if (code == RADIUS_CODE_ACCESS_ACCEPT && sess->t_c_filtering) {
                u8 buf[4] = { 0x01, 0x00, 0x00, 0x00 }; /* E=1 */
+               const char *url = data->t_c_server_url, *pos;
+               char *url2, *end2, *pos2;
+               size_t url_len;
 
                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");
+                       radius_msg_free(msg);
+                       return NULL;
+               }
+
+               if (!url) {
+                       RADIUS_DEBUG("No t_c_server_url configured");
+                       radius_msg_free(msg);
+                       return NULL;
+               }
+
+               pos = os_strstr(url, "@1@");
+               if (!pos) {
+                       RADIUS_DEBUG("No @1@ macro in t_c_server_url");
+                       radius_msg_free(msg);
+                       return NULL;
+               }
+
+               url_len = os_strlen(url) + ETH_ALEN * 3 - 1 - 3;
+               url2 = os_malloc(url_len);
+               if (!url2) {
+                       RADIUS_DEBUG("Failed to allocate room for T&C Server URL");
+                       os_free(url2);
+                       radius_msg_free(msg);
+                       return NULL;
                }
+               pos2 = url2;
+               end2 = url2 + url_len;
+               os_memcpy(pos2, url, pos - url);
+               pos2 += pos - url;
+               os_snprintf(pos2, end2 - pos2, MACSTR, MAC2STR(sess->mac_addr));
+               pos2 += ETH_ALEN * 3 - 1;
+               os_memcpy(pos2, pos + 3, os_strlen(pos + 3));
+               if (!radius_msg_add_wfa(msg,
+                                       RADIUS_VENDOR_ATTR_WFA_HS20_T_C_URL,
+                                       (const u8 *) url2, url_len)) {
+                       RADIUS_DEBUG("Failed to add WFA-HS20-T-C-URL");
+                       os_free(url2);
+                       radius_msg_free(msg);
+                       return NULL;
+               }
+               os_free(url2);
+
                radius_srv_hs20_t_c_pending(sess);
        }
 #endif /* CONFIG_HS20 */
@@ -1894,6 +1940,9 @@ radius_server_init(struct radius_server_conf *conf)
        }
        data->subscr_remediation_method = conf->subscr_remediation_method;
 
+       if (conf->t_c_server_url)
+               data->t_c_server_url = os_strdup(conf->t_c_server_url);
+
 #ifdef CONFIG_SQLITE
        if (conf->sqlite_file) {
                if (sqlite3_open(conf->sqlite_file, &data->db)) {
@@ -2010,6 +2059,7 @@ void radius_server_deinit(struct radius_server_data *data)
        os_free(data->dump_msk_file);
 #endif /* CONFIG_RADIUS_TEST */
        os_free(data->subscr_remediation_url);
+       os_free(data->t_c_server_url);
 
 #ifdef CONFIG_SQLITE
        if (data->db)
index 996f00eed258c1f5af431c40c4e342ecfda19384..298f3c10547e06c939abd9d73ab192b572b82c4e 100644 (file)
@@ -233,6 +233,8 @@ struct radius_server_conf {
 
        char *subscr_remediation_url;
        u8 subscr_remediation_method;
+
+       char *t_c_server_url;
 };