Interworking: Add ctrl_iface commands for managing credentials
authorJouni Malinen <jouni@qca.qualcomm.com>
Thu, 16 Feb 2012 14:36:00 +0000 (16:36 +0200)
committerJouni Malinen <j@w1.fi>
Thu, 16 Feb 2012 14:36:00 +0000 (16:36 +0200)
New wpa_cli commands list_creds, add_cred, remove_cred, and set_cred
can now be used to manage credentials similarly to the commands used
with network blocks.

Signed-hostap: 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 3d3552f..1ccce44 100644 (file)
@@ -2272,6 +2272,74 @@ int wpa_config_set_cred(struct wpa_cred *cred, const char *var,
 }
 
 
+struct wpa_cred * wpa_config_get_cred(struct wpa_config *config, int id)
+{
+       struct wpa_cred *cred;
+
+       cred = config->cred;
+       while (cred) {
+               if (id == cred->id)
+                       break;
+               cred = cred->next;
+       }
+
+       return cred;
+}
+
+
+struct wpa_cred * wpa_config_add_cred(struct wpa_config *config)
+{
+       int id;
+       struct wpa_cred *cred, *last = NULL;
+
+       id = -1;
+       cred = config->cred;
+       while (cred) {
+               if (cred->id > id)
+                       id = cred->id;
+               last = cred;
+               cred = cred->next;
+       }
+       id++;
+
+       cred = os_zalloc(sizeof(*cred));
+       if (cred == NULL)
+               return NULL;
+       cred->id = id;
+       if (last)
+               last->next = cred;
+       else
+               config->cred = cred;
+
+       return cred;
+}
+
+
+int wpa_config_remove_cred(struct wpa_config *config, int id)
+{
+       struct wpa_cred *cred, *prev = NULL;
+
+       cred = config->cred;
+       while (cred) {
+               if (id == cred->id)
+                       break;
+               prev = cred;
+               cred = cred->next;
+       }
+
+       if (cred == NULL)
+               return -1;
+
+       if (prev)
+               prev->next = cred->next;
+       else
+               config->cred = cred->next;
+
+       wpa_config_free_cred(cred);
+       return 0;
+}
+
+
 #ifndef CONFIG_NO_CONFIG_BLOBS
 /**
  * wpa_config_get_blob - Get a named configuration blob
index e45b608..35fdc94 100644 (file)
@@ -547,6 +547,9 @@ void wpa_config_set_blob(struct wpa_config *config,
 void wpa_config_free_blob(struct wpa_config_blob *blob);
 int wpa_config_remove_blob(struct wpa_config *config, const char *name);
 
+struct wpa_cred * wpa_config_get_cred(struct wpa_config *config, int id);
+struct wpa_cred * wpa_config_add_cred(struct wpa_config *config);
+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);
index 1cdb082..1bbdebe 100644 (file)
@@ -1897,6 +1897,132 @@ static int wpa_supplicant_ctrl_iface_get_network(
 }
 
 
+static int wpa_supplicant_ctrl_iface_list_creds(struct wpa_supplicant *wpa_s,
+                                               char *buf, size_t buflen)
+{
+       char *pos, *end;
+       struct wpa_cred *cred;
+       int ret;
+
+       pos = buf;
+       end = buf + buflen;
+       ret = os_snprintf(pos, end - pos,
+                         "cred id / realm / username / domain / imsi\n");
+       if (ret < 0 || ret >= end - pos)
+               return pos - buf;
+       pos += ret;
+
+       cred = wpa_s->conf->cred;
+       while (cred) {
+               ret = os_snprintf(pos, end - pos, "%d\t%s\t%s\t%s\t%s\n",
+                                 cred->id, cred->realm ? cred->realm : "",
+                                 cred->username ? cred->username : "",
+                                 cred->domain ? cred->domain : "",
+                                 cred->imsi ? cred->imsi : "");
+               if (ret < 0 || ret >= end - pos)
+                       return pos - buf;
+               pos += ret;
+
+               cred = cred->next;
+       }
+
+       return pos - buf;
+}
+
+
+static int wpa_supplicant_ctrl_iface_add_cred(struct wpa_supplicant *wpa_s,
+                                             char *buf, size_t buflen)
+{
+       struct wpa_cred *cred;
+       int ret;
+
+       wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_CRED");
+
+       cred = wpa_config_add_cred(wpa_s->conf);
+       if (cred == NULL)
+               return -1;
+
+       ret = os_snprintf(buf, buflen, "%d\n", cred->id);
+       if (ret < 0 || (size_t) ret >= buflen)
+               return -1;
+       return ret;
+}
+
+
+static int wpa_supplicant_ctrl_iface_remove_cred(struct wpa_supplicant *wpa_s,
+                                                char *cmd)
+{
+       int id;
+       struct wpa_cred *cred;
+
+       /* cmd: "<cred id>" or "all" */
+       if (os_strcmp(cmd, "all") == 0) {
+               wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED all");
+               cred = wpa_s->conf->cred;
+               while (cred) {
+                       id = cred->id;
+                       cred = cred->next;
+                       wpa_config_remove_cred(wpa_s->conf, id);
+               }
+               return 0;
+       }
+
+       id = atoi(cmd);
+       wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED id=%d", id);
+
+       cred = wpa_config_get_cred(wpa_s->conf, id);
+       if (cred == NULL ||
+           wpa_config_remove_cred(wpa_s->conf, id) < 0) {
+               wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred id=%d",
+                          id);
+               return -1;
+       }
+
+       return 0;
+}
+
+
+static int wpa_supplicant_ctrl_iface_set_cred(struct wpa_supplicant *wpa_s,
+                                             char *cmd)
+{
+       int id;
+       struct wpa_cred *cred;
+       char *name, *value;
+
+       /* cmd: "<cred id> <variable name> <value>" */
+       name = os_strchr(cmd, ' ');
+       if (name == NULL)
+               return -1;
+       *name++ = '\0';
+
+       value = os_strchr(name, ' ');
+       if (value == NULL)
+               return -1;
+       *value++ = '\0';
+
+       id = atoi(cmd);
+       wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_CRED id=%d name='%s'",
+                  id, name);
+       wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
+                             (u8 *) value, os_strlen(value));
+
+       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;
+       }
+
+       if (wpa_config_set_cred(cred, name, value, 0) < 0) {
+               wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set cred "
+                          "variable '%s'", name);
+               return -1;
+       }
+
+       return 0;
+}
+
+
 #ifndef CONFIG_NO_CONFIG_WRITE
 static int wpa_supplicant_ctrl_iface_save_config(struct wpa_supplicant *wpa_s)
 {
@@ -3801,6 +3927,18 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
        } else if (os_strncmp(buf, "GET_NETWORK ", 12) == 0) {
                reply_len = wpa_supplicant_ctrl_iface_get_network(
                        wpa_s, buf + 12, reply, reply_size);
+       } else if (os_strcmp(buf, "LIST_CREDS") == 0) {
+               reply_len = wpa_supplicant_ctrl_iface_list_creds(
+                       wpa_s, reply, reply_size);
+       } else if (os_strcmp(buf, "ADD_CRED") == 0) {
+               reply_len = wpa_supplicant_ctrl_iface_add_cred(
+                       wpa_s, reply, reply_size);
+       } else if (os_strncmp(buf, "REMOVE_CRED ", 12) == 0) {
+               if (wpa_supplicant_ctrl_iface_remove_cred(wpa_s, buf + 12))
+                       reply_len = -1;
+       } else if (os_strncmp(buf, "SET_CRED ", 9) == 0) {
+               if (wpa_supplicant_ctrl_iface_set_cred(wpa_s, buf + 9))
+                       reply_len = -1;
 #ifndef CONFIG_NO_CONFIG_WRITE
        } else if (os_strcmp(buf, "SAVE_CONFIG") == 0) {
                if (wpa_supplicant_ctrl_iface_save_config(wpa_s))
index ed269b2..d28641b 100644 (file)
@@ -1602,6 +1602,61 @@ static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
 }
 
 
+static int wpa_cli_cmd_list_creds(struct wpa_ctrl *ctrl, int argc,
+                                 char *argv[])
+{
+       return wpa_ctrl_command(ctrl, "LIST_CREDS");
+}
+
+
+static int wpa_cli_cmd_add_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
+{
+       return wpa_ctrl_command(ctrl, "ADD_CRED");
+}
+
+
+static int wpa_cli_cmd_remove_cred(struct wpa_ctrl *ctrl, int argc,
+                                  char *argv[])
+{
+       char cmd[32];
+       int res;
+
+       if (argc < 1) {
+               printf("Invalid REMOVE_CRED command: needs one argument "
+                      "(cred id)\n");
+               return -1;
+       }
+
+       res = os_snprintf(cmd, sizeof(cmd), "REMOVE_CRED %s", argv[0]);
+       if (res < 0 || (size_t) res >= sizeof(cmd))
+               return -1;
+       cmd[sizeof(cmd) - 1] = '\0';
+
+       return wpa_ctrl_command(ctrl, cmd);
+}
+
+
+static int wpa_cli_cmd_set_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
+{
+       char cmd[256];
+       int res;
+
+       if (argc != 3) {
+               printf("Invalid SET_CRED command: needs three arguments\n"
+                      "(cred id, variable name, and value)\n");
+               return -1;
+       }
+
+       res = os_snprintf(cmd, sizeof(cmd), "SET_CRED %s %s %s",
+                         argv[0], argv[1], argv[2]);
+       if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
+               printf("Too long SET_CRED command.\n");
+               return -1;
+       }
+       return wpa_ctrl_command(ctrl, cmd);
+}
+
+
 static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
                                  char *argv[])
 {
@@ -2784,6 +2839,18 @@ static struct wpa_cli_cmd wpa_cli_commands[] = {
        { "get_network", wpa_cli_cmd_get_network,
          cli_cmd_flag_none,
          "<network id> <variable> = get network variables" },
+       { "list_creds", wpa_cli_cmd_list_creds,
+         cli_cmd_flag_none,
+         "= list configured credentials" },
+       { "add_cred", wpa_cli_cmd_add_cred,
+         cli_cmd_flag_none,
+         "= add a credential" },
+       { "remove_cred", wpa_cli_cmd_remove_cred,
+         cli_cmd_flag_none,
+         "<cred id> = remove a credential" },
+       { "set_cred", wpa_cli_cmd_set_cred,
+         cli_cmd_flag_sensitive,
+         "<cred id> <variable> <value> = set credential variables" },
        { "save_config", wpa_cli_cmd_save_config,
          cli_cmd_flag_none,
          "= save the current configuration" },