EAP peer: Add framework for external SIM/USIM processing
[mech_eap.git] / wpa_supplicant / config.c
index 7a860b6..ea7ac5a 100644 (file)
@@ -546,10 +546,10 @@ static char * wpa_config_write_key_mgmt(const struct parse_data *data,
        char *buf, *pos, *end;
        int ret;
 
-       pos = buf = os_zalloc(50);
+       pos = buf = os_zalloc(100);
        if (buf == NULL)
                return NULL;
-       end = buf + 50;
+       end = buf + 100;
 
        if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) {
                ret = os_snprintf(pos, end - pos, "%sWPA-PSK",
@@ -602,29 +602,59 @@ static char * wpa_config_write_key_mgmt(const struct parse_data *data,
        }
 
 #ifdef CONFIG_IEEE80211R
-       if (ssid->key_mgmt & WPA_KEY_MGMT_FT_PSK)
-               pos += os_snprintf(pos, end - pos, "%sFT-PSK",
-                                  pos == buf ? "" : " ");
+       if (ssid->key_mgmt & WPA_KEY_MGMT_FT_PSK) {
+               ret = os_snprintf(pos, end - pos, "%sFT-PSK",
+                                 pos == buf ? "" : " ");
+               if (ret < 0 || ret >= end - pos) {
+                       end[-1] = '\0';
+                       return buf;
+               }
+               pos += ret;
+       }
 
-       if (ssid->key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X)
-               pos += os_snprintf(pos, end - pos, "%sFT-EAP",
-                                  pos == buf ? "" : " ");
+       if (ssid->key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) {
+               ret = os_snprintf(pos, end - pos, "%sFT-EAP",
+                                 pos == buf ? "" : " ");
+               if (ret < 0 || ret >= end - pos) {
+                       end[-1] = '\0';
+                       return buf;
+               }
+               pos += ret;
+       }
 #endif /* CONFIG_IEEE80211R */
 
 #ifdef CONFIG_IEEE80211W
-       if (ssid->key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
-               pos += os_snprintf(pos, end - pos, "%sWPA-PSK-SHA256",
-                                  pos == buf ? "" : " ");
+       if (ssid->key_mgmt & WPA_KEY_MGMT_PSK_SHA256) {
+               ret = os_snprintf(pos, end - pos, "%sWPA-PSK-SHA256",
+                                 pos == buf ? "" : " ");
+               if (ret < 0 || ret >= end - pos) {
+                       end[-1] = '\0';
+                       return buf;
+               }
+               pos += ret;
+       }
 
-       if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256)
-               pos += os_snprintf(pos, end - pos, "%sWPA-EAP-SHA256",
-                                  pos == buf ? "" : " ");
+       if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) {
+               ret = os_snprintf(pos, end - pos, "%sWPA-EAP-SHA256",
+                                 pos == buf ? "" : " ");
+               if (ret < 0 || ret >= end - pos) {
+                       end[-1] = '\0';
+                       return buf;
+               }
+               pos += ret;
+       }
 #endif /* CONFIG_IEEE80211W */
 
 #ifdef CONFIG_WPS
-       if (ssid->key_mgmt & WPA_KEY_MGMT_WPS)
-               pos += os_snprintf(pos, end - pos, "%sWPS",
-                                  pos == buf ? "" : " ");
+       if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
+               ret = os_snprintf(pos, end - pos, "%sWPS",
+                                 pos == buf ? "" : " ");
+               if (ret < 0 || ret >= end - pos) {
+                       end[-1] = '\0';
+                       return buf;
+               }
+               pos += ret;
+       }
 #endif /* CONFIG_WPS */
 
        return buf;
@@ -873,6 +903,10 @@ static int wpa_config_parse_scan_freq(const struct parse_data *data,
        freqs = wpa_config_parse_int_array(value);
        if (freqs == NULL)
                return -1;
+       if (freqs[0] == 0) {
+               os_free(freqs);
+               freqs = NULL;
+       }
        os_free(ssid->scan_freq);
        ssid->scan_freq = freqs;
 
@@ -889,6 +923,10 @@ static int wpa_config_parse_freq_list(const struct parse_data *data,
        freqs = wpa_config_parse_int_array(value);
        if (freqs == NULL)
                return -1;
+       if (freqs[0] == 0) {
+               os_free(freqs);
+               freqs = NULL;
+       }
        os_free(ssid->freq_list);
        ssid->freq_list = freqs;
 
@@ -1372,6 +1410,60 @@ static char * wpa_config_write_p2p_client_list(const struct parse_data *data,
 }
 #endif /* NO_CONFIG_WRITE */
 
+
+static int wpa_config_parse_psk_list(const struct parse_data *data,
+                                    struct wpa_ssid *ssid, int line,
+                                    const char *value)
+{
+       struct psk_list_entry *p;
+       const char *pos;
+
+       p = os_zalloc(sizeof(*p));
+       if (p == NULL)
+               return -1;
+
+       pos = value;
+       if (os_strncmp(pos, "P2P-", 4) == 0) {
+               p->p2p = 1;
+               pos += 4;
+       }
+
+       if (hwaddr_aton(pos, p->addr)) {
+               wpa_printf(MSG_ERROR, "Line %d: Invalid psk_list address '%s'",
+                          line, pos);
+               os_free(p);
+               return -1;
+       }
+       pos += 17;
+       if (*pos != '-') {
+               wpa_printf(MSG_ERROR, "Line %d: Invalid psk_list '%s'",
+                          line, pos);
+               os_free(p);
+               return -1;
+       }
+       pos++;
+
+       if (hexstr2bin(pos, p->psk, PMK_LEN) || pos[PMK_LEN * 2] != '\0') {
+               wpa_printf(MSG_ERROR, "Line %d: Invalid psk_list PSK '%s'",
+                          line, pos);
+               os_free(p);
+               return -1;
+       }
+
+       dl_list_add(&ssid->psk_list, &p->list);
+
+       return 0;
+}
+
+
+#ifndef NO_CONFIG_WRITE
+static char * wpa_config_write_psk_list(const struct parse_data *data,
+                                       struct wpa_ssid *ssid)
+{
+       return NULL;
+}
+#endif /* NO_CONFIG_WRITE */
+
 #endif /* CONFIG_P2P */
 
 /* Helper macros for network block parser */
@@ -1487,6 +1579,7 @@ static const struct parse_data ssid_fields[] = {
        { STRe(dh_file) },
        { STRe(subject_match) },
        { STRe(altsubject_match) },
+       { STRe(domain_suffix_match) },
        { STRe(ca_cert2) },
        { STRe(ca_path2) },
        { STRe(client_cert2) },
@@ -1495,6 +1588,7 @@ static const struct parse_data ssid_fields[] = {
        { STRe(dh_file2) },
        { STRe(subject_match2) },
        { STRe(altsubject_match2) },
+       { STRe(domain_suffix_match2) },
        { STRe(phase1) },
        { STRe(phase2) },
        { STRe(pcsc) },
@@ -1522,6 +1616,7 @@ static const struct parse_data ssid_fields[] = {
        { INT(eap_workaround) },
        { STRe(pac_file) },
        { INTe(fragment_size) },
+       { INTe(ocsp) },
 #endif /* IEEE8021X_EAPOL */
        { INT_RANGE(mode, 0, 4) },
        { INT_RANGE(proactive_key_caching, 0, 1) },
@@ -1538,6 +1633,7 @@ static const struct parse_data ssid_fields[] = {
        { INT_RANGE(ignore_broadcast_ssid, 0, 2) },
 #ifdef CONFIG_P2P
        { FUNC(p2p_client_list) },
+       { FUNC(psk_list) },
 #endif /* CONFIG_P2P */
 #ifdef CONFIG_HT_OVERRIDES
        { INT_RANGE(disable_ht, 0, 1) },
@@ -1692,6 +1788,7 @@ static void eap_peer_config_free(struct eap_peer_config *eap)
        os_free(eap->dh_file);
        os_free(eap->subject_match);
        os_free(eap->altsubject_match);
+       os_free(eap->domain_suffix_match);
        os_free(eap->ca_cert2);
        os_free(eap->ca_path2);
        os_free(eap->client_cert2);
@@ -1700,6 +1797,7 @@ static void eap_peer_config_free(struct eap_peer_config *eap)
        os_free(eap->dh_file2);
        os_free(eap->subject_match2);
        os_free(eap->altsubject_match2);
+       os_free(eap->domain_suffix_match2);
        os_free(eap->phase1);
        os_free(eap->phase2);
        os_free(eap->pcsc);
@@ -1717,6 +1815,7 @@ static void eap_peer_config_free(struct eap_peer_config *eap)
        os_free(eap->pending_req_otp);
        os_free(eap->pac_file);
        os_free(eap->new_password);
+       os_free(eap->external_sim_resp);
 }
 #endif /* IEEE8021X_EAPOL */
 
@@ -1730,6 +1829,8 @@ static void eap_peer_config_free(struct eap_peer_config *eap)
  */
 void wpa_config_free_ssid(struct wpa_ssid *ssid)
 {
+       struct psk_list_entry *psk;
+
        os_free(ssid->ssid);
        os_free(ssid->passphrase);
        os_free(ssid->ext_psk);
@@ -1744,12 +1845,19 @@ void wpa_config_free_ssid(struct wpa_ssid *ssid)
 #ifdef CONFIG_HT_OVERRIDES
        os_free(ssid->ht_mcs);
 #endif /* CONFIG_HT_OVERRIDES */
+       while ((psk = dl_list_first(&ssid->psk_list, struct psk_list_entry,
+                                   list))) {
+               dl_list_del(&psk->list);
+               os_free(psk);
+       }
        os_free(ssid);
 }
 
 
 void wpa_config_free_cred(struct wpa_cred *cred)
 {
+       size_t i;
+
        os_free(cred->realm);
        os_free(cred->username);
        os_free(cred->password);
@@ -1759,7 +1867,10 @@ void wpa_config_free_cred(struct wpa_cred *cred)
        os_free(cred->private_key_passwd);
        os_free(cred->imsi);
        os_free(cred->milenage);
+       for (i = 0; i < cred->num_domain; i++)
+               os_free(cred->domain[i]);
        os_free(cred->domain);
+       os_free(cred->domain_suffix_match);
        os_free(cred->eap_method);
        os_free(cred->phase1);
        os_free(cred->phase2);
@@ -1907,6 +2018,7 @@ struct wpa_ssid * wpa_config_add_network(struct wpa_config *config)
        if (ssid == NULL)
                return NULL;
        ssid->id = id;
+       dl_list_init(&ssid->psk_list);
        if (last)
                last->next = ssid;
        else
@@ -2330,9 +2442,23 @@ int wpa_config_set_cred(struct wpa_cred *cred, const char *var,
                return 0;
        }
 
+       if (os_strcmp(var, "domain_suffix_match") == 0) {
+               os_free(cred->domain_suffix_match);
+               cred->domain_suffix_match = val;
+               return 0;
+       }
+
        if (os_strcmp(var, "domain") == 0) {
-               os_free(cred->domain);
-               cred->domain = val;
+               char **new_domain;
+               new_domain = os_realloc_array(cred->domain,
+                                             cred->num_domain + 1,
+                                             sizeof(char *));
+               if (new_domain == NULL) {
+                       os_free(val);
+                       return -1;
+               }
+               new_domain[cred->num_domain++] = val;
+               cred->domain = new_domain;
                return 0;
        }
 
@@ -2362,6 +2488,21 @@ int wpa_config_set_cred(struct wpa_cred *cred, const char *var,
                return 0;
        }
 
+       if (os_strcmp(var, "required_roaming_consortium") == 0) {
+               if (len < 3 || len > sizeof(cred->required_roaming_consortium))
+               {
+                       wpa_printf(MSG_ERROR, "Line %d: invalid "
+                                  "required_roaming_consortium length %d "
+                                  "(3..15 expected)", line, (int) len);
+                       os_free(val);
+                       return -1;
+               }
+               os_memcpy(cred->required_roaming_consortium, val, len);
+               cred->required_roaming_consortium_len = len;
+               os_free(val);
+               return 0;
+       }
+
        if (os_strcmp(var, "excluded_ssid") == 0) {
                struct excluded_ssid *e;
 
@@ -2744,6 +2885,10 @@ static int wpa_config_process_freq_list(const struct global_parse_data *data,
        freqs = wpa_config_parse_int_array(value);
        if (freqs == NULL)
                return -1;
+       if (freqs[0] == 0) {
+               os_free(freqs);
+               freqs = NULL;
+       }
        os_free(config->freq_list);
        config->freq_list = freqs;
        return 0;
@@ -3006,6 +3151,19 @@ static int wpa_config_process_ap_vendor_elements(
 }
 
 
+#ifdef CONFIG_CTRL_IFACE
+static int wpa_config_process_no_ctrl_interface(
+       const struct global_parse_data *data,
+       struct wpa_config *config, int line, const char *pos)
+{
+       wpa_printf(MSG_DEBUG, "no_ctrl_interface -> ctrl_interface=NULL");
+       os_free(config->ctrl_interface);
+       config->ctrl_interface = NULL;
+       return 0;
+}
+#endif /* CONFIG_CTRL_IFACE */
+
+
 #ifdef OFFSET
 #undef OFFSET
 #endif /* OFFSET */
@@ -3025,6 +3183,7 @@ static int wpa_config_process_ap_vendor_elements(
 static const struct global_parse_data global_fields[] = {
 #ifdef CONFIG_CTRL_IFACE
        { STR(ctrl_interface), 0 },
+       { FUNC_NO_VAR(no_ctrl_interface), 0 },
        { STR(ctrl_interface_group), 0 } /* deprecated */,
 #endif /* CONFIG_CTRL_IFACE */
        { INT_RANGE(eapol_version, 1, 2), 0 },
@@ -3036,6 +3195,7 @@ static const struct global_parse_data global_fields[] = {
        { STR(pkcs11_module_path), 0 },
        { STR(pcsc_reader), 0 },
        { STR(pcsc_pin), 0 },
+       { INT(external_sim), 0 },
        { STR(driver_param), 0 },
        { INT(dot11RSNAConfigPMKLifetime), 0 },
        { INT(dot11RSNAConfigPMKReauthThreshold), 0 },
@@ -3061,8 +3221,8 @@ static const struct global_parse_data global_fields[] = {
        { FUNC(sec_device_type), CFG_CHANGED_SEC_DEVICE_TYPE },
        { INT(p2p_listen_reg_class), 0 },
        { INT(p2p_listen_channel), 0 },
-       { INT(p2p_oper_reg_class), 0 },
-       { INT(p2p_oper_channel), 0 },
+       { INT(p2p_oper_reg_class), CFG_CHANGED_P2P_OPER_CHANNEL },
+       { INT(p2p_oper_channel), CFG_CHANGED_P2P_OPER_CHANNEL },
        { INT_RANGE(p2p_go_intent, 0, 15), 0 },
        { STR(p2p_ssid_postfix), CFG_CHANGED_P2P_SSID_POSTFIX },
        { INT_RANGE(persistent_reconnect, 0, 1), 0 },