]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
Interworking: Add GET_CRED ctrl_iface command
authorJouni Malinen <jouni@qca.qualcomm.com>
Fri, 4 Apr 2014 17:10:49 +0000 (20:10 +0300)
committerJouni Malinen <j@w1.fi>
Fri, 4 Apr 2014 17:13:53 +0000 (20:13 +0300)
"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>
wpa_supplicant/config.c
wpa_supplicant/config.h
wpa_supplicant/ctrl_iface.c
wpa_supplicant/wpa_cli.c

index 6a4621021d0b45d856d4d2f1b9c8942d24ee8ea0..74283eb756dbf583bdf141cae980a9b304cb5abb 100644 (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 *cred;
index de43970606f13ae2014afee9d8c7dd71cf0ea6b1..a39804949b621f81023a0690d8c1da340ef77fe2 100644 (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);
 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);
index 4a63f4a8c9d8ee426e3b1ca560f5771bd5d43bf9..65ee15e82ec885192f13313b96c96ebb3c76dede 100644 (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
 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) {
                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))
index 2a9ab7fe014314b76bfbf8df3ed90e7987bb6c63..83817f9937934ef71536f406e196501a99327189 100644 (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,
                                  char *argv[])
 {
@@ -2594,6 +2606,9 @@ static struct wpa_cli_cmd wpa_cli_commands[] = {
        { "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" },