Allow PSK/passphrase to be set only when needed
The new network profile parameter mem_only_psk=1 can be used to specify that the PSK/passphrase for that network is requested over the control interface (ctrl_iface or D-Bus) similarly to the EAP network parameter requests. The PSK/passphrase can then be configured temporarily in a way that prevents it from getting stored to the configuration file. For example: Event: CTRL-REQ-PSK_PASSPHRASE-0:PSK or passphrase needed for SSID test-wpa2-psk Response: CTRL-RSP-PSK_PASSPHRASE-0:"qwertyuiop" Note: The response value uses the same encoding as the psk network profile parameter, i.e., passphrase is within double quotation marks. Signed-off-by: Jouni Malinen <j@w1.fi>
This commit is contained in:
parent
b898a6ee72
commit
a52410c29f
9 changed files with 109 additions and 27 deletions
|
@ -310,6 +310,7 @@ enum wpa_ctrl_req_type {
|
|||
WPA_CTRL_REQ_EAP_OTP,
|
||||
WPA_CTRL_REQ_EAP_PASSPHRASE,
|
||||
WPA_CTRL_REQ_SIM,
|
||||
WPA_CTRL_REQ_PSK_PASSPHRASE,
|
||||
NUM_WPA_CTRL_REQS
|
||||
};
|
||||
|
||||
|
|
|
@ -1816,6 +1816,7 @@ static const struct parse_data ssid_fields[] = {
|
|||
{ FUNC(bssid_blacklist) },
|
||||
{ FUNC(bssid_whitelist) },
|
||||
{ FUNC_KEY(psk) },
|
||||
{ INT(mem_only_psk) },
|
||||
{ FUNC(proto) },
|
||||
{ FUNC(key_mgmt) },
|
||||
{ INT(bg_scan_period) },
|
||||
|
|
|
@ -501,7 +501,12 @@ static void write_bssid(FILE *f, struct wpa_ssid *ssid)
|
|||
|
||||
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 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid)
|
|||
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);
|
||||
|
|
|
@ -180,6 +180,14 @@ struct wpa_ssid {
|
|||
*/
|
||||
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_*
|
||||
*/
|
||||
|
|
|
@ -1085,14 +1085,13 @@ struct wpa_bss * wpa_supplicant_pick_network(struct wpa_supplicant *wpa_s,
|
|||
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 @@ struct wpa_bss * wpa_supplicant_pick_network(struct wpa_supplicant *wpa_s,
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -1239,7 +1239,12 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
|
|||
}
|
||||
|
||||
if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
|
||||
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 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
|
|||
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 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
|
|||
"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 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
|
|||
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 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
|
|||
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 @@ int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
|
|||
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 @@ int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
|
|||
}
|
||||
|
||||
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;
|
||||
|
|
|
@ -740,6 +740,11 @@ fast_reauth=1
|
|||
# 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
|
||||
|
|
|
@ -737,6 +737,8 @@ enum wpa_ctrl_req_type wpa_supplicant_ctrl_req_from_string(const char *field)
|
|||
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 @@ const char * wpa_supplicant_ctrl_req_to_string(enum wpa_ctrl_req_type field,
|
|||
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 @@ const char * wpa_supplicant_ctrl_req_to_string(enum wpa_ctrl_req_type field,
|
|||
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 @@ 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;
|
||||
|
@ -817,25 +849,7 @@ static void wpa_supplicant_eap_param_needed(void *ctx,
|
|||
|
||||
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
|
||||
|
|
|
@ -22,4 +22,7 @@ const char * wpa_supplicant_ctrl_req_to_string(enum wpa_ctrl_req_type field,
|
|||
|
||||
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 */
|
||||
|
|
Loading…
Reference in a new issue