Cumulative patch from commit 848905b12abf2df650c43cb821d36a13246baacb
848905b Avoid undefined references with CONFIG_WPA_TRACE_BFD=y
9e38836 wpa_debug: Remove 2048 byte message length limit
f667e03 P2P: Address few issues seen with P2P SD
e9a6f18 TLS: Add tls_disable_tlsv1_1 and tls_disable_tlsv1_2 phase1 params
cb10c7d RADIUS DAS: Add support for NAS identification attributes
0d7c5e1 RADIUS DAS: Remove PMKSA entry on Disconnect-Request
d87a6ac WPS: Fix STA state validation when processing PutWLANResponse
Change-Id: I4799cad2fe661db567eb3a92af2b3eefb7c96dab
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index f9edf3b..98148da 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -529,7 +529,34 @@
static int hostapd_das_nas_mismatch(struct hostapd_data *hapd,
struct radius_das_attrs *attr)
{
- /* TODO */
+ if (attr->nas_identifier &&
+ (!hapd->conf->nas_identifier ||
+ os_strlen(hapd->conf->nas_identifier) !=
+ attr->nas_identifier_len ||
+ os_memcmp(hapd->conf->nas_identifier, attr->nas_identifier,
+ attr->nas_identifier_len) != 0)) {
+ wpa_printf(MSG_DEBUG, "RADIUS DAS: NAS-Identifier mismatch");
+ return 1;
+ }
+
+ if (attr->nas_ip_addr &&
+ (hapd->conf->own_ip_addr.af != AF_INET ||
+ os_memcmp(&hapd->conf->own_ip_addr.u.v4, attr->nas_ip_addr, 4) !=
+ 0)) {
+ wpa_printf(MSG_DEBUG, "RADIUS DAS: NAS-IP-Address mismatch");
+ return 1;
+ }
+
+#ifdef CONFIG_IPV6
+ if (attr->nas_ipv6_addr &&
+ (hapd->conf->own_ip_addr.af != AF_INET6 ||
+ os_memcmp(&hapd->conf->own_ip_addr.u.v6, attr->nas_ipv6_addr, 16)
+ != 0)) {
+ wpa_printf(MSG_DEBUG, "RADIUS DAS: NAS-IPv6-Address mismatch");
+ return 1;
+ }
+#endif /* CONFIG_IPV6 */
+
return 0;
}
@@ -596,6 +623,8 @@
if (sta == NULL)
return RADIUS_DAS_SESSION_NOT_FOUND;
+ wpa_auth_pmksa_remove(hapd->wpa_auth, sta->addr);
+
hostapd_drv_sta_deauth(hapd, sta->addr,
WLAN_REASON_PREV_AUTH_NOT_VALID);
ap_sta_deauthenticate(hapd, sta, WLAN_REASON_PREV_AUTH_NOT_VALID);
diff --git a/src/ap/wps_hostapd.c b/src/ap/wps_hostapd.c
index 8aafa63..3a40125 100644
--- a/src/ap/wps_hostapd.c
+++ b/src/ap/wps_hostapd.c
@@ -1479,6 +1479,16 @@
return 0;
}
+ if (!sta->eapol_sm) {
+ /*
+ * This can happen, e.g., if an ER sends an extra message after
+ * the station has disassociated (but not fully
+ * deauthenticated).
+ */
+ wpa_printf(MSG_DEBUG, "WPS UPnP: Matching STA did not have EAPOL state machine initialized");
+ return 0;
+ }
+
p = os_zalloc(sizeof(*p));
if (p == NULL)
return -1;
diff --git a/src/crypto/tls.h b/src/crypto/tls.h
index feba13f..88afae4 100644
--- a/src/crypto/tls.h
+++ b/src/crypto/tls.h
@@ -85,6 +85,8 @@
#define TLS_CONN_DISABLE_SESSION_TICKET BIT(2)
#define TLS_CONN_REQUEST_OCSP BIT(3)
#define TLS_CONN_REQUIRE_OCSP BIT(4)
+#define TLS_CONN_DISABLE_TLSv1_1 BIT(5)
+#define TLS_CONN_DISABLE_TLSv1_2 BIT(6)
/**
* struct tls_connection_params - Parameters for TLS connection
diff --git a/src/crypto/tls_openssl.c b/src/crypto/tls_openssl.c
index 2fd7bbb..0b4e267 100644
--- a/src/crypto/tls_openssl.c
+++ b/src/crypto/tls_openssl.c
@@ -3182,6 +3182,19 @@
#endif /* SSL_clear_options */
#endif /* SSL_OP_NO_TICKET */
+#ifdef SSL_OP_NO_TLSv1_1
+ if (params->flags & TLS_CONN_DISABLE_TLSv1_1)
+ SSL_set_options(conn->ssl, SSL_OP_NO_TLSv1_1);
+ else
+ SSL_clear_options(conn->ssl, SSL_OP_NO_TLSv1_1);
+#endif /* SSL_OP_NO_TLSv1_1 */
+#ifdef SSL_OP_NO_TLSv1_2
+ if (params->flags & TLS_CONN_DISABLE_TLSv1_2)
+ SSL_set_options(conn->ssl, SSL_OP_NO_TLSv1_2);
+ else
+ SSL_clear_options(conn->ssl, SSL_OP_NO_TLSv1_2);
+#endif /* SSL_OP_NO_TLSv1_2 */
+
#ifdef HAVE_OCSP
if (params->flags & TLS_CONN_REQUEST_OCSP) {
SSL_CTX *ssl_ctx = tls_ctx;
diff --git a/src/eap_peer/eap_tls_common.c b/src/eap_peer/eap_tls_common.c
index 008af37..b3a99b6 100644
--- a/src/eap_peer/eap_tls_common.c
+++ b/src/eap_peer/eap_tls_common.c
@@ -64,6 +64,14 @@
params->flags |= TLS_CONN_DISABLE_SESSION_TICKET;
if (os_strstr(txt, "tls_disable_session_ticket=0"))
params->flags &= ~TLS_CONN_DISABLE_SESSION_TICKET;
+ if (os_strstr(txt, "tls_disable_tlsv1_1=1"))
+ params->flags |= TLS_CONN_DISABLE_TLSv1_1;
+ if (os_strstr(txt, "tls_disable_tlsv1_1=0"))
+ params->flags &= ~TLS_CONN_DISABLE_TLSv1_1;
+ if (os_strstr(txt, "tls_disable_tlsv1_2=1"))
+ params->flags |= TLS_CONN_DISABLE_TLSv1_2;
+ if (os_strstr(txt, "tls_disable_tlsv1_2=0"))
+ params->flags &= ~TLS_CONN_DISABLE_TLSv1_2;
}
diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c
index 2ecc547..7170e47 100644
--- a/src/p2p/p2p.c
+++ b/src/p2p/p2p.c
@@ -733,9 +733,6 @@
p2p_parse_free(&msg);
- if (p2p_pending_sd_req(p2p, dev))
- dev->flags |= P2P_DEV_SD_SCHEDULE;
-
if (dev->flags & P2P_DEV_REPORTED)
return 0;
@@ -2406,6 +2403,7 @@
p2p->go_timeout = 100;
p2p->client_timeout = 20;
+ p2p->num_p2p_sd_queries = 0;
p2p_dbg(p2p, "initialized");
p2p_channels_dump(p2p, "channels", &p2p->cfg->channels);
@@ -2641,13 +2639,16 @@
struct p2p_device *dev;
p2p_set_state(p2p, P2P_SEARCH);
dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
- if (dev->flags & P2P_DEV_SD_SCHEDULE) {
- if (p2p_start_sd(p2p, dev) == 0)
- return;
- else
- break;
- } else if (dev->req_config_methods &&
- !(dev->flags & P2P_DEV_PD_FOR_JOIN)) {
+ if (dev->sd_pending_bcast_queries == 0) {
+ /* Initialize with total number of registered broadcast
+ * SD queries. */
+ dev->sd_pending_bcast_queries = p2p->num_p2p_sd_queries;
+ }
+
+ if (p2p_start_sd(p2p, dev) == 0)
+ return;
+ if (dev->req_config_methods &&
+ !(dev->flags & P2P_DEV_PD_FOR_JOIN)) {
p2p_dbg(p2p, "Send pending Provision Discovery Request to "
MACSTR " (config methods 0x%x)",
MAC2STR(dev->info.p2p_device_addr),
@@ -2668,10 +2669,7 @@
p2p->pending_action_state = P2P_NO_PENDING_ACTION;
if (!success) {
- if (p2p->sd_peer) {
- p2p->sd_peer->flags &= ~P2P_DEV_SD_SCHEDULE;
- p2p->sd_peer = NULL;
- }
+ p2p->sd_peer = NULL;
p2p_continue_find(p2p);
return;
}
@@ -3216,7 +3214,6 @@
p2p_dbg(p2p, "Service Discovery Query timeout");
if (p2p->sd_peer) {
p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
- p2p->sd_peer->flags &= ~P2P_DEV_SD_SCHEDULE;
p2p->sd_peer = NULL;
}
p2p_continue_find(p2p);
@@ -3487,7 +3484,7 @@
"country=%c%c\n"
"oper_freq=%d\n"
"req_config_methods=0x%x\n"
- "flags=%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n"
+ "flags=%s%s%s%s%s%s%s%s%s%s%s%s%s\n"
"status=%d\n"
"wait_count=%u\n"
"invitation_reqs=%u\n",
@@ -3510,9 +3507,6 @@
dev->flags & P2P_DEV_REPORTED ? "[REPORTED]" : "",
dev->flags & P2P_DEV_NOT_YET_READY ?
"[NOT_YET_READY]" : "",
- dev->flags & P2P_DEV_SD_INFO ? "[SD_INFO]" : "",
- dev->flags & P2P_DEV_SD_SCHEDULE ? "[SD_SCHEDULE]" :
- "",
dev->flags & P2P_DEV_PD_PEER_DISPLAY ?
"[PD_PEER_DISPLAY]" : "",
dev->flags & P2P_DEV_PD_PEER_KEYPAD ?
diff --git a/src/p2p/p2p_i.h b/src/p2p/p2p_i.h
index f105083..6de3461 100644
--- a/src/p2p/p2p_i.h
+++ b/src/p2p/p2p_i.h
@@ -81,8 +81,6 @@
#define P2P_DEV_PROBE_REQ_ONLY BIT(0)
#define P2P_DEV_REPORTED BIT(1)
#define P2P_DEV_NOT_YET_READY BIT(2)
-#define P2P_DEV_SD_INFO BIT(3)
-#define P2P_DEV_SD_SCHEDULE BIT(4)
#define P2P_DEV_PD_PEER_DISPLAY BIT(5)
#define P2P_DEV_PD_PEER_KEYPAD BIT(6)
#define P2P_DEV_USER_REJECTED BIT(7)
@@ -110,6 +108,7 @@
u8 go_timeout;
u8 client_timeout;
+ int sd_pending_bcast_queries;
};
struct p2p_sd_query {
@@ -256,6 +255,12 @@
*/
struct p2p_sd_query *sd_query;
+ /**
+ * num_p2p_sd_queries - Total number of broadcast SD queries present in
+ * the list
+ */
+ int num_p2p_sd_queries;
+
/* GO Negotiation data */
/**
diff --git a/src/p2p/p2p_sd.c b/src/p2p/p2p_sd.c
index 0e0c7f1..26b9c2d 100644
--- a/src/p2p/p2p_sd.c
+++ b/src/p2p/p2p_sd.c
@@ -52,6 +52,7 @@
{
struct p2p_sd_query *q;
int wsd = 0;
+ int count = 0;
if (!(dev->info.dev_capab & P2P_DEV_CAPAB_SERVICE_DISCOVERY))
return NULL; /* peer does not support SD */
@@ -64,8 +65,19 @@
/* Use WSD only if the peer indicates support or it */
if (q->wsd && !wsd)
continue;
- if (q->for_all_peers && !(dev->flags & P2P_DEV_SD_INFO))
- return q;
+ /* if the query is a broadcast query */
+ if (q->for_all_peers) {
+ /*
+ * check if there are any broadcast queries pending for
+ * this device
+ */
+ if (dev->sd_pending_bcast_queries <= 0)
+ return NULL;
+ /* query number that needs to be send to the device */
+ if (count == dev->sd_pending_bcast_queries - 1)
+ return q;
+ count++;
+ }
if (!q->for_all_peers &&
os_memcmp(q->peer, dev->info.p2p_device_addr, ETH_ALEN) ==
0)
@@ -76,14 +88,37 @@
}
+static void p2p_decrease_sd_bc_queries(struct p2p_data *p2p, int query_number)
+{
+ struct p2p_device *dev;
+
+ p2p->num_p2p_sd_queries--;
+ dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
+ if (query_number <= dev->sd_pending_bcast_queries - 1) {
+ /*
+ * Query not yet sent to the device and it is to be
+ * removed, so update the pending count.
+ */
+ dev->sd_pending_bcast_queries--;
+ }
+ }
+}
+
+
static int p2p_unlink_sd_query(struct p2p_data *p2p,
struct p2p_sd_query *query)
{
struct p2p_sd_query *q, *prev;
+ int query_number = 0;
+
q = p2p->sd_queries;
prev = NULL;
while (q) {
if (q == query) {
+ /* If the query is a broadcast query, decrease one from
+ * all the devices */
+ if (query->for_all_peers)
+ p2p_decrease_sd_bc_queries(p2p, query_number);
if (prev)
prev->next = q->next;
else
@@ -92,6 +127,8 @@
p2p->sd_query = NULL;
return 1;
}
+ if (q->for_all_peers)
+ query_number++;
prev = q;
q = q->next;
}
@@ -118,6 +155,7 @@
q = q->next;
p2p_free_sd_query(prev);
}
+ p2p->num_p2p_sd_queries = 0;
}
@@ -262,6 +300,16 @@
ret = -1;
}
+ /* Update the pending broadcast SD query count for this device */
+ dev->sd_pending_bcast_queries--;
+
+ /*
+ * If there are no pending broadcast queries for this device, mark it as
+ * done (-1).
+ */
+ if (dev->sd_pending_bcast_queries == 0)
+ dev->sd_pending_bcast_queries = -1;
+
wpabuf_free(req);
return ret;
@@ -541,8 +589,6 @@
p2p_dbg(p2p, "Service Update Indicator: %u", update_indic);
pos += 2;
- p2p->sd_peer->flags |= P2P_DEV_SD_INFO;
- p2p->sd_peer->flags &= ~P2P_DEV_SD_SCHEDULE;
p2p->sd_peer = NULL;
if (p2p->sd_query) {
@@ -787,8 +833,6 @@
return;
}
- p2p->sd_peer->flags |= P2P_DEV_SD_INFO;
- p2p->sd_peer->flags &= ~P2P_DEV_SD_SCHEDULE;
p2p->sd_peer = NULL;
if (p2p->sd_query) {
@@ -841,8 +885,16 @@
if (dst == NULL) {
struct p2p_device *dev;
- dl_list_for_each(dev, &p2p->devices, struct p2p_device, list)
- dev->flags &= ~P2P_DEV_SD_INFO;
+
+ p2p->num_p2p_sd_queries++;
+
+ /* Update all the devices for the newly added broadcast query */
+ dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
+ if (dev->sd_pending_bcast_queries <= 0)
+ dev->sd_pending_bcast_queries = 1;
+ else
+ dev->sd_pending_bcast_queries++;
+ }
}
return q;
diff --git a/src/radius/radius_das.c b/src/radius/radius_das.c
index b2a2773..9655f4c 100644
--- a/src/radius/radius_das.c
+++ b/src/radius/radius_das.c
@@ -38,11 +38,16 @@
struct radius_msg *reply;
u8 allowed[] = {
RADIUS_ATTR_USER_NAME,
+ RADIUS_ATTR_NAS_IP_ADDRESS,
RADIUS_ATTR_CALLING_STATION_ID,
+ RADIUS_ATTR_NAS_IDENTIFIER,
RADIUS_ATTR_ACCT_SESSION_ID,
RADIUS_ATTR_EVENT_TIMESTAMP,
RADIUS_ATTR_MESSAGE_AUTHENTICATOR,
RADIUS_ATTR_CHARGEABLE_USER_IDENTITY,
+#ifdef CONFIG_IPV6
+ RADIUS_ATTR_NAS_IPV6_ADDRESS,
+#endif /* CONFIG_IPV6 */
0
};
int error = 405;
@@ -67,6 +72,36 @@
os_memset(&attrs, 0, sizeof(attrs));
+ if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_NAS_IP_ADDRESS,
+ &buf, &len, NULL) == 0) {
+ if (len != 4) {
+ wpa_printf(MSG_INFO, "DAS: Invalid NAS-IP-Address from %s:%d",
+ abuf, from_port);
+ error = 407;
+ goto fail;
+ }
+ attrs.nas_ip_addr = buf;
+ }
+
+#ifdef CONFIG_IPV6
+ if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_NAS_IPV6_ADDRESS,
+ &buf, &len, NULL) == 0) {
+ if (len != 16) {
+ wpa_printf(MSG_INFO, "DAS: Invalid NAS-IPv6-Address from %s:%d",
+ abuf, from_port);
+ error = 407;
+ goto fail;
+ }
+ attrs.nas_ipv6_addr = buf;
+ }
+#endif /* CONFIG_IPV6 */
+
+ if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_NAS_IDENTIFIER,
+ &buf, &len, NULL) == 0) {
+ attrs.nas_identifier = buf;
+ attrs.nas_identifier_len = len;
+ }
+
if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_CALLING_STATION_ID,
&buf, &len, NULL) == 0) {
if (len >= sizeof(tmp))
diff --git a/src/radius/radius_das.h b/src/radius/radius_das.h
index 738b18b..e3ed540 100644
--- a/src/radius/radius_das.h
+++ b/src/radius/radius_das.h
@@ -18,6 +18,13 @@
};
struct radius_das_attrs {
+ /* NAS identification attributes */
+ const u8 *nas_ip_addr;
+ const u8 *nas_identifier;
+ size_t nas_identifier_len;
+ const u8 *nas_ipv6_addr;
+
+ /* Session identification attributes */
const u8 *sta_addr;
const u8 *user_name;
size_t user_name_len;
diff --git a/src/utils/wpa_debug.c b/src/utils/wpa_debug.c
index 7846c1e..647f6b4 100644
--- a/src/utils/wpa_debug.c
+++ b/src/utils/wpa_debug.c
@@ -596,10 +596,14 @@
{
va_list ap;
char *buf;
- const int buflen = 2048;
+ int buflen;
int len;
char prefix[130];
+ va_start(ap, fmt);
+ buflen = vsnprintf(NULL, 0, fmt, ap) + 1;
+ va_end(ap);
+
buf = os_malloc(buflen);
if (buf == NULL) {
wpa_printf(MSG_ERROR, "wpa_msg: Failed to allocate message "
@@ -630,12 +634,16 @@
{
va_list ap;
char *buf;
- const int buflen = 2048;
+ int buflen;
int len;
if (!wpa_msg_cb)
return;
+ va_start(ap, fmt);
+ buflen = vsnprintf(NULL, 0, fmt, ap) + 1;
+ va_end(ap);
+
buf = os_malloc(buflen);
if (buf == NULL) {
wpa_printf(MSG_ERROR, "wpa_msg_ctrl: Failed to allocate "
@@ -654,9 +662,13 @@
{
va_list ap;
char *buf;
- const int buflen = 2048;
+ int buflen;
int len;
+ va_start(ap, fmt);
+ buflen = vsnprintf(NULL, 0, fmt, ap) + 1;
+ va_end(ap);
+
buf = os_malloc(buflen);
if (buf == NULL) {
wpa_printf(MSG_ERROR, "wpa_msg_global: Failed to allocate "
@@ -677,9 +689,13 @@
{
va_list ap;
char *buf;
- const int buflen = 2048;
+ int buflen;
int len;
+ va_start(ap, fmt);
+ buflen = vsnprintf(NULL, 0, fmt, ap) + 1;
+ va_end(ap);
+
buf = os_malloc(buflen);
if (buf == NULL) {
wpa_printf(MSG_ERROR, "wpa_msg_no_global: Failed to allocate "
@@ -712,9 +728,13 @@
{
va_list ap;
char *buf;
- const int buflen = 2048;
+ int buflen;
int len;
+ va_start(ap, fmt);
+ buflen = vsnprintf(NULL, 0, fmt, ap) + 1;
+ va_end(ap);
+
buf = os_malloc(buflen);
if (buf == NULL) {
wpa_printf(MSG_ERROR, "hostapd_logger: Failed to allocate "