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:
Jouni Malinen 2009-02-06 21:39:32 +02:00 committed by Jouni Malinen
parent 745f8b664d
commit 915c1ba3c5
8 changed files with 121 additions and 35 deletions

View file

@ -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);
if (!sta) {
wpa_printf(MSG_DEBUG, "WPS UPnP: No matching STA found");
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);
}

View file

@ -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);

View file

@ -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);
}
}

View file

@ -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 */

View file

@ -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,14 +1349,31 @@ 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 */
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 "
"pending message available");
@ -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;

View file

@ -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);

View file

@ -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"

View file

@ -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);