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);
|
||||
os_free(hapd->wps->network_key);
|
||||
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);
|
||||
hapd->wps = NULL;
|
||||
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(
|
||||
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 sta_info *sta;
|
||||
struct upnp_pending_message *p;
|
||||
|
||||
wpa_printf(MSG_DEBUG, "WPS UPnP: PutWLANResponse ev_type=%d 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.
|
||||
*/
|
||||
|
||||
/* 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);
|
||||
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 "
|
||||
"on NewWLANEventMAC; try wildcard match");
|
||||
for (sta = hapd->sta_list; sta; sta = sta->next) {
|
||||
if (sta->eapol_sm &&
|
||||
sta->eapol_sm->eap == hapd->wps->pending_session)
|
||||
if (sta->eapol_sm && (sta->flags & WLAN_STA_WPS))
|
||||
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:
|
||||
eap_wsc_state(data, MSG);
|
||||
sm->method_pending = METHOD_PENDING_WAIT;
|
||||
sm->wps->pending_session = sm;
|
||||
eloop_cancel_timeout(eap_wsc_ext_reg_timeout, sm, data);
|
||||
eloop_register_timeout(5, 0, eap_wsc_ext_reg_timeout,
|
||||
sm, data);
|
||||
|
|
|
@ -320,3 +320,16 @@ struct wpabuf * wps_build_probe_req_ie(int pbc, struct wps_device_data *dev,
|
|||
|
||||
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;
|
||||
};
|
||||
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
|
@ -476,10 +490,8 @@ struct wps_context {
|
|||
|
||||
struct upnp_wps_device_sm *wps_upnp;
|
||||
|
||||
/* TODO: support multiple pending messages from UPnP PutWLANResponse */
|
||||
u8 upnp_msg_addr[ETH_ALEN];
|
||||
struct wpabuf *upnp_msg;
|
||||
void *pending_session;
|
||||
/* Pending messages from UPnP PutWLANResponse */
|
||||
struct upnp_pending_message *upnp_msgs;
|
||||
};
|
||||
|
||||
|
||||
|
@ -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_valid(unsigned int pin);
|
||||
unsigned int wps_generate_pin(void);
|
||||
void wps_free_pending_msgs(struct upnp_pending_message *msgs);
|
||||
|
||||
#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,
|
||||
struct wpabuf *msg)
|
||||
{
|
||||
|
@ -1324,13 +1349,30 @@ struct wpabuf * wps_registrar_get_msg(struct wps_data *wps,
|
|||
struct wpabuf *msg;
|
||||
|
||||
#ifdef CONFIG_WPS_UPNP
|
||||
if (wps->wps->wps_upnp && wps->wps->upnp_msg) {
|
||||
wpa_printf(MSG_DEBUG, "WPS: Use pending message from UPnP");
|
||||
msg = wps->wps->upnp_msg;
|
||||
wps->wps->upnp_msg = NULL;
|
||||
*op_code = WSC_MSG; /* FIX: ack/nack */
|
||||
wps->ext_reg = 1;
|
||||
return msg;
|
||||
if (wps->wps->wps_upnp) {
|
||||
struct upnp_pending_message *p, *prev = NULL;
|
||||
if (wps->ext_reg > 1)
|
||||
wps_registrar_free_pending_m2(wps->wps);
|
||||
p = wps->wps->upnp_msgs;
|
||||
/* TODO: check pending message MAC address */
|
||||
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) {
|
||||
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
|
||||
if (wps->wps->wps_upnp && attr.mac_addr) {
|
||||
/* Remove old pending messages when starting new run */
|
||||
wpabuf_free(wps->wps->upnp_msg);
|
||||
wps->wps->upnp_msg = NULL;
|
||||
wps_free_pending_msgs(wps->wps->upnp_msgs);
|
||||
wps->wps->upnp_msgs = NULL;
|
||||
|
||||
upnp_wps_device_send_wlan_event(
|
||||
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
|
||||
if (wps->wps->wps_upnp && wps->ext_reg && wps->state == RECV_M2D_ACK &&
|
||||
upnp_wps_subscribers(wps->wps->wps_upnp)) {
|
||||
if (wps->wps->upnp_msg)
|
||||
if (wps->wps->upnp_msgs)
|
||||
return WPS_CONTINUE;
|
||||
wpa_printf(MSG_DEBUG, "WPS: Wait for response from an "
|
||||
"external Registrar");
|
||||
|
@ -2055,8 +2097,10 @@ static enum wps_process_res wps_process_wsc_ack(struct wps_data *wps,
|
|||
#ifdef CONFIG_WPS_UPNP
|
||||
if (wps->wps->wps_upnp &&
|
||||
upnp_wps_subscribers(wps->wps->wps_upnp)) {
|
||||
if (wps->wps->upnp_msg)
|
||||
if (wps->wps->upnp_msgs)
|
||||
return WPS_CONTINUE;
|
||||
if (wps->ext_reg == 0)
|
||||
wps->ext_reg = 1;
|
||||
wpa_printf(MSG_DEBUG, "WPS: Wait for response from an "
|
||||
"external Registrar");
|
||||
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);
|
||||
|
||||
#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)) {
|
||||
struct wps_parse_attr attr;
|
||||
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_put_wlan_event_response)(
|
||||
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,
|
||||
const struct wpabuf *msg);
|
||||
int (*rx_req_reboot_ap)(void *priv, const struct wpabuf *msg);
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "eloop.h"
|
||||
#include "uuid.h"
|
||||
#include "httpread.h"
|
||||
#include "wps_defs.h"
|
||||
#include "wps_upnp.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;
|
||||
u8 macaddr[ETH_ALEN];
|
||||
int ev_type;
|
||||
int type;
|
||||
char *val;
|
||||
|
||||
/*
|
||||
|
@ -1020,17 +1021,17 @@ web_process_put_wlan_response(struct upnp_wps_device_sm *sm, char *data,
|
|||
os_free(val);
|
||||
if (ev_type == UPNP_WPS_WLANEVENT_TYPE_EAP) {
|
||||
struct wps_parse_attr attr;
|
||||
int type;
|
||||
if (wps_parse_msg(msg, &attr) < 0 ||
|
||||
attr.msg_type == NULL)
|
||||
type = -1;
|
||||
else
|
||||
type = *attr.msg_type;
|
||||
wpa_printf(MSG_DEBUG, "WPS UPnP: Message Type %d", type);
|
||||
}
|
||||
} else
|
||||
type = -1;
|
||||
if (!sm->ctx->rx_req_put_wlan_event_response ||
|
||||
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->"
|
||||
"rx_req_put_wlan_event_response");
|
||||
wpabuf_free(msg);
|
||||
|
|
Loading…
Reference in a new issue