WPA_CTRL_REQ_EAP_OTP,
WPA_CTRL_REQ_EAP_PASSPHRASE,
WPA_CTRL_REQ_SIM,
+ WPA_CTRL_REQ_PSK_PASSPHRASE,
NUM_WPA_CTRL_REQS
};
{ FUNC(bssid_blacklist) },
{ FUNC(bssid_whitelist) },
{ FUNC_KEY(psk) },
+ { INT(mem_only_psk) },
{ FUNC(proto) },
{ FUNC(key_mgmt) },
{ INT(bg_scan_period) },
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);
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);
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;
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)
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;
}
}
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) {
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 */
"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 */
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 "
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);
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;
}
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;
# 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
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;
}
case WPA_CTRL_REQ_SIM:
ret = "SIM";
break;
+ case WPA_CTRL_REQ_PSK_PASSPHRASE:
+ *txt = "PSK or passphrase";
+ ret = "PSK_PASSPHRASE";
+ break;
default:
break;
}
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,
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;
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
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 */