Cumulative patch from commit 989e784601887734e696b3fac0ad6d101badd7ea
989e784 P2P: Optimize scan frequencies list when re-joining a persistent group
154a1d5 hostapd: Fix some compilation errors
ce18c10 Add support for CONFIG_NO_ROAMING to Makefile
65a7b21 OpenSSL: Implement AES-128 CBC using EVP API
22ba05c Explicitly clear temporary stack buffers in tls_prf_sha1_md5()
940a4db Explicitly clear temporary stack buffer in sha1_t_prf()
eccca10 Explicitly clear temporary stack buffer in hmac_sha256_kdf()
e8e365d wext: Add support for renamed Host AP driver ifname
fc48d33 Improve error messages related to EAP DB
c469d62 Error out if user configures SQLite DB without CONFIG_SQLITE
270427e HS 2.0R2: Add more logging for hs20-osu-client icon matching
8e31cd2 OSU server: Improve logging for SPP schema validation failures
23dd15a http-curl: Improve log messages
e7d285c OSU server: Print out signup ID if there is some problem with it
1b45006 HS 2.0R2: Remove unused argument identifier from hs20-osu-client
2e7a228 HS 2.0R2: Allow custom libcurl linkage for hs20-osu-client
a52410c Allow PSK/passphrase to be set only when needed
3e808b8 EAP-pwd peer: Add support for hashed password
e4840b3 EAP-pwd server: Add support for hashed password
2bd2ed2 EAP-pwd: Mark helper function arguments const when appropriate
9ccc10f wpa_cli: Use tab as only word separator for networks
5a997b2 wpa_cli: Completion routine for dup_network command
1ca6c0f wpa_cli: Completion for remove, select, disable, enable network
7e6cc90 wpa_cli: Implement completion routine for get_network/set_network
32a097f wpa_cli: Keep track of available networks
94dc0e9 wpa_cli: Allow tab as alternative separator for cli_txt_list words
efa232f Add support for virtual interface creation/deletion
ba87329 wpa_cli: Use .wpa_cli_history under Android
0f8385e Show OSEN key management properly in scan results
e7b4cd0 wpa_gui: Add tray icon based signal strength meter
54d3dc9 AP: Unset HT capabilities for an HT association request without WMM
Change-Id: I71425b8e20fe1dfdb777592257dc4e4063da8d85
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/hostapd/Android.mk b/hostapd/Android.mk
index 54b139c..78a1506 100644
--- a/hostapd/Android.mk
+++ b/hostapd/Android.mk
@@ -688,8 +688,10 @@
endif
ifdef NEED_AES_CBC
NEED_AES_DEC=y
+ifneq ($(CONFIG_TLS), openssl)
AESOBJS += src/crypto/aes-cbc.c
endif
+endif
ifdef NEED_AES_DEC
ifdef CONFIG_INTERNAL_AES
AESOBJS += src/crypto/aes-internal-dec.c
diff --git a/hostapd/Makefile b/hostapd/Makefile
index d718c15..3c7bd6f 100644
--- a/hostapd/Makefile
+++ b/hostapd/Makefile
@@ -227,6 +227,7 @@
OBJS += ../src/common/sae.o
NEED_ECC=y
NEED_DH_GROUPS=y
+NEED_AP_MLME=y
endif
ifdef CONFIG_WNM
@@ -683,8 +684,10 @@
endif
ifdef NEED_AES_CBC
NEED_AES_DEC=y
+ifneq ($(CONFIG_TLS), openssl)
AESOBJS += ../src/crypto/aes-cbc.o
endif
+endif
ifdef NEED_AES_DEC
ifdef CONFIG_INTERNAL_AES
AESOBJS += ../src/crypto/aes-internal-dec.o
diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index cae9fd3..82b08f9 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -222,9 +222,15 @@
return 0;
if (os_strncmp(fname, "sqlite:", 7) == 0) {
+#ifdef CONFIG_SQLITE
os_free(conf->eap_user_sqlite);
conf->eap_user_sqlite = os_strdup(fname + 7);
return 0;
+#else /* CONFIG_SQLITE */
+ wpa_printf(MSG_ERROR,
+ "EAP user file in SQLite DB, but CONFIG_SQLITE was not enabled in the build.");
+ return -1;
+#endif /* CONFIG_SQLITE */
}
f = fopen(fname, "r");
diff --git a/hs20/client/Makefile b/hs20/client/Makefile
index ca67b54..94cd5f1 100644
--- a/hs20/client/Makefile
+++ b/hs20/client/Makefile
@@ -67,7 +67,13 @@
CFLAGS += $(shell xml2-config --cflags)
LIBS += $(shell xml2-config --libs)
+
+# Allow static/custom linking of libcurl.
+ifdef CUST_CURL_LINKAGE
+LIBS += ${CUST_CURL_LINKAGE}
+else
LIBS += -lcurl
+endif
CFLAGS += -DEAP_TLS_OPENSSL
LIBS += -lssl -lcrypto
diff --git a/hs20/client/osu_client.c b/hs20/client/osu_client.c
index de7f351..649a884 100644
--- a/hs20/client/osu_client.c
+++ b/hs20/client/osu_client.c
@@ -2139,7 +2139,7 @@
snprintf(fname, sizeof(fname), "%s/osu-providers.txt", dir);
osu = parse_osu_providers(fname, &osu_count);
if (osu == NULL) {
- wpa_printf(MSG_INFO, "Could not any OSU providers from %s",
+ wpa_printf(MSG_INFO, "Could not find any OSU providers from %s",
fname);
write_result(ctx, "No OSU providers available");
return -1;
@@ -2810,17 +2810,21 @@
char *name = ctx->icon_filename[j];
size_t name_len = os_strlen(name);
- wpa_printf(MSG_INFO, "Looking for icon file name '%s' match",
- name);
+ wpa_printf(MSG_INFO,
+ "[%i] Looking for icon file name '%s' match",
+ j, name);
for (i = 0; i < cert->num_logo; i++) {
struct http_logo *logo = &cert->logo[i];
size_t uri_len = os_strlen(logo->uri);
char *pos;
- wpa_printf(MSG_INFO, "Comparing to '%s' uri_len=%d name_len=%d",
- logo->uri, (int) uri_len, (int) name_len);
- if (uri_len < 1 + name_len)
+ wpa_printf(MSG_INFO,
+ "[%i] Comparing to '%s' uri_len=%d name_len=%d",
+ i, logo->uri, (int) uri_len, (int) name_len);
+ if (uri_len < 1 + name_len) {
+ wpa_printf(MSG_INFO, "URI Length is too short");
continue;
+ }
pos = &logo->uri[uri_len - name_len - 1];
if (*pos != '/')
continue;
@@ -2847,17 +2851,30 @@
for (i = 0; i < cert->num_logo; i++) {
struct http_logo *logo = &cert->logo[i];
- if (logo->hash_len != 32)
+ if (logo->hash_len != 32) {
+ wpa_printf(MSG_INFO,
+ "[%i][%i] Icon hash length invalid (should be 32): %d",
+ j, i, (int) logo->hash_len);
continue;
+ }
if (os_memcmp(logo->hash, ctx->icon_hash[j], 32) == 0) {
found = 1;
break;
}
+
+ wpa_printf(MSG_DEBUG,
+ "[%u][%u] Icon hash did not match", j, i);
+ wpa_hexdump_ascii(MSG_DEBUG, "logo->hash",
+ logo->hash, 32);
+ wpa_hexdump_ascii(MSG_DEBUG, "ctx->icon_hash[j]",
+ ctx->icon_hash[j], 32);
}
if (!found) {
- wpa_printf(MSG_INFO, "No icon hash match found");
- write_result(ctx, "No icon hash match found");
+ wpa_printf(MSG_INFO,
+ "No icon hash match (by hash) found");
+ write_result(ctx,
+ "No icon hash match (by hash) found");
return -1;
}
}
@@ -2996,7 +3013,7 @@
return -1;
for (;;) {
- c = getopt(argc, argv, "df:hi:KNO:qr:s:S:tw:");
+ c = getopt(argc, argv, "df:hKNO:qr:s:S:tw:");
if (c < 0)
break;
switch (c) {
diff --git a/hs20/server/spp_server.c b/hs20/server/spp_server.c
index 8a2abf1..33e3fa1 100644
--- a/hs20/server/spp_server.c
+++ b/hs20/server/spp_server.c
@@ -2196,7 +2196,9 @@
session_id = xml_node_get_attr_value_ns(ctx->xml, node,
SPP_NS_URI,
"sessionID");
- debug_print(ctx, 1, "SPP message failed validation");
+ debug_print(ctx, 1,
+ "SPP message failed validation, xsd file: %s xml-error: %s",
+ fname, xml_err);
hs20_eventlog_node(ctx, auth_user, auth_realm, session_id,
"SPP message failed validation", node);
hs20_eventlog(ctx, auth_user, auth_realm, session_id,
diff --git a/hs20/server/www/signup.php b/hs20/server/www/signup.php
index a626704..aeb2f68 100644
--- a/hs20/server/www/signup.php
+++ b/hs20/server/www/signup.php
@@ -17,7 +17,7 @@
$row = $db->query("SELECT realm FROM sessions WHERE id='$id'")->fetch();
if ($row == false) {
- die("Session not found");
+ die("Session not found for id: $id");
}
$realm = $row['realm'];
diff --git a/src/ap/authsrv.c b/src/ap/authsrv.c
index bd1778e..f10e1b7 100644
--- a/src/ap/authsrv.c
+++ b/src/ap/authsrv.c
@@ -55,10 +55,11 @@
{
const struct hostapd_eap_user *eap_user;
int i;
+ int rv = -1;
eap_user = hostapd_get_eap_user(ctx, identity, identity_len, phase2);
if (eap_user == NULL)
- return -1;
+ goto out;
if (user == NULL)
return 0;
@@ -72,7 +73,7 @@
if (eap_user->password) {
user->password = os_malloc(eap_user->password_len);
if (user->password == NULL)
- return -1;
+ goto out;
os_memcpy(user->password, eap_user->password,
eap_user->password_len);
user->password_len = eap_user->password_len;
@@ -83,8 +84,13 @@
user->ttls_auth = eap_user->ttls_auth;
user->remediation = eap_user->remediation;
user->accept_attr = eap_user->accept_attr;
+ rv = 0;
- return 0;
+out:
+ if (rv)
+ wpa_printf(MSG_DEBUG, "%s: Failed to find user", __func__);
+
+ return rv;
}
diff --git a/src/ap/eap_user_db.c b/src/ap/eap_user_db.c
index 559d77f..082d0f5 100644
--- a/src/ap/eap_user_db.c
+++ b/src/ap/eap_user_db.c
@@ -138,8 +138,12 @@
char id_str[256], cmd[300];
size_t i;
- if (identity_len >= sizeof(id_str))
+ if (identity_len >= sizeof(id_str)) {
+ wpa_printf(MSG_DEBUG, "%s: identity len too big: %d >= %d",
+ __func__, (int) identity_len,
+ (int) (sizeof(id_str)));
return NULL;
+ }
os_memcpy(id_str, identity, identity_len);
id_str[identity_len] = '\0';
for (i = 0; i < identity_len; i++) {
@@ -182,7 +186,9 @@
wpa_printf(MSG_DEBUG, "DB: %s", cmd);
if (sqlite3_exec(db, cmd, get_user_cb, &hapd->tmp_eap_user, NULL) !=
SQLITE_OK) {
- wpa_printf(MSG_DEBUG, "DB: Failed to complete SQL operation");
+ wpa_printf(MSG_DEBUG,
+ "DB: Failed to complete SQL operation: %s db: %s",
+ sqlite3_errmsg(db), hapd->conf->eap_user_sqlite);
} else if (hapd->tmp_eap_user.next)
user = &hapd->tmp_eap_user;
@@ -192,8 +198,10 @@
wpa_printf(MSG_DEBUG, "DB: %s", cmd);
if (sqlite3_exec(db, cmd, get_wildcard_cb, &hapd->tmp_eap_user,
NULL) != SQLITE_OK) {
- wpa_printf(MSG_DEBUG, "DB: Failed to complete SQL "
- "operation");
+ wpa_printf(MSG_DEBUG,
+ "DB: Failed to complete SQL operation: %s db: %s",
+ sqlite3_errmsg(db),
+ hapd->conf->eap_user_sqlite);
} else if (hapd->tmp_eap_user.next) {
user = &hapd->tmp_eap_user;
os_free(user->identity);
diff --git a/src/ap/hw_features.h b/src/ap/hw_features.h
index 0f67ab8..ca7f22b 100644
--- a/src/ap/hw_features.h
+++ b/src/ap/hw_features.h
@@ -36,6 +36,11 @@
return -1;
}
+static inline int hostapd_acs_completed(struct hostapd_iface *iface, int err)
+{
+ return -1;
+}
+
static inline int hostapd_select_hw_mode(struct hostapd_iface *iface)
{
return -100;
diff --git a/src/ap/ieee802_11_ht.c b/src/ap/ieee802_11_ht.c
index 4b0653d..15edbe9 100644
--- a/src/ap/ieee802_11_ht.c
+++ b/src/ap/ieee802_11_ht.c
@@ -312,10 +312,14 @@
u16 copy_sta_ht_capab(struct hostapd_data *hapd, struct sta_info *sta,
const u8 *ht_capab, size_t ht_capab_len)
{
- /* Disable HT caps for STAs associated to no-HT BSSes. */
+ /*
+ * Disable HT caps for STAs associated to no-HT BSSes, or for stations
+ * that did not specify a valid WMM IE in the (Re)Association Request
+ * frame.
+ */
if (!ht_capab ||
ht_capab_len < sizeof(struct ieee80211_ht_capabilities) ||
- hapd->conf->disable_11n) {
+ !(sta->flags & WLAN_STA_WMM) || hapd->conf->disable_11n) {
sta->flags &= ~WLAN_STA_HT;
os_free(sta->ht_capabilities);
sta->ht_capabilities = NULL;
diff --git a/src/ap/ieee802_1x.c b/src/ap/ieee802_1x.c
index 79dc0f9..7e17ef4 100644
--- a/src/ap/ieee802_1x.c
+++ b/src/ap/ieee802_1x.c
@@ -1926,10 +1926,11 @@
struct hostapd_data *hapd = ctx;
const struct hostapd_eap_user *eap_user;
int i;
+ int rv = -1;
eap_user = hostapd_get_eap_user(hapd, identity, identity_len, phase2);
if (eap_user == NULL)
- return -1;
+ goto out;
os_memset(user, 0, sizeof(*user));
user->phase2 = phase2;
@@ -1941,7 +1942,7 @@
if (eap_user->password) {
user->password = os_malloc(eap_user->password_len);
if (user->password == NULL)
- return -1;
+ goto out;
os_memcpy(user->password, eap_user->password,
eap_user->password_len);
user->password_len = eap_user->password_len;
@@ -1951,8 +1952,13 @@
user->macacl = eap_user->macacl;
user->ttls_auth = eap_user->ttls_auth;
user->remediation = eap_user->remediation;
+ rv = 0;
- return 0;
+out:
+ if (rv)
+ wpa_printf(MSG_DEBUG, "%s: Failed to find user", __func__);
+
+ return rv;
}
diff --git a/src/common/defs.h b/src/common/defs.h
index b5f4f80..24f80ad 100644
--- a/src/common/defs.h
+++ b/src/common/defs.h
@@ -310,6 +310,7 @@
WPA_CTRL_REQ_EAP_OTP,
WPA_CTRL_REQ_EAP_PASSPHRASE,
WPA_CTRL_REQ_SIM,
+ WPA_CTRL_REQ_PSK_PASSPHRASE,
NUM_WPA_CTRL_REQS
};
diff --git a/src/common/wpa_common.c b/src/common/wpa_common.c
index 5534eab..0368904 100644
--- a/src/common/wpa_common.c
+++ b/src/common/wpa_common.c
@@ -486,6 +486,8 @@
return WPA_KEY_MGMT_IEEE8021X_SUITE_B;
if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192)
return WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
+ if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_OSEN)
+ return WPA_KEY_MGMT_OSEN;
return 0;
}
@@ -520,7 +522,6 @@
int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
struct wpa_ie_data *data)
{
- const struct rsn_ie_hdr *hdr;
const u8 *pos;
int left;
int i, count;
@@ -550,19 +551,30 @@
return -1;
}
- hdr = (const struct rsn_ie_hdr *) rsn_ie;
+ if (rsn_ie_len >= 6 && rsn_ie[1] >= 4 &&
+ rsn_ie[1] == rsn_ie_len - 2 &&
+ WPA_GET_BE32(&rsn_ie[2]) == OSEN_IE_VENDOR_TYPE) {
+ pos = rsn_ie + 6;
+ left = rsn_ie_len - 6;
- if (hdr->elem_id != WLAN_EID_RSN ||
- hdr->len != rsn_ie_len - 2 ||
- WPA_GET_LE16(hdr->version) != RSN_VERSION) {
- wpa_printf(MSG_DEBUG, "%s: malformed ie or unknown version",
- __func__);
- return -2;
+ data->proto = WPA_PROTO_OSEN;
+ } else {
+ const struct rsn_ie_hdr *hdr;
+
+ hdr = (const struct rsn_ie_hdr *) rsn_ie;
+
+ if (hdr->elem_id != WLAN_EID_RSN ||
+ hdr->len != rsn_ie_len - 2 ||
+ WPA_GET_LE16(hdr->version) != RSN_VERSION) {
+ wpa_printf(MSG_DEBUG, "%s: malformed ie or unknown version",
+ __func__);
+ return -2;
+ }
+
+ pos = (const u8 *) (hdr + 1);
+ left = rsn_ie_len - sizeof(*hdr);
}
- pos = (const u8 *) (hdr + 1);
- left = rsn_ie_len - sizeof(*hdr);
-
if (left >= RSN_SELECTOR_LEN) {
data->group_cipher = rsn_selector_to_bitfield(pos);
if (!wpa_cipher_valid_group(data->group_cipher)) {
diff --git a/src/crypto/crypto_openssl.c b/src/crypto/crypto_openssl.c
index f158ef4..9834b25 100644
--- a/src/crypto/crypto_openssl.c
+++ b/src/crypto/crypto_openssl.c
@@ -324,6 +324,56 @@
}
+int aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len)
+{
+ EVP_CIPHER_CTX ctx;
+ int clen, len;
+ u8 buf[16];
+
+ EVP_CIPHER_CTX_init(&ctx);
+ if (EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, key, iv) != 1)
+ return -1;
+ EVP_CIPHER_CTX_set_padding(&ctx, 0);
+
+ clen = data_len;
+ if (EVP_EncryptUpdate(&ctx, data, &clen, data, data_len) != 1 ||
+ clen != (int) data_len)
+ return -1;
+
+ len = sizeof(buf);
+ if (EVP_EncryptFinal_ex(&ctx, buf, &len) != 1 || len != 0)
+ return -1;
+ EVP_CIPHER_CTX_cleanup(&ctx);
+
+ return 0;
+}
+
+
+int aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len)
+{
+ EVP_CIPHER_CTX ctx;
+ int plen, len;
+ u8 buf[16];
+
+ EVP_CIPHER_CTX_init(&ctx);
+ if (EVP_DecryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, key, iv) != 1)
+ return -1;
+ EVP_CIPHER_CTX_set_padding(&ctx, 0);
+
+ plen = data_len;
+ if (EVP_DecryptUpdate(&ctx, data, &plen, data, data_len) != 1 ||
+ plen != (int) data_len)
+ return -1;
+
+ len = sizeof(buf);
+ if (EVP_DecryptFinal_ex(&ctx, buf, &len) != 1 || len != 0)
+ return -1;
+ EVP_CIPHER_CTX_cleanup(&ctx);
+
+ return 0;
+}
+
+
int crypto_mod_exp(const u8 *base, size_t base_len,
const u8 *power, size_t power_len,
const u8 *modulus, size_t modulus_len,
diff --git a/src/crypto/sha1-tlsprf.c b/src/crypto/sha1-tlsprf.c
index 0effd9b..f9bc0eb 100644
--- a/src/crypto/sha1-tlsprf.c
+++ b/src/crypto/sha1-tlsprf.c
@@ -95,5 +95,10 @@
SHA1_pos++;
}
+ os_memset(A_MD5, 0, MD5_MAC_LEN);
+ os_memset(P_MD5, 0, MD5_MAC_LEN);
+ os_memset(A_SHA1, 0, SHA1_MAC_LEN);
+ os_memset(P_SHA1, 0, SHA1_MAC_LEN);
+
return 0;
}
diff --git a/src/crypto/sha1-tprf.c b/src/crypto/sha1-tprf.c
index a529494..562510f 100644
--- a/src/crypto/sha1-tprf.c
+++ b/src/crypto/sha1-tprf.c
@@ -66,5 +66,7 @@
len[0] = SHA1_MAC_LEN;
}
+ os_memset(hash, 0, SHA1_MAC_LEN);
+
return 0;
}
diff --git a/src/crypto/sha256-kdf.c b/src/crypto/sha256-kdf.c
index d8a1beb..e7509ce 100644
--- a/src/crypto/sha256-kdf.c
+++ b/src/crypto/sha256-kdf.c
@@ -61,6 +61,7 @@
if (iter == 255) {
os_memset(out, 0, outlen);
+ os_memset(T, 0, SHA256_MAC_LEN);
return -1;
}
iter++;
@@ -68,9 +69,11 @@
if (hmac_sha256_vector(secret, secret_len, 4, addr, len, T) < 0)
{
os_memset(out, 0, outlen);
+ os_memset(T, 0, SHA256_MAC_LEN);
return -1;
}
}
+ os_memset(T, 0, SHA256_MAC_LEN);
return 0;
}
diff --git a/src/drivers/driver_wext.c b/src/drivers/driver_wext.c
index a1581b8..22e1184 100644
--- a/src/drivers/driver_wext.c
+++ b/src/drivers/driver_wext.c
@@ -1,6 +1,6 @@
/*
* Driver interaction with generic Linux Wireless Extensions
- * Copyright (c) 2003-2010, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2015, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -18,6 +18,7 @@
#include <sys/stat.h>
#include <fcntl.h>
#include <net/if_arp.h>
+#include <dirent.h>
#include "linux_wext.h"
#include "common.h"
@@ -874,6 +875,105 @@
}
+static int wext_hostap_ifname(struct wpa_driver_wext_data *drv,
+ const char *ifname)
+{
+ char buf[200], *res;
+ int type;
+ FILE *f;
+
+ if (strcmp(ifname, ".") == 0 || strcmp(ifname, "..") == 0)
+ return -1;
+
+ snprintf(buf, sizeof(buf), "/sys/class/net/%s/device/net/%s/type",
+ drv->ifname, ifname);
+
+ f = fopen(buf, "r");
+ if (!f)
+ return -1;
+ res = fgets(buf, sizeof(buf), f);
+ fclose(f);
+
+ type = res ? atoi(res) : -1;
+ wpa_printf(MSG_DEBUG, "WEXT: hostap ifname %s type %d", ifname, type);
+
+ if (type == ARPHRD_IEEE80211) {
+ wpa_printf(MSG_DEBUG,
+ "WEXT: Found hostap driver wifi# interface (%s)",
+ ifname);
+ wpa_driver_wext_alternative_ifindex(drv, ifname);
+ return 0;
+ }
+ return -1;
+}
+
+
+static int wext_add_hostap(struct wpa_driver_wext_data *drv)
+{
+ char buf[200];
+ int n;
+ struct dirent **names;
+ int ret = -1;
+
+ snprintf(buf, sizeof(buf), "/sys/class/net/%s/device/net", drv->ifname);
+ n = scandir(buf, &names, NULL, alphasort);
+ if (n < 0)
+ return -1;
+
+ while (n--) {
+ if (ret < 0 && wext_hostap_ifname(drv, names[n]->d_name) == 0)
+ ret = 0;
+ free(names[n]);
+ }
+ free(names);
+
+ return ret;
+}
+
+
+static void wext_check_hostap(struct wpa_driver_wext_data *drv)
+{
+ char buf[200], *pos;
+ ssize_t res;
+
+ /*
+ * Host AP driver may use both wlan# and wifi# interface in wireless
+ * events. Since some of the versions included WE-18 support, let's add
+ * the alternative ifindex also from driver_wext.c for the time being.
+ * This may be removed at some point once it is believed that old
+ * versions of the driver are not in use anymore. However, it looks like
+ * the wifi# interface is still used in the current kernel tree, so it
+ * may not really be possible to remove this before the Host AP driver
+ * gets removed from the kernel.
+ */
+
+ /* First, try to see if driver information is available from sysfs */
+ snprintf(buf, sizeof(buf), "/sys/class/net/%s/device/driver",
+ drv->ifname);
+ res = readlink(buf, buf, sizeof(buf) - 1);
+ if (res > 0) {
+ buf[res] = '\0';
+ pos = strrchr(buf, '/');
+ if (pos)
+ pos++;
+ else
+ pos = buf;
+ wpa_printf(MSG_DEBUG, "WEXT: Driver: %s", pos);
+ if (os_strncmp(pos, "hostap", 6) == 0 &&
+ wext_add_hostap(drv) == 0)
+ return;
+ }
+
+ /* Second, use the old design with hardcoded ifname */
+ if (os_strncmp(drv->ifname, "wlan", 4) == 0) {
+ char ifname2[IFNAMSIZ + 1];
+ os_strlcpy(ifname2, drv->ifname, sizeof(ifname2));
+ os_memcpy(ifname2, "wifi", 4);
+ wpa_driver_wext_alternative_ifindex(drv, ifname2);
+ }
+}
+
+
static int wpa_driver_wext_finish_drv_init(struct wpa_driver_wext_data *drv)
{
int send_rfkill_event = 0;
@@ -914,20 +1014,7 @@
drv->ifindex = if_nametoindex(drv->ifname);
- 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
- * support, let's add the alternative ifindex also from
- * driver_wext.c for the time being. This may be removed at
- * some point once it is believed that old versions of the
- * driver are not in use anymore.
- */
- char ifname2[IFNAMSIZ + 1];
- os_strlcpy(ifname2, drv->ifname, sizeof(ifname2));
- os_memcpy(ifname2, "wifi", 4);
- wpa_driver_wext_alternative_ifindex(drv, ifname2);
- }
+ wext_check_hostap(drv);
netlink_send_oper_ifla(drv->netlink, drv->ifindex,
1, IF_OPER_DORMANT);
diff --git a/src/eap_common/eap_pwd_common.c b/src/eap_common/eap_pwd_common.c
index 631c363..4d27623 100644
--- a/src/eap_common/eap_pwd_common.c
+++ b/src/eap_common/eap_pwd_common.c
@@ -86,9 +86,10 @@
* on the password and identities.
*/
int compute_password_element(EAP_PWD_group *grp, u16 num,
- u8 *password, int password_len,
- u8 *id_server, int id_server_len,
- u8 *id_peer, int id_peer_len, u8 *token)
+ const u8 *password, size_t password_len,
+ const u8 *id_server, size_t id_server_len,
+ const u8 *id_peer, size_t id_peer_len,
+ const u8 *token)
{
BIGNUM *x_candidate = NULL, *rnd = NULL, *cofactor = NULL;
struct crypto_hash *hash;
@@ -283,10 +284,10 @@
}
-int compute_keys(EAP_PWD_group *grp, BN_CTX *bnctx, BIGNUM *k,
- BIGNUM *peer_scalar, BIGNUM *server_scalar,
- u8 *confirm_peer, u8 *confirm_server,
- u32 *ciphersuite, u8 *msk, u8 *emsk, u8 *session_id)
+int compute_keys(EAP_PWD_group *grp, BN_CTX *bnctx, const BIGNUM *k,
+ const BIGNUM *peer_scalar, const BIGNUM *server_scalar,
+ const u8 *confirm_peer, const u8 *confirm_server,
+ const u32 *ciphersuite, u8 *msk, u8 *emsk, u8 *session_id)
{
struct crypto_hash *hash;
u8 mk[SHA256_MAC_LEN], *cruft;
@@ -306,7 +307,7 @@
os_free(cruft);
return -1;
}
- eap_pwd_h_update(hash, (u8 *) ciphersuite, sizeof(u32));
+ eap_pwd_h_update(hash, (const u8 *) ciphersuite, sizeof(u32));
offset = BN_num_bytes(grp->order) - BN_num_bytes(peer_scalar);
os_memset(cruft, 0, BN_num_bytes(grp->prime));
BN_bn2bin(peer_scalar, cruft + offset);
diff --git a/src/eap_common/eap_pwd_common.h b/src/eap_common/eap_pwd_common.h
index c54c441..a0d717e 100644
--- a/src/eap_common/eap_pwd_common.h
+++ b/src/eap_common/eap_pwd_common.h
@@ -56,10 +56,15 @@
} STRUCT_PACKED;
/* common routines */
-int compute_password_element(EAP_PWD_group *, u16, u8 *, int, u8 *, int, u8 *,
- int, u8 *);
-int compute_keys(EAP_PWD_group *, BN_CTX *, BIGNUM *, BIGNUM *, BIGNUM *,
- u8 *, u8 *, u32 *, u8 *, u8 *, u8 *);
+int compute_password_element(EAP_PWD_group *grp, u16 num,
+ const u8 *password, size_t password_len,
+ const u8 *id_server, size_t id_server_len,
+ const u8 *id_peer, size_t id_peer_len,
+ const u8 *token);
+int compute_keys(EAP_PWD_group *grp, BN_CTX *bnctx, const BIGNUM *k,
+ const BIGNUM *peer_scalar, const BIGNUM *server_scalar,
+ const u8 *confirm_peer, const u8 *confirm_server,
+ const u32 *ciphersuite, u8 *msk, u8 *emsk, u8 *session_id);
struct crypto_hash * eap_pwd_h_init(void);
void eap_pwd_h_update(struct crypto_hash *hash, const u8 *data, size_t len);
void eap_pwd_h_final(struct crypto_hash *hash, u8 *digest);
diff --git a/src/eap_peer/eap_pwd.c b/src/eap_peer/eap_pwd.c
index 059bbee..f2b0926 100644
--- a/src/eap_peer/eap_pwd.c
+++ b/src/eap_peer/eap_pwd.c
@@ -10,6 +10,7 @@
#include "common.h"
#include "crypto/sha256.h"
+#include "crypto/ms_funcs.h"
#include "eap_peer/eap_i.h"
#include "eap_common/eap_pwd_common.h"
@@ -25,6 +26,7 @@
size_t id_server_len;
u8 *password;
size_t password_len;
+ int password_hash;
u16 group_num;
EAP_PWD_group *grp;
@@ -86,8 +88,9 @@
const u8 *identity, *password;
size_t identity_len, password_len;
int fragment_size;
+ int pwhash;
- password = eap_get_config_password(sm, &password_len);
+ password = eap_get_config_password2(sm, &password_len, &pwhash);
if (password == NULL) {
wpa_printf(MSG_INFO, "EAP-PWD: No password configured!");
return NULL;
@@ -129,6 +132,7 @@
}
os_memcpy(data->password, password, password_len);
data->password_len = password_len;
+ data->password_hash = pwhash;
data->out_frag_pos = data->in_frag_pos = 0;
data->inbuf = data->outbuf = NULL;
@@ -216,6 +220,10 @@
const u8 *payload, size_t payload_len)
{
struct eap_pwd_id *id;
+ const u8 *password;
+ size_t password_len;
+ u8 pwhashhash[16];
+ int res;
if (data->state != PWD_ID_Req) {
ret->ignore = TRUE;
@@ -231,6 +239,9 @@
id = (struct eap_pwd_id *) payload;
data->group_num = be_to_host16(id->group_num);
+ wpa_printf(MSG_DEBUG,
+ "EAP-PWD: Server EAP-pwd-ID proposal: group=%u random=%u prf=%u prep=%u",
+ data->group_num, id->random_function, id->prf, id->prep);
if ((id->random_function != EAP_PWD_DEFAULT_RAND_FUNC) ||
(id->prf != EAP_PWD_DEFAULT_PRF)) {
ret->ignore = TRUE;
@@ -238,6 +249,22 @@
return;
}
+ if (id->prep != EAP_PWD_PREP_NONE &&
+ id->prep != EAP_PWD_PREP_MS) {
+ wpa_printf(MSG_DEBUG,
+ "EAP-PWD: Unsupported password pre-processing technique (Prep=%u)",
+ id->prep);
+ eap_pwd_state(data, FAILURE);
+ return;
+ }
+
+ if (id->prep == EAP_PWD_PREP_NONE && data->password_hash) {
+ wpa_printf(MSG_DEBUG,
+ "EAP-PWD: Unhashed password not available");
+ eap_pwd_state(data, FAILURE);
+ return;
+ }
+
wpa_printf(MSG_DEBUG, "EAP-PWD (peer): using group %d",
data->group_num);
@@ -260,12 +287,39 @@
return;
}
+ if (id->prep == EAP_PWD_PREP_MS) {
+ if (data->password_hash) {
+ res = hash_nt_password_hash(data->password, pwhashhash);
+ } else {
+ u8 pwhash[16];
+
+ res = nt_password_hash(data->password,
+ data->password_len, pwhash);
+ if (res == 0)
+ res = hash_nt_password_hash(pwhash, pwhashhash);
+ os_memset(pwhash, 0, sizeof(pwhash));
+ }
+
+ if (res) {
+ eap_pwd_state(data, FAILURE);
+ return;
+ }
+
+ password = pwhashhash;
+ password_len = sizeof(pwhashhash);
+ } else {
+ password = data->password;
+ password_len = data->password_len;
+ }
+
/* compute PWE */
- if (compute_password_element(data->grp, data->group_num,
- data->password, data->password_len,
- data->id_server, data->id_server_len,
- data->id_peer, data->id_peer_len,
- id->token)) {
+ res = compute_password_element(data->grp, data->group_num,
+ password, password_len,
+ data->id_server, data->id_server_len,
+ data->id_peer, data->id_peer_len,
+ id->token);
+ os_memset(pwhashhash, 0, sizeof(pwhashhash));
+ if (res) {
wpa_printf(MSG_INFO, "EAP-PWD (peer): unable to compute PWE");
eap_pwd_state(data, FAILURE);
return;
diff --git a/src/eap_server/eap_server_pwd.c b/src/eap_server/eap_server_pwd.c
index 943af0d..66bd5d2 100644
--- a/src/eap_server/eap_server_pwd.c
+++ b/src/eap_server/eap_server_pwd.c
@@ -10,6 +10,7 @@
#include "common.h"
#include "crypto/sha256.h"
+#include "crypto/ms_funcs.h"
#include "eap_server/eap_i.h"
#include "eap_common/eap_pwd_common.h"
@@ -24,6 +25,7 @@
size_t id_server_len;
u8 *password;
size_t password_len;
+ int password_hash;
u32 token;
u16 group_num;
EAP_PWD_group *grp;
@@ -112,6 +114,7 @@
}
data->password_len = sm->user->password_len;
os_memcpy(data->password, sm->user->password, data->password_len);
+ data->password_hash = sm->user->password_hash;
data->bnctx = BN_CTX_new();
if (data->bnctx == NULL) {
@@ -181,7 +184,8 @@
wpabuf_put_u8(data->outbuf, EAP_PWD_DEFAULT_RAND_FUNC);
wpabuf_put_u8(data->outbuf, EAP_PWD_DEFAULT_PRF);
wpabuf_put_data(data->outbuf, &data->token, sizeof(data->token));
- wpabuf_put_u8(data->outbuf, EAP_PWD_PREP_NONE);
+ wpabuf_put_u8(data->outbuf, data->password_hash ? EAP_PWD_PREP_MS :
+ EAP_PWD_PREP_NONE);
wpabuf_put_data(data->outbuf, data->id_server, data->id_server_len);
}
@@ -579,6 +583,10 @@
const u8 *payload, size_t payload_len)
{
struct eap_pwd_id *id;
+ const u8 *password;
+ size_t password_len;
+ u8 pwhashhash[16];
+ int res;
if (payload_len < sizeof(struct eap_pwd_id)) {
wpa_printf(MSG_INFO, "EAP-pwd: Invalid ID response");
@@ -610,11 +618,25 @@
"group");
return;
}
- if (compute_password_element(data->grp, data->group_num,
- data->password, data->password_len,
- data->id_server, data->id_server_len,
- data->id_peer, data->id_peer_len,
- (u8 *) &data->token)) {
+
+ if (data->password_hash) {
+ res = hash_nt_password_hash(data->password, pwhashhash);
+ if (res)
+ return;
+ password = pwhashhash;
+ password_len = sizeof(pwhashhash);
+ } else {
+ password = data->password;
+ password_len = data->password_len;
+ }
+
+ res = compute_password_element(data->grp, data->group_num,
+ password, password_len,
+ data->id_server, data->id_server_len,
+ data->id_peer, data->id_peer_len,
+ (u8 *) &data->token);
+ os_memset(pwhashhash, 0, sizeof(pwhashhash));
+ if (res) {
wpa_printf(MSG_INFO, "EAP-PWD (server): unable to compute "
"PWE");
return;
diff --git a/src/radius/radius_server.c b/src/radius/radius_server.c
index 85a485e..3f881cf 100644
--- a/src/radius/radius_server.c
+++ b/src/radius/radius_server.c
@@ -2035,6 +2035,12 @@
sess->remediation = user->remediation;
sess->macacl = user->macacl;
}
+
+ if (ret) {
+ RADIUS_DEBUG("%s: User-Name not found from user database",
+ __func__);
+ }
+
return ret;
}
diff --git a/src/rsn_supp/wpa_ie.c b/src/rsn_supp/wpa_ie.c
index cb334df..0d96216 100644
--- a/src/rsn_supp/wpa_ie.c
+++ b/src/rsn_supp/wpa_ie.c
@@ -30,6 +30,9 @@
{
if (wpa_ie_len >= 1 && wpa_ie[0] == WLAN_EID_RSN)
return wpa_parse_wpa_ie_rsn(wpa_ie, wpa_ie_len, data);
+ if (wpa_ie_len >= 6 && wpa_ie[0] == WLAN_EID_VENDOR_SPECIFIC &&
+ wpa_ie[1] >= 4 && WPA_GET_BE32(&wpa_ie[2]) == OSEN_IE_VENDOR_TYPE)
+ return wpa_parse_wpa_ie_rsn(wpa_ie, wpa_ie_len, data);
else
return wpa_parse_wpa_ie_wpa(wpa_ie, wpa_ie_len, data);
}
diff --git a/src/utils/http_curl.c b/src/utils/http_curl.c
index b38cf79..653eb54 100644
--- a/src/utils/http_curl.c
+++ b/src/utils/http_curl.c
@@ -855,8 +855,10 @@
struct http_cert hcert;
int ret;
- if (ctx->cert_cb == NULL)
+ if (ctx->cert_cb == NULL) {
+ wpa_printf(MSG_DEBUG, "%s: no cert_cb configured", __func__);
return 0;
+ }
if (0) {
BIO *out;
@@ -950,7 +952,8 @@
ssl_ctx = ssl->ctx;
ctx = SSL_CTX_get_app_data(ssl_ctx);
- wpa_printf(MSG_DEBUG, "curl_cb_ssl_verify");
+ wpa_printf(MSG_DEBUG, "curl_cb_ssl_verify, preverify_ok: %d",
+ preverify_ok);
err = X509_STORE_CTX_get_error(x509_ctx);
err_str = X509_verify_cert_error_string(err);
@@ -1249,9 +1252,14 @@
const char *client_key)
{
CURL *curl;
+#ifdef EAP_TLS_OPENSSL
+ const char *extra = " tls=openssl";
+#else /* EAP_TLS_OPENSSL */
+ const char *extra = "";
+#endif /* EAP_TLS_OPENSSL */
wpa_printf(MSG_DEBUG, "Start HTTP client: address=%s ca_fname=%s "
- "username=%s", address, ca_fname, username);
+ "username=%s%s", address, ca_fname, username, extra);
curl = curl_easy_init();
if (curl == NULL)
diff --git a/wpa_supplicant/Android.mk b/wpa_supplicant/Android.mk
index 5ce8da1..657784b 100644
--- a/wpa_supplicant/Android.mk
+++ b/wpa_supplicant/Android.mk
@@ -40,6 +40,9 @@
L_CFLAGS += -DCONFIG_CTRL_IFACE_CLIENT_DIR=\"/data/misc/wifi/sockets\"
L_CFLAGS += -DCONFIG_CTRL_IFACE_DIR=\"/data/system/wpa_supplicant\"
+# Use Android specific directory for wpa_cli command completion history
+L_CFLAGS += -DCONFIG_WPA_CLI_HISTORY_DIR=\"/data/misc/wifi\"
+
# To force sizeof(enum) = 4
ifeq ($(TARGET_ARCH),arm)
L_CFLAGS += -mabi=aapcs-linux
@@ -1142,8 +1145,10 @@
endif
ifdef NEED_AES_CBC
NEED_AES_ENC=y
+ifneq ($(CONFIG_TLS), openssl)
AESOBJS += src/crypto/aes-cbc.c
endif
+endif
ifdef NEED_AES_ENC
ifdef CONFIG_INTERNAL_AES
AESOBJS += src/crypto/aes-internal-enc.c
diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile
index d086eeb..af2d924 100644
--- a/wpa_supplicant/Makefile
+++ b/wpa_supplicant/Makefile
@@ -317,6 +317,10 @@
NEED_GAS=y
endif
+ifdef CONFIG_NO_ROAMING
+CFLAGS += -DCONFIG_NO_ROAMING
+endif
+
include ../src/drivers/drivers.mak
ifdef CONFIG_AP
OBJS_d += $(DRV_BOTH_OBJS)
@@ -1162,8 +1166,10 @@
endif
ifdef NEED_AES_CBC
NEED_AES_ENC=y
+ifneq ($(CONFIG_TLS), openssl)
AESOBJS += ../src/crypto/aes-cbc.o
endif
+endif
ifdef NEED_AES_ENC
ifdef CONFIG_INTERNAL_AES
AESOBJS += ../src/crypto/aes-internal-enc.o
diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
index a01a910..c690542 100644
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -1816,6 +1816,7 @@
{ FUNC(bssid_blacklist) },
{ FUNC(bssid_whitelist) },
{ FUNC_KEY(psk) },
+ { INT(mem_only_psk) },
{ FUNC(proto) },
{ FUNC(key_mgmt) },
{ INT(bg_scan_period) },
diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c
index 3d3a6e4..781f5e5 100644
--- a/wpa_supplicant/config_file.c
+++ b/wpa_supplicant/config_file.c
@@ -501,7 +501,12 @@
static void write_psk(FILE *f, struct wpa_ssid *ssid)
{
- char *value = wpa_config_get(ssid, "psk");
+ char *value;
+
+ if (ssid->mem_only_psk)
+ return;
+
+ value = wpa_config_get(ssid, "psk");
if (value == NULL)
return;
fprintf(f, "\tpsk=%s\n", value);
@@ -673,6 +678,7 @@
write_str(f, "bssid_blacklist", ssid);
write_str(f, "bssid_whitelist", ssid);
write_psk(f, ssid);
+ INT(mem_only_psk);
write_proto(f, ssid);
write_key_mgmt(f, ssid);
INT_DEF(bg_scan_period, DEFAULT_BG_SCAN_PERIOD);
diff --git a/wpa_supplicant/config_ssid.h b/wpa_supplicant/config_ssid.h
index 7c826cf..23a37cc 100644
--- a/wpa_supplicant/config_ssid.h
+++ b/wpa_supplicant/config_ssid.h
@@ -181,6 +181,14 @@
char *ext_psk;
/**
+ * mem_only_psk - Whether to keep PSK/passphrase only in memory
+ *
+ * 0 = allow psk/passphrase to be stored to the configuration file
+ * 1 = do not store psk/passphrase to the configuration file
+ */
+ int mem_only_psk;
+
+ /**
* pairwise_cipher - Bitfield of allowed pairwise ciphers, WPA_CIPHER_*
*/
int pairwise_cipher;
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index 53d2d01..377b9ed 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -2366,6 +2366,14 @@
}
#endif /* CONFIG_SUITEB192 */
+ if (data.key_mgmt & WPA_KEY_MGMT_OSEN) {
+ ret = os_snprintf(pos, end - pos, "%sOSEN",
+ pos == start ? "" : "+");
+ if (os_snprintf_error(end - pos, ret))
+ return pos;
+ pos += ret;
+ }
+
pos = wpa_supplicant_cipher_txt(pos, end, data.pairwise_cipher);
if (data.capabilities & WPA_CAPABILITY_PREAUTH) {
@@ -2433,7 +2441,7 @@
{
char *pos, *end;
int ret;
- const u8 *ie, *ie2, *p2p, *mesh;
+ const u8 *ie, *ie2, *osen_ie, *p2p, *mesh;
mesh = wpa_bss_get_ie(bss, WLAN_EID_MESH_ID);
p2p = wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE);
@@ -2460,8 +2468,12 @@
pos = wpa_supplicant_ie_txt(pos, end, mesh ? "RSN" : "WPA2",
ie2, 2 + ie2[1]);
}
+ osen_ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
+ if (osen_ie)
+ pos = wpa_supplicant_ie_txt(pos, end, "OSEN",
+ osen_ie, 2 + osen_ie[1]);
pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
- if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) {
+ if (!ie && !ie2 && !osen_ie && (bss->caps & IEEE80211_CAP_PRIVACY)) {
ret = os_snprintf(pos, end - pos, "[WEP]");
if (os_snprintf_error(end - pos, ret))
return -1;
@@ -3937,7 +3949,7 @@
size_t i;
int ret;
char *pos, *end;
- const u8 *ie, *ie2;
+ const u8 *ie, *ie2, *osen_ie;
pos = buf;
end = buf + buflen;
@@ -4054,8 +4066,13 @@
if (ie2)
pos = wpa_supplicant_ie_txt(pos, end, "WPA2", ie2,
2 + ie2[1]);
+ osen_ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE);
+ if (osen_ie)
+ pos = wpa_supplicant_ie_txt(pos, end, "OSEN",
+ osen_ie, 2 + osen_ie[1]);
pos = wpa_supplicant_wps_ie_txt(wpa_s, pos, end, bss);
- if (!ie && !ie2 && bss->caps & IEEE80211_CAP_PRIVACY) {
+ if (!ie && !ie2 && !osen_ie &&
+ (bss->caps & IEEE80211_CAP_PRIVACY)) {
ret = os_snprintf(pos, end - pos, "[WEP]");
if (os_snprintf_error(end - pos, ret))
return 0;
@@ -8504,11 +8521,14 @@
char *cmd)
{
struct wpa_interface iface;
- char *pos;
+ char *pos, *extra;
+ struct wpa_supplicant *wpa_s;
+ unsigned int create_iface = 0;
+ u8 mac_addr[ETH_ALEN];
/*
* <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param>
- * TAB<bridge_ifname>
+ * TAB<bridge_ifname>[TAB<create>]
*/
wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd);
@@ -8568,12 +8588,47 @@
iface.bridge_ifname = NULL;
if (pos == NULL)
break;
+
+ extra = pos;
+ pos = os_strchr(pos, '\t');
+ if (pos)
+ *pos++ = '\0';
+ if (os_strcmp(extra, "create") == 0)
+ create_iface = 1;
+ else
+ return -1;
} while (0);
- if (wpa_supplicant_get_iface(global, iface.ifname))
- return -1;
+ if (create_iface) {
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE creating interface '%s'",
+ iface.ifname);
+ if (!global->ifaces)
+ return -1;
+ if (wpa_drv_if_add(global->ifaces, WPA_IF_STATION, iface.ifname,
+ NULL, NULL, NULL, mac_addr, NULL) < 0) {
+ wpa_printf(MSG_ERROR,
+ "CTRL_IFACE interface creation failed");
+ return -1;
+ }
- return wpa_supplicant_add_iface(global, &iface, NULL) ? 0 : -1;
+ wpa_printf(MSG_DEBUG,
+ "CTRL_IFACE interface '%s' created with MAC addr: "
+ MACSTR, iface.ifname, MAC2STR(mac_addr));
+ }
+
+ if (wpa_supplicant_get_iface(global, iface.ifname))
+ goto fail;
+
+ wpa_s = wpa_supplicant_add_iface(global, &iface, NULL);
+ if (!wpa_s)
+ goto fail;
+ wpa_s->added_vif = create_iface;
+ return 0;
+
+fail:
+ if (create_iface)
+ wpa_drv_if_remove(global->ifaces, WPA_IF_STATION, iface.ifname);
+ return -1;
}
@@ -8581,13 +8636,22 @@
char *cmd)
{
struct wpa_supplicant *wpa_s;
+ int ret;
+ unsigned int delete_iface;
wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_REMOVE '%s'", cmd);
wpa_s = wpa_supplicant_get_iface(global, cmd);
if (wpa_s == NULL)
return -1;
- return wpa_supplicant_remove_iface(global, wpa_s, 0);
+ delete_iface = wpa_s->added_vif;
+ ret = wpa_supplicant_remove_iface(global, wpa_s, 0);
+ if (!ret && delete_iface) {
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE deleting the interface '%s'",
+ cmd);
+ ret = wpa_drv_if_remove(global->ifaces, WPA_IF_STATION, cmd);
+ }
+ return ret;
}
diff --git a/wpa_supplicant/doc/docbook/wpa_gui.sgml b/wpa_supplicant/doc/docbook/wpa_gui.sgml
index fe91236..5f7b49d 100644
--- a/wpa_supplicant/doc/docbook/wpa_gui.sgml
+++ b/wpa_supplicant/doc/docbook/wpa_gui.sgml
@@ -16,6 +16,7 @@
<command>wpa_gui</command>
<arg>-p <replaceable>path to ctrl sockets</replaceable></arg>
<arg>-i <replaceable>ifname</replaceable></arg>
+ <arg>-m <replaceable>seconds</replaceable></arg>
<arg>-t</arg>
<arg>-q</arg>
</cmdsynopsis>
@@ -52,6 +53,14 @@
</varlistentry>
<varlistentry>
+ <term>-m seconds</term>
+
+ <listitem><para>Set the update interval in seconds for the signal
+ strength meter. This value must be a positive integer, otherwise
+ meter is not enabled (default behavior).</para></listitem>
+ </varlistentry>
+
+ <varlistentry>
<term>-t</term>
<listitem><para>Start program in the system tray only (if the window
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index 6ed2549..11946cd 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -1085,14 +1085,13 @@
struct wpa_bss *selected = NULL;
int prio;
struct wpa_ssid *next_ssid = NULL;
+ struct wpa_ssid *ssid;
if (wpa_s->last_scan_res == NULL ||
wpa_s->last_scan_res_used == 0)
return NULL; /* no scan results from last update */
if (wpa_s->next_ssid) {
- struct wpa_ssid *ssid;
-
/* check that next_ssid is still valid */
for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
if (ssid == wpa_s->next_ssid)
@@ -1128,6 +1127,27 @@
break;
}
+ ssid = *selected_ssid;
+ if (selected && ssid && ssid->mem_only_psk && !ssid->psk_set &&
+ !ssid->passphrase && !ssid->ext_psk) {
+ const char *field_name, *txt = NULL;
+
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "PSK/passphrase not yet available for the selected network");
+
+ wpas_notify_network_request(wpa_s, ssid,
+ WPA_CTRL_REQ_PSK_PASSPHRASE, NULL);
+
+ field_name = wpa_supplicant_ctrl_req_to_string(
+ WPA_CTRL_REQ_PSK_PASSPHRASE, NULL, &txt);
+ if (field_name == NULL)
+ return NULL;
+
+ wpas_send_ctrl_req(wpa_s, ssid, field_name, txt);
+
+ selected = NULL;
+ }
+
return selected;
}
@@ -1266,7 +1286,9 @@
struct wpa_ssid *ssid)
{
struct wpa_bss *current_bss = NULL;
+#ifndef CONFIG_NO_ROAMING
int min_diff;
+#endif /* CONFIG_NO_ROAMING */
if (wpa_s->reassociate)
return 1; /* explicit request to reassociate */
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index bb61808..4c71ef4 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -5504,18 +5504,26 @@
(freq > 0 && !freq_included(channels, freq)))
freq = 0;
}
- } else {
+ } else if (ssid->mode == WPAS_MODE_INFRA) {
freq = neg_freq;
- if (freq < 0 ||
- (freq > 0 && !freq_included(channels, freq)))
- freq = 0;
- }
+ if (freq <= 0 || !freq_included(channels, freq)) {
+ struct os_reltime now;
+ struct wpa_bss *bss =
+ wpa_bss_get_p2p_dev_addr(wpa_s, ssid->bssid);
- if (ssid->mode == WPAS_MODE_INFRA)
+ os_get_reltime(&now);
+ if (bss &&
+ !os_reltime_expired(&now, &bss->last_update, 5) &&
+ freq_included(channels, bss->freq))
+ freq = bss->freq;
+ else
+ freq = 0;
+ }
+
return wpas_start_p2p_client(wpa_s, ssid, addr_allocated, freq);
-
- if (ssid->mode != WPAS_MODE_P2P_GO)
+ } else {
return -1;
+ }
if (wpas_p2p_init_go_params(wpa_s, ¶ms, freq, ht40, vht, channels))
return -1;
diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c
index 2b40bbf..1a4579e 100644
--- a/wpa_supplicant/wpa_cli.c
+++ b/wpa_supplicant/wpa_cli.c
@@ -92,6 +92,7 @@
static DEFINE_DL_LIST(p2p_peers); /* struct cli_txt_entry */
static DEFINE_DL_LIST(p2p_groups); /* struct cli_txt_entry */
static DEFINE_DL_LIST(ifnames); /* struct cli_txt_entry */
+static DEFINE_DL_LIST(networks); /* struct cli_txt_entry */
static void print_help(const char *cmd);
@@ -99,6 +100,7 @@
static void wpa_cli_close_connection(void);
static char * wpa_cli_get_default_ifname(void);
static char ** wpa_list_cmd_list(void);
+static void update_networks(struct wpa_ctrl *ctrl);
static void usage(void)
@@ -168,11 +170,12 @@
#ifdef CONFIG_P2P
-static void cli_txt_list_del_word(struct dl_list *txt_list, const char *txt)
+static void cli_txt_list_del_word(struct dl_list *txt_list, const char *txt,
+ int separator)
{
const char *end;
char *buf;
- end = os_strchr(txt, ' ');
+ end = os_strchr(txt, separator);
if (end == NULL)
end = txt + os_strlen(txt);
buf = dup_binstr(txt, end - txt);
@@ -213,14 +216,16 @@
os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
return cli_txt_list_add(txt_list, buf);
}
+#endif /* CONFIG_P2P */
-static int cli_txt_list_add_word(struct dl_list *txt_list, const char *txt)
+static int cli_txt_list_add_word(struct dl_list *txt_list, const char *txt,
+ int separator)
{
const char *end;
char *buf;
int ret;
- end = os_strchr(txt, ' ');
+ end = os_strchr(txt, separator);
if (end == NULL)
end = txt + os_strlen(txt);
buf = dup_binstr(txt, end - txt);
@@ -230,7 +235,6 @@
os_free(buf);
return ret;
}
-#endif /* CONFIG_P2P */
static char ** cli_txt_list_array(struct dl_list *txt_list)
@@ -1451,14 +1455,18 @@
static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
- return wpa_ctrl_command(ctrl, "ADD_NETWORK");
+ int res = wpa_ctrl_command(ctrl, "ADD_NETWORK");
+ update_networks(ctrl);
+ return res;
}
static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
- return wpa_cli_cmd(ctrl, "REMOVE_NETWORK", 1, argc, argv);
+ int res = wpa_cli_cmd(ctrl, "REMOVE_NETWORK", 1, argc, argv);
+ update_networks(ctrl);
+ return res;
}
@@ -1519,6 +1527,105 @@
}
+static const char *network_fields[] = {
+ "ssid", "scan_ssid", "bssid", "bssid_blacklist",
+ "bssid_whitelist", "psk", "proto", "key_mgmt",
+ "bg_scan_period", "pairwise", "group", "auth_alg", "scan_freq",
+ "freq_list",
+#ifdef IEEE8021X_EAPOL
+ "eap", "identity", "anonymous_identity", "password", "ca_cert",
+ "ca_path", "client_cert", "private_key", "private_key_passwd",
+ "dh_file", "subject_match", "altsubject_match",
+ "domain_suffix_match", "domain_match", "ca_cert2", "ca_path2",
+ "client_cert2", "private_key2", "private_key2_passwd",
+ "dh_file2", "subject_match2", "altsubject_match2",
+ "domain_suffix_match2", "domain_match2", "phase1", "phase2",
+ "pcsc", "pin", "engine_id", "key_id", "cert_id", "ca_cert_id",
+ "pin2", "engine2_id", "key2_id", "cert2_id", "ca_cert2_id",
+ "engine", "engine2", "eapol_flags", "sim_num",
+ "openssl_ciphers", "erp",
+#endif /* IEEE8021X_EAPOL */
+ "wep_key0", "wep_key1", "wep_key2", "wep_key3",
+ "wep_tx_keyidx", "priority",
+#ifdef IEEE8021X_EAPOL
+ "eap_workaround", "pac_file", "fragment_size", "ocsp",
+#endif /* IEEE8021X_EAPOL */
+#ifdef CONFIG_MESH
+ "mode", "no_auto_peer",
+#else /* CONFIG_MESH */
+ "mode",
+#endif /* CONFIG_MESH */
+ "proactive_key_caching", "disabled", "id_str",
+#ifdef CONFIG_IEEE80211W
+ "ieee80211w",
+#endif /* CONFIG_IEEE80211W */
+ "peerkey", "mixed_cell", "frequency", "fixed_freq",
+#ifdef CONFIG_MESH
+ "mesh_basic_rates", "dot11MeshMaxRetries",
+ "dot11MeshRetryTimeout", "dot11MeshConfirmTimeout",
+ "dot11MeshHoldingTimeout",
+#endif /* CONFIG_MESH */
+ "wpa_ptk_rekey", "bgscan", "ignore_broadcast_ssid",
+#ifdef CONFIG_P2P
+ "go_p2p_dev_addr", "p2p_client_list", "psk_list",
+#endif /* CONFIG_P2P */
+#ifdef CONFIG_HT_OVERRIDES
+ "disable_ht", "disable_ht40", "disable_sgi", "disable_ldpc",
+ "ht40_intolerant", "disable_max_amsdu", "ampdu_factor",
+ "ampdu_density", "ht_mcs",
+#endif /* CONFIG_HT_OVERRIDES */
+#ifdef CONFIG_VHT_OVERRIDES
+ "disable_vht", "vht_capa", "vht_capa_mask", "vht_rx_mcs_nss_1",
+ "vht_rx_mcs_nss_2", "vht_rx_mcs_nss_3", "vht_rx_mcs_nss_4",
+ "vht_rx_mcs_nss_5", "vht_rx_mcs_nss_6", "vht_rx_mcs_nss_7",
+ "vht_rx_mcs_nss_8", "vht_tx_mcs_nss_1", "vht_tx_mcs_nss_2",
+ "vht_tx_mcs_nss_3", "vht_tx_mcs_nss_4", "vht_tx_mcs_nss_5",
+ "vht_tx_mcs_nss_6", "vht_tx_mcs_nss_7", "vht_tx_mcs_nss_8",
+#endif /* CONFIG_VHT_OVERRIDES */
+ "ap_max_inactivity", "dtim_period", "beacon_int",
+#ifdef CONFIG_MACSEC
+ "macsec_policy",
+#endif /* CONFIG_MACSEC */
+#ifdef CONFIG_HS20
+ "update_identifier",
+#endif /* CONFIG_HS20 */
+ "mac_addr"
+};
+
+
+static char ** wpa_cli_complete_network(const char *str, int pos)
+{
+ int arg = get_cmd_arg_num(str, pos);
+ int i, num_fields = ARRAY_SIZE(network_fields);
+ char **res = NULL;
+
+ switch (arg) {
+ case 1:
+ res = cli_txt_list_array(&networks);
+ break;
+ case 2:
+ res = os_calloc(num_fields + 1, sizeof(char *));
+ if (res == NULL)
+ return NULL;
+ for (i = 0; i < num_fields; i++) {
+ res[i] = os_strdup(network_fields[i]);
+ if (res[i] == NULL)
+ break;
+ }
+ }
+ return res;
+}
+
+
+static char ** wpa_cli_complete_network_id(const char *str, int pos)
+{
+ int arg = get_cmd_arg_num(str, pos);
+ if (arg == 1)
+ return cli_txt_list_array(&networks);
+ return NULL;
+}
+
+
static int wpa_cli_cmd_dup_network(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
@@ -1537,6 +1644,31 @@
}
+static char ** wpa_cli_complete_dup_network(const char *str, int pos)
+{
+ int arg = get_cmd_arg_num(str, pos);
+ int i, num_fields = ARRAY_SIZE(network_fields);
+ char **res = NULL;
+
+ switch (arg) {
+ case 1:
+ case 2:
+ res = cli_txt_list_array(&networks);
+ break;
+ case 3:
+ res = os_calloc(num_fields + 1, sizeof(char *));
+ if (res == NULL)
+ return NULL;
+ for (i = 0; i < num_fields; i++) {
+ res[i] = os_strdup(network_fields[i]);
+ if (res[i] == NULL)
+ break;
+ }
+ }
+ return res;
+}
+
+
static int wpa_cli_cmd_list_creds(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
@@ -1711,20 +1843,20 @@
printf("Invalid INTERFACE_ADD command: needs at least one "
"argument (interface name)\n"
"All arguments: ifname confname driver ctrl_interface "
- "driver_param bridge_name\n");
+ "driver_param bridge_name [create]\n");
return -1;
}
/*
* INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
- * <driver_param>TAB<bridge_name>
+ * <driver_param>TAB<bridge_name>[TAB<create>]
*/
res = os_snprintf(cmd, sizeof(cmd),
- "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
+ "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s\t%s",
argv[0],
argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
- argc > 5 ? argv[5] : "");
+ argc > 5 ? argv[5] : "", argc > 6 ? argv[6] : "");
if (os_snprintf_error(sizeof(cmd), res))
return -1;
cmd[sizeof(cmd) - 1] = '\0';
@@ -2776,29 +2908,33 @@
{ "list_networks", wpa_cli_cmd_list_networks, NULL,
cli_cmd_flag_none,
"= list configured networks" },
- { "select_network", wpa_cli_cmd_select_network, NULL,
+ { "select_network", wpa_cli_cmd_select_network,
+ wpa_cli_complete_network_id,
cli_cmd_flag_none,
"<network id> = select a network (disable others)" },
- { "enable_network", wpa_cli_cmd_enable_network, NULL,
+ { "enable_network", wpa_cli_cmd_enable_network,
+ wpa_cli_complete_network_id,
cli_cmd_flag_none,
"<network id> = enable a network" },
- { "disable_network", wpa_cli_cmd_disable_network, NULL,
+ { "disable_network", wpa_cli_cmd_disable_network,
+ wpa_cli_complete_network_id,
cli_cmd_flag_none,
"<network id> = disable a network" },
{ "add_network", wpa_cli_cmd_add_network, NULL,
cli_cmd_flag_none,
"= add a network" },
- { "remove_network", wpa_cli_cmd_remove_network, NULL,
+ { "remove_network", wpa_cli_cmd_remove_network,
+ wpa_cli_complete_network_id,
cli_cmd_flag_none,
"<network id> = remove a network" },
- { "set_network", wpa_cli_cmd_set_network, NULL,
+ { "set_network", wpa_cli_cmd_set_network, wpa_cli_complete_network,
cli_cmd_flag_sensitive,
"<network id> <variable> <value> = set network variables (shows\n"
" list of variables when run without arguments)" },
- { "get_network", wpa_cli_cmd_get_network, NULL,
+ { "get_network", wpa_cli_cmd_get_network, wpa_cli_complete_network,
cli_cmd_flag_none,
"<network id> <variable> = get network variables" },
- { "dup_network", wpa_cli_cmd_dup_network, NULL,
+ { "dup_network", wpa_cli_cmd_dup_network, wpa_cli_complete_dup_network,
cli_cmd_flag_none,
"<src network id> <dst network id> <variable> = duplicate network variables"
},
@@ -3614,7 +3750,7 @@
s = os_strchr(start, ' ');
if (s == NULL)
return;
- cli_txt_list_add_word(&p2p_groups, s + 1);
+ cli_txt_list_add_word(&p2p_groups, s + 1, ' ');
return;
}
@@ -3622,7 +3758,7 @@
s = os_strchr(start, ' ');
if (s == NULL)
return;
- cli_txt_list_del_word(&p2p_groups, s + 1);
+ cli_txt_list_del_word(&p2p_groups, s + 1, ' ');
return;
}
#endif /* CONFIG_P2P */
@@ -3781,7 +3917,11 @@
ps = wpa_ctrl_get_remote_ifname(ctrl_conn);
#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
+#ifdef CONFIG_WPA_CLI_HISTORY_DIR
+ home = CONFIG_WPA_CLI_HISTORY_DIR;
+#else /* CONFIG_WPA_CLI_HISTORY_DIR */
home = getenv("HOME");
+#endif /* CONFIG_WPA_CLI_HISTORY_DIR */
if (home) {
const char *fname = ".wpa_cli_history";
int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
@@ -3864,6 +4004,38 @@
}
+static void update_networks(struct wpa_ctrl *ctrl)
+{
+ char buf[4096];
+ size_t len = sizeof(buf);
+ int ret;
+ char *cmd = "LIST_NETWORKS";
+ char *pos, *end;
+ int header = 1;
+
+ cli_txt_list_flush(&networks);
+
+ if (ctrl == NULL)
+ return;
+ ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
+ if (ret < 0)
+ return;
+ buf[len] = '\0';
+
+ pos = buf;
+ while (pos) {
+ end = os_strchr(pos, '\n');
+ if (end == NULL)
+ break;
+ *end = '\0';
+ if (!header)
+ cli_txt_list_add_word(&networks, pos, '\t');
+ header = 0;
+ pos = end + 1;
+ }
+}
+
+
static void try_connection(void *eloop_ctx, void *timeout_ctx)
{
if (ctrl_conn)
@@ -3884,6 +4056,7 @@
}
update_bssid_list(ctrl_conn);
+ update_networks(ctrl_conn);
if (warning_displayed)
printf("Connection established.\n");
@@ -3905,6 +4078,7 @@
cli_txt_list_flush(&p2p_groups);
cli_txt_list_flush(&bsses);
cli_txt_list_flush(&ifnames);
+ cli_txt_list_flush(&networks);
if (edit_started)
edit_deinit(hfile, wpa_cli_edit_filter_history_cb);
os_free(hfile);
diff --git a/wpa_supplicant/wpa_gui-qt4/wpagui.cpp b/wpa_supplicant/wpa_gui-qt4/wpagui.cpp
index bc6fa7f..408e387 100644
--- a/wpa_supplicant/wpa_gui-qt4/wpagui.cpp
+++ b/wpa_supplicant/wpa_gui-qt4/wpagui.cpp
@@ -135,6 +135,7 @@
monitor_conn = NULL;
msgNotifier = NULL;
ctrl_iface_dir = strdup("/var/run/wpa_supplicant");
+ signalMeterInterval = 0;
parse_argv();
@@ -161,6 +162,10 @@
timer->setSingleShot(FALSE);
timer->start(1000);
+ signalMeterTimer = new QTimer(this);
+ signalMeterTimer->setInterval(signalMeterInterval);
+ connect(signalMeterTimer, SIGNAL(timeout()), SLOT(signalMeterUpdate()));
+
if (openCtrlConnection(ctrl_iface) < 0) {
debug("Failed to open control connection to "
"wpa_supplicant.");
@@ -234,7 +239,7 @@
{
int c;
for (;;) {
- c = getopt(qApp->argc(), qApp->argv(), "i:p:tq");
+ c = getopt(qApp->argc(), qApp->argv(), "i:m:p:tq");
if (c < 0)
break;
switch (c) {
@@ -242,6 +247,9 @@
free(ctrl_iface);
ctrl_iface = strdup(optarg);
break;
+ case 'm':
+ signalMeterInterval = atoi(optarg) * 1000;
+ break;
case 'p':
free(ctrl_iface_dir);
ctrl_iface_dir = strdup(optarg);
@@ -496,6 +504,8 @@
textBssid->clear();
textIpAddress->clear();
updateTrayToolTip(tr("no status information"));
+ updateTrayIcon(TrayIconOffline);
+ signalMeterTimer->stop();
#ifdef CONFIG_NATIVE_WINDOWS
static bool first = true;
@@ -544,6 +554,11 @@
ssid_updated = true;
textSsid->setText(pos);
updateTrayToolTip(pos + tr(" (associated)"));
+ if (!signalMeterInterval) {
+ /* if signal meter is not enabled show
+ * full signal strength */
+ updateTrayIcon(TrayIconSignalExcellent);
+ }
} else if (strcmp(start, "ip_address") == 0) {
ipaddr_updated = true;
textIpAddress->setText(pos);
@@ -587,6 +602,23 @@
} else
textEncryption->clear();
+ if (signalMeterInterval) {
+ /*
+ * Handle signal meter service. When network is not associated,
+ * deactivate timer, otherwise keep it going. Tray icon has to
+ * be initialized here, because of the initial delay of the
+ * timer.
+ */
+ if (ssid_updated) {
+ if (!signalMeterTimer->isActive()) {
+ updateTrayIcon(TrayIconConnected);
+ signalMeterTimer->start();
+ }
+ } else {
+ signalMeterTimer->stop();
+ }
+ }
+
if (!status_updated)
textStatus->clear();
if (!auth_updated)
@@ -594,6 +626,7 @@
if (!ssid_updated) {
textSsid->clear();
updateTrayToolTip(tr("(not-associated)"));
+ updateTrayIcon(TrayIconOffline);
}
if (!bssid_updated)
textBssid->clear();
@@ -828,6 +861,53 @@
}
+void WpaGui::signalMeterUpdate()
+{
+ char reply[128];
+ size_t reply_len = sizeof(reply);
+ char *rssi;
+ int rssi_value;
+
+ ctrlRequest("SIGNAL_POLL", reply, &reply_len);
+
+ /* In order to eliminate signal strength fluctuations, try
+ * to obtain averaged RSSI value in the first place. */
+ if ((rssi = strstr(reply, "AVG_RSSI=")) != NULL)
+ rssi_value = atoi(&rssi[sizeof("AVG_RSSI")]);
+ else if ((rssi = strstr(reply, "RSSI=")) != NULL)
+ rssi_value = atoi(&rssi[sizeof("RSSI")]);
+ else {
+ debug("Failed to get RSSI value");
+ updateTrayIcon(TrayIconSignalNone);
+ return;
+ }
+
+ debug("RSSI value: %d", rssi_value);
+
+ /*
+ * NOTE: The code below assumes, that the unit of the value returned
+ * by the SIGNAL POLL request is dBm. It might not be true for all
+ * wpa_supplicant drivers.
+ */
+
+ /*
+ * Calibration is based on "various Internet sources". Nonetheless,
+ * it seems to be compatible with the Windows 8.1 strength meter -
+ * tested on Intel Centrino Advanced-N 6235.
+ */
+ if (rssi_value >= -60)
+ updateTrayIcon(TrayIconSignalExcellent);
+ else if (rssi_value >= -68)
+ updateTrayIcon(TrayIconSignalGood);
+ else if (rssi_value >= -76)
+ updateTrayIcon(TrayIconSignalOk);
+ else if (rssi_value >= -84)
+ updateTrayIcon(TrayIconSignalWeak);
+ else
+ updateTrayIcon(TrayIconSignalNone);
+}
+
+
static int str_match(const char *a, const char *b)
{
return strncmp(a, b, strlen(b)) == 0;
@@ -1278,10 +1358,7 @@
QApplication::setQuitOnLastWindowClosed(false);
tray_icon = new QSystemTrayIcon(this);
- if (QImageReader::supportedImageFormats().contains(QByteArray("svg")))
- tray_icon->setIcon(QIcon(":/icons/wpa_gui.svg"));
- else
- tray_icon->setIcon(QIcon(":/icons/wpa_gui.png"));
+ updateTrayIcon(TrayIconOffline);
connect(tray_icon,
SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
@@ -1421,6 +1498,59 @@
}
+void WpaGui::updateTrayIcon(TrayIconType type)
+{
+ if (!tray_icon || currentIconType == type)
+ return;
+
+ QIcon icon;
+ QIcon fallback_icon;
+
+ if (QImageReader::supportedImageFormats().contains(QByteArray("svg")))
+ fallback_icon = QIcon(":/icons/wpa_gui.svg");
+ else
+ fallback_icon = QIcon(":/icons/wpa_gui.png");
+
+ switch (type) {
+ case TrayIconOffline:
+ icon = QIcon::fromTheme("network-wireless-offline",
+ fallback_icon);
+ break;
+ case TrayIconAcquiring:
+ icon = QIcon::fromTheme("network-wireless-acquiring",
+ fallback_icon);
+ break;
+ case TrayIconConnected:
+ icon = QIcon::fromTheme("network-wireless-connected",
+ fallback_icon);
+ break;
+ case TrayIconSignalNone:
+ icon = QIcon::fromTheme("network-wireless-signal-none",
+ fallback_icon);
+ break;
+ case TrayIconSignalWeak:
+ icon = QIcon::fromTheme("network-wireless-signal-weak",
+ fallback_icon);
+ break;
+ case TrayIconSignalOk:
+ icon = QIcon::fromTheme("network-wireless-signal-ok",
+ fallback_icon);
+ break;
+ case TrayIconSignalGood:
+ icon = QIcon::fromTheme("network-wireless-signal-good",
+ fallback_icon);
+ break;
+ case TrayIconSignalExcellent:
+ icon = QIcon::fromTheme("network-wireless-signal-excellent",
+ fallback_icon);
+ break;
+ }
+
+ currentIconType = type;
+ tray_icon->setIcon(icon);
+}
+
+
void WpaGui::closeEvent(QCloseEvent *event)
{
if (eh) {
diff --git a/wpa_supplicant/wpa_gui-qt4/wpagui.h b/wpa_supplicant/wpa_gui-qt4/wpagui.h
index 026eacb..c0de67b 100644
--- a/wpa_supplicant/wpa_gui-qt4/wpagui.h
+++ b/wpa_supplicant/wpa_gui-qt4/wpagui.h
@@ -22,6 +22,18 @@
Q_OBJECT
public:
+
+ enum TrayIconType {
+ TrayIconOffline = 0,
+ TrayIconAcquiring,
+ TrayIconConnected,
+ TrayIconSignalNone,
+ TrayIconSignalWeak,
+ TrayIconSignalOk,
+ TrayIconSignalGood,
+ TrayIconSignalExcellent,
+ };
+
WpaGui(QApplication *app, QWidget *parent = 0, const char *name = 0,
Qt::WFlags fl = 0);
~WpaGui();
@@ -49,6 +61,7 @@
virtual void scan();
virtual void eventHistory();
virtual void ping();
+ virtual void signalMeterUpdate();
virtual void processMsg(char *msg);
virtual void processCtrlReq(const char *req);
virtual void receiveMsgs();
@@ -70,6 +83,7 @@
virtual void showTrayMessage(QSystemTrayIcon::MessageIcon type,
int sec, const QString &msg);
virtual void showTrayStatus();
+ virtual void updateTrayIcon(TrayIconType type);
virtual void updateTrayToolTip(const QString &msg);
virtual void wpsDialog();
virtual void peersDialog();
@@ -113,6 +127,7 @@
QAction *quitAction;
QMenu *tray_menu;
QSystemTrayIcon *tray_icon;
+ TrayIconType currentIconType;
QString wpaStateTranslate(char *state);
void createTrayIcon(bool);
bool ackTrayIcon;
@@ -127,6 +142,9 @@
void stopWpsRun(bool success);
+ QTimer *signalMeterTimer;
+ int signalMeterInterval;
+
#ifdef CONFIG_NATIVE_WINDOWS
QAction *fileStartServiceAction;
QAction *fileStopServiceAction;
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 6f5fbad..f690b91 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -1239,7 +1239,12 @@
}
if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
- wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN, NULL);
+ int psk_set = 0;
+
+ if (ssid->psk_set) {
+ wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN, NULL);
+ psk_set = 1;
+ }
#ifndef CONFIG_NO_PBKDF2
if (bss && ssid->bssid_set && ssid->ssid_len == 0 &&
ssid->passphrase) {
@@ -1249,6 +1254,7 @@
wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
psk, PMK_LEN);
wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL);
+ psk_set = 1;
os_memset(psk, 0, sizeof(psk));
}
#endif /* CONFIG_NO_PBKDF2 */
@@ -1286,6 +1292,7 @@
"external passphrase)",
psk, PMK_LEN);
wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL);
+ psk_set = 1;
os_memset(psk, 0, sizeof(psk));
} else
#endif /* CONFIG_NO_PBKDF2 */
@@ -1298,6 +1305,7 @@
return -1;
}
wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL);
+ psk_set = 1;
os_memset(psk, 0, sizeof(psk));
} else {
wpa_msg(wpa_s, MSG_INFO, "EXT PW: No suitable "
@@ -1311,6 +1319,12 @@
ext_password_free(pw);
}
#endif /* CONFIG_EXT_PASSWORD */
+
+ if (!psk_set) {
+ wpa_msg(wpa_s, MSG_INFO,
+ "No PSK available for association");
+ return -1;
+ }
} else
wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
@@ -4967,6 +4981,15 @@
str_clear_free(eap->external_sim_resp);
eap->external_sim_resp = os_strdup(value);
break;
+ case WPA_CTRL_REQ_PSK_PASSPHRASE:
+ if (wpa_config_set(ssid, "psk", value, 0) < 0)
+ return -1;
+ ssid->mem_only_psk = 1;
+ if (ssid->passphrase)
+ wpa_config_update_psk(ssid);
+ if (wpa_s->wpa_state == WPA_SCANNING && !wpa_s->scanning)
+ wpa_supplicant_req_scan(wpa_s, 0, 0);
+ break;
default:
wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", field);
return -1;
@@ -5014,7 +5037,8 @@
}
if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set &&
- (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk)
+ (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk &&
+ !ssid->mem_only_psk)
return 1;
return 0;
diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf
index 8964b3f..853b156 100644
--- a/wpa_supplicant/wpa_supplicant.conf
+++ b/wpa_supplicant/wpa_supplicant.conf
@@ -740,6 +740,11 @@
# startup and reconfiguration time can be optimized by generating the PSK only
# only when the passphrase or SSID has actually changed.
#
+# mem_only_psk: Whether to keep PSK/passphrase only in memory
+# 0 = allow psk/passphrase to be stored to the configuration file
+# 1 = do not store psk/passphrase to the configuration file
+#mem_only_psk=0
+#
# eapol_flags: IEEE 802.1X/EAPOL options (bit field)
# Dynamic WEP key required for non-WPA mode
# bit0 (1): require dynamically generated unicast WEP key
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index 0ec102f..2d517f1 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -648,6 +648,7 @@
unsigned int eap_expected_failure:1;
unsigned int reattach:1; /* reassociation to the same BSS requested */
unsigned int mac_addr_changed:1;
+ unsigned int added_vif:1;
struct os_reltime last_mac_addr_change;
int last_mac_addr_style;
diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c
index 1bb82ba..48a5d69 100644
--- a/wpa_supplicant/wpas_glue.c
+++ b/wpa_supplicant/wpas_glue.c
@@ -737,6 +737,8 @@
return WPA_CTRL_REQ_EAP_PASSPHRASE;
else if (os_strcmp(field, "SIM") == 0)
return WPA_CTRL_REQ_SIM;
+ else if (os_strcmp(field, "PSK_PASSPHRASE") == 0)
+ return WPA_CTRL_REQ_PSK_PASSPHRASE;
return WPA_CTRL_REQ_UNKNOWN;
}
@@ -776,6 +778,10 @@
case WPA_CTRL_REQ_SIM:
ret = "SIM";
break;
+ case WPA_CTRL_REQ_PSK_PASSPHRASE:
+ *txt = "PSK or passphrase";
+ ret = "PSK_PASSPHRASE";
+ break;
default:
break;
}
@@ -789,6 +795,35 @@
return ret;
}
+
+void wpas_send_ctrl_req(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
+ const char *field_name, const char *txt)
+{
+ char *buf;
+ size_t buflen;
+ int len;
+
+ buflen = 100 + os_strlen(txt) + ssid->ssid_len;
+ buf = os_malloc(buflen);
+ if (buf == NULL)
+ return;
+ len = os_snprintf(buf, buflen, "%s-%d:%s needed for SSID ",
+ field_name, ssid->id, txt);
+ if (os_snprintf_error(buflen, len)) {
+ os_free(buf);
+ return;
+ }
+ if (ssid->ssid && buflen > len + ssid->ssid_len) {
+ os_memcpy(buf + len, ssid->ssid, ssid->ssid_len);
+ len += ssid->ssid_len;
+ buf[len] = '\0';
+ }
+ buf[buflen - 1] = '\0';
+ wpa_msg(wpa_s, MSG_INFO, WPA_CTRL_REQ "%s", buf);
+ os_free(buf);
+}
+
+
#ifdef IEEE8021X_EAPOL
#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
static void wpa_supplicant_eap_param_needed(void *ctx,
@@ -798,9 +833,6 @@
struct wpa_supplicant *wpa_s = ctx;
struct wpa_ssid *ssid = wpa_s->current_ssid;
const char *field_name, *txt = NULL;
- char *buf;
- size_t buflen;
- int len;
if (ssid == NULL)
return;
@@ -817,25 +849,7 @@
wpas_notify_eap_status(wpa_s, "eap parameter needed", field_name);
- buflen = 100 + os_strlen(txt) + ssid->ssid_len;
- buf = os_malloc(buflen);
- if (buf == NULL)
- return;
- len = os_snprintf(buf, buflen,
- WPA_CTRL_REQ "%s-%d:%s needed for SSID ",
- field_name, ssid->id, txt);
- if (os_snprintf_error(buflen, len)) {
- os_free(buf);
- return;
- }
- if (ssid->ssid && buflen > len + ssid->ssid_len) {
- os_memcpy(buf + len, ssid->ssid, ssid->ssid_len);
- len += ssid->ssid_len;
- buf[len] = '\0';
- }
- buf[buflen - 1] = '\0';
- wpa_msg(wpa_s, MSG_INFO, "%s", buf);
- os_free(buf);
+ wpas_send_ctrl_req(wpa_s, ssid, field_name, txt);
}
#else /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
#define wpa_supplicant_eap_param_needed NULL
diff --git a/wpa_supplicant/wpas_glue.h b/wpa_supplicant/wpas_glue.h
index 9808c22..5585e56 100644
--- a/wpa_supplicant/wpas_glue.h
+++ b/wpa_supplicant/wpas_glue.h
@@ -22,4 +22,7 @@
enum wpa_ctrl_req_type wpa_supplicant_ctrl_req_from_string(const char *field);
+void wpas_send_ctrl_req(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
+ const char *field_name, const char *txt);
+
#endif /* WPAS_GLUE_H */