WPS UPnP: Added support for multiple external Registrars
Allow more than one pending PutWLANMessage data to be stored (M2/M2D from multiple external Registrars) and drop pending M2/M2D messages when the Enrollee replies with M3.
This commit is contained in:
parent
745f8b664d
commit
915c1ba3c5
8 changed files with 121 additions and 35 deletions
|
@ -661,7 +661,7 @@ void hostapd_deinit_wps(struct hostapd_data *hapd)
|
||||||
wps_registrar_deinit(hapd->wps->registrar);
|
wps_registrar_deinit(hapd->wps->registrar);
|
||||||
os_free(hapd->wps->network_key);
|
os_free(hapd->wps->network_key);
|
||||||
wps_device_data_free(&hapd->wps->dev);
|
wps_device_data_free(&hapd->wps->dev);
|
||||||
wpabuf_free(hapd->wps->upnp_msg);
|
wps_free_pending_msgs(hapd->wps->upnp_msgs);
|
||||||
os_free(hapd->wps);
|
os_free(hapd->wps);
|
||||||
hapd->wps = NULL;
|
hapd->wps = NULL;
|
||||||
hostapd_wps_clear_ies(hapd);
|
hostapd_wps_clear_ies(hapd);
|
||||||
|
@ -855,10 +855,12 @@ static int hostapd_rx_req_del_sta_settings(void *priv,
|
||||||
|
|
||||||
static int hostapd_rx_req_put_wlan_event_response(
|
static int hostapd_rx_req_put_wlan_event_response(
|
||||||
void *priv, enum upnp_wps_wlanevent_type ev_type,
|
void *priv, enum upnp_wps_wlanevent_type ev_type,
|
||||||
const u8 *mac_addr, const struct wpabuf *msg)
|
const u8 *mac_addr, const struct wpabuf *msg,
|
||||||
|
enum wps_msg_type msg_type)
|
||||||
{
|
{
|
||||||
struct hostapd_data *hapd = priv;
|
struct hostapd_data *hapd = priv;
|
||||||
struct sta_info *sta;
|
struct sta_info *sta;
|
||||||
|
struct upnp_pending_message *p;
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "WPS UPnP: PutWLANResponse ev_type=%d mac_addr="
|
wpa_printf(MSG_DEBUG, "WPS UPnP: PutWLANResponse ev_type=%d mac_addr="
|
||||||
MACSTR, ev_type, MAC2STR(mac_addr));
|
MACSTR, ev_type, MAC2STR(mac_addr));
|
||||||
|
@ -875,11 +877,6 @@ static int hostapd_rx_req_put_wlan_event_response(
|
||||||
* server implementation for delivery to the peer.
|
* server implementation for delivery to the peer.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* TODO: support multiple pending UPnP messages */
|
|
||||||
os_memcpy(hapd->wps->upnp_msg_addr, mac_addr, ETH_ALEN);
|
|
||||||
wpabuf_free(hapd->wps->upnp_msg);
|
|
||||||
hapd->wps->upnp_msg = wpabuf_dup(msg);
|
|
||||||
|
|
||||||
sta = ap_get_sta(hapd, mac_addr);
|
sta = ap_get_sta(hapd, mac_addr);
|
||||||
if (!sta) {
|
if (!sta) {
|
||||||
/*
|
/*
|
||||||
|
@ -890,18 +887,26 @@ static int hostapd_rx_req_put_wlan_event_response(
|
||||||
wpa_printf(MSG_DEBUG, "WPS UPnP: No matching STA found based "
|
wpa_printf(MSG_DEBUG, "WPS UPnP: No matching STA found based "
|
||||||
"on NewWLANEventMAC; try wildcard match");
|
"on NewWLANEventMAC; try wildcard match");
|
||||||
for (sta = hapd->sta_list; sta; sta = sta->next) {
|
for (sta = hapd->sta_list; sta; sta = sta->next) {
|
||||||
if (sta->eapol_sm &&
|
if (sta->eapol_sm && (sta->flags & WLAN_STA_WPS))
|
||||||
sta->eapol_sm->eap == hapd->wps->pending_session)
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (sta)
|
|
||||||
return eapol_auth_eap_pending_cb(sta->eapol_sm,
|
|
||||||
hapd->wps->pending_session);
|
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "WPS UPnP: No matching STA found");
|
if (!sta) {
|
||||||
|
wpa_printf(MSG_DEBUG, "WPS UPnP: No matching STA found");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
p = os_zalloc(sizeof(*p));
|
||||||
|
if (p == NULL)
|
||||||
|
return -1;
|
||||||
|
os_memcpy(p->addr, sta->addr, ETH_ALEN);
|
||||||
|
p->msg = wpabuf_dup(msg);
|
||||||
|
p->type = msg_type;
|
||||||
|
p->next = hapd->wps->upnp_msgs;
|
||||||
|
hapd->wps->upnp_msgs = p;
|
||||||
|
|
||||||
|
return eapol_auth_eap_pending_cb(sta->eapol_sm, sta->eapol_sm->eap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -436,7 +436,6 @@ static void eap_wsc_process(struct eap_sm *sm, void *priv,
|
||||||
case WPS_PENDING:
|
case WPS_PENDING:
|
||||||
eap_wsc_state(data, MSG);
|
eap_wsc_state(data, MSG);
|
||||||
sm->method_pending = METHOD_PENDING_WAIT;
|
sm->method_pending = METHOD_PENDING_WAIT;
|
||||||
sm->wps->pending_session = sm;
|
|
||||||
eloop_cancel_timeout(eap_wsc_ext_reg_timeout, sm, data);
|
eloop_cancel_timeout(eap_wsc_ext_reg_timeout, sm, data);
|
||||||
eloop_register_timeout(5, 0, eap_wsc_ext_reg_timeout,
|
eloop_register_timeout(5, 0, eap_wsc_ext_reg_timeout,
|
||||||
sm, data);
|
sm, data);
|
||||||
|
|
|
@ -320,3 +320,16 @@ struct wpabuf * wps_build_probe_req_ie(int pbc, struct wps_device_data *dev,
|
||||||
|
|
||||||
return ie;
|
return ie;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void wps_free_pending_msgs(struct upnp_pending_message *msgs)
|
||||||
|
{
|
||||||
|
struct upnp_pending_message *p, *prev;
|
||||||
|
p = msgs;
|
||||||
|
while (p) {
|
||||||
|
prev = p;
|
||||||
|
p = p->next;
|
||||||
|
wpabuf_free(prev->msg);
|
||||||
|
os_free(prev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -332,6 +332,20 @@ union wps_event_data {
|
||||||
} pwd_auth_fail;
|
} pwd_auth_fail;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct upnp_pending_message - Pending PutWLANResponse messages
|
||||||
|
* @next: Pointer to next pending message or %NULL
|
||||||
|
* @addr: NewWLANEventMAC
|
||||||
|
* @msg: NewMessage
|
||||||
|
* @type: Message Type
|
||||||
|
*/
|
||||||
|
struct upnp_pending_message {
|
||||||
|
struct upnp_pending_message *next;
|
||||||
|
u8 addr[ETH_ALEN];
|
||||||
|
struct wpabuf *msg;
|
||||||
|
enum wps_msg_type type;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct wps_context - Long term WPS context data
|
* struct wps_context - Long term WPS context data
|
||||||
*
|
*
|
||||||
|
@ -476,10 +490,8 @@ struct wps_context {
|
||||||
|
|
||||||
struct upnp_wps_device_sm *wps_upnp;
|
struct upnp_wps_device_sm *wps_upnp;
|
||||||
|
|
||||||
/* TODO: support multiple pending messages from UPnP PutWLANResponse */
|
/* Pending messages from UPnP PutWLANResponse */
|
||||||
u8 upnp_msg_addr[ETH_ALEN];
|
struct upnp_pending_message *upnp_msgs;
|
||||||
struct wpabuf *upnp_msg;
|
|
||||||
void *pending_session;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -501,5 +513,6 @@ int wps_registrar_set_selected_registrar(struct wps_registrar *reg,
|
||||||
unsigned int wps_pin_checksum(unsigned int pin);
|
unsigned int wps_pin_checksum(unsigned int pin);
|
||||||
unsigned int wps_pin_valid(unsigned int pin);
|
unsigned int wps_pin_valid(unsigned int pin);
|
||||||
unsigned int wps_generate_pin(void);
|
unsigned int wps_generate_pin(void);
|
||||||
|
void wps_free_pending_msgs(struct upnp_pending_message *msgs);
|
||||||
|
|
||||||
#endif /* WPS_H */
|
#endif /* WPS_H */
|
||||||
|
|
|
@ -216,6 +216,31 @@ static int wps_build_wps_state(struct wps_context *wps, struct wpabuf *msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef CONFIG_WPS_UPNP
|
||||||
|
static void wps_registrar_free_pending_m2(struct wps_context *wps)
|
||||||
|
{
|
||||||
|
struct upnp_pending_message *p, *p2, *prev = NULL;
|
||||||
|
p = wps->upnp_msgs;
|
||||||
|
while (p) {
|
||||||
|
if (p->type == WPS_M2 || p->type == WPS_M2D) {
|
||||||
|
if (prev == NULL)
|
||||||
|
wps->upnp_msgs = p->next;
|
||||||
|
else
|
||||||
|
prev->next = p->next;
|
||||||
|
wpa_printf(MSG_DEBUG, "WPS UPnP: Drop pending M2/M2D");
|
||||||
|
p2 = p;
|
||||||
|
p = p->next;
|
||||||
|
wpabuf_free(p2->msg);
|
||||||
|
os_free(p2);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
prev = p;
|
||||||
|
p = p->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_WPS_UPNP */
|
||||||
|
|
||||||
|
|
||||||
static int wps_build_ap_setup_locked(struct wps_context *wps,
|
static int wps_build_ap_setup_locked(struct wps_context *wps,
|
||||||
struct wpabuf *msg)
|
struct wpabuf *msg)
|
||||||
{
|
{
|
||||||
|
@ -1324,13 +1349,30 @@ struct wpabuf * wps_registrar_get_msg(struct wps_data *wps,
|
||||||
struct wpabuf *msg;
|
struct wpabuf *msg;
|
||||||
|
|
||||||
#ifdef CONFIG_WPS_UPNP
|
#ifdef CONFIG_WPS_UPNP
|
||||||
if (wps->wps->wps_upnp && wps->wps->upnp_msg) {
|
if (wps->wps->wps_upnp) {
|
||||||
wpa_printf(MSG_DEBUG, "WPS: Use pending message from UPnP");
|
struct upnp_pending_message *p, *prev = NULL;
|
||||||
msg = wps->wps->upnp_msg;
|
if (wps->ext_reg > 1)
|
||||||
wps->wps->upnp_msg = NULL;
|
wps_registrar_free_pending_m2(wps->wps);
|
||||||
*op_code = WSC_MSG; /* FIX: ack/nack */
|
p = wps->wps->upnp_msgs;
|
||||||
wps->ext_reg = 1;
|
/* TODO: check pending message MAC address */
|
||||||
return msg;
|
while (p && p->next) {
|
||||||
|
prev = p;
|
||||||
|
p = p->next;
|
||||||
|
}
|
||||||
|
if (p) {
|
||||||
|
wpa_printf(MSG_DEBUG, "WPS: Use pending message from "
|
||||||
|
"UPnP");
|
||||||
|
if (prev)
|
||||||
|
prev->next = NULL;
|
||||||
|
else
|
||||||
|
wps->wps->upnp_msgs = NULL;
|
||||||
|
msg = p->msg;
|
||||||
|
os_free(p);
|
||||||
|
*op_code = WSC_MSG;
|
||||||
|
if (wps->ext_reg == 0)
|
||||||
|
wps->ext_reg = 1;
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (wps->ext_reg) {
|
if (wps->ext_reg) {
|
||||||
wpa_printf(MSG_DEBUG, "WPS: Using external Registrar, but no "
|
wpa_printf(MSG_DEBUG, "WPS: Using external Registrar, but no "
|
||||||
|
@ -1958,8 +2000,8 @@ static enum wps_process_res wps_process_wsc_msg(struct wps_data *wps,
|
||||||
#ifdef CONFIG_WPS_UPNP
|
#ifdef CONFIG_WPS_UPNP
|
||||||
if (wps->wps->wps_upnp && attr.mac_addr) {
|
if (wps->wps->wps_upnp && attr.mac_addr) {
|
||||||
/* Remove old pending messages when starting new run */
|
/* Remove old pending messages when starting new run */
|
||||||
wpabuf_free(wps->wps->upnp_msg);
|
wps_free_pending_msgs(wps->wps->upnp_msgs);
|
||||||
wps->wps->upnp_msg = NULL;
|
wps->wps->upnp_msgs = NULL;
|
||||||
|
|
||||||
upnp_wps_device_send_wlan_event(
|
upnp_wps_device_send_wlan_event(
|
||||||
wps->wps->wps_upnp, attr.mac_addr,
|
wps->wps->wps_upnp, attr.mac_addr,
|
||||||
|
@ -2030,7 +2072,7 @@ static enum wps_process_res wps_process_wsc_ack(struct wps_data *wps,
|
||||||
#ifdef CONFIG_WPS_UPNP
|
#ifdef CONFIG_WPS_UPNP
|
||||||
if (wps->wps->wps_upnp && wps->ext_reg && wps->state == RECV_M2D_ACK &&
|
if (wps->wps->wps_upnp && wps->ext_reg && wps->state == RECV_M2D_ACK &&
|
||||||
upnp_wps_subscribers(wps->wps->wps_upnp)) {
|
upnp_wps_subscribers(wps->wps->wps_upnp)) {
|
||||||
if (wps->wps->upnp_msg)
|
if (wps->wps->upnp_msgs)
|
||||||
return WPS_CONTINUE;
|
return WPS_CONTINUE;
|
||||||
wpa_printf(MSG_DEBUG, "WPS: Wait for response from an "
|
wpa_printf(MSG_DEBUG, "WPS: Wait for response from an "
|
||||||
"external Registrar");
|
"external Registrar");
|
||||||
|
@ -2055,8 +2097,10 @@ static enum wps_process_res wps_process_wsc_ack(struct wps_data *wps,
|
||||||
#ifdef CONFIG_WPS_UPNP
|
#ifdef CONFIG_WPS_UPNP
|
||||||
if (wps->wps->wps_upnp &&
|
if (wps->wps->wps_upnp &&
|
||||||
upnp_wps_subscribers(wps->wps->wps_upnp)) {
|
upnp_wps_subscribers(wps->wps->wps_upnp)) {
|
||||||
if (wps->wps->upnp_msg)
|
if (wps->wps->upnp_msgs)
|
||||||
return WPS_CONTINUE;
|
return WPS_CONTINUE;
|
||||||
|
if (wps->ext_reg == 0)
|
||||||
|
wps->ext_reg = 1;
|
||||||
wpa_printf(MSG_DEBUG, "WPS: Wait for response from an "
|
wpa_printf(MSG_DEBUG, "WPS: Wait for response from an "
|
||||||
"external Registrar");
|
"external Registrar");
|
||||||
return WPS_PENDING;
|
return WPS_PENDING;
|
||||||
|
@ -2278,7 +2322,16 @@ enum wps_process_res wps_registrar_process_msg(struct wps_data *wps,
|
||||||
(unsigned long) wpabuf_len(msg), op_code);
|
(unsigned long) wpabuf_len(msg), op_code);
|
||||||
|
|
||||||
#ifdef CONFIG_WPS_UPNP
|
#ifdef CONFIG_WPS_UPNP
|
||||||
if (wps->wps->wps_upnp && wps->ext_reg && wps->wps->upnp_msg == NULL &&
|
if (wps->wps->wps_upnp && op_code == WSC_MSG && wps->ext_reg == 1) {
|
||||||
|
struct wps_parse_attr attr;
|
||||||
|
if (wps_parse_msg(msg, &attr) == 0 && attr.msg_type &&
|
||||||
|
*attr.msg_type == WPS_M3)
|
||||||
|
wps->ext_reg = 2; /* past M2/M2D phase */
|
||||||
|
}
|
||||||
|
if (wps->ext_reg > 1)
|
||||||
|
wps_registrar_free_pending_m2(wps->wps);
|
||||||
|
if (wps->wps->wps_upnp && wps->ext_reg &&
|
||||||
|
wps->wps->upnp_msgs == NULL &&
|
||||||
(op_code == WSC_MSG || op_code == WSC_Done)) {
|
(op_code == WSC_MSG || op_code == WSC_Done)) {
|
||||||
struct wps_parse_attr attr;
|
struct wps_parse_attr attr;
|
||||||
int type;
|
int type;
|
||||||
|
|
|
@ -40,7 +40,8 @@ struct upnp_wps_device_ctx {
|
||||||
int (*rx_req_del_sta_settings)(void *priv, const struct wpabuf *msg);
|
int (*rx_req_del_sta_settings)(void *priv, const struct wpabuf *msg);
|
||||||
int (*rx_req_put_wlan_event_response)(
|
int (*rx_req_put_wlan_event_response)(
|
||||||
void *priv, enum upnp_wps_wlanevent_type ev_type,
|
void *priv, enum upnp_wps_wlanevent_type ev_type,
|
||||||
const u8 *mac_addr, const struct wpabuf *msg);
|
const u8 *mac_addr, const struct wpabuf *msg,
|
||||||
|
enum wps_msg_type msg_type);
|
||||||
int (*rx_req_set_selected_registrar)(void *priv,
|
int (*rx_req_set_selected_registrar)(void *priv,
|
||||||
const struct wpabuf *msg);
|
const struct wpabuf *msg);
|
||||||
int (*rx_req_reboot_ap)(void *priv, const struct wpabuf *msg);
|
int (*rx_req_reboot_ap)(void *priv, const struct wpabuf *msg);
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include "eloop.h"
|
#include "eloop.h"
|
||||||
#include "uuid.h"
|
#include "uuid.h"
|
||||||
#include "httpread.h"
|
#include "httpread.h"
|
||||||
|
#include "wps_defs.h"
|
||||||
#include "wps_upnp.h"
|
#include "wps_upnp.h"
|
||||||
#include "wps_upnp_i.h"
|
#include "wps_upnp_i.h"
|
||||||
|
|
||||||
|
|
|
@ -993,6 +993,7 @@ web_process_put_wlan_response(struct upnp_wps_device_sm *sm, char *data,
|
||||||
enum http_reply_code ret;
|
enum http_reply_code ret;
|
||||||
u8 macaddr[ETH_ALEN];
|
u8 macaddr[ETH_ALEN];
|
||||||
int ev_type;
|
int ev_type;
|
||||||
|
int type;
|
||||||
char *val;
|
char *val;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1020,17 +1021,17 @@ web_process_put_wlan_response(struct upnp_wps_device_sm *sm, char *data,
|
||||||
os_free(val);
|
os_free(val);
|
||||||
if (ev_type == UPNP_WPS_WLANEVENT_TYPE_EAP) {
|
if (ev_type == UPNP_WPS_WLANEVENT_TYPE_EAP) {
|
||||||
struct wps_parse_attr attr;
|
struct wps_parse_attr attr;
|
||||||
int type;
|
|
||||||
if (wps_parse_msg(msg, &attr) < 0 ||
|
if (wps_parse_msg(msg, &attr) < 0 ||
|
||||||
attr.msg_type == NULL)
|
attr.msg_type == NULL)
|
||||||
type = -1;
|
type = -1;
|
||||||
else
|
else
|
||||||
type = *attr.msg_type;
|
type = *attr.msg_type;
|
||||||
wpa_printf(MSG_DEBUG, "WPS UPnP: Message Type %d", type);
|
wpa_printf(MSG_DEBUG, "WPS UPnP: Message Type %d", type);
|
||||||
}
|
} else
|
||||||
|
type = -1;
|
||||||
if (!sm->ctx->rx_req_put_wlan_event_response ||
|
if (!sm->ctx->rx_req_put_wlan_event_response ||
|
||||||
sm->ctx->rx_req_put_wlan_event_response(sm->priv, ev_type,
|
sm->ctx->rx_req_put_wlan_event_response(sm->priv, ev_type,
|
||||||
macaddr, msg)) {
|
macaddr, msg, type)) {
|
||||||
wpa_printf(MSG_INFO, "WPS UPnP: Fail: sm->ctx->"
|
wpa_printf(MSG_INFO, "WPS UPnP: Fail: sm->ctx->"
|
||||||
"rx_req_put_wlan_event_response");
|
"rx_req_put_wlan_event_response");
|
||||||
wpabuf_free(msg);
|
wpabuf_free(msg);
|
||||||
|
|
Loading…
Reference in a new issue