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
|
# 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
|
# 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:
|
# Macros:
|
||||||
# @1@ = MAC address of the STA (colon separated hex octets)
|
# @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
|
#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
|
#ifdef CONFIG_HS20
|
||||||
srv.subscr_remediation_url = conf->subscr_remediation_url;
|
srv.subscr_remediation_url = conf->subscr_remediation_url;
|
||||||
srv.subscr_remediation_method = conf->subscr_remediation_method;
|
srv.subscr_remediation_method = conf->subscr_remediation_method;
|
||||||
|
srv.t_c_server_url = conf->t_c_server_url;
|
||||||
#endif /* CONFIG_HS20 */
|
#endif /* CONFIG_HS20 */
|
||||||
srv.erp = conf->eap_server_erp;
|
srv.erp = conf->eap_server_erp;
|
||||||
srv.erp_domain = conf->erp_domain;
|
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,
|
int hs20_send_wnm_notification_t_c(struct hostapd_data *hapd,
|
||||||
const u8 *addr)
|
const u8 *addr, const char *url)
|
||||||
{
|
{
|
||||||
struct wpabuf *buf;
|
struct wpabuf *buf;
|
||||||
int ret;
|
int ret;
|
||||||
const char *url = hapd->conf->t_c_server_url, *pos;
|
size_t url_len = os_strlen(url);
|
||||||
size_t url_len;
|
|
||||||
|
|
||||||
if (!url)
|
if (!url) {
|
||||||
return -1;
|
wpa_printf(MSG_INFO, "HS 2.0: No T&C Server URL available");
|
||||||
pos = os_strstr(url, "@1@");
|
|
||||||
if (!pos)
|
|
||||||
return -1;
|
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);
|
buf = wpabuf_alloc(4 + 7 + url_len);
|
||||||
if (!buf)
|
if (!buf)
|
||||||
return -1;
|
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_be24(buf, OUI_WFA);
|
||||||
wpabuf_put_u8(buf, HS20_WNM_T_C_ACCEPTANCE);
|
wpabuf_put_u8(buf, HS20_WNM_T_C_ACCEPTANCE);
|
||||||
wpabuf_put_u8(buf, url_len);
|
wpabuf_put_u8(buf, url_len);
|
||||||
wpabuf_put_data(buf, url, pos - url);
|
wpabuf_put_str(buf, url);
|
||||||
wpabuf_printf(buf, MACSTR, MAC2STR(addr));
|
|
||||||
wpabuf_put_str(buf, pos + 3);
|
|
||||||
|
|
||||||
ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr,
|
ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr,
|
||||||
wpabuf_head(buf), wpabuf_len(buf));
|
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 u8 *addr,
|
||||||
const struct wpabuf *payload);
|
const struct wpabuf *payload);
|
||||||
int hs20_send_wnm_notification_t_c(struct hostapd_data *hapd,
|
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,
|
void hs20_t_c_filtering(struct hostapd_data *hapd, struct sta_info *sta,
|
||||||
int enabled);
|
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));
|
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 */
|
#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:
|
case RADIUS_VENDOR_ATTR_WFA_HS20_T_C_FILTERING:
|
||||||
ieee802_1x_hs20_t_c_filtering(hapd, sta, pos, sublen);
|
ieee802_1x_hs20_t_c_filtering(hapd, sta, pos, sublen);
|
||||||
break;
|
break;
|
||||||
|
case RADIUS_VENDOR_ATTR_WFA_HS20_T_C_URL:
|
||||||
|
ieee802_1x_hs20_t_c_url(hapd, sta, pos, sublen);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_HS20 */
|
#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 "
|
wpa_printf(MSG_DEBUG, "HS 2.0: Send WNM-Notification to "
|
||||||
MACSTR " to indicate Terms and Conditions filtering",
|
MACSTR " to indicate Terms and Conditions filtering",
|
||||||
MAC2STR(sta->addr));
|
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 */
|
#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->identity);
|
||||||
os_free(sta->radius_cui);
|
os_free(sta->radius_cui);
|
||||||
os_free(sta->remediation_url);
|
os_free(sta->remediation_url);
|
||||||
|
os_free(sta->t_c_url);
|
||||||
wpabuf_free(sta->hs20_deauth_req);
|
wpabuf_free(sta->hs20_deauth_req);
|
||||||
os_free(sta->hs20_session_info_url);
|
os_free(sta->hs20_session_info_url);
|
||||||
|
|
||||||
|
|
|
@ -187,6 +187,7 @@ struct sta_info {
|
||||||
struct wpabuf *roaming_consortium;
|
struct wpabuf *roaming_consortium;
|
||||||
u8 remediation_method;
|
u8 remediation_method;
|
||||||
char *remediation_url; /* HS 2.0 Subscription Remediation Server URL */
|
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;
|
struct wpabuf *hs20_deauth_req;
|
||||||
char *hs20_session_info_url;
|
char *hs20_session_info_url;
|
||||||
int hs20_disassoc_timer;
|
int hs20_disassoc_timer;
|
||||||
|
|
|
@ -202,6 +202,7 @@ enum {
|
||||||
RADIUS_VENDOR_ATTR_WFA_HS20_T_C_FILENAME = 7,
|
RADIUS_VENDOR_ATTR_WFA_HS20_T_C_FILENAME = 7,
|
||||||
RADIUS_VENDOR_ATTR_WFA_HS20_TIMESTAMP = 8,
|
RADIUS_VENDOR_ATTR_WFA_HS20_TIMESTAMP = 8,
|
||||||
RADIUS_VENDOR_ATTR_WFA_HS20_T_C_FILTERING = 9,
|
RADIUS_VENDOR_ATTR_WFA_HS20_T_C_FILTERING = 9,
|
||||||
|
RADIUS_VENDOR_ATTR_WFA_HS20_T_C_URL = 10,
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
|
|
|
@ -350,6 +350,8 @@ struct radius_server_data {
|
||||||
char *subscr_remediation_url;
|
char *subscr_remediation_url;
|
||||||
u8 subscr_remediation_method;
|
u8 subscr_remediation_method;
|
||||||
|
|
||||||
|
char *t_c_server_url;
|
||||||
|
|
||||||
#ifdef CONFIG_SQLITE
|
#ifdef CONFIG_SQLITE
|
||||||
sqlite3 *db;
|
sqlite3 *db;
|
||||||
#endif /* CONFIG_SQLITE */
|
#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) {
|
if (code == RADIUS_CODE_ACCESS_ACCEPT && sess->t_c_filtering) {
|
||||||
u8 buf[4] = { 0x01, 0x00, 0x00, 0x00 }; /* E=1 */
|
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(
|
if (!radius_msg_add_wfa(
|
||||||
msg, RADIUS_VENDOR_ATTR_WFA_HS20_T_C_FILTERING,
|
msg, RADIUS_VENDOR_ATTR_WFA_HS20_T_C_FILTERING,
|
||||||
buf, sizeof(buf))) {
|
buf, sizeof(buf))) {
|
||||||
RADIUS_DEBUG("Failed to add WFA-HS20-T-C-Filtering");
|
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);
|
radius_srv_hs20_t_c_pending(sess);
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_HS20 */
|
#endif /* CONFIG_HS20 */
|
||||||
|
@ -1894,6 +1940,9 @@ radius_server_init(struct radius_server_conf *conf)
|
||||||
}
|
}
|
||||||
data->subscr_remediation_method = conf->subscr_remediation_method;
|
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
|
#ifdef CONFIG_SQLITE
|
||||||
if (conf->sqlite_file) {
|
if (conf->sqlite_file) {
|
||||||
if (sqlite3_open(conf->sqlite_file, &data->db)) {
|
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);
|
os_free(data->dump_msk_file);
|
||||||
#endif /* CONFIG_RADIUS_TEST */
|
#endif /* CONFIG_RADIUS_TEST */
|
||||||
os_free(data->subscr_remediation_url);
|
os_free(data->subscr_remediation_url);
|
||||||
|
os_free(data->t_c_server_url);
|
||||||
|
|
||||||
#ifdef CONFIG_SQLITE
|
#ifdef CONFIG_SQLITE
|
||||||
if (data->db)
|
if (data->db)
|
||||||
|
|
|
@ -233,6 +233,8 @@ struct radius_server_conf {
|
||||||
|
|
||||||
char *subscr_remediation_url;
|
char *subscr_remediation_url;
|
||||||
u8 subscr_remediation_method;
|
u8 subscr_remediation_method;
|
||||||
|
|
||||||
|
char *t_c_server_url;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue