#
# 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
#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;
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;
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));
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);
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 */
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 */
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 */
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);
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;
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
char *subscr_remediation_url;
u8 subscr_remediation_method;
+ char *t_c_server_url;
+
#ifdef CONFIG_SQLITE
sqlite3 *db;
#endif /* CONFIG_SQLITE */
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 */
}
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)) {
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)
char *subscr_remediation_url;
u8 subscr_remediation_method;
+
+ char *t_c_server_url;
};