Interworking: Add GET_CRED ctrl_iface command

"GET_CRED <id> <field>" can now be used to fetch credential parameters
over the control interface. This does not allow passwords etc. private
material to be retrieved ("*" is returned for those if the value is set
regardless of the value). FAIL is returned if the requested parameter
has not been set. For cred parameters that can have multiple values,
newline separated list of values is returned.

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
Jouni Malinen 2014-04-04 20:10:49 +03:00 committed by Jouni Malinen
parent 1619e9d512
commit c880ab87ee
4 changed files with 334 additions and 0 deletions

View file

@ -2796,6 +2796,275 @@ int wpa_config_set_cred(struct wpa_cred *cred, const char *var,
} }
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 * wpa_config_get_cred(struct wpa_config *config, int id)
{ {
struct wpa_cred *cred; struct wpa_cred *cred;

View file

@ -1053,6 +1053,7 @@ int wpa_config_remove_cred(struct wpa_config *config, int id);
void wpa_config_free_cred(struct wpa_cred *cred); void wpa_config_free_cred(struct wpa_cred *cred);
int wpa_config_set_cred(struct wpa_cred *cred, const char *var, int wpa_config_set_cred(struct wpa_cred *cred, const char *var,
const char *value, int line); 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, struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface,
const char *driver_param); const char *driver_param);

View file

@ -2811,6 +2811,51 @@ static int wpa_supplicant_ctrl_iface_set_cred(struct wpa_supplicant *wpa_s,
} }
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 #ifndef CONFIG_NO_CONFIG_WRITE
static int wpa_supplicant_ctrl_iface_save_config(struct wpa_supplicant *wpa_s) static int wpa_supplicant_ctrl_iface_save_config(struct wpa_supplicant *wpa_s)
{ {
@ -6434,6 +6479,10 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
} else if (os_strncmp(buf, "SET_CRED ", 9) == 0) { } else if (os_strncmp(buf, "SET_CRED ", 9) == 0) {
if (wpa_supplicant_ctrl_iface_set_cred(wpa_s, buf + 9)) if (wpa_supplicant_ctrl_iface_set_cred(wpa_s, buf + 9))
reply_len = -1; 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 #ifndef CONFIG_NO_CONFIG_WRITE
} else if (os_strcmp(buf, "SAVE_CONFIG") == 0) { } else if (os_strcmp(buf, "SAVE_CONFIG") == 0) {
if (wpa_supplicant_ctrl_iface_save_config(wpa_s)) if (wpa_supplicant_ctrl_iface_save_config(wpa_s))

View file

@ -1474,6 +1474,18 @@ static int wpa_cli_cmd_set_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
} }
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, static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
char *argv[]) char *argv[])
{ {
@ -2594,6 +2606,9 @@ static struct wpa_cli_cmd wpa_cli_commands[] = {
{ "set_cred", wpa_cli_cmd_set_cred, NULL, { "set_cred", wpa_cli_cmd_set_cred, NULL,
cli_cmd_flag_sensitive, cli_cmd_flag_sensitive,
"<cred id> <variable> <value> = set credential variables" }, "<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, { "save_config", wpa_cli_cmd_save_config, NULL,
cli_cmd_flag_none, cli_cmd_flag_none,
"= save the current configuration" }, "= save the current configuration" },