Remove WEP40/WEP104 cipher suite support for WPA/WPA2
[mech_eap.git] / wpa_supplicant / config.c
index a810632..4d801cc 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant / Configuration parser and common functions
- * Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2015, Jouni Malinen <j@w1.fi>
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -678,8 +678,14 @@ static int wpa_config_parse_key_mgmt(const struct parse_data *data,
                else if (os_strcmp(start, "OSEN") == 0)
                        val |= WPA_KEY_MGMT_OSEN;
 #endif /* CONFIG_HS20 */
+#ifdef CONFIG_SUITEB
                else if (os_strcmp(start, "WPA-EAP-SUITE-B") == 0)
                        val |= WPA_KEY_MGMT_IEEE8021X_SUITE_B;
+#endif /* CONFIG_SUITEB */
+#ifdef CONFIG_SUITEB192
+               else if (os_strcmp(start, "WPA-EAP-SUITE-B-192") == 0)
+                       val |= WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
+#endif /* CONFIG_SUITEB192 */
                else {
                        wpa_printf(MSG_ERROR, "Line %d: invalid key_mgmt '%s'",
                                   line, start);
@@ -856,6 +862,7 @@ static char * wpa_config_write_key_mgmt(const struct parse_data *data,
        }
 #endif /* CONFIG_HS20 */
 
+#ifdef CONFIG_SUITEB
        if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) {
                ret = os_snprintf(pos, end - pos, "%sWPA-EAP-SUITE-B",
                                  pos == buf ? "" : " ");
@@ -865,6 +872,19 @@ static char * wpa_config_write_key_mgmt(const struct parse_data *data,
                }
                pos += ret;
        }
+#endif /* CONFIG_SUITEB */
+
+#ifdef CONFIG_SUITEB192
+       if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
+               ret = os_snprintf(pos, end - pos, "%sWPA-EAP-SUITE-B-192",
+                                 pos == buf ? "" : " ");
+               if (os_snprintf_error(end - pos, ret)) {
+                       end[-1] = '\0';
+                       return buf;
+               }
+               pos += ret;
+       }
+#endif /* CONFIG_SUITEB192 */
 
        if (pos == buf) {
                os_free(buf);
@@ -947,6 +967,13 @@ static int wpa_config_parse_group(const struct parse_data *data,
        val = wpa_config_parse_cipher(line, value);
        if (val == -1)
                return -1;
+
+       /*
+        * Backwards compatibility - filter out WEP ciphers that were previously
+        * allowed.
+        */
+       val &= ~(WPA_CIPHER_WEP104 | WPA_CIPHER_WEP40);
+
        if (val & ~WPA_ALLOWED_GROUP_CIPHERS) {
                wpa_printf(MSG_ERROR, "Line %d: not allowed group cipher "
                           "(0x%x).", line, val);
@@ -1276,6 +1303,7 @@ static int wpa_config_parse_eap(const struct parse_data *data,
 }
 
 
+#ifndef NO_CONFIG_WRITE
 static char * wpa_config_write_eap(const struct parse_data *data,
                                   struct wpa_ssid *ssid)
 {
@@ -1309,6 +1337,7 @@ static char * wpa_config_write_eap(const struct parse_data *data,
 
        return buf;
 }
+#endif /* NO_CONFIG_WRITE */
 
 
 static int wpa_config_parse_password(const struct parse_data *data,
@@ -1391,6 +1420,7 @@ static int wpa_config_parse_password(const struct parse_data *data,
 }
 
 
+#ifndef NO_CONFIG_WRITE
 static char * wpa_config_write_password(const struct parse_data *data,
                                        struct wpa_ssid *ssid)
 {
@@ -1424,6 +1454,7 @@ static char * wpa_config_write_password(const struct parse_data *data,
 
        return buf;
 }
+#endif /* NO_CONFIG_WRITE */
 #endif /* IEEE8021X_EAPOL */
 
 
@@ -1790,12 +1821,13 @@ static char * wpa_config_write_mesh_basic_rates(const struct parse_data *data,
  * functions.
  */
 static const struct parse_data ssid_fields[] = {
-       { STR_RANGE(ssid, 0, MAX_SSID_LEN) },
+       { STR_RANGE(ssid, 0, SSID_MAX_LEN) },
        { INT_RANGE(scan_ssid, 0, 1) },
        { FUNC(bssid) },
        { FUNC(bssid_blacklist) },
        { FUNC(bssid_whitelist) },
        { FUNC_KEY(psk) },
+       { INT(mem_only_psk) },
        { FUNC(proto) },
        { FUNC(key_mgmt) },
        { INT(bg_scan_period) },
@@ -1818,6 +1850,7 @@ static const struct parse_data ssid_fields[] = {
        { STRe(subject_match) },
        { STRe(altsubject_match) },
        { STRe(domain_suffix_match) },
+       { STRe(domain_match) },
        { STRe(ca_cert2) },
        { STRe(ca_path2) },
        { STRe(client_cert2) },
@@ -1827,6 +1860,7 @@ static const struct parse_data ssid_fields[] = {
        { STRe(subject_match2) },
        { STRe(altsubject_match2) },
        { STRe(domain_suffix_match2) },
+       { STRe(domain_match2) },
        { STRe(phase1) },
        { STRe(phase2) },
        { STRe(pcsc) },
@@ -1874,6 +1908,7 @@ static const struct parse_data ssid_fields[] = {
        { INT_RANGE(peerkey, 0, 1) },
        { INT_RANGE(mixed_cell, 0, 1) },
        { INT_RANGE(frequency, 0, 65000) },
+       { INT_RANGE(fixed_freq, 0, 1) },
 #ifdef CONFIG_MESH
        { FUNC(mesh_basic_rates) },
        { INT(dot11MeshMaxRetries) },
@@ -2052,6 +2087,7 @@ static void eap_peer_config_free(struct eap_peer_config *eap)
        os_free(eap->subject_match);
        os_free(eap->altsubject_match);
        os_free(eap->domain_suffix_match);
+       os_free(eap->domain_match);
        os_free(eap->ca_cert2);
        os_free(eap->ca_path2);
        os_free(eap->client_cert2);
@@ -2061,6 +2097,7 @@ static void eap_peer_config_free(struct eap_peer_config *eap)
        os_free(eap->subject_match2);
        os_free(eap->altsubject_match2);
        os_free(eap->domain_suffix_match2);
+       os_free(eap->domain_match2);
        os_free(eap->phase1);
        os_free(eap->phase2);
        os_free(eap->pcsc);
@@ -2230,6 +2267,7 @@ void wpa_config_free(struct wpa_config *config)
        os_free(config->sae_groups);
        wpabuf_free(config->ap_vendor_elements);
        os_free(config->osu_dir);
+       os_free(config->bgscan);
        os_free(config->wowlan_triggers);
        os_free(config);
 }
@@ -2490,6 +2528,9 @@ int wpa_config_set_quoted(struct wpa_ssid *ssid, const char *var,
  */
 char ** wpa_config_get_all(struct wpa_ssid *ssid, int get_keys)
 {
+#ifdef NO_CONFIG_WRITE
+       return NULL;
+#else /* NO_CONFIG_WRITE */
        const struct parse_data *field;
        char *key, *value;
        size_t i;
@@ -2535,6 +2576,7 @@ err:
                os_free(value++);
        os_free(props);
        return NULL;
+#endif /* NO_CONFIG_WRITE */
 }
 
 
@@ -2921,7 +2963,7 @@ int wpa_config_set_cred(struct wpa_cred *cred, const char *var,
        if (os_strcmp(var, "excluded_ssid") == 0) {
                struct excluded_ssid *e;
 
-               if (len > MAX_SSID_LEN) {
+               if (len > SSID_MAX_LEN) {
                        wpa_printf(MSG_ERROR, "Line %d: invalid "
                                   "excluded_ssid length %d", line, (int) len);
                        os_free(val);
@@ -3472,11 +3514,13 @@ struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface,
        config->ap_scan = DEFAULT_AP_SCAN;
        config->user_mpm = DEFAULT_USER_MPM;
        config->max_peer_links = DEFAULT_MAX_PEER_LINKS;
+       config->mesh_max_inactivity = DEFAULT_MESH_MAX_INACTIVITY;
        config->fast_reauth = DEFAULT_FAST_REAUTH;
        config->p2p_go_intent = DEFAULT_P2P_GO_INTENT;
        config->p2p_intra_bss = DEFAULT_P2P_INTRA_BSS;
        config->p2p_go_max_inactivity = DEFAULT_P2P_GO_MAX_INACTIVITY;
        config->p2p_optimize_listen_chan = DEFAULT_P2P_OPTIMIZE_LISTEN_CHAN;
+       config->p2p_go_ctwindow = DEFAULT_P2P_GO_CTWINDOW;
        config->bss_max_count = DEFAULT_BSS_MAX_COUNT;
        config->bss_expiration_age = DEFAULT_BSS_EXPIRATION_AGE;
        config->bss_expiration_scan_count = DEFAULT_BSS_EXPIRATION_SCAN_COUNT;
@@ -3490,6 +3534,7 @@ struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface,
        config->p2p_search_delay = DEFAULT_P2P_SEARCH_DELAY;
        config->rand_addr_lifetime = DEFAULT_RAND_ADDR_LIFETIME;
        config->key_mgmt_offload = DEFAULT_KEY_MGMT_OFFLOAD;
+       config->cert_in_cb = DEFAULT_CERT_IN_CB;
 
        if (ctrl_interface)
                config->ctrl_interface = os_strdup(ctrl_interface);
@@ -3529,6 +3574,8 @@ struct global_parse_data {
        char *name;
        int (*parser)(const struct global_parse_data *data,
                      struct wpa_config *config, int line, const char *value);
+       int (*get)(const char *name, struct wpa_config *config, long offset,
+                  char *buf, size_t buflen, int pretty_print);
        void *param1, *param2, *param3;
        unsigned int changed_flag;
 };
@@ -3988,22 +4035,81 @@ static int wpa_config_process_no_ctrl_interface(
 #endif /* CONFIG_CTRL_IFACE */
 
 
+static int wpa_config_get_int(const char *name, struct wpa_config *config,
+                             long offset, char *buf, size_t buflen,
+                             int pretty_print)
+{
+       int *val = (int *) (((u8 *) config) + (long) offset);
+
+       if (pretty_print)
+               return os_snprintf(buf, buflen, "%s=%d\n", name, *val);
+       return os_snprintf(buf, buflen, "%d", *val);
+}
+
+
+static int wpa_config_get_str(const char *name, struct wpa_config *config,
+                             long offset, char *buf, size_t buflen,
+                             int pretty_print)
+{
+       char **val = (char **) (((u8 *) config) + (long) offset);
+       int res;
+
+       if (pretty_print)
+               res = os_snprintf(buf, buflen, "%s=%s\n", name,
+                                 *val ? *val : "null");
+       else if (!*val)
+               return -1;
+       else
+               res = os_snprintf(buf, buflen, "%s", *val);
+       if (os_snprintf_error(buflen, res))
+               res = -1;
+
+       return res;
+}
+
+
+#ifdef CONFIG_P2P
+static int wpa_config_get_ipv4(const char *name, struct wpa_config *config,
+                              long offset, char *buf, size_t buflen,
+                              int pretty_print)
+{
+       void *val = ((u8 *) config) + (long) offset;
+       int res;
+       char addr[INET_ADDRSTRLEN];
+
+       if (!val || !inet_ntop(AF_INET, val, addr, sizeof(addr)))
+               return -1;
+
+       if (pretty_print)
+               res = os_snprintf(buf, buflen, "%s=%s\n", name, addr);
+       else
+               res = os_snprintf(buf, buflen, "%s", addr);
+
+       if (os_snprintf_error(buflen, res))
+               res = -1;
+
+       return res;
+}
+#endif /* CONFIG_P2P */
+
+
 #ifdef OFFSET
 #undef OFFSET
 #endif /* OFFSET */
 /* OFFSET: Get offset of a variable within the wpa_config structure */
 #define OFFSET(v) ((void *) &((struct wpa_config *) 0)->v)
 
-#define FUNC(f) #f, wpa_config_process_ ## f, OFFSET(f), NULL, NULL
-#define FUNC_NO_VAR(f) #f, wpa_config_process_ ## f, NULL, NULL, NULL
-#define _INT(f) #f, wpa_global_config_parse_int, OFFSET(f)
+#define FUNC(f) #f, wpa_config_process_ ## f, NULL, OFFSET(f), NULL, NULL
+#define FUNC_NO_VAR(f) #f, wpa_config_process_ ## f, NULL, NULL, NULL, NULL
+#define _INT(f) #f, wpa_global_config_parse_int, wpa_config_get_int, OFFSET(f)
 #define INT(f) _INT(f), NULL, NULL
 #define INT_RANGE(f, min, max) _INT(f), (void *) min, (void *) max
-#define _STR(f) #f, wpa_global_config_parse_str, OFFSET(f)
+#define _STR(f) #f, wpa_global_config_parse_str, wpa_config_get_str, OFFSET(f)
 #define STR(f) _STR(f), NULL, NULL
 #define STR_RANGE(f, min, max) _STR(f), (void *) min, (void *) max
-#define BIN(f) #f, wpa_global_config_parse_bin, OFFSET(f), NULL, NULL
-#define IPV4(f) #f, wpa_global_config_parse_ipv4, OFFSET(f), NULL, NULL
+#define BIN(f) #f, wpa_global_config_parse_bin, NULL, OFFSET(f), NULL, NULL
+#define IPV4(f) #f, wpa_global_config_parse_ipv4, wpa_config_get_ipv4,  \
+       OFFSET(f), NULL, NULL
 
 static const struct global_parse_data global_fields[] = {
 #ifdef CONFIG_CTRL_IFACE
@@ -4021,6 +4127,7 @@ static const struct global_parse_data global_fields[] = {
 #ifdef CONFIG_MESH
        { INT(user_mpm), 0 },
        { INT_RANGE(max_peer_links, 0, 255), 0 },
+       { INT(mesh_max_inactivity), 0 },
 #endif /* CONFIG_MESH */
        { INT(disable_scan_offload), 0 },
        { INT(fast_reauth), 0 },
@@ -4041,7 +4148,8 @@ static const struct global_parse_data global_fields[] = {
        { FUNC_NO_VAR(load_dynamic_eap), 0 },
 #ifdef CONFIG_WPS
        { FUNC(uuid), CFG_CHANGED_UUID },
-       { STR_RANGE(device_name, 0, 32), CFG_CHANGED_DEVICE_NAME },
+       { STR_RANGE(device_name, 0, WPS_DEV_NAME_MAX_LEN),
+         CFG_CHANGED_DEVICE_NAME },
        { STR_RANGE(manufacturer, 0, 64), CFG_CHANGED_WPS_STRING },
        { STR_RANGE(model_name, 0, 32), CFG_CHANGED_WPS_STRING },
        { STR_RANGE(model_number, 0, 32), CFG_CHANGED_WPS_STRING },
@@ -4072,12 +4180,14 @@ static const struct global_parse_data global_fields[] = {
        { INT(p2p_go_ht40), 0 },
        { INT(p2p_go_vht), 0 },
        { INT(p2p_disabled), 0 },
+       { INT_RANGE(p2p_go_ctwindow, 0, 127), 0 },
        { INT(p2p_no_group_iface), 0 },
        { INT_RANGE(p2p_ignore_shared_freq, 0, 1), 0 },
        { IPV4(ip_addr_go), 0 },
        { IPV4(ip_addr_mask), 0 },
        { IPV4(ip_addr_start), 0 },
        { IPV4(ip_addr_end), 0 },
+       { INT_RANGE(p2p_cli_probe, 0, 1), 0 },
 #endif /* CONFIG_P2P */
        { FUNC(country), CFG_CHANGED_COUNTRY },
        { INT(bss_max_count), 0 },
@@ -4121,6 +4231,9 @@ static const struct global_parse_data global_fields[] = {
        { INT(rand_addr_lifetime), 0 },
        { INT(preassoc_mac_addr), 0 },
        { INT(key_mgmt_offload), 0},
+       { INT(passive_scan), 0 },
+       { INT(reassoc_same_bss_optim), 0 },
+       { INT(wps_priority), 0},
 };
 
 #undef FUNC
@@ -4135,6 +4248,50 @@ static const struct global_parse_data global_fields[] = {
 #define NUM_GLOBAL_FIELDS ARRAY_SIZE(global_fields)
 
 
+int wpa_config_dump_values(struct wpa_config *config, char *buf, size_t buflen)
+{
+       int result = 0;
+       size_t i;
+
+       for (i = 0; i < NUM_GLOBAL_FIELDS; i++) {
+               const struct global_parse_data *field = &global_fields[i];
+               int tmp;
+
+               if (!field->get)
+                       continue;
+
+               tmp = field->get(field->name, config, (long) field->param1,
+                                buf, buflen, 1);
+               if (tmp < 0)
+                       return -1;
+               buf += tmp;
+               buflen -= tmp;
+               result += tmp;
+       }
+       return result;
+}
+
+
+int wpa_config_get_value(const char *name, struct wpa_config *config,
+                        char *buf, size_t buflen)
+{
+       size_t i;
+
+       for (i = 0; i < NUM_GLOBAL_FIELDS; i++) {
+               const struct global_parse_data *field = &global_fields[i];
+
+               if (os_strcmp(name, field->name) != 0)
+                       continue;
+               if (!field->get)
+                       break;
+               return field->get(name, config, (long) field->param1,
+                                 buf, buflen, 0);
+       }
+
+       return -1;
+}
+
+
 int wpa_config_process_global(struct wpa_config *config, char *pos, int line)
 {
        size_t i;