]> git.ipfire.org Git - thirdparty/hostap.git/blobdiff - src/ap/ap_config.c
WPS: Make it possible to use PSKs loaded from the PSK file
[thirdparty/hostap.git] / src / ap / ap_config.c
index 09ab3727a08966aeeb650ac1c0e22a164dcf2537..d4d098b38c84b4715ae99154dbfeadb93230c4b8 100644 (file)
 #include "crypto/tls.h"
 #include "radius/radius_client.h"
 #include "common/ieee802_11_defs.h"
+#include "common/ieee802_1x_defs.h"
 #include "common/eapol_common.h"
 #include "common/dhcp.h"
+#include "common/sae.h"
 #include "eap_common/eap_wsc_common.h"
 #include "eap_server/eap.h"
 #include "wpa_auth.h"
@@ -77,6 +79,7 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
 
        bss->radius_server_auth_port = 1812;
        bss->eap_sim_db_timeout = 1;
+       bss->eap_sim_id = 3;
        bss->ap_max_inactivity = AP_MAX_INACTIVITY;
        bss->eapol_version = EAPOL_VERSION;
 
@@ -84,11 +87,9 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
 
        bss->pwd_group = 19; /* ECC: GF(p=256) */
 
-#ifdef CONFIG_IEEE80211W
        bss->assoc_sa_query_max_timeout = 1000;
        bss->assoc_sa_query_retry_timeout = 201;
        bss->group_mgmt_cipher = WPA_CIPHER_AES_128_CMAC;
-#endif /* CONFIG_IEEE80211W */
 #ifdef EAP_SERVER_FAST
         /* both anonymous and authenticated provisioning */
        bss->eap_fast_prov = 3;
@@ -133,12 +134,20 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
         * completed and tested with other implementations. */
        bss->tls_flags = TLS_CONN_DISABLE_TLSv1_3;
 
+       bss->max_auth_rounds = 100;
+       bss->max_auth_rounds_short = 50;
+
        bss->send_probe_response = 1;
 
 #ifdef CONFIG_HS20
        bss->hs20_release = (HS20_VERSION >> 4) + 1;
 #endif /* CONFIG_HS20 */
 
+#ifdef CONFIG_MACSEC
+       bss->mka_priority = DEFAULT_PRIO_NOT_KEY_SERVER;
+       bss->macsec_port = 1;
+#endif /* CONFIG_MACSEC */
+
        /* Default to strict CRL checking. */
        bss->check_crl_strict = 1;
 }
@@ -240,6 +249,8 @@ struct hostapd_config * hostapd_config_defaults(void)
 #ifdef CONFIG_IEEE80211AX
        conf->he_op.he_rts_threshold = HE_OPERATION_RTS_THRESHOLD_MASK >>
                HE_OPERATION_RTS_THRESHOLD_OFFSET;
+       /* Set default basic MCS/NSS set to single stream MCS 0-7 */
+       conf->he_op.he_basic_mcs_nss_set = 0xfffc;
 #endif /* CONFIG_IEEE80211AX */
 
        /* The third octet of the country string uses an ASCII space character
@@ -290,6 +301,7 @@ static int hostapd_config_read_wpa_psk(const char *fname,
 
        while (fgets(buf, sizeof(buf), f)) {
                int vlan_id = 0;
+               int wps = 0;
 
                line++;
 
@@ -320,6 +332,8 @@ static int hostapd_config_read_wpa_psk(const char *fname,
                                value = "";
                        if (!os_strcmp(name, "keyid")) {
                                keyid = value;
+                       } else if (!os_strcmp(name, "wps")) {
+                               wps = atoi(value);
                        } else if (!os_strcmp(name, "vlanid")) {
                                vlan_id = atoi(value);
                        } else {
@@ -337,8 +351,9 @@ static int hostapd_config_read_wpa_psk(const char *fname,
                if (!token)
                        token = "";
                if (hwaddr_aton(token, addr)) {
-                       wpa_printf(MSG_ERROR, "Invalid MAC address '%s' on "
-                                  "line %d in '%s'", token, line, fname);
+                       wpa_printf(MSG_ERROR,
+                                  "Invalid MAC address '%s' on line %d in '%s'",
+                                  token, line, fname);
                        ret = -1;
                        break;
                }
@@ -366,16 +381,17 @@ static int hostapd_config_read_wpa_psk(const char *fname,
 
                ok = 0;
                len = os_strlen(pos);
-               if (len == 64 && hexstr2bin(pos, psk->psk, PMK_LEN) == 0)
+               if (len == 2 * PMK_LEN &&
+                   hexstr2bin(pos, psk->psk, PMK_LEN) == 0)
                        ok = 1;
-               else if (len >= 8 && len < 64) {
-                       pbkdf2_sha1(pos, ssid->ssid, ssid->ssid_len,
-                                   4096, psk->psk, PMK_LEN);
+               else if (len >= 8 && len < 64 &&
+                        pbkdf2_sha1(pos, ssid->ssid, ssid->ssid_len,
+                                    4096, psk->psk, PMK_LEN) == 0)
                        ok = 1;
-               }
                if (!ok) {
-                       wpa_printf(MSG_ERROR, "Invalid PSK '%s' on line %d in "
-                                  "'%s'", pos, line, fname);
+                       wpa_printf(MSG_ERROR,
+                                  "Invalid PSK '%s' on line %d in '%s'",
+                                  pos, line, fname);
                        os_free(psk);
                        ret = -1;
                        break;
@@ -393,6 +409,8 @@ static int hostapd_config_read_wpa_psk(const char *fname,
                        }
                }
 
+               psk->wps = wps;
+
                psk->next = ssid->wpa_psk;
                ssid->wpa_psk = psk;
        }
@@ -424,10 +442,52 @@ static int hostapd_derive_psk(struct hostapd_ssid *ssid)
 }
 
 
+int hostapd_setup_sae_pt(struct hostapd_bss_config *conf)
+{
+#ifdef CONFIG_SAE
+       struct hostapd_ssid *ssid = &conf->ssid;
+       struct sae_password_entry *pw;
+
+       if ((conf->sae_pwe == 0 && !hostapd_sae_pw_id_in_use(conf)) ||
+           conf->sae_pwe == 3 ||
+           !wpa_key_mgmt_sae(conf->wpa_key_mgmt))
+               return 0; /* PT not needed */
+
+       sae_deinit_pt(ssid->pt);
+       ssid->pt = NULL;
+       if (ssid->wpa_passphrase) {
+               ssid->pt = sae_derive_pt(conf->sae_groups, ssid->ssid,
+                                        ssid->ssid_len,
+                                        (const u8 *) ssid->wpa_passphrase,
+                                        os_strlen(ssid->wpa_passphrase),
+                                        NULL);
+               if (!ssid->pt)
+                       return -1;
+       }
+
+       for (pw = conf->sae_passwords; pw; pw = pw->next) {
+               sae_deinit_pt(pw->pt);
+               pw->pt = sae_derive_pt(conf->sae_groups, ssid->ssid,
+                                      ssid->ssid_len,
+                                      (const u8 *) pw->password,
+                                      os_strlen(pw->password),
+                                      pw->identifier);
+               if (!pw->pt)
+                       return -1;
+       }
+#endif /* CONFIG_SAE */
+
+       return 0;
+}
+
+
 int hostapd_setup_wpa_psk(struct hostapd_bss_config *conf)
 {
        struct hostapd_ssid *ssid = &conf->ssid;
 
+       if (hostapd_setup_sae_pt(conf) < 0)
+               return -1;
+
        if (ssid->wpa_passphrase != NULL) {
                if (ssid->wpa_psk != NULL) {
                        wpa_printf(MSG_DEBUG, "Using pre-configured WPA PSK "
@@ -468,7 +528,76 @@ hostapd_config_get_radius_attr(struct hostapd_radius_attr *attr, u8 type)
 }
 
 
-static void hostapd_config_free_radius_attr(struct hostapd_radius_attr *attr)
+struct hostapd_radius_attr * hostapd_parse_radius_attr(const char *value)
+{
+       const char *pos;
+       char syntax;
+       struct hostapd_radius_attr *attr;
+       size_t len;
+
+       attr = os_zalloc(sizeof(*attr));
+       if (!attr)
+               return NULL;
+
+       attr->type = atoi(value);
+
+       pos = os_strchr(value, ':');
+       if (!pos) {
+               attr->val = wpabuf_alloc(1);
+               if (!attr->val) {
+                       os_free(attr);
+                       return NULL;
+               }
+               wpabuf_put_u8(attr->val, 0);
+               return attr;
+       }
+
+       pos++;
+       if (pos[0] == '\0' || pos[1] != ':') {
+               os_free(attr);
+               return NULL;
+       }
+       syntax = *pos++;
+       pos++;
+
+       switch (syntax) {
+       case 's':
+               attr->val = wpabuf_alloc_copy(pos, os_strlen(pos));
+               break;
+       case 'x':
+               len = os_strlen(pos);
+               if (len & 1)
+                       break;
+               len /= 2;
+               attr->val = wpabuf_alloc(len);
+               if (!attr->val)
+                       break;
+               if (hexstr2bin(pos, wpabuf_put(attr->val, len), len) < 0) {
+                       wpabuf_free(attr->val);
+                       os_free(attr);
+                       return NULL;
+               }
+               break;
+       case 'd':
+               attr->val = wpabuf_alloc(4);
+               if (attr->val)
+                       wpabuf_put_be32(attr->val, atoi(pos));
+               break;
+       default:
+               os_free(attr);
+               return NULL;
+       }
+
+       if (!attr->val) {
+               os_free(attr);
+               return NULL;
+       }
+
+       return attr;
+}
+
+
+void hostapd_config_free_radius_attr(struct hostapd_radius_attr *attr)
 {
        struct hostapd_radius_attr *prev;
 
@@ -564,6 +693,9 @@ static void hostapd_config_free_sae_passwords(struct hostapd_bss_config *conf)
                pw = pw->next;
                str_clear_free(tmp->password);
                os_free(tmp->identifier);
+#ifdef CONFIG_SAE
+               sae_deinit_pt(tmp->pt);
+#endif /* CONFIG_SAE */
                os_free(tmp);
        }
 }
@@ -585,6 +717,10 @@ static void hostapd_dpp_controller_conf_free(struct dpp_controller_conf *conf)
 
 void hostapd_config_free_bss(struct hostapd_bss_config *conf)
 {
+#if defined(CONFIG_WPS) || defined(CONFIG_HS20)
+       size_t i;
+#endif
+
        if (conf == NULL)
                return;
 
@@ -596,6 +732,9 @@ void hostapd_config_free_bss(struct hostapd_bss_config *conf)
 #ifdef CONFIG_FULL_DYNAMIC_VLAN
        os_free(conf->ssid.vlan_tagged_interface);
 #endif /* CONFIG_FULL_DYNAMIC_VLAN */
+#ifdef CONFIG_SAE
+       sae_deinit_pt(conf->ssid.pt);
+#endif /* CONFIG_SAE */
 
        hostapd_config_free_eap_users(conf->eap_user);
        os_free(conf->eap_user_sqlite);
@@ -613,12 +752,16 @@ void hostapd_config_free_bss(struct hostapd_bss_config *conf)
        }
        hostapd_config_free_radius_attr(conf->radius_auth_req_attr);
        hostapd_config_free_radius_attr(conf->radius_acct_req_attr);
+       os_free(conf->radius_req_attr_sqlite);
        os_free(conf->rsn_preauth_interfaces);
        os_free(conf->ctrl_interface);
        os_free(conf->ca_cert);
        os_free(conf->server_cert);
+       os_free(conf->server_cert2);
        os_free(conf->private_key);
+       os_free(conf->private_key2);
        os_free(conf->private_key_passwd);
+       os_free(conf->private_key_passwd2);
        os_free(conf->check_cert_subject);
        os_free(conf->ocsp_stapling_response);
        os_free(conf->ocsp_stapling_response_multi);
@@ -677,12 +820,9 @@ void hostapd_config_free_bss(struct hostapd_bss_config *conf)
        os_free(conf->model_description);
        os_free(conf->model_url);
        os_free(conf->upc);
-       {
-               unsigned int i;
-
-               for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++)
-                       wpabuf_free(conf->wps_vendor_ext[i]);
-       }
+       for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++)
+               wpabuf_free(conf->wps_vendor_ext[i]);
+       wpabuf_free(conf->wps_application_ext);
        wpabuf_free(conf->wps_nfc_dh_pubkey);
        wpabuf_free(conf->wps_nfc_dh_privkey);
        wpabuf_free(conf->wps_nfc_dev_pw);
@@ -708,7 +848,6 @@ void hostapd_config_free_bss(struct hostapd_bss_config *conf)
        os_free(conf->hs20_operating_class);
        os_free(conf->hs20_icons);
        if (conf->hs20_osu_providers) {
-               size_t i;
                for (i = 0; i < conf->hs20_osu_providers_count; i++) {
                        struct hs20_osu_provider *p;
                        size_t j;
@@ -726,8 +865,6 @@ void hostapd_config_free_bss(struct hostapd_bss_config *conf)
                os_free(conf->hs20_osu_providers);
        }
        if (conf->hs20_operator_icon) {
-               size_t i;
-
                for (i = 0; i < conf->hs20_operator_icon_count; i++)
                        os_free(conf->hs20_operator_icon[i]);
                os_free(conf->hs20_operator_icon);
@@ -753,6 +890,9 @@ void hostapd_config_free_bss(struct hostapd_bss_config *conf)
 #ifdef CONFIG_TESTING_OPTIONS
        wpabuf_free(conf->own_ie_override);
        wpabuf_free(conf->sae_commit_override);
+       wpabuf_free(conf->rsnxe_override_eapol);
+       wpabuf_free(conf->gtk_rsc_override);
+       wpabuf_free(conf->igtk_rsc_override);
 #endif /* CONFIG_TESTING_OPTIONS */
 
        os_free(conf->no_probe_resp_if_seen_on);
@@ -761,6 +901,8 @@ void hostapd_config_free_bss(struct hostapd_bss_config *conf)
        hostapd_config_free_fils_realms(conf);
 
 #ifdef CONFIG_DPP
+       os_free(conf->dpp_name);
+       os_free(conf->dpp_mud_url);
        os_free(conf->dpp_connector);
        wpabuf_free(conf->dpp_netaccesskey);
        wpabuf_free(conf->dpp_csign);
@@ -806,6 +948,7 @@ void hostapd_config_free(struct hostapd_config *conf)
        os_free(conf->supported_rates);
        os_free(conf->basic_rates);
        os_free(conf->acs_ch_list.range);
+       os_free(conf->acs_freq_list.range);
        os_free(conf->driver_params);
 #ifdef CONFIG_ACS
        os_free(conf->acs_chan_bias);