Cumulative patch from commit 204c9ac4eed9f0ad69497f2efcd0d095dfd6e61c
204c9ac Extend select_network command with freq= to reduce scan time
6a6afc0 Fix radius_example build
75aea3e Interworking: Add writing of forgotten cred parameters into config file
c880ab8 Interworking: Add GET_CRED ctrl_iface command
1619e9d Interworking: Add ctrl_iface events on cred block modifications
Change-Id: I1944c63f5e0debfc465d6852aa908748c227303a
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h
index 6d17228..7f39ccd 100644
--- a/src/common/wpa_ctrl.h
+++ b/src/common/wpa_ctrl.h
@@ -164,6 +164,13 @@
#define INTERWORKING_ALREADY_CONNECTED "INTERWORKING-ALREADY-CONNECTED "
#define INTERWORKING_SELECTED "INTERWORKING-SELECTED "
+/* Credential block added; parameters: <id> */
+#define CRED_ADDED "CRED-ADDED "
+/* Credential block modified; parameters: <id> <field> */
+#define CRED_MODIFIED "CRED-MODIFIED "
+/* Credential block removed; parameters: <id> */
+#define CRED_REMOVED "CRED-REMOVED "
+
#define GAS_RESPONSE_INFO "GAS-RESPONSE-INFO "
/* parameters: <addr> <dialog_token> <freq> */
#define GAS_QUERY_START "GAS-QUERY-START "
diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
index 6a46210..74283eb 100644
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -2796,6 +2796,275 @@
}
+char * alloc_int_str(int val)
+{
+ char *buf;
+
+ buf = os_malloc(20);
+ if (buf == NULL)
+ return NULL;
+ os_snprintf(buf, 20, "%d", val);
+ return buf;
+}
+
+
+char * alloc_strdup(const char *str)
+{
+ if (str == NULL)
+ return NULL;
+ return os_strdup(str);
+}
+
+
+char * wpa_config_get_cred_no_key(struct wpa_cred *cred, const char *var)
+{
+ if (os_strcmp(var, "temporary") == 0)
+ return alloc_int_str(cred->temporary);
+
+ if (os_strcmp(var, "priority") == 0)
+ return alloc_int_str(cred->priority);
+
+ if (os_strcmp(var, "sp_priority") == 0)
+ return alloc_int_str(cred->sp_priority);
+
+ if (os_strcmp(var, "pcsc") == 0)
+ return alloc_int_str(cred->pcsc);
+
+ if (os_strcmp(var, "eap") == 0) {
+ if (!cred->eap_method)
+ return NULL;
+ return alloc_strdup(eap_get_name(cred->eap_method[0].vendor,
+ cred->eap_method[0].method));
+ }
+
+ if (os_strcmp(var, "update_identifier") == 0)
+ return alloc_int_str(cred->update_identifier);
+
+ if (os_strcmp(var, "min_dl_bandwidth_home") == 0)
+ return alloc_int_str(cred->min_dl_bandwidth_home);
+
+ if (os_strcmp(var, "min_ul_bandwidth_home") == 0)
+ return alloc_int_str(cred->min_ul_bandwidth_home);
+
+ if (os_strcmp(var, "min_dl_bandwidth_roaming") == 0)
+ return alloc_int_str(cred->min_dl_bandwidth_roaming);
+
+ if (os_strcmp(var, "min_ul_bandwidth_roaming") == 0)
+ return alloc_int_str(cred->min_ul_bandwidth_roaming);
+
+ if (os_strcmp(var, "max_bss_load") == 0)
+ return alloc_int_str(cred->max_bss_load);
+
+ if (os_strcmp(var, "req_conn_capab") == 0) {
+ unsigned int i;
+ char *buf, *end, *pos;
+ int ret;
+
+ if (!cred->num_req_conn_capab)
+ return NULL;
+
+ buf = os_malloc(4000);
+ if (buf == NULL)
+ return NULL;
+ pos = buf;
+ end = pos + 4000;
+ for (i = 0; i < cred->num_req_conn_capab; i++) {
+ int *ports;
+
+ ret = os_snprintf(pos, end - pos, "%s%u",
+ i > 0 ? "\n" : "",
+ cred->req_conn_capab_proto[i]);
+ if (ret < 0 || ret >= end - pos)
+ return buf;
+ pos += ret;
+
+ ports = cred->req_conn_capab_port[i];
+ if (ports) {
+ int j;
+ for (j = 0; ports[j] != -1; j++) {
+ ret = os_snprintf(pos, end - pos,
+ "%s%d",
+ j > 0 ? "," : ":",
+ ports[j]);
+ if (ret < 0 || ret >= end - pos)
+ return buf;
+ pos += ret;
+ }
+ }
+ }
+
+ return buf;
+ }
+
+ if (os_strcmp(var, "ocsp") == 0)
+ return alloc_int_str(cred->ocsp);
+
+ if (os_strcmp(var, "realm") == 0)
+ return alloc_strdup(cred->realm);
+
+ if (os_strcmp(var, "username") == 0)
+ return alloc_strdup(cred->username);
+
+ if (os_strcmp(var, "password") == 0) {
+ if (!cred->password)
+ return NULL;
+ return alloc_strdup("*");
+ }
+
+ if (os_strcmp(var, "ca_cert") == 0)
+ return alloc_strdup(cred->ca_cert);
+
+ if (os_strcmp(var, "client_cert") == 0)
+ return alloc_strdup(cred->client_cert);
+
+ if (os_strcmp(var, "private_key") == 0)
+ return alloc_strdup(cred->private_key);
+
+ if (os_strcmp(var, "private_key_passwd") == 0) {
+ if (!cred->private_key_passwd)
+ return NULL;
+ return alloc_strdup("*");
+ }
+
+ if (os_strcmp(var, "imsi") == 0)
+ return alloc_strdup(cred->imsi);
+
+ if (os_strcmp(var, "milenage") == 0) {
+ if (!(cred->milenage))
+ return NULL;
+ return alloc_strdup("*");
+ }
+
+ if (os_strcmp(var, "domain_suffix_match") == 0)
+ return alloc_strdup(cred->domain_suffix_match);
+
+ if (os_strcmp(var, "domain") == 0) {
+ unsigned int i;
+ char *buf, *end, *pos;
+ int ret;
+
+ if (!cred->num_domain)
+ return NULL;
+
+ buf = os_malloc(4000);
+ if (buf == NULL)
+ return NULL;
+ pos = buf;
+ end = pos + 4000;
+
+ for (i = 0; i < cred->num_domain; i++) {
+ ret = os_snprintf(pos, end - pos, "%s%s",
+ i > 0 ? "\n" : "", cred->domain[i]);
+ if (ret < 0 || ret >= end - pos)
+ return buf;
+ pos += ret;
+ }
+
+ return buf;
+ }
+
+ if (os_strcmp(var, "phase1") == 0)
+ return alloc_strdup(cred->phase1);
+
+ if (os_strcmp(var, "phase2") == 0)
+ return alloc_strdup(cred->phase2);
+
+ if (os_strcmp(var, "roaming_consortium") == 0) {
+ size_t buflen;
+ char *buf;
+
+ if (!cred->roaming_consortium_len)
+ return NULL;
+ buflen = cred->roaming_consortium_len * 2 + 1;
+ buf = os_malloc(buflen);
+ if (buf == NULL)
+ return NULL;
+ wpa_snprintf_hex(buf, buflen, cred->roaming_consortium,
+ cred->roaming_consortium_len);
+ return buf;
+ }
+
+ if (os_strcmp(var, "required_roaming_consortium") == 0) {
+ size_t buflen;
+ char *buf;
+
+ if (!cred->required_roaming_consortium_len)
+ return NULL;
+ buflen = cred->required_roaming_consortium_len * 2 + 1;
+ buf = os_malloc(buflen);
+ if (buf == NULL)
+ return NULL;
+ wpa_snprintf_hex(buf, buflen, cred->required_roaming_consortium,
+ cred->required_roaming_consortium_len);
+ return buf;
+ }
+
+ if (os_strcmp(var, "excluded_ssid") == 0) {
+ unsigned int i;
+ char *buf, *end, *pos;
+
+ if (!cred->num_excluded_ssid)
+ return NULL;
+
+ buf = os_malloc(4000);
+ if (buf == NULL)
+ return NULL;
+ pos = buf;
+ end = pos + 4000;
+
+ for (i = 0; i < cred->num_excluded_ssid; i++) {
+ struct excluded_ssid *e;
+ int ret;
+
+ e = &cred->excluded_ssid[i];
+ ret = os_snprintf(pos, end - pos, "%s%s",
+ i > 0 ? "\n" : "",
+ wpa_ssid_txt(e->ssid, e->ssid_len));
+ if (ret < 0 || ret >= end - pos)
+ return buf;
+ pos += ret;
+ }
+
+ return buf;
+ }
+
+ if (os_strcmp(var, "roaming_partner") == 0) {
+ unsigned int i;
+ char *buf, *end, *pos;
+
+ if (!cred->num_roaming_partner)
+ return NULL;
+
+ buf = os_malloc(4000);
+ if (buf == NULL)
+ return NULL;
+ pos = buf;
+ end = pos + 4000;
+
+ for (i = 0; i < cred->num_roaming_partner; i++) {
+ struct roaming_partner *p;
+ int ret;
+
+ p = &cred->roaming_partner[i];
+ ret = os_snprintf(pos, end - pos, "%s%s,%d,%u,%s",
+ i > 0 ? "\n" : "",
+ p->fqdn, p->exact_match, p->priority,
+ p->country);
+ if (ret < 0 || ret >= end - pos)
+ return buf;
+ pos += ret;
+ }
+
+ return buf;
+ }
+
+ if (os_strcmp(var, "provisioning_sp") == 0)
+ return alloc_strdup(cred->provisioning_sp);
+
+ return NULL;
+}
+
+
struct wpa_cred * wpa_config_get_cred(struct wpa_config *config, int id)
{
struct wpa_cred *cred;
diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h
index de43970..a398049 100644
--- a/wpa_supplicant/config.h
+++ b/wpa_supplicant/config.h
@@ -1053,6 +1053,7 @@
void wpa_config_free_cred(struct wpa_cred *cred);
int wpa_config_set_cred(struct wpa_cred *cred, const char *var,
const char *value, int line);
+char * wpa_config_get_cred_no_key(struct wpa_cred *cred, const char *var);
struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface,
const char *driver_param);
diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c
index 7394593..505d405 100644
--- a/wpa_supplicant/config_file.c
+++ b/wpa_supplicant/config_file.c
@@ -832,6 +832,32 @@
if (cred->ocsp)
fprintf(f, "\tocsp=%d\n", cred->ocsp);
+
+ if (cred->num_req_conn_capab) {
+ for (i = 0; i < cred->num_req_conn_capab; i++) {
+ int *ports;
+
+ fprintf(f, "\treq_conn_capab=%u",
+ cred->req_conn_capab_proto[i]);
+ ports = cred->req_conn_capab_port[i];
+ if (ports) {
+ int j;
+ for (j = 0; ports[j] != -1; j++) {
+ fprintf(f, "%s%d", j > 0 ? "," : ":",
+ ports[j]);
+ }
+ }
+ fprintf(f, "\n");
+ }
+ }
+
+ if (cred->required_roaming_consortium_len) {
+ fprintf(f, "\trequired_roaming_consortium=");
+ for (i = 0; i < cred->required_roaming_consortium_len; i++)
+ fprintf(f, "%02x",
+ cred->required_roaming_consortium[i]);
+ fprintf(f, "\n");
+ }
}
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index 925ece1..13c0830 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -2305,9 +2305,10 @@
{
int id;
struct wpa_ssid *ssid;
+ char *pos;
/* cmd: "<network id>" or "any" */
- if (os_strcmp(cmd, "any") == 0) {
+ if (os_strncmp(cmd, "any", 3) == 0) {
wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK any");
ssid = NULL;
} else {
@@ -2327,6 +2328,16 @@
}
}
+ pos = os_strstr(cmd, " freq=");
+ if (pos) {
+ int *freqs = freq_range_to_channel_list(wpa_s, pos + 6);
+ if (freqs) {
+ wpa_s->scan_req = MANUAL_SCAN_REQ;
+ os_free(wpa_s->manual_scan_freqs);
+ wpa_s->manual_scan_freqs = freqs;
+ }
+ }
+
wpa_supplicant_select_network(wpa_s, ssid);
return 0;
@@ -2660,6 +2671,8 @@
if (cred == NULL)
return -1;
+ wpa_msg(wpa_s, MSG_INFO, CRED_ADDED "%d", cred->id);
+
ret = os_snprintf(buf, buflen, "%d\n", cred->id);
if (ret < 0 || (size_t) ret >= buflen)
return -1;
@@ -2672,12 +2685,21 @@
{
struct wpa_ssid *ssid;
char str[20];
+ int id;
- if (cred == NULL || wpa_config_remove_cred(wpa_s->conf, cred->id) < 0) {
+ if (cred == NULL) {
wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred");
return -1;
}
+ id = cred->id;
+ if (wpa_config_remove_cred(wpa_s->conf, id) < 0) {
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred");
+ return -1;
+ }
+
+ wpa_msg(wpa_s, MSG_INFO, CRED_REMOVED "%d", id);
+
/* Remove any network entry created based on the removed credential */
ssid = wpa_s->conf->ssid;
while (ssid) {
@@ -2794,10 +2816,57 @@
return -1;
}
+ wpa_msg(wpa_s, MSG_INFO, CRED_MODIFIED "%d %s", cred->id, name);
+
return 0;
}
+static int wpa_supplicant_ctrl_iface_get_cred(struct wpa_supplicant *wpa_s,
+ char *cmd, char *buf,
+ size_t buflen)
+{
+ int id;
+ size_t res;
+ struct wpa_cred *cred;
+ char *name, *value;
+
+ /* cmd: "<cred id> <variable name>" */
+ name = os_strchr(cmd, ' ');
+ if (name == NULL)
+ return -1;
+ *name++ = '\0';
+
+ id = atoi(cmd);
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CRED id=%d name='%s'",
+ id, name);
+
+ cred = wpa_config_get_cred(wpa_s->conf, id);
+ if (cred == NULL) {
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred id=%d",
+ id);
+ return -1;
+ }
+
+ value = wpa_config_get_cred_no_key(cred, name);
+ if (value == NULL) {
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get cred variable '%s'",
+ name);
+ return -1;
+ }
+
+ res = os_strlcpy(buf, value, buflen);
+ if (res >= buflen) {
+ os_free(value);
+ return -1;
+ }
+
+ os_free(value);
+
+ return res;
+}
+
+
#ifndef CONFIG_NO_CONFIG_WRITE
static int wpa_supplicant_ctrl_iface_save_config(struct wpa_supplicant *wpa_s)
{
@@ -6421,6 +6490,10 @@
} else if (os_strncmp(buf, "SET_CRED ", 9) == 0) {
if (wpa_supplicant_ctrl_iface_set_cred(wpa_s, buf + 9))
reply_len = -1;
+ } else if (os_strncmp(buf, "GET_CRED ", 9) == 0) {
+ reply_len = wpa_supplicant_ctrl_iface_get_cred(wpa_s, buf + 9,
+ reply,
+ reply_size);
#ifndef CONFIG_NO_CONFIG_WRITE
} else if (os_strcmp(buf, "SAVE_CONFIG") == 0) {
if (wpa_supplicant_ctrl_iface_save_config(wpa_s))
diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c
index 2a9ab7f..83817f9 100644
--- a/wpa_supplicant/wpa_cli.c
+++ b/wpa_supplicant/wpa_cli.c
@@ -1474,6 +1474,18 @@
}
+static int wpa_cli_cmd_get_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
+{
+ if (argc != 2) {
+ printf("Invalid GET_CRED command: needs two arguments\n"
+ "(cred id, variable name)\n");
+ return -1;
+ }
+
+ return wpa_cli_cmd(ctrl, "GET_CRED", 2, argc, argv);
+}
+
+
static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
@@ -2594,6 +2606,9 @@
{ "set_cred", wpa_cli_cmd_set_cred, NULL,
cli_cmd_flag_sensitive,
"<cred id> <variable> <value> = set credential variables" },
+ { "get_cred", wpa_cli_cmd_get_cred, NULL,
+ cli_cmd_flag_none,
+ "<cred id> <variable> = get credential variables" },
{ "save_config", wpa_cli_cmd_save_config, NULL,
cli_cmd_flag_none,
"= save the current configuration" },