HS 2.0: Move Terms and Conditions Server URL generation from AP to AS
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>
This commit is contained in:
parent
e6f8042d17
commit
d4e39c51f8
10 changed files with 92 additions and 14 deletions
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
return -1;
|
||||
pos = os_strstr(url, "@1@");
|
||||
if (!pos)
|
||||
if (!url) {
|
||||
wpa_printf(MSG_INFO, "HS 2.0: No T&C Server URL available");
|
||||
return -1;
|
||||
}
|
||||
|
||||
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));
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -233,6 +233,8 @@ struct radius_server_conf {
|
|||
|
||||
char *subscr_remediation_url;
|
||||
u8 subscr_remediation_method;
|
||||
|
||||
char *t_c_server_url;
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue