aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJouni Malinen <jouni.malinen@atheros.com>2009-02-06 19:39:32 (GMT)
committerJouni Malinen <j@w1.fi>2009-02-08 10:37:24 (GMT)
commitd594afcd1aedaa5e171f0ab29d388f6a5d6d12e4 (patch)
treec9887313ceee4c259568a1bad31fcebd21d32035 /src
parentb8650ac71d001546a6475c4f22d081d754827823 (diff)
downloadhostap-06-d594afcd1aedaa5e171f0ab29d388f6a5d6d12e4.zip
hostap-06-d594afcd1aedaa5e171f0ab29d388f6a5d6d12e4.tar.gz
hostap-06-d594afcd1aedaa5e171f0ab29d388f6a5d6d12e4.tar.bz2
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. (cherry picked from commit 915c1ba3c575c32b9d31453b1a55b1a966f622bd)
Diffstat (limited to 'src')
-rw-r--r--src/eap_server/eap_wsc.c1
-rw-r--r--src/wps/wps.c13
-rw-r--r--src/wps/wps.h21
-rw-r--r--src/wps/wps_registrar.c77
-rw-r--r--src/wps/wps_upnp.h3
-rw-r--r--src/wps/wps_upnp_event.c1
-rw-r--r--src/wps/wps_upnp_web.c7
7 files changed, 102 insertions, 21 deletions
diff --git a/src/eap_server/eap_wsc.c b/src/eap_server/eap_wsc.c
index 097e8c4..3c17577 100644
--- a/src/eap_server/eap_wsc.c
+++ b/src/eap_server/eap_wsc.c
@@ -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);
diff --git a/src/wps/wps.c b/src/wps/wps.c
index 015eb07..395eba6 100644
--- a/src/wps/wps.c
+++ b/src/wps/wps.c
@@ -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);
+ }
+}
diff --git a/src/wps/wps.h b/src/wps/wps.h
index c42ce1e..e0f2b2d 100644
--- a/src/wps/wps.h
+++ b/src/wps/wps.h
@@ -333,6 +333,20 @@ union wps_event_data {
};
/**
+ * 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
*
* This data is stored at the higher layer Authenticator or Supplicant 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 */
diff --git a/src/wps/wps_registrar.c b/src/wps/wps_registrar.c
index de76a00..949f540 100644
--- a/src/wps/wps_registrar.c
+++ b/src/wps/wps_registrar.c
@@ -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;
diff --git a/src/wps/wps_upnp.h b/src/wps/wps_upnp.h
index 995a7f2..eb3397e 100644
--- a/src/wps/wps_upnp.h
+++ b/src/wps/wps_upnp.h
@@ -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);
diff --git a/src/wps/wps_upnp_event.c b/src/wps/wps_upnp_event.c
index 7470e61..f278f35 100644
--- a/src/wps/wps_upnp_event.c
+++ b/src/wps/wps_upnp_event.c
@@ -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"
diff --git a/src/wps/wps_upnp_web.c b/src/wps/wps_upnp_web.c
index 3e68672..241afaa 100644
--- a/src/wps/wps_upnp_web.c
+++ b/src/wps/wps_upnp_web.c
@@ -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);