ChangeLog for wpa_supplicant
+2008-11-28 - v0.5.11
+ * fixed race condition between disassociation event and group key
+ handshake to avoid getting stuck in incorrect state [Bug 261]
+ * updated D-Bus usage to avoid deprecated functions
+ * silence SIOCSIWAUTH ioctl failure message (these can be ignored in
+ most cases and are now only shown in debug output)
+ * increase timeout for IBSS connection
+ * driver_wext: do not overwrite BSS frequency if channel was already
+ received
+ * driver_wext: set interface down for mode switches, if needed (e.g.,
+ for mac80211)
+ * driver_wext: fixed re-initialization of a removed and re-inserted
+ interface (e.g., USB dongle or on resume if driver was unloaded for
+ suspend)
+ * improve per-SSID scanning for drivers that report background scan
+ results frequently
+ * fixed scanning behavior after a failed initial association
+ * driver_wext: fixed processing of invalid event messages from kernel
+ not to crash wpa_supplicant (this could happen when using 64-bit
+ kernel with 32-bit userspace)
+ * fixed EAP-AKA to use RES Length field in AT_RES as length in bits,
+ not bytes
+ * fixed canceling of PMKSA caching when using drivers that generate
+ RSN IE and refuse to drop PMKIDs that wpa_supplicant does not know
+ about
+
2008-02-19 - v0.5.10
* added support for Makefile builds to include debug-log-to-a-file
functionality (CONFIG_DEBUG_FILE=y and -f<path> on command line)
ifdef CONFIG_DRIVER_NDIS
CFLAGS += -DCONFIG_DRIVER_NDIS
-OBJS_d += driver_ndis.o driver_ndis_.o
+OBJS_d += driver_ndis.o
+ifdef CONFIG_NDIS_EVENTS_INTEGRATED
+OBJS_d += driver_ndis_.o
+endif
ifndef CONFIG_L2_PACKET
CONFIG_L2_PACKET=pcap
endif
count++;
}
- if (count % 4)
+ if (count == 0 || count % 4)
return NULL;
olen = count / 4 * 3;
}
+#ifdef IEEE8021X_EAPOL
static int wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant *wpa_s,
char *addr)
{
return 0;
}
+#endif /* IEEE8021X_EAPOL */
#ifdef CONFIG_PEERKEY
return 0;
if (wpa_s->scan_results == NULL)
return 0;
-
+
pos = buf;
end = buf + buflen;
ret = os_snprintf(pos, end - pos, "bssid / frequency / signal level / "
wpa_s->reassociate = 1;
wpa_supplicant_req_scan(wpa_s, 0, 0);
}
+#ifdef IEEE8021X_EAPOL
} else if (os_strncmp(buf, "PREAUTH ", 8) == 0) {
if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8))
reply_len = -1;
+#endif /* IEEE8021X_EAPOL */
#ifdef CONFIG_PEERKEY
} else if (os_strncmp(buf, "STKSTART ", 9) == 0) {
if (wpa_supplicant_ctrl_iface_stkstart(wpa_s, buf + 9))
#include "wpa_ctrl.h"
#include "eap.h"
-#define DBUS_VERSION (DBUS_VERSION_MAJOR << 8 | DBUS_VERSION_MINOR)
+#define _DBUS_VERSION (DBUS_VERSION_MAJOR << 8 | DBUS_VERSION_MINOR)
#define DBUS_VER(major, minor) ((major) << 8 | (minor))
-#if DBUS_VERSION < DBUS_VER(1,1)
+#if _DBUS_VERSION < DBUS_VER(1,1)
#define dbus_watch_get_unix_fd dbus_watch_get_fd
#endif
/* Group name not found - try to parse this as gid */
gid = strtol(gid_str, &endp, 10);
if (*gid_str == '\0' || *endp != '\0') {
- wpa_printf(MSG_DEBUG, "CTRL: Invalid group "
+ wpa_printf(MSG_ERROR, "CTRL: Invalid group "
"'%s'", gid_str);
goto fail;
}
}
+#define BYTE_ARRAY_CHUNK_SIZE 34
+#define BYTE_ARRAY_ITEM_SIZE (sizeof (char))
+
static dbus_bool_t _wpa_dbus_dict_entry_get_byte_array(
- DBusMessageIter *iter, int array_len, int array_type,
+ DBusMessageIter *iter, int array_type,
struct wpa_dbus_dict_entry *entry)
{
- dbus_uint32_t i = 0;
+ dbus_uint32_t count = 0;
dbus_bool_t success = FALSE;
- char byte;
+ char *buffer;
- /* Zero-length arrays are valid. */
- if (array_len == 0) {
- entry->bytearray_value = NULL;
- entry->array_type = DBUS_TYPE_BYTE;
- success = TRUE;
- goto done;
- }
+ entry->bytearray_value = NULL;
+ entry->array_type = DBUS_TYPE_BYTE;
- entry->bytearray_value = wpa_zalloc(array_len * sizeof(char));
- if (!entry->bytearray_value) {
+ buffer = wpa_zalloc(BYTE_ARRAY_ITEM_SIZE * BYTE_ARRAY_CHUNK_SIZE);
+ if (!buffer) {
perror("_wpa_dbus_dict_entry_get_byte_array[dbus]: out of "
"memory");
goto done;
}
- entry->array_type = DBUS_TYPE_BYTE;
- entry->array_len = array_len;
+ entry->bytearray_value = buffer;
+ entry->array_len = 0;
while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_BYTE) {
+ char byte;
+
+ if ((count % BYTE_ARRAY_CHUNK_SIZE) == 0 && count != 0) {
+ buffer = realloc(buffer, BYTE_ARRAY_ITEM_SIZE *
+ (count + BYTE_ARRAY_CHUNK_SIZE));
+ if (buffer == NULL) {
+ perror("_wpa_dbus_dict_entry_get_byte_array["
+ "dbus] out of memory trying to "
+ "retrieve the string array");
+ goto done;
+ }
+ }
+ entry->bytearray_value = buffer;
+
dbus_message_iter_get_basic(iter, &byte);
- entry->bytearray_value[i++] = byte;
+ entry->bytearray_value[count] = byte;
+ entry->array_len = ++count;
dbus_message_iter_next(iter);
}
+
+ /* Zero-length arrays are valid. */
+ if (entry->array_len == 0) {
+ free(entry->bytearray_value);
+ entry->bytearray_value = NULL;
+ }
+
success = TRUE;
done:
}
+#define STR_ARRAY_CHUNK_SIZE 8
+#define STR_ARRAY_ITEM_SIZE (sizeof (char *))
+
static dbus_bool_t _wpa_dbus_dict_entry_get_string_array(
- DBusMessageIter *iter, int array_len, int array_type,
+ DBusMessageIter *iter, int array_type,
struct wpa_dbus_dict_entry *entry)
{
dbus_uint32_t count = 0;
entry->strarray_value = NULL;
entry->array_type = DBUS_TYPE_STRING;
- /* Zero-length arrays are valid. */
- if (array_len == 0) {
- success = TRUE;
- goto done;
- }
-
- buffer = wpa_zalloc(sizeof (char *) * 8);
+ buffer = wpa_zalloc(STR_ARRAY_ITEM_SIZE * STR_ARRAY_CHUNK_SIZE);
if (buffer == NULL) {
perror("_wpa_dbus_dict_entry_get_string_array[dbus] out of "
"memory trying to retrieve a string array");
const char *value;
char *str;
- if ((count % 8) == 0 && count != 0) {
- char **tmp;
- tmp = realloc(buffer, sizeof(char *) * (count + 8));
- if (tmp == NULL) {
+ if ((count % STR_ARRAY_CHUNK_SIZE) == 0 && count != 0) {
+ buffer = realloc(buffer, STR_ARRAY_ITEM_SIZE *
+ (count + STR_ARRAY_CHUNK_SIZE));
+ if (buffer == NULL) {
perror("_wpa_dbus_dict_entry_get_string_array["
"dbus] out of memory trying to "
"retrieve the string array");
- free(buffer);
- buffer = NULL;
goto done;
}
- buffer = tmp;
}
entry->strarray_value = buffer;
entry->array_len = ++count;
dbus_message_iter_next(iter);
}
+
+ /* Zero-length arrays are valid. */
+ if (entry->array_len == 0) {
+ free(entry->strarray_value);
+ entry->strarray_value = NULL;
+ }
+
success = TRUE;
done:
DBusMessageIter *iter_dict_val, struct wpa_dbus_dict_entry *entry)
{
int array_type = dbus_message_iter_get_element_type(iter_dict_val);
- int array_len;
dbus_bool_t success = FALSE;
DBusMessageIter iter_array;
dbus_message_iter_recurse(iter_dict_val, &iter_array);
- array_len = dbus_message_iter_get_array_len(&iter_array);
- if (array_len < 0)
- return FALSE;
-
switch (array_type) {
case DBUS_TYPE_BYTE:
success = _wpa_dbus_dict_entry_get_byte_array(&iter_array,
- array_len,
array_type,
entry);
break;
case DBUS_TYPE_STRING:
success = _wpa_dbus_dict_entry_get_string_array(&iter_array,
- array_len,
array_type,
entry);
break;
break;
case DBUS_TYPE_ARRAY:
switch (entry->array_type) {
- case DBUS_TYPE_BYTE:
- free(entry->bytearray_value);
- break;
+ case DBUS_TYPE_BYTE: {
+ free(entry->bytearray_value);
+ break;
+ }
+ case DBUS_TYPE_STRING: {
+ unsigned int i;
+ for (i = 0; i < entry->array_len; i++)
+ free(entry->strarray_value[i]);
+ free(entry->strarray_value);
+ break;
+ }
}
break;
}
wbi = (wl_bss_info_t *) ((u8 *) wbi + wbi->length);
}
- wpa_printf(MSG_MSGDUMP, "Received %d bytes of scan results (%d BSSes)",
- wsr->buflen, ap_num);
+ wpa_printf(MSG_MSGDUMP, "Received %d bytes of scan results (%lu "
+ "BSSes)",
+ wsr->buflen, (unsigned long) ap_num);
os_free(buf);
return ap_num;
#define PRISM2_HOSTAPD_MAX_BUF_SIZE 1024
#define PRISM2_HOSTAPD_RID_HDR_LEN \
-((int) (&((struct prism2_hostapd_param *) 0)->u.rid.data))
+((size_t) (&((struct prism2_hostapd_param *) 0)->u.rid.data))
#define PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN \
-((int) (&((struct prism2_hostapd_param *) 0)->u.generic_elem.data))
+((size_t) (&((struct prism2_hostapd_param *) 0)->u.generic_elem.data))
/* Maximum length for algorithm names (-1 for nul termination) used in ioctl()
*/
#include "driver_ndis.h"
int wpa_driver_register_event_cb(struct wpa_driver_ndis_data *drv);
+#ifdef CONFIG_NDIS_EVENTS_INTEGRATED
void wpa_driver_ndis_event_pipe_cb(void *eloop_data, void *user_data);
+#endif /* CONFIG_NDIS_EVENTS_INTEGRATED */
static void wpa_driver_ndis_deinit(void *priv);
static void wpa_driver_ndis_poll(void *drv);
char ifname[IFNAMSIZ + 1];
int ifindex;
int ifindex2;
+ int if_removed;
u8 *assoc_req_ies;
size_t assoc_req_ies_len;
u8 *assoc_resp_ies;
static int wpa_driver_wext_flush_pmkid(void *priv);
static int wpa_driver_wext_get_range(void *priv);
+static void wpa_driver_wext_finish_drv_init(struct wpa_driver_wext_data *drv);
+
static int wpa_driver_wext_send_oper_ifla(struct wpa_driver_wext_data *drv,
int linkmode, int operstate)
iwr.u.param.value = value;
if (ioctl(drv->ioctl_sock, SIOCSIWAUTH, &iwr) < 0) {
- perror("ioctl[SIOCSIWAUTH]");
- fprintf(stderr, "WEXT auth param %d value 0x%x - ",
- idx, value);
+ if (errno != EOPNOTSUPP) {
+ wpa_printf(MSG_DEBUG, "WEXT: SIOCSIWAUTH(param %d "
+ "value 0x%x) failed: %s)",
+ idx, value, strerror(errno));
+ }
ret = errno == EOPNOTSUPP ? -2 : -1;
}
}
break;
case IWEVMICHAELMICFAILURE:
+ if (custom + iwe->u.data.length > end) {
+ wpa_printf(MSG_DEBUG, "WEXT: Invalid "
+ "IWEVMICHAELMICFAILURE length");
+ return;
+ }
wpa_driver_wext_event_wireless_michaelmicfailure(
ctx, custom, iwe->u.data.length);
break;
case IWEVCUSTOM:
- if (custom + iwe->u.data.length > end)
+ if (custom + iwe->u.data.length > end) {
+ wpa_printf(MSG_DEBUG, "WEXT: Invalid "
+ "IWEVCUSTOM length");
return;
+ }
buf = os_malloc(iwe->u.data.length + 1);
if (buf == NULL)
return;
wpa_supplicant_event(ctx, EVENT_SCAN_RESULTS, NULL);
break;
case IWEVASSOCREQIE:
+ if (custom + iwe->u.data.length > end) {
+ wpa_printf(MSG_DEBUG, "WEXT: Invalid "
+ "IWEVASSOCREQIE length");
+ return;
+ }
wpa_driver_wext_event_wireless_assocreqie(
drv, custom, iwe->u.data.length);
break;
case IWEVASSOCRESPIE:
+ if (custom + iwe->u.data.length > end) {
+ wpa_printf(MSG_DEBUG, "WEXT: Invalid "
+ "IWEVASSOCRESPIE length");
+ return;
+ }
wpa_driver_wext_event_wireless_assocrespie(
drv, custom, iwe->u.data.length);
break;
case IWEVPMKIDCAND:
+ if (custom + iwe->u.data.length > end) {
+ wpa_printf(MSG_DEBUG, "WEXT: Invalid "
+ "IWEVPMKIDCAND length");
+ return;
+ }
wpa_driver_wext_event_wireless_pmkidcand(
drv, custom, iwe->u.data.length);
break;
}
-static void wpa_driver_wext_event_link(void *ctx, char *buf, size_t len,
+static void wpa_driver_wext_event_link(struct wpa_driver_wext_data *drv,
+ void *ctx, char *buf, size_t len,
int del)
{
union wpa_event_data event;
event.interface_status.ifname,
del ? "removed" : "added");
+ if (os_strcmp(drv->ifname, event.interface_status.ifname) == 0) {
+ if (del)
+ drv->if_removed = 1;
+ else
+ drv->if_removed = 0;
+ }
+
wpa_supplicant_event(ctx, EVENT_INTERFACE_STATUS, &event);
}
+static int wpa_driver_wext_own_ifname(struct wpa_driver_wext_data *drv,
+ struct nlmsghdr *h)
+{
+ struct ifinfomsg *ifi;
+ int attrlen, nlmsg_len, rta_len;
+ struct rtattr *attr;
+
+ ifi = NLMSG_DATA(h);
+
+ nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg));
+
+ attrlen = h->nlmsg_len - nlmsg_len;
+ if (attrlen < 0)
+ return 0;
+
+ attr = (struct rtattr *) (((char *) ifi) + nlmsg_len);
+
+ rta_len = RTA_ALIGN(sizeof(struct rtattr));
+ while (RTA_OK(attr, attrlen)) {
+ if (attr->rta_type == IFLA_IFNAME) {
+ if (os_strcmp(((char *) attr) + rta_len, drv->ifname)
+ == 0)
+ return 1;
+ else
+ break;
+ }
+ attr = RTA_NEXT(attr, attrlen);
+ }
+
+ return 0;
+}
+
+
+static int wpa_driver_wext_own_ifindex(struct wpa_driver_wext_data *drv,
+ int ifindex, struct nlmsghdr *h)
+{
+ if (drv->ifindex == ifindex || drv->ifindex2 == ifindex)
+ return 1;
+
+ if (drv->if_removed && wpa_driver_wext_own_ifname(drv, h)) {
+ drv->ifindex = if_nametoindex(drv->ifname);
+ wpa_printf(MSG_DEBUG, "WEXT: Update ifindex for a removed "
+ "interface");
+ wpa_driver_wext_finish_drv_init(drv);
+ return 1;
+ }
+
+ return 0;
+}
+
+
static void wpa_driver_wext_event_rtm_newlink(struct wpa_driver_wext_data *drv,
void *ctx, struct nlmsghdr *h,
size_t len)
ifi = NLMSG_DATA(h);
- if (drv->ifindex != ifi->ifi_index && drv->ifindex2 != ifi->ifi_index)
- {
+ if (!wpa_driver_wext_own_ifindex(drv, ifi->ifi_index, h)) {
wpa_printf(MSG_DEBUG, "Ignore event for foreign ifindex %d",
ifi->ifi_index);
return;
(ifi->ifi_flags & IFF_UP) ? "[UP]" : "",
(ifi->ifi_flags & IFF_RUNNING) ? "[RUNNING]" : "",
(ifi->ifi_flags & IFF_LOWER_UP) ? "[LOWER_UP]" : "",
- (ifi->ifi_flags & IFF_DORMANT) ? "[DORMANT" : "");
+ (ifi->ifi_flags & IFF_DORMANT) ? "[DORMANT]" : "");
/*
* Some drivers send the association event before the operup event--in
* this case, lifting operstate in wpa_driver_wext_set_operstate()
drv, ctx, ((char *) attr) + rta_len,
attr->rta_len - rta_len);
} else if (attr->rta_type == IFLA_IFNAME) {
- wpa_driver_wext_event_link(ctx,
+ wpa_driver_wext_event_link(drv, ctx,
((char *) attr) + rta_len,
attr->rta_len - rta_len, 0);
}
rta_len = RTA_ALIGN(sizeof(struct rtattr));
while (RTA_OK(attr, attrlen)) {
if (attr->rta_type == IFLA_IFNAME) {
- wpa_driver_wext_event_link(ctx,
+ wpa_driver_wext_event_link(drv, ctx,
((char *) attr) + rta_len,
attr->rta_len - rta_len, 1);
}
*/
void * wpa_driver_wext_init(void *ctx, const char *ifname)
{
- int s, flags;
+ int s;
struct sockaddr_nl local;
struct wpa_driver_wext_data *drv;
drv->mlme_sock = -1;
+ wpa_driver_wext_finish_drv_init(drv);
+
+ return drv;
+}
+
+
+static void wpa_driver_wext_finish_drv_init(struct wpa_driver_wext_data *drv)
+{
+ int flags;
+
/*
* Make sure that the driver does not have any obsolete PMKID entries.
*/
drv->ifindex = if_nametoindex(drv->ifname);
- if (os_strncmp(ifname, "wlan", 4) == 0) {
+ if (os_strncmp(drv->ifname, "wlan", 4) == 0) {
/*
* Host AP driver may use both wlan# and wifi# interface in
* wireless events. Since some of the versions included WE-18
* driver are not in use anymore.
*/
char ifname2[IFNAMSIZ + 1];
- os_strncpy(ifname2, ifname, sizeof(ifname2));
+ os_strncpy(ifname2, drv->ifname, sizeof(ifname2));
os_memcpy(ifname2, "wifi", 4);
wpa_driver_wext_alternative_ifindex(drv, ifname2);
}
wpa_driver_wext_send_oper_ifla(drv, 1, IF_OPER_DORMANT);
-
- return drv;
}
* Some drivers do not report
* frequency, but a channel. Try to map
* this to frequency by assuming they
- * are using IEEE 802.11b/g.
+ * are using IEEE 802.11b/g. But don't
+ * overwrite a previously parsed
+ * frequency if the driver sends both
+ * frequency and channel, since the
+ * driver may be sending an A-band
+ * channel that we don't handle here.
*/
+
+ if (results[ap_num].freq)
+ break;
+
if (iwe->u.freq.m >= 1 &&
iwe->u.freq.m <= 13) {
results[ap_num].freq =
{
struct wpa_driver_wext_data *drv = priv;
struct iwreq iwr;
- int ret = 0;
+ int ret = -1, flags;
+ unsigned int new_mode = mode ? IW_MODE_ADHOC : IW_MODE_INFRA;
os_memset(&iwr, 0, sizeof(iwr));
os_strncpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
- iwr.u.mode = mode ? IW_MODE_ADHOC : IW_MODE_INFRA;
+ iwr.u.mode = new_mode;
+ if (ioctl(drv->ioctl_sock, SIOCSIWMODE, &iwr) == 0) {
+ ret = 0;
+ goto done;
+ }
- if (ioctl(drv->ioctl_sock, SIOCSIWMODE, &iwr) < 0) {
+ if (errno != EBUSY) {
perror("ioctl[SIOCSIWMODE]");
- ret = -1;
+ goto done;
+ }
+
+ /* mac80211 doesn't allow mode changes while the device is up, so if
+ * the device isn't in the mode we're about to change to, take device
+ * down, try to set the mode again, and bring it back up.
+ */
+ if (ioctl(drv->ioctl_sock, SIOCGIWMODE, &iwr) < 0) {
+ perror("ioctl[SIOCGIWMODE]");
+ goto done;
+ }
+
+ if (iwr.u.mode == new_mode) {
+ ret = 0;
+ goto done;
+ }
+
+ if (wpa_driver_wext_get_ifflags(drv, &flags) == 0) {
+ (void) wpa_driver_wext_set_ifflags(drv, flags & ~IFF_UP);
+
+ /* Try to set the mode again while the interface is down */
+ iwr.u.mode = new_mode;
+ if (ioctl(drv->ioctl_sock, SIOCSIWMODE, &iwr) < 0)
+ perror("ioctl[SIOCSIWMODE]");
+ else
+ ret = 0;
+
+ /* Ignore return value of get_ifflags to ensure that the device
+ * is always up like it was before this function was called.
+ */
+ (void) wpa_driver_wext_get_ifflags(drv, &flags);
+ (void) wpa_driver_wext_set_ifflags(drv, flags | IFF_UP);
}
+done:
return ret;
}
#endif /* PCSC_FUNCS */
-static int eap_sm_get_scard_identity(struct eap_sm *sm, struct wpa_ssid *ssid)
+static int eap_sm_set_scard_pin(struct eap_sm *sm, struct wpa_ssid *ssid)
{
#ifdef PCSC_FUNCS
if (scard_set_pin(sm->scard_ctx, ssid->pin)) {
eap_sm_request_pin(sm);
return -1;
}
+ return 0;
+#else /* PCSC_FUNCS */
+ return -1;
+#endif /* PCSC_FUNCS */
+}
+
+static int eap_sm_get_scard_identity(struct eap_sm *sm, struct wpa_ssid *ssid)
+{
+#ifdef PCSC_FUNCS
+ if (eap_sm_set_scard_pin(sm, ssid))
+ return -1;
return eap_sm_imsi_identity(sm, ssid);
#else /* PCSC_FUNCS */
eap_sm_request_identity(sm);
return NULL;
}
+ } else if (config->pcsc) {
+ if (eap_sm_set_scard_pin(sm, config) < 0)
+ return NULL;
}
*len = sizeof(struct eap_hdr) + 1 + identity_len;
msg = eap_sim_msg_init(EAP_CODE_RESPONSE, req->identifier,
EAP_TYPE_AKA, EAP_AKA_SUBTYPE_CHALLENGE);
wpa_printf(MSG_DEBUG, " AT_RES");
- eap_sim_msg_add(msg, EAP_SIM_AT_RES, data->res_len,
+ eap_sim_msg_add(msg, EAP_SIM_AT_RES, data->res_len * 8,
data->res, data->res_len);
wpa_printf(MSG_DEBUG, " AT_MAC");
eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
return NULL;
}
if (*list_len == 0 || (*list_len % sizeof(struct eap_gpsk_csuite))) {
- wpa_printf(MSG_DEBUG, "EAP-GPSK: Invalid CSuite_List len %d",
- *list_len);
+ wpa_printf(MSG_DEBUG, "EAP-GPSK: Invalid CSuite_List len %lu",
+ (unsigned long) *list_len);
return NULL;
}
*list = pos;
data->id_server, data->id_server_len);
wpa_hexdump_ascii(MSG_DEBUG, "EAP-GPSK: ID_Server in GPSK-3",
pos, len);
+ return NULL;
}
pos += len;
miclen = eap_gpsk_mic_len(data->vendor, data->specifier);
if (end - pos < (int) miclen) {
wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for MIC "
- "(left=%d miclen=%d)", end - pos, miclen);
+ "(left=%lu miclen=%lu)",
+ (unsigned long) (end - pos),
+ (unsigned long) miclen);
return NULL;
}
if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor,
return NULL;
}
if (pos != end) {
- wpa_printf(MSG_DEBUG, "EAP-GPSK: Ignored %d bytes of extra "
- "data in the end of GPSK-2", end - pos);
+ wpa_printf(MSG_DEBUG, "EAP-GPSK: Ignored %lu bytes of extra "
+ "data in the end of GPSK-2",
+ (unsigned long) (end - pos));
}
req = (const struct eap_hdr *) reqData;
const u8 *data, size_t len, u8 *mic)
{
if (sk_len != 16) {
- wpa_printf(MSG_DEBUG, "EAP-GPSK: Invalid SK length %d for "
- "AES-CMAC MIC", sk_len);
+ wpa_printf(MSG_DEBUG, "EAP-GPSK: Invalid SK length %lu for "
+ "AES-CMAC MIC", (unsigned long) sk_len);
return -1;
}
/* MS-CHAP-Challenge */
challenge = eap_ttls_implicit_challenge(
- sm, data, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN * 2 + 1);
+ sm, data, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN + 1);
if (challenge == NULL) {
os_free(buf);
wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAPV2: Failed to derive "
config->identity, config->identity_len);
/* MS-CHAP-Challenge */
- challenge = eap_ttls_implicit_challenge(sm, data, EAP_TLS_KEY_LEN);
+ challenge = eap_ttls_implicit_challenge(
+ sm, data, EAP_TTLS_MSCHAP_CHALLENGE_LEN + 1);
if (challenge == NULL) {
os_free(buf);
wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAP: Failed to derive "
config->identity, config->identity_len);
/* CHAP-Challenge */
- challenge = eap_ttls_implicit_challenge(sm, data, EAP_TLS_KEY_LEN);
+ challenge = eap_ttls_implicit_challenge(
+ sm, data, EAP_TTLS_CHAP_CHALLENGE_LEN + 1);
if (challenge == NULL) {
os_free(buf);
wpa_printf(MSG_ERROR, "EAP-TTLS/CHAP: Failed to derive "
timeout = os_malloc(sizeof(*timeout));
if (timeout == NULL)
return -1;
- os_get_time(&timeout->time);
+ if (os_get_time(&timeout->time) < 0) {
+ os_free(timeout);
+ return -1;
+ }
timeout->time.sec += secs;
timeout->time.usec += usecs;
while (timeout->time.usec >= 1000000) {
}
+int eloop_is_timeout_registered(eloop_timeout_handler handler,
+ void *eloop_data, void *user_data)
+{
+ struct eloop_timeout *tmp;
+
+ tmp = eloop.timeout;
+ while (tmp != NULL) {
+ if (tmp->handler == handler &&
+ tmp->eloop_data == eloop_data &&
+ tmp->user_data == user_data)
+ return 1;
+
+ tmp = tmp->next;
+ }
+
+ return 0;
+}
+
+
#ifndef CONFIG_NATIVE_WINDOWS
static void eloop_handle_alarm(int sig)
{
void *eloop_data, void *user_data);
/**
+ * eloop_is_timeout_registered - Check if a timeout is already registered
+ * @handler: Matching callback function
+ * @eloop_data: Matching eloop_data
+ * @user_data: Matching user_data
+ * Returns: 1 if the timeout is registered, 0 if the timeout is not registered
+ *
+ * Determine if a matching <handler,eloop_data,user_data> timeout is registered
+ * with eloop_register_timeout().
+ */
+int eloop_is_timeout_registered(eloop_timeout_handler handler,
+ void *eloop_data, void *user_data);
+
+/**
* eloop_register_signal - Register handler for signals
* @sig: Signal number (e.g., SIGHUP)
* @handler: Callback function to be called when the signal is received
}
+int eloop_is_timeout_registered(void (*handler)(void *eloop_ctx,
+ void *timeout_ctx),
+ void *eloop_data, void *user_data)
+{
+ struct eloop_timeout *tmp;
+
+ tmp = eloop.timeout;
+ while (tmp != NULL) {
+ if (tmp->handler == handler &&
+ tmp->eloop_data == eloop_data &&
+ tmp->user_data == user_data)
+ return 1;
+
+ tmp = tmp->next;
+ }
+
+ return 0;
+}
+
+
/* TODO: replace with suitable signal handler */
#if 0
static void eloop_handle_signal(int sig)
}
+int eloop_is_timeout_registered(eloop_timeout_handler handler,
+ void *eloop_data, void *user_data)
+{
+ struct eloop_timeout *tmp;
+
+ tmp = eloop.timeout;
+ while (tmp != NULL) {
+ if (tmp->handler == handler &&
+ tmp->eloop_data == eloop_data &&
+ tmp->user_data == user_data)
+ return 1;
+
+ tmp = tmp->next;
+ }
+
+ return 0;
+}
+
+
/* TODO: replace with suitable signal handler */
#if 0
static void eloop_handle_signal(int sig)
supp_rates[1] = 0;
for (i = 0; i < wpa_s->mlme.num_curr_rates; i++) {
struct wpa_rate_data *rate = &wpa_s->mlme.curr_rates[i];
- if (!(rate->flags & WPA_RATE_SUPPORTED))
- continue;
if (esupp_rates) {
pos = buf + len;
len++;
esupp_rates[0] = WLAN_EID_EXT_SUPP_RATES;
esupp_rates[1] = 1;
pos = &esupp_rates[2];
+ len += 3;
} else {
pos = buf + len;
len++;
return NULL;
}
- fread(buf, 1, *len, f);
+ if (fread(buf, 1, *len, f) != *len) {
+ fclose(f);
+ free(buf);
+ return NULL;
+ }
+
fclose(f);
return buf;
};
-static void _wpa_supplicant_req_scan(void *wpa_s, int sec, int usec)
-{
- wpa_supplicant_req_scan(wpa_s, sec, usec);
-}
-
-
static void _wpa_supplicant_disassociate(void *wpa_s, int reason_code)
{
wpa_supplicant_disassociate(wpa_s, reason_code);
ctx->ctx = wpa_s;
ctx->set_state = _wpa_supplicant_set_state;
ctx->get_state = _wpa_supplicant_get_state;
- ctx->req_scan = _wpa_supplicant_req_scan;
ctx->deauthenticate = _wpa_supplicant_deauthenticate;
ctx->disassociate = _wpa_supplicant_disassociate;
ctx->set_key = wpa_supplicant_set_key;
ppos = plain = os_malloc(plen);
if (plain == NULL)
return NULL;
+ plain[0] = 0;
while (left > 0) {
/* b(1) = MD5(Secret + Request-Authenticator + Salt)
left -= MD5_MAC_LEN;
}
- if (plain[0] > plen - 1) {
+ if (plain[0] == 0 || plain[0] > plen - 1) {
printf("Failed to decrypt MPPE key\n");
os_free(plain);
return NULL;
L_S1 = L_S2 = (secret_len + 1) / 2;
S1 = secret;
S2 = secret + L_S1;
+ if (secret_len & 1) {
+ /* The last byte of S1 will be shared with S2 */
+ S2--;
+ }
hmac_md5_vector(S1, L_S1, 2, &MD5_addr[1], &MD5_len[1], A_MD5);
hmac_sha1_vector(S2, L_S2, 2, &SHA1_addr[1], &SHA1_len[1], A_SHA1);
{
SSL_CTX *ssl = ssl_ctx;
struct tls_connection *conn;
+ long options;
conn = os_zalloc(sizeof(*conn));
if (conn == NULL)
}
SSL_set_app_data(conn->ssl, conn);
- SSL_set_options(conn->ssl,
- SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
- SSL_OP_SINGLE_DH_USE);
+ options = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
+ SSL_OP_SINGLE_DH_USE;
+#ifdef SSL_OP_NO_COMPRESSION
+ options |= SSL_OP_NO_COMPRESSION;
+#endif /* SSL_OP_NO_COMPRESSION */
+ SSL_set_options(conn->ssl, options);
conn->ssl_in = BIO_new(BIO_s_mem());
if (!conn->ssl_in) {
#ifndef VERSION_H
#define VERSION_H
-#define VERSION_STR "0.5.10"
+#define VERSION_STR "0.5.11"
#endif /* VERSION_H */
struct wpa_ie_hdr {
u8 elem_id;
u8 len;
- u8 oui[3];
- u8 oui_type;
+ u8 oui[4]; /* 24-bit OUI followed by 8-bit OUI type */
u8 version[2];
} STRUCT_PACKED;
"caching attempt");
sm->cur_pmksa = NULL;
abort_cached = 1;
- } else {
+ } else if (!abort_cached) {
return -1;
}
}
MACSTR " [PTK=%s GTK=%s]", MAC2STR(addr),
wpa_cipher_txt(sm->pairwise_cipher),
wpa_cipher_txt(sm->group_cipher));
- eloop_cancel_timeout(sm->ctx->scan, sm->ctx->ctx, NULL);
wpa_sm_cancel_auth_timeout(sm);
wpa_sm_set_state(sm, WPA_COMPLETED);
}
wpa_sm_disassociate(sm, REASON_IE_IN_4WAY_DIFFERS);
- wpa_sm_req_scan(sm, 0, 0);
}
os_memset(sm->pmk, 0, sizeof(sm->pmk));
wpa_sm_deauthenticate(sm, REASON_UNSPECIFIED);
- wpa_sm_req_scan(sm, 0, 0);
}
}
void (*set_state)(void *ctx, wpa_states state);
wpa_states (*get_state)(void *ctx);
- void (*req_scan)(void *ctx, int sec, int usec);
void (*deauthenticate)(void * ctx, int reason_code);
void (*disassociate)(void *ctx, int reason_code);
int (*set_key)(void *ctx, wpa_alg alg,
* See README and COPYING for more details.
*/
+#include <cstdio>
#include <QMessageBox>
#include "networkconfig.h"
#include <QTimer>
+#include <cstdio>
+
#include "scanresults.h"
#include "wpagui.h"
#include "networkconfig.h"
#include <unistd.h>
#endif
+#include <cstdio>
#include <QMessageBox>
#include "wpagui.h"
** destructor.
*****************************************************************************/
+#include <stdlib.h>
enum {
AUTH_NONE = 0,
** destructor.
*****************************************************************************/
+#include <stdlib.h>
+
int UserDataRequest::setParams(WpaGui *_wpagui, const char *reqMsg)
{
char *tmp, *pos, *pos2;
#include <unistd.h>
#endif
+#include <stdlib.h>
void WpaGui::init()
{
return sm->ctx->get_state(sm->ctx->ctx);
}
-static inline void wpa_sm_req_scan(struct wpa_sm *sm, int sec, int usec)
-{
- sm->ctx->req_scan(sm->ctx->ctx, sec, usec);
-}
-
static inline void wpa_sm_deauthenticate(struct wpa_sm *sm, int reason_code)
{
sm->ctx->deauthenticate(sm->ctx->ctx, reason_code);
if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X) {
wpa_supplicant_set_state(wpa_s, WPA_4WAY_HANDSHAKE);
} else {
- eloop_cancel_timeout(wpa_supplicant_scan, wpa_s, NULL);
wpa_supplicant_cancel_auth_timeout(wpa_s);
wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
}
*/
void wpa_supplicant_req_scan(struct wpa_supplicant *wpa_s, int sec, int usec)
{
+ /* If there's at least one network that should be specifically scanned
+ * then don't cancel the scan and reschedule. Some drivers do
+ * background scanning which generates frequent scan results, and that
+ * causes the specific SSID scan to get continually pushed back and
+ * never happen, which causes hidden APs to never get probe-scanned.
+ */
+ if (eloop_is_timeout_registered(wpa_supplicant_scan, wpa_s, NULL) &&
+ wpa_s->conf->ap_scan == 1) {
+ struct wpa_ssid *ssid = wpa_s->conf->ssid;
+
+ while (ssid) {
+ if (!ssid->disabled && ssid->scan_ssid)
+ break;
+ ssid = ssid->next;
+ }
+ if (ssid) {
+ wpa_msg(wpa_s, MSG_DEBUG, "Not rescheduling scan to "
+ "ensure that specific SSID scans occur");
+ return;
+ }
+ }
+
wpa_msg(wpa_s, MSG_DEBUG, "Setting scan request: %d sec %d usec",
sec, usec);
eloop_cancel_timeout(wpa_supplicant_scan, wpa_s, NULL);
void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s, wpa_states state)
{
#ifdef ANDROID
- int network_id = -1;
- if (wpa_s && wpa_s->current_ssid) {
- network_id = wpa_s->current_ssid->id;
- }
+ int network_id = -1;
+ if (wpa_s && wpa_s->current_ssid) {
+ network_id = wpa_s->current_ssid->id;
+ }
wpa_states reported_state = state;
if (state == WPA_DISCONNECTED && wpa_s->disconnected) {
reported_state = WPA_IDLE;
if (wpa_s->scan_res_tried == 0 && wpa_s->conf->ap_scan == 1) {
wpa_s->scan_res_tried++;
+ wpa_s->scan_req = scan_req;
wpa_printf(MSG_DEBUG, "Trying to get current scan results "
"first without requesting a new scan to speed up "
"initial association");
wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
} else {
/* Timeout for IEEE 802.11 authentication and association */
- int timeout;
- if (assoc_failed)
- timeout = 5;
- else if (wpa_s->conf->ap_scan == 1)
- timeout = 10;
- else
- timeout = 60;
+ int timeout = 60;
+
+ if (assoc_failed) {
+ /* give IBSS a bit more time */
+ timeout = ssid->mode ? 10 : 5;
+ } else if (wpa_s->conf->ap_scan == 1) {
+ /* give IBSS a bit more time */
+ timeout = ssid->mode ? 20 : 10;
+ }
wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0);
}
}
-static void _wpa_supplicant_req_scan(void *wpa_s, int sec, int usec)
-{
- wpa_supplicant_req_scan(wpa_s, sec, usec);
-}
-
-
static void _wpa_supplicant_cancel_auth_timeout(void *wpa_s)
{
wpa_supplicant_cancel_auth_timeout(wpa_s);
static void _wpa_supplicant_disassociate(void *wpa_s, int reason_code)
{
wpa_supplicant_disassociate(wpa_s, reason_code);
+ /* Schedule a scan to make sure we continue looking for networks */
+ wpa_supplicant_req_scan(wpa_s, 0, 0);
}
static void _wpa_supplicant_deauthenticate(void *wpa_s, int reason_code)
{
wpa_supplicant_deauthenticate(wpa_s, reason_code);
+ /* Schedule a scan to make sure we continue looking for networks */
+ wpa_supplicant_req_scan(wpa_s, 0, 0);
}
ctx->ctx = wpa_s;
ctx->set_state = _wpa_supplicant_set_state;
ctx->get_state = _wpa_supplicant_get_state;
- ctx->req_scan = _wpa_supplicant_req_scan;
ctx->deauthenticate = _wpa_supplicant_deauthenticate;
ctx->disassociate = _wpa_supplicant_disassociate;
ctx->set_key = wpa_supplicant_set_key;
char scan_prop[PROPERTY_VALUE_MAX];
char *endp;
if (property_get("wifi.supplicant_scan_interval", scan_prop, "5") != 0) {
- wpa_s->scan_interval = (int)strtol(scan_prop, &endp, 0);
- if (endp == scan_prop) {
- wpa_s->scan_interval = 5;
- }
+ wpa_s->scan_interval = (int)strtol(scan_prop, &endp, 0);
+ if (endp == scan_prop) {
+ wpa_s->scan_interval = 5;
+ }
}
#endif
wpa_s->next = global->ifaces;