diff options
Diffstat (limited to 'contrib/wpa/wpa_supplicant')
27 files changed, 824 insertions, 110 deletions
diff --git a/contrib/wpa/wpa_supplicant/Android.mk b/contrib/wpa/wpa_supplicant/Android.mk index 0aacafd4ab96..7e597f396a07 100644 --- a/contrib/wpa/wpa_supplicant/Android.mk +++ b/contrib/wpa/wpa_supplicant/Android.mk @@ -279,6 +279,9 @@ NEED_ASN1=y ifdef CONFIG_DPP2 L_CFLAGS += -DCONFIG_DPP2 endif +ifdef CONFIG_DPP3 +L_CFLAGS += -DCONFIG_DPP3 +endif endif ifdef CONFIG_OWE diff --git a/contrib/wpa/wpa_supplicant/Makefile b/contrib/wpa/wpa_supplicant/Makefile index ce1c8b2e3366..cb66defac7c8 100644 --- a/contrib/wpa/wpa_supplicant/Makefile +++ b/contrib/wpa/wpa_supplicant/Makefile @@ -294,6 +294,9 @@ NEED_ASN1=y ifdef CONFIG_DPP2 CFLAGS += -DCONFIG_DPP2 endif +ifdef CONFIG_DPP3 +CFLAGS += -DCONFIG_DPP3 +endif endif ifdef CONFIG_OWE diff --git a/contrib/wpa/wpa_supplicant/README-HS20 b/contrib/wpa/wpa_supplicant/README-HS20 index 484e4cbf4724..b076621db527 100644 --- a/contrib/wpa/wpa_supplicant/README-HS20 +++ b/contrib/wpa/wpa_supplicant/README-HS20 @@ -286,6 +286,12 @@ Credentials can be pre-configured for automatic network selection: # # sim_num: Identifier for which SIM to use in multi-SIM devices # +# engine: Whether to use an engine for private key operations (0/1) +# engine_id: String identifying the engine to use +# ca_cert_id: The CA certificate identifier when using an engine +# cert_id: The certificate identifier when using an engine +# key_id: The private key identifier when using an engine +# # for example: # #cred={ diff --git a/contrib/wpa/wpa_supplicant/config.c b/contrib/wpa/wpa_supplicant/config.c index c5177d915524..bf062b0792b7 100644 --- a/contrib/wpa/wpa_supplicant/config.c +++ b/contrib/wpa/wpa_supplicant/config.c @@ -2527,6 +2527,7 @@ static const struct parse_data ssid_fields[] = { #ifdef CONFIG_MESH { INT_RANGE(mode, 0, 5) }, { INT_RANGE(no_auto_peer, 0, 1) }, + { INT_RANGE(mesh_fwding, 0, 1) }, { INT_RANGE(mesh_rssi_threshold, -255, 1) }, #else /* CONFIG_MESH */ { INT_RANGE(mode, 0, 4) }, @@ -2855,6 +2856,10 @@ void wpa_config_free_cred(struct wpa_cred *cred) os_free(cred->client_cert); os_free(cred->private_key); str_clear_free(cred->private_key_passwd); + os_free(cred->engine_id); + os_free(cred->ca_cert_id); + os_free(cred->cert_id); + os_free(cred->key_id); os_free(cred->imsi); str_clear_free(cred->milenage); for (i = 0; i < cred->num_domain; i++) @@ -3107,6 +3112,7 @@ void wpa_config_set_network_defaults(struct wpa_ssid *ssid) ssid->dot11MeshRetryTimeout = DEFAULT_MESH_RETRY_TIMEOUT; ssid->dot11MeshConfirmTimeout = DEFAULT_MESH_CONFIRM_TIMEOUT; ssid->dot11MeshHoldingTimeout = DEFAULT_MESH_HOLDING_TIMEOUT; + ssid->mesh_fwding = DEFAULT_MESH_FWDING; ssid->mesh_rssi_threshold = DEFAULT_MESH_RSSI_THRESHOLD; #endif /* CONFIG_MESH */ #ifdef CONFIG_HT_OVERRIDES @@ -3618,6 +3624,11 @@ int wpa_config_set_cred(struct wpa_cred *cred, const char *var, return 0; } + if (os_strcmp(var, "engine") == 0) { + cred->engine = atoi(value); + return 0; + } + val = wpa_config_parse_string(value, &len); if (val == NULL || (os_strcmp(var, "excluded_ssid") != 0 && @@ -3673,6 +3684,30 @@ int wpa_config_set_cred(struct wpa_cred *cred, const char *var, return 0; } + if (os_strcmp(var, "engine_id") == 0) { + os_free(cred->engine_id); + cred->engine_id = val; + return 0; + } + + if (os_strcmp(var, "ca_cert_id") == 0) { + os_free(cred->ca_cert_id); + cred->ca_cert_id = val; + return 0; + } + + if (os_strcmp(var, "cert_id") == 0) { + os_free(cred->cert_id); + cred->cert_id = val; + return 0; + } + + if (os_strcmp(var, "key_id") == 0) { + os_free(cred->key_id); + cred->key_id = val; + return 0; + } + if (os_strcmp(var, "imsi") == 0) { os_free(cred->imsi); cred->imsi = val; @@ -4349,6 +4384,7 @@ struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface, config->user_mpm = DEFAULT_USER_MPM; config->max_peer_links = DEFAULT_MAX_PEER_LINKS; config->mesh_max_inactivity = DEFAULT_MESH_MAX_INACTIVITY; + config->mesh_fwding = DEFAULT_MESH_FWDING; config->dot11RSNASAERetransPeriod = DEFAULT_DOT11_RSNA_SAE_RETRANS_PERIOD; config->fast_reauth = DEFAULT_FAST_REAUTH; @@ -5062,6 +5098,7 @@ static const struct global_parse_data global_fields[] = { { INT(user_mpm), 0 }, { INT_RANGE(max_peer_links, 0, 255), 0 }, { INT(mesh_max_inactivity), 0 }, + { INT_RANGE(mesh_fwding, 0, 1), 0 }, { INT(dot11RSNASAERetransPeriod), 0 }, #endif /* CONFIG_MESH */ { INT(disable_scan_offload), 0 }, diff --git a/contrib/wpa/wpa_supplicant/config.h b/contrib/wpa/wpa_supplicant/config.h index 0320d9eebb57..d22ef05fb8ba 100644 --- a/contrib/wpa/wpa_supplicant/config.h +++ b/contrib/wpa/wpa_supplicant/config.h @@ -18,6 +18,7 @@ #define DEFAULT_USER_MPM 1 #define DEFAULT_MAX_PEER_LINKS 99 #define DEFAULT_MESH_MAX_INACTIVITY 300 +#define DEFAULT_MESH_FWDING 1 /* * The default dot11RSNASAERetransPeriod is defined as 40 ms in the standard, * but use 1000 ms in practice to avoid issues on low power CPUs. @@ -180,6 +181,31 @@ struct wpa_cred { char *milenage; /** + * engine - Use an engine for private key operations + */ + int engine; + + /** + * engine_id - String identifying the engine to use + */ + char *engine_id; + + /** + * ca_cert_id - The CA certificate identifier when using an engine + */ + char *ca_cert_id; + + /** + * cert_id - The certificate identifier when using an engine + */ + char *cert_id; + + /** + * key_id - The private key identifier when using an engine + */ + char *key_id; + + /** * domain_suffix_match - Constraint for server domain name * * If set, this FQDN is used as a suffix match requirement for the AAA @@ -1389,6 +1415,14 @@ struct wpa_config { int mesh_max_inactivity; /** + * mesh_fwding - Mesh network layer-2 forwarding (dot11MeshForwarding) + * + * This controls whether to enable layer-2 forwarding. + * By default: 1: enabled + */ + int mesh_fwding; + + /** * dot11RSNASAERetransPeriod - Timeout to retransmit SAE Auth frame * * This timeout value is used in mesh STA to retransmit diff --git a/contrib/wpa/wpa_supplicant/config_file.c b/contrib/wpa/wpa_supplicant/config_file.c index 54fb72d8c1f7..6db5010db3a7 100644 --- a/contrib/wpa/wpa_supplicant/config_file.c +++ b/contrib/wpa/wpa_supplicant/config_file.c @@ -769,6 +769,7 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid) #endif /* IEEE8021X_EAPOL */ INT(mode); INT(no_auto_peer); + INT(mesh_fwding); INT(frequency); INT(enable_edmg); INT(edmg_channel); @@ -1026,6 +1027,17 @@ static void wpa_config_write_cred(FILE *f, struct wpa_cred *cred) if (cred->sim_num != DEFAULT_USER_SELECTED_SIM) fprintf(f, "\tsim_num=%d\n", cred->sim_num); + + if (cred->engine) + fprintf(f, "\tengine=%d\n", cred->engine); + if (cred->engine_id) + fprintf(f, "\tengine_id=\"%s\"\n", cred->engine_id); + if (cred->key_id) + fprintf(f, "\tkey_id=\"%s\"\n", cred->key_id); + if (cred->cert_id) + fprintf(f, "\tcert_id=\"%s\"\n", cred->cert_id); + if (cred->ca_cert_id) + fprintf(f, "\tca_cert_id=\"%s\"\n", cred->ca_cert_id); } @@ -1462,6 +1474,9 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config) fprintf(f, "mesh_max_inactivity=%d\n", config->mesh_max_inactivity); + if (config->mesh_fwding != DEFAULT_MESH_FWDING) + fprintf(f, "mesh_fwding=%d\n", config->mesh_fwding); + if (config->dot11RSNASAERetransPeriod != DEFAULT_DOT11_RSNA_SAE_RETRANS_PERIOD) fprintf(f, "dot11RSNASAERetransPeriod=%d\n", diff --git a/contrib/wpa/wpa_supplicant/config_ssid.h b/contrib/wpa/wpa_supplicant/config_ssid.h index 339eead1c333..724534dd0123 100644 --- a/contrib/wpa/wpa_supplicant/config_ssid.h +++ b/contrib/wpa/wpa_supplicant/config_ssid.h @@ -549,6 +549,11 @@ struct wpa_ssid { int dot11MeshConfirmTimeout; /* msec */ int dot11MeshHoldingTimeout; /* msec */ + /** + * Mesh network layer-2 forwarding (dot11MeshForwarding) + */ + int mesh_fwding; + int ht; int ht40; diff --git a/contrib/wpa/wpa_supplicant/ctrl_iface.c b/contrib/wpa/wpa_supplicant/ctrl_iface.c index 9dc17f5eef85..bcd67fca3e12 100644 --- a/contrib/wpa/wpa_supplicant/ctrl_iface.c +++ b/contrib/wpa/wpa_supplicant/ctrl_iface.c @@ -3793,47 +3793,6 @@ static int wpa_supplicant_ctrl_iface_add_cred(struct wpa_supplicant *wpa_s, } -static int wpas_ctrl_remove_cred(struct wpa_supplicant *wpa_s, - struct wpa_cred *cred) -{ - struct wpa_ssid *ssid; - char str[20]; - int id; - - if (cred == NULL) { - wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred"); - return -1; - } - - id = cred->id; - if (wpa_config_remove_cred(wpa_s->conf, id) < 0) { - wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find cred"); - return -1; - } - - wpa_msg(wpa_s, MSG_INFO, CRED_REMOVED "%d", id); - - /* Remove any network entry created based on the removed credential */ - ssid = wpa_s->conf->ssid; - while (ssid) { - if (ssid->parent_cred == cred) { - int res; - - wpa_printf(MSG_DEBUG, "Remove network id %d since it " - "used the removed credential", ssid->id); - res = os_snprintf(str, sizeof(str), "%d", ssid->id); - if (os_snprintf_error(sizeof(str), res)) - str[sizeof(str) - 1] = '\0'; - ssid = ssid->next; - wpa_supplicant_ctrl_iface_remove_network(wpa_s, str); - } else - ssid = ssid->next; - } - - return 0; -} - - static int wpa_supplicant_ctrl_iface_remove_cred(struct wpa_supplicant *wpa_s, char *cmd) { @@ -3844,13 +3803,7 @@ static int wpa_supplicant_ctrl_iface_remove_cred(struct wpa_supplicant *wpa_s, * "provisioning_sp=<FQDN> */ if (os_strcmp(cmd, "all") == 0) { wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED all"); - cred = wpa_s->conf->cred; - while (cred) { - prev = cred; - cred = cred->next; - wpas_ctrl_remove_cred(wpa_s, prev); - } - return 0; + return wpas_remove_all_creds(wpa_s); } if (os_strncmp(cmd, "sp_fqdn=", 8) == 0) { @@ -3866,7 +3819,7 @@ static int wpa_supplicant_ctrl_iface_remove_cred(struct wpa_supplicant *wpa_s, if (os_strcmp(prev->domain[i], cmd + 8) != 0) continue; - wpas_ctrl_remove_cred(wpa_s, prev); + wpas_remove_cred(wpa_s, prev); break; } } @@ -3883,7 +3836,7 @@ static int wpa_supplicant_ctrl_iface_remove_cred(struct wpa_supplicant *wpa_s, cred = cred->next; if (prev->provisioning_sp && os_strcmp(prev->provisioning_sp, cmd + 16) == 0) - wpas_ctrl_remove_cred(wpa_s, prev); + wpas_remove_cred(wpa_s, prev); } return 0; } @@ -3892,7 +3845,7 @@ static int wpa_supplicant_ctrl_iface_remove_cred(struct wpa_supplicant *wpa_s, wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_CRED id=%d", id); cred = wpa_config_get_cred(wpa_s->conf, id); - return wpas_ctrl_remove_cred(wpa_s, cred); + return wpas_remove_cred(wpa_s, cred); } @@ -4826,7 +4779,9 @@ static int wpa_supplicant_ctrl_iface_get_capability( #ifdef CONFIG_DPP if (os_strcmp(field, "dpp") == 0) { -#ifdef CONFIG_DPP2 +#ifdef CONFIG_DPP3 + res = os_snprintf(buf, buflen, "DPP=3"); +#elif defined(CONFIG_DPP2) res = os_snprintf(buf, buflen, "DPP=2"); #else /* CONFIG_DPP2 */ res = os_snprintf(buf, buflen, "DPP=1"); @@ -8477,7 +8432,9 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s) dpp_pkex_ephemeral_key_override_len = 0; dpp_protocol_key_override_len = 0; dpp_nonce_override_len = 0; -#ifdef CONFIG_DPP2 +#ifdef CONFIG_DPP3 + dpp_version_override = 3; +#elif defined(CONFIG_DPP2) dpp_version_override = 2; #else /* CONFIG_DPP2 */ dpp_version_override = 1; diff --git a/contrib/wpa/wpa_supplicant/dbus/dbus_new.c b/contrib/wpa/wpa_supplicant/dbus/dbus_new.c index 2c01943f754e..9279ae4d5847 100644 --- a/contrib/wpa/wpa_supplicant/dbus/dbus_new.c +++ b/contrib/wpa/wpa_supplicant/dbus/dbus_new.c @@ -937,6 +937,95 @@ void wpas_dbus_signal_mesh_peer_disconnected(struct wpa_supplicant *wpa_s, #endif /* CONFIG_MESH */ +#ifdef CONFIG_INTERWORKING + +void wpas_dbus_signal_interworking_ap_added(struct wpa_supplicant *wpa_s, + struct wpa_bss *bss, + struct wpa_cred *cred, + const char *type, + int excluded, + int bh, + int bss_load, + int conn_capab) +{ + struct wpas_dbus_priv *iface; + DBusMessage *msg; + DBusMessageIter iter, dict_iter; + char bss_path[WPAS_DBUS_OBJECT_PATH_MAX], *bss_obj_path; + char cred_path[WPAS_DBUS_OBJECT_PATH_MAX], *cred_obj_path; + + iface = wpa_s->global->dbus; + + /* Do nothing if the control interface is not turned on */ + if (!iface || !wpa_s->dbus_new_path) + return; + + msg = dbus_message_new_signal(wpa_s->dbus_new_path, + WPAS_DBUS_NEW_IFACE_INTERFACE, + "InterworkingAPAdded"); + if (!msg) + return; + + os_snprintf(bss_path, WPAS_DBUS_OBJECT_PATH_MAX, + "%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u", + wpa_s->dbus_new_path, bss->id); + bss_obj_path = bss_path; + + os_snprintf(cred_path, WPAS_DBUS_OBJECT_PATH_MAX, + "%s/" WPAS_DBUS_NEW_CREDENTIALS_PART "/%u", + wpa_s->dbus_new_path, cred->id); + cred_obj_path = cred_path; + + dbus_message_iter_init_append(msg, &iter); + if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, + &bss_obj_path) || + !dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, + &cred_obj_path) || + !wpa_dbus_dict_open_write(&iter, &dict_iter) || + !wpa_dbus_dict_append_string(&dict_iter, "type", type) || + !wpa_dbus_dict_append_int32(&dict_iter, "excluded", excluded) || + !wpa_dbus_dict_append_int32(&dict_iter, "priority", + cred->priority) || + !wpa_dbus_dict_append_int32(&dict_iter, "sp_priority", + cred->sp_priority) || + !wpa_dbus_dict_append_int32(&dict_iter, "below_min_backhaul", bh) || + !wpa_dbus_dict_append_int32(&dict_iter, "over_max_bss_load", + bss_load) || + !wpa_dbus_dict_append_int32(&dict_iter, "conn_capab_missing", + conn_capab) || + !wpa_dbus_dict_close_write(&iter, &dict_iter)) + wpa_printf(MSG_ERROR, "dbus: Failed to construct signal"); + else + dbus_connection_send(iface->con, msg, NULL); + dbus_message_unref(msg); +} + + +void wpas_dbus_signal_interworking_select_done(struct wpa_supplicant *wpa_s) +{ + struct wpas_dbus_priv *iface; + DBusMessage *msg; + + iface = wpa_s->global->dbus; + + /* Do nothing if the control interface is not turned on */ + if (!iface || !wpa_s->dbus_new_path) + return; + + msg = dbus_message_new_signal(wpa_s->dbus_new_path, + WPAS_DBUS_NEW_IFACE_INTERFACE, + "InterworkingSelectDone"); + if (!msg) + return; + + dbus_connection_send(iface->con, msg, NULL); + + dbus_message_unref(msg); +} + +#endif /* CONFIG_INTERWORKING */ + + void wpas_dbus_signal_certification(struct wpa_supplicant *wpa_s, int depth, const char *subject, const char *altsubject[], @@ -3570,6 +3659,35 @@ static const struct wpa_dbus_method_desc wpas_dbus_interface_methods[] = { END_ARGS } }, +#ifdef CONFIG_INTERWORKING + { "AddCred", WPAS_DBUS_NEW_IFACE_INTERFACE, + (WPADBusMethodHandler) wpas_dbus_handler_add_cred, + { + { "args", "a{sv}", ARG_IN }, + { "path", "o", ARG_OUT }, + END_ARGS + } + }, + { "RemoveCred", WPAS_DBUS_NEW_IFACE_INTERFACE, + (WPADBusMethodHandler) wpas_dbus_handler_remove_cred, + { + { "path", "o", ARG_IN }, + END_ARGS + } + }, + { "RemoveAllCreds", WPAS_DBUS_NEW_IFACE_INTERFACE, + (WPADBusMethodHandler) wpas_dbus_handler_remove_all_creds, + { + END_ARGS + } + }, + { "InterworkingSelect", WPAS_DBUS_NEW_IFACE_INTERFACE, + (WPADBusMethodHandler) wpas_dbus_handler_interworking_select, + { + END_ARGS + } + }, +#endif /* CONFIG_INTERWORKING */ { NULL, NULL, NULL, { END_ARGS } } }; @@ -4137,6 +4255,21 @@ static const struct wpa_dbus_signal_desc wpas_dbus_interface_signals[] = { } }, #endif /* CONFIG_MESH */ +#ifdef CONFIG_INTERWORKING + { "InterworkingAPAdded", WPAS_DBUS_NEW_IFACE_INTERFACE, + { + { "bss", "o", ARG_OUT }, + { "cred", "o", ARG_OUT }, + { "properties", "a{sv}", ARG_OUT }, + END_ARGS + } + }, + { "InterworkingSelectDone", WPAS_DBUS_NEW_IFACE_INTERFACE, + { + END_ARGS + } + }, +#endif /* CONFIG_INTERWORKING */ { NULL, NULL, { END_ARGS } } }; diff --git a/contrib/wpa/wpa_supplicant/dbus/dbus_new.h b/contrib/wpa/wpa_supplicant/dbus/dbus_new.h index 42db3892ed77..26bdcb548de8 100644 --- a/contrib/wpa/wpa_supplicant/dbus/dbus_new.h +++ b/contrib/wpa/wpa_supplicant/dbus/dbus_new.h @@ -16,6 +16,8 @@ struct wpa_global; struct wpa_supplicant; struct wpa_ssid; +struct wpa_cred; +struct wpa_bss; struct wps_event_m2d; struct wps_event_fail; struct wps_credential; @@ -96,6 +98,9 @@ enum wpas_dbus_sta_prop { #define WPAS_DBUS_NEW_P2P_PEERS_PART "Peers" #define WPAS_DBUS_NEW_IFACE_P2P_PEER WPAS_DBUS_NEW_INTERFACE ".Peer" +#define WPAS_DBUS_NEW_CREDENTIALS_PART "Credentials" +#define WPAS_DBUS_NEW_IFACE_CREDENTIAL WPAS_DBUS_NEW_INTERFACE ".Credential" + /* Top-level Errors */ #define WPAS_DBUS_ERROR_UNKNOWN_ERROR \ WPAS_DBUS_NEW_INTERFACE ".UnknownError" @@ -264,6 +269,13 @@ void wpas_dbus_signal_mesh_peer_connected(struct wpa_supplicant *wpa_s, const u8 *peer_addr); void wpas_dbus_signal_mesh_peer_disconnected(struct wpa_supplicant *wpa_s, const u8 *peer_addr, int reason); +void wpas_dbus_signal_interworking_ap_added(struct wpa_supplicant *wpa_s, + struct wpa_bss *bss, + struct wpa_cred *cred, + const char *type, int excluded, + int bh, int bss_load, + int conn_capab); +void wpas_dbus_signal_interworking_select_done(struct wpa_supplicant *wpa_s); #else /* CONFIG_CTRL_IFACE_DBUS_NEW */ @@ -616,6 +628,21 @@ void wpas_dbus_signal_mesh_peer_disconnected(struct wpa_supplicant *wpa_s, { } +static inline +void wpas_dbus_signal_interworking_ap_added(struct wpa_supplicant *wpa_s, + struct wpa_bss *bss, + struct wpa_cred *cred, + const char *type, int excluded, + int bh, int bss_load, + int conn_capab) +{ +} + +static inline +void wpas_dbus_signal_interworking_select_done(struct wpa_supplicant *wpa_s) +{ +} + #endif /* CONFIG_CTRL_IFACE_DBUS_NEW */ #endif /* CTRL_IFACE_DBUS_H_NEW */ diff --git a/contrib/wpa/wpa_supplicant/dbus/dbus_new_handlers.c b/contrib/wpa/wpa_supplicant/dbus/dbus_new_handlers.c index db9f30c9aabf..545e9f64295a 100644 --- a/contrib/wpa/wpa_supplicant/dbus/dbus_new_handlers.c +++ b/contrib/wpa/wpa_supplicant/dbus/dbus_new_handlers.c @@ -26,6 +26,7 @@ #include "../scan.h" #include "../autoscan.h" #include "../ap.h" +#include "../interworking.h" #include "dbus_new_helpers.h" #include "dbus_new.h" #include "dbus_new_handlers.h" @@ -148,6 +149,9 @@ static const char * const dont_quote[] = { #ifdef CONFIG_P2P "go_p2p_dev_addr", "p2p_client_list", "psk_list", #endif /* CONFIG_P2P */ +#ifdef CONFIG_INTERWORKING + "roaming_consortium", "required_roaming_consortium", +#endif /* CONFIG_INTERWORKING */ NULL }; @@ -329,6 +333,110 @@ error: /** + * set_cred_properties - Set the properties of a configured credential + * @wpa_s: wpa_supplicant structure for a network interface + * @cred: wpa_cred structure for a configured credential + * @iter: DBus message iterator containing dictionary of network + * properties to set. + * @error: On failure, an error describing the failure + * Returns: TRUE if the request succeeds, FALSE if it failed + */ +static dbus_bool_t set_cred_properties(struct wpa_supplicant *wpa_s, + struct wpa_cred *cred, + DBusMessageIter *iter, + DBusError *error) +{ + struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING }; + DBusMessageIter iter_dict; + char *value = NULL; + + if (!wpa_dbus_dict_open_read(iter, &iter_dict, error)) + return FALSE; + + while (wpa_dbus_dict_has_dict_entry(&iter_dict)) { + size_t size = 50; + int ret; + + if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) + goto error; + + value = NULL; + if (entry.type == DBUS_TYPE_ARRAY && + entry.array_type == DBUS_TYPE_BYTE) { + if (entry.array_len <= 0) + goto error; + + size = entry.array_len * 2 + 1; + value = os_zalloc(size); + if (!value) + goto error; + + ret = wpa_snprintf_hex(value, size, + (u8 *) entry.bytearray_value, + entry.array_len); + if (ret <= 0) + goto error; + } else if (entry.type == DBUS_TYPE_STRING) { + if (should_quote_opt(entry.key)) { + size = os_strlen(entry.str_value); + + size += 3; + value = os_zalloc(size); + if (!value) + goto error; + + ret = os_snprintf(value, size, "\"%s\"", + entry.str_value); + if (os_snprintf_error(size, ret)) + goto error; + } else { + value = os_strdup(entry.str_value); + if (!value) + goto error; + } + } else if (entry.type == DBUS_TYPE_UINT32) { + value = os_zalloc(size); + if (!value) + goto error; + + ret = os_snprintf(value, size, "%u", + entry.uint32_value); + if (os_snprintf_error(size, ret)) + goto error; + } else if (entry.type == DBUS_TYPE_INT32) { + value = os_zalloc(size); + if (!value) + goto error; + + ret = os_snprintf(value, size, "%d", + entry.int32_value); + if (os_snprintf_error(size, ret)) + goto error; + } else { + goto error; + } + + ret = wpa_config_set_cred(cred, entry.key, value, 0); + if (ret < 0) + goto error; + + os_free(value); + value = NULL; + wpa_dbus_dict_entry_clear(&entry); + } + + return TRUE; + +error: + os_free(value); + wpa_dbus_dict_entry_clear(&entry); + dbus_set_error_const(error, DBUS_ERROR_INVALID_ARGS, + "invalid message format"); + return FALSE; +} + + +/** * wpas_dbus_simple_property_getter - Get basic type property * @iter: Message iter to use when appending arguments * @type: DBus type of property (must be basic type) @@ -1516,6 +1624,185 @@ DBusMessage * wpas_dbus_handler_abort_scan(DBusMessage *message, /** + * wpas_dbus_new_iface_add_cred - Add a new credential + * @message: Pointer to incoming dbus message + * @wpa_s: wpa_supplicant structure for a network interface + * Returns: A dbus message containing the object path of the new credential + * + * Handler function for "AddCred" method call of a network interface. + */ +DBusMessage * wpas_dbus_handler_add_cred(DBusMessage *message, + struct wpa_supplicant *wpa_s) +{ + DBusMessage *reply = NULL; + DBusMessageIter iter; + struct wpa_cred *cred = NULL; + char path_buf[WPAS_DBUS_OBJECT_PATH_MAX], *path = path_buf; + DBusError error; + + dbus_message_iter_init(message, &iter); + + if (wpa_s->dbus_new_path) + cred = wpa_config_add_cred(wpa_s->conf); + if (!cred) { + wpa_printf(MSG_ERROR, "%s[dbus]: can't add new credential.", + __func__); + reply = wpas_dbus_error_unknown_error( + message, + "wpa_supplicant could not add a credential on this interface."); + goto err; + } + + dbus_error_init(&error); + if (!set_cred_properties(wpa_s, cred, &iter, &error)) { + wpa_printf(MSG_DEBUG, + "%s[dbus]: control interface couldn't set credential properties", + __func__); + reply = wpas_dbus_reply_new_from_error(message, &error, + DBUS_ERROR_INVALID_ARGS, + "Failed to add credential"); + dbus_error_free(&error); + goto err; + } + + /* Construct the object path for this network. */ + os_snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX, + "%s/" WPAS_DBUS_NEW_CREDENTIALS_PART "/%d", + wpa_s->dbus_new_path, cred->id); + + reply = dbus_message_new_method_return(message); + if (!reply) { + reply = wpas_dbus_error_no_memory(message); + goto err; + } + if (!dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path, + DBUS_TYPE_INVALID)) { + dbus_message_unref(reply); + reply = wpas_dbus_error_no_memory(message); + goto err; + } + + return reply; + +err: + if (cred) + wpa_config_remove_cred(wpa_s->conf, cred->id); + return reply; +} + + +/** + * wpas_dbus_handler_remove_cred - Remove a configured credential + * @message: Pointer to incoming dbus message + * @wpa_s: wpa_supplicant structure for a network interface + * Returns: NULL on success or dbus error on failure + * + * Handler function for "RemoveCred" method call of a network interface. + */ +DBusMessage * wpas_dbus_handler_remove_cred(DBusMessage *message, + struct wpa_supplicant *wpa_s) +{ + DBusMessage *reply = NULL; + const char *op; + char *iface, *cred_id; + int id; + struct wpa_cred *cred; + + dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op, + DBUS_TYPE_INVALID); + + /* Extract the network ID and ensure the network is actually a child of + * this interface */ + iface = wpas_dbus_new_decompose_object_path( + op, WPAS_DBUS_NEW_CREDENTIALS_PART, &cred_id); + if (!iface || !cred_id || !wpa_s->dbus_new_path || + os_strcmp(iface, wpa_s->dbus_new_path) != 0) { + reply = wpas_dbus_error_invalid_args(message, op); + goto out; + } + + errno = 0; + id = strtoul(cred_id, NULL, 10); + if (errno != 0) { + reply = wpas_dbus_error_invalid_args(message, op); + goto out; + } + + cred = wpa_config_get_cred(wpa_s->conf, id); + if (!cred) { + wpa_printf(MSG_ERROR, "%s[dbus]: could not find credential %s", + __func__, op); + reply = wpas_dbus_error_invalid_args( + message, "could not find credential"); + goto out; + } + + if (wpas_remove_cred(wpa_s, cred) < 0) { + wpa_printf(MSG_ERROR, + "%s[dbus]: error occurred when removing cred %d", + __func__, id); + reply = wpas_dbus_error_unknown_error( + message, + "error removing the specified credential on its interface."); + goto out; + } + +out: + os_free(iface); + return reply; +} + + +/** + * wpas_dbus_handler_remove_all_creds - Remove all the configured credentials + * @message: Pointer to incoming dbus message + * @wpa_s: wpa_supplicant structure for a network interface + * Returns: NULL indicating success or DBus error message on failure + * + * Handler function for "RemoveAllCreds" method call of a network interface. + */ +DBusMessage * wpas_dbus_handler_remove_all_creds(DBusMessage *message, + struct wpa_supplicant *wpa_s) +{ + int res; + DBusMessage *reply = NULL; + + res = wpas_remove_all_creds(wpa_s); + if (res < 0) { + wpa_printf(MSG_ERROR, + "%s[dbus]: failed to remove all credentials", + __func__); + reply = wpas_dbus_error_unknown_error( + message, "failed to remove all credentials"); + } + + return reply; +} + + +DBusMessage * +wpas_dbus_handler_interworking_select(DBusMessage *message, + struct wpa_supplicant *wpa_s) +{ + int result; + DBusMessage *reply = NULL; + + /* Automatic selection is disabled and no constraint on channels */ + result = interworking_select(wpa_s, 0, NULL); + if (result < 0) { + wpa_printf(MSG_ERROR, + "%s[dbus]: failed to start Interworking selection", + __func__); + reply = wpas_dbus_error_scan_error( + message, + "error starting Interworking selection."); + } + + return reply; +} + + +/** * wpas_dbus_handler_signal_poll - Request immediate signal properties * @message: Pointer to incoming dbus message * @wpa_s: wpa_supplicant structure for a network interface diff --git a/contrib/wpa/wpa_supplicant/dbus/dbus_new_handlers.h b/contrib/wpa/wpa_supplicant/dbus/dbus_new_handlers.h index c36383f05668..a421083f7fe2 100644 --- a/contrib/wpa/wpa_supplicant/dbus/dbus_new_handlers.h +++ b/contrib/wpa/wpa_supplicant/dbus/dbus_new_handlers.h @@ -144,6 +144,19 @@ DBusMessage * wpas_dbus_handler_eap_logoff(DBusMessage *message, DBusMessage * wpas_dbus_handler_eap_logon(DBusMessage *message, struct wpa_supplicant *wpa_s); +DBusMessage * wpas_dbus_handler_add_cred(DBusMessage *message, + struct wpa_supplicant *wpa_s); + +DBusMessage * wpas_dbus_handler_remove_cred(DBusMessage *message, + struct wpa_supplicant *wpa_s); + +DBusMessage * wpas_dbus_handler_remove_all_creds(DBusMessage *message, + struct wpa_supplicant *wpa_s); + +DBusMessage * +wpas_dbus_handler_interworking_select(DBusMessage *message, + struct wpa_supplicant *wpa_s); + DECLARE_ACCESSOR(wpas_dbus_getter_capabilities); DECLARE_ACCESSOR(wpas_dbus_getter_state); DECLARE_ACCESSOR(wpas_dbus_getter_scanning); diff --git a/contrib/wpa/wpa_supplicant/dbus/dbus_new_handlers_p2p.c b/contrib/wpa/wpa_supplicant/dbus/dbus_new_handlers_p2p.c index 565ced0fd7e2..de79178f4655 100644 --- a/contrib/wpa/wpa_supplicant/dbus/dbus_new_handlers_p2p.c +++ b/contrib/wpa/wpa_supplicant/dbus/dbus_new_handlers_p2p.c @@ -744,6 +744,7 @@ DBusMessage * wpas_dbus_handler_p2p_invite(DBusMessage *message, unsigned int group_id = 0; int persistent = 0; struct wpa_ssid *ssid; + const char *group_ifname; if (!wpa_dbus_p2p_check_enabled(wpa_s, message, &reply, NULL)) return reply; @@ -777,6 +778,8 @@ DBusMessage * wpas_dbus_handler_p2p_invite(DBusMessage *message, !p2p_peer_known(wpa_s->global->p2p, peer_addr)) goto err; + /* Capture the interface name for the group first */ + group_ifname = wpa_s->ifname; wpa_s = wpa_s->global->p2p_init_wpa_s; if (persistent) { @@ -821,7 +824,7 @@ DBusMessage * wpas_dbus_handler_p2p_invite(DBusMessage *message, /* * No group ID means propose to a peer to join my active group */ - if (wpas_p2p_invite_group(wpa_s, wpa_s->ifname, + if (wpas_p2p_invite_group(wpa_s, group_ifname, peer_addr, NULL, false)) { reply = wpas_dbus_error_unknown_error( message, "Failed to join to an active group"); diff --git a/contrib/wpa/wpa_supplicant/defconfig b/contrib/wpa/wpa_supplicant/defconfig index 708a82385170..a4719dbb543d 100644 --- a/contrib/wpa/wpa_supplicant/defconfig +++ b/contrib/wpa/wpa_supplicant/defconfig @@ -603,8 +603,13 @@ CONFIG_BGSCAN_SIMPLE=y # Experimental implementation of draft-harkins-owe-07.txt #CONFIG_OWE=y -# Device Provisioning Protocol (DPP) +# Device Provisioning Protocol (DPP) (also known as Wi-Fi Easy Connect) CONFIG_DPP=y +# DPP version 2 support +CONFIG_DPP2=y +# DPP version 3 support (experimental and still changing; do not enable for +# production use) +#CONFIG_DPP3=y # Wired equivalent privacy (WEP) # WEP is an obsolete cryptographic data confidentiality algorithm that is not diff --git a/contrib/wpa/wpa_supplicant/dpp_supplicant.c b/contrib/wpa/wpa_supplicant/dpp_supplicant.c index 40ef8aeb510f..584654a6cb2c 100644 --- a/contrib/wpa/wpa_supplicant/dpp_supplicant.c +++ b/contrib/wpa/wpa_supplicant/dpp_supplicant.c @@ -1021,6 +1021,7 @@ void wpas_dpp_listen_stop(struct wpa_supplicant *wpa_s) wpa_drv_dpp_listen(wpa_s, false); wpa_s->dpp_listen_freq = 0; wpas_dpp_listen_work_done(wpa_s); + radio_remove_works(wpa_s, "dpp-listen", 0); } @@ -2462,6 +2463,16 @@ static void wpas_dpp_rx_peer_disc_resp(struct wpa_supplicant *wpa_s, &version_len); if (version && version_len >= 1) peer_version = version[0]; +#ifdef CONFIG_DPP3 + if (intro.peer_version && intro.peer_version >= 2 && + peer_version != intro.peer_version) { + wpa_printf(MSG_INFO, + "DPP: Protocol version mismatch (Connector: %d Attribute: %d", + intro.peer_version, peer_version); + wpas_dpp_send_conn_status_result(wpa_s, DPP_STATUS_NO_MATCH); + goto fail; + } +#endif /* CONFIG_DPP3 */ entry->dpp_pfs = peer_version >= 2; #endif /* CONFIG_DPP2 */ if (expiry) { @@ -2568,7 +2579,9 @@ static void wpas_dpp_pkex_retry_timeout(void *eloop_ctx, void *timeout_ctx) wpa_printf(MSG_DEBUG, "DPP: Retransmit PKEX Exchange Request (try %u)", pkex->exch_req_tries); wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d", - MAC2STR(broadcast), pkex->freq, DPP_PA_PKEX_EXCHANGE_REQ); + MAC2STR(broadcast), pkex->freq, + pkex->v2 ? DPP_PA_PKEX_EXCHANGE_REQ : + DPP_PA_PKEX_V1_EXCHANGE_REQ); offchannel_send_action(wpa_s, pkex->freq, broadcast, wpa_s->own_addr, broadcast, wpabuf_head(pkex->exchange_req), @@ -2627,7 +2640,8 @@ wpas_dpp_tx_pkex_status(struct wpa_supplicant *wpa_s, static void wpas_dpp_rx_pkex_exchange_req(struct wpa_supplicant *wpa_s, const u8 *src, - const u8 *buf, size_t len, unsigned int freq) + const u8 *buf, size_t len, unsigned int freq, + bool v2) { struct wpabuf *msg; unsigned int wait_time; @@ -2655,7 +2669,7 @@ wpas_dpp_rx_pkex_exchange_req(struct wpa_supplicant *wpa_s, const u8 *src, wpa_s->own_addr, src, wpa_s->dpp_pkex_identifier, wpa_s->dpp_pkex_code, - buf, len); + buf, len, v2); if (!wpa_s->dpp_pkex) { wpa_printf(MSG_DEBUG, "DPP: Failed to process the request - ignore it"); @@ -2878,8 +2892,17 @@ void wpas_dpp_rx_action(struct wpa_supplicant *wpa_s, const u8 *src, case DPP_PA_PEER_DISCOVERY_RESP: wpas_dpp_rx_peer_disc_resp(wpa_s, src, buf, len); break; +#ifdef CONFIG_DPP3 case DPP_PA_PKEX_EXCHANGE_REQ: - wpas_dpp_rx_pkex_exchange_req(wpa_s, src, buf, len, freq); + /* This is for PKEXv2, but for now, process only with + * CONFIG_DPP3 to avoid issues with a capability that has not + * been tested with other implementations. */ + wpas_dpp_rx_pkex_exchange_req(wpa_s, src, buf, len, freq, true); + break; +#endif /* CONFIG_DPP3 */ + case DPP_PA_PKEX_V1_EXCHANGE_REQ: + wpas_dpp_rx_pkex_exchange_req(wpa_s, src, buf, len, freq, + false); break; case DPP_PA_PKEX_EXCHANGE_RESP: wpas_dpp_rx_pkex_exchange_resp(wpa_s, src, buf, len, freq); @@ -3192,17 +3215,38 @@ skip_trans_id: #ifdef CONFIG_TESTING_OPTIONS skip_connector: + if (dpp_test == DPP_TEST_NO_PROTOCOL_VERSION_PEER_DISC_REQ) { + wpa_printf(MSG_INFO, "DPP: TESTING - no Protocol Version"); + goto skip_proto_ver; + } #endif /* CONFIG_TESTING_OPTIONS */ #ifdef CONFIG_DPP2 if (DPP_VERSION > 1) { + u8 ver = DPP_VERSION; +#ifdef CONFIG_DPP3 + int conn_ver; + + conn_ver = dpp_get_connector_version(ssid->dpp_connector); + if (conn_ver > 0 && ver != conn_ver) { + wpa_printf(MSG_DEBUG, + "DPP: Use Connector version %d instead of current protocol version %d", + conn_ver, ver); + ver = conn_ver; + } +#endif /* CONFIG_DPP3 */ + /* Protocol Version */ wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION); wpabuf_put_le16(msg, 1); - wpabuf_put_u8(msg, DPP_VERSION); + wpabuf_put_u8(msg, ver); } #endif /* CONFIG_DPP2 */ +#ifdef CONFIG_TESTING_OPTIONS +skip_proto_ver: +#endif /* CONFIG_TESTING_OPTIONS */ + /* TODO: Timeout on AP response */ wait_time = wpa_s->max_remain_on_chan; if (wait_time > 2000) @@ -3270,15 +3314,16 @@ int wpas_dpp_pkex_add(struct wpa_supplicant *wpa_s, const char *cmd) if (!wpa_s->dpp_pkex_code) return -1; - if (os_strstr(cmd, " init=1")) { + if (os_strstr(cmd, " init=1") || os_strstr(cmd, " init=2")) { struct dpp_pkex *pkex; struct wpabuf *msg; + bool v2 = os_strstr(cmd, " init=2") != NULL; wpa_printf(MSG_DEBUG, "DPP: Initiating PKEX"); dpp_pkex_free(wpa_s->dpp_pkex); wpa_s->dpp_pkex = dpp_pkex_init(wpa_s, own_bi, wpa_s->own_addr, wpa_s->dpp_pkex_identifier, - wpa_s->dpp_pkex_code); + wpa_s->dpp_pkex_code, v2); pkex = wpa_s->dpp_pkex; if (!pkex) return -1; @@ -3291,7 +3336,8 @@ int wpas_dpp_pkex_add(struct wpa_supplicant *wpa_s, const char *cmd) wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d", MAC2STR(broadcast), pkex->freq, - DPP_PA_PKEX_EXCHANGE_REQ); + v2 ? DPP_PA_PKEX_EXCHANGE_REQ : + DPP_PA_PKEX_V1_EXCHANGE_REQ); offchannel_send_action(wpa_s, pkex->freq, broadcast, wpa_s->own_addr, broadcast, wpabuf_head(msg), wpabuf_len(msg), diff --git a/contrib/wpa/wpa_supplicant/events.c b/contrib/wpa/wpa_supplicant/events.c index 5f5c50ba9754..f55e1846e205 100644 --- a/contrib/wpa/wpa_supplicant/events.c +++ b/contrib/wpa/wpa_supplicant/events.c @@ -2177,7 +2177,7 @@ static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s, if (wnm_scan_process(wpa_s, 1) > 0) goto scan_work_done; - if (sme_proc_obss_scan(wpa_s, scan_res) > 0) + if (sme_proc_obss_scan(wpa_s) > 0) goto scan_work_done; if (own_request && data && diff --git a/contrib/wpa/wpa_supplicant/interworking.c b/contrib/wpa/wpa_supplicant/interworking.c index 1c82d2117ab0..71a5c16510d4 100644 --- a/contrib/wpa/wpa_supplicant/interworking.c +++ b/contrib/wpa/wpa_supplicant/interworking.c @@ -702,12 +702,14 @@ static struct nai_realm_eap * nai_realm_find_eap(struct wpa_supplicant *wpa_s, ((cred->password == NULL || cred->password[0] == '\0') && (cred->private_key == NULL || - cred->private_key[0] == '\0'))) { + cred->private_key[0] == '\0') && + (!cred->key_id || cred->key_id[0] == '\0'))) { wpa_msg(wpa_s, MSG_DEBUG, - "nai-realm-find-eap: incomplete cred info: username: %s password: %s private_key: %s", + "nai-realm-find-eap: incomplete cred info: username: %s password: %s private_key: %s key_id: %s", cred->username ? cred->username : "NULL", cred->password ? cred->password : "NULL", - cred->private_key ? cred->private_key : "NULL"); + cred->private_key ? cred->private_key : "NULL", + cred->key_id ? cred->key_id : "NULL"); return NULL; } @@ -716,7 +718,8 @@ static struct nai_realm_eap * nai_realm_find_eap(struct wpa_supplicant *wpa_s, if (cred->password && cred->password[0] && nai_realm_cred_username(wpa_s, eap)) return eap; - if (cred->private_key && cred->private_key[0] && + if (((cred->private_key && cred->private_key[0]) || + (cred->key_id && cred->key_id[0])) && nai_realm_cred_cert(wpa_s, eap)) return eap; } @@ -1539,6 +1542,24 @@ static int interworking_set_eap_params(struct wpa_ssid *ssid, cred->private_key_passwd) < 0) return -1; + if (cred->ca_cert_id && cred->ca_cert_id[0] && + wpa_config_set_quoted(ssid, "ca_cert_id", cred->ca_cert_id) < 0) + return -1; + + if (cred->cert_id && cred->cert_id[0] && + wpa_config_set_quoted(ssid, "cert_id", cred->cert_id) < 0) + return -1; + + if (cred->key_id && cred->key_id[0] && + wpa_config_set_quoted(ssid, "key_id", cred->key_id) < 0) + return -1; + + if (cred->engine_id && cred->engine_id[0] && + wpa_config_set_quoted(ssid, "engine_id", cred->engine_id) < 0) + return -1; + + ssid->eap.cert.engine = cred->engine; + if (cred->phase1) { os_free(ssid->eap.phase1); ssid->eap.phase1 = os_strdup(cred->phase1); @@ -2481,13 +2502,9 @@ static void interworking_select_network(struct wpa_supplicant *wpa_s) bh = cred_below_min_backhaul(wpa_s, cred, bss); bss_load = cred_over_max_bss_load(wpa_s, cred, bss); conn_capab = cred_conn_capab_missing(wpa_s, cred, bss); - wpa_msg(wpa_s, MSG_INFO, "%s" MACSTR " type=%s%s%s%s id=%d priority=%d sp_priority=%d", - excluded ? INTERWORKING_EXCLUDED : INTERWORKING_AP, - MAC2STR(bss->bssid), type, - bh ? " below_min_backhaul=1" : "", - bss_load ? " over_max_bss_load=1" : "", - conn_capab ? " conn_capab_missing=1" : "", - cred->id, cred->priority, cred->sp_priority); + wpas_notify_interworking_ap_added(wpa_s, bss, cred, excluded, + type, bh, bss_load, + conn_capab); if (excluded) continue; if (wpa_s->auto_select || @@ -2578,6 +2595,8 @@ static void interworking_select_network(struct wpa_supplicant *wpa_s) wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); } + wpas_notify_interworking_select_done(wpa_s); + if (selected) { wpa_printf(MSG_DEBUG, "Interworking: Selected " MACSTR, MAC2STR(selected->bssid)); diff --git a/contrib/wpa/wpa_supplicant/mesh.c b/contrib/wpa/wpa_supplicant/mesh.c index 7938b8b4903e..d6b8a1ad9e36 100644 --- a/contrib/wpa/wpa_supplicant/mesh.c +++ b/contrib/wpa/wpa_supplicant/mesh.c @@ -140,6 +140,7 @@ static struct mesh_conf * mesh_config_create(struct wpa_supplicant *wpa_s, conf->mesh_cc_id = 0; conf->mesh_sp_id = MESH_SYNC_METHOD_NEIGHBOR_OFFSET; conf->mesh_auth_id = (conf->security & MESH_CONF_SEC_AUTH) ? 1 : 0; + conf->mesh_fwding = ssid->mesh_fwding; conf->dot11MeshMaxRetries = ssid->dot11MeshMaxRetries; conf->dot11MeshRetryTimeout = ssid->dot11MeshRetryTimeout; conf->dot11MeshConfirmTimeout = ssid->dot11MeshConfirmTimeout; @@ -472,6 +473,7 @@ static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s, bss->conf->start_disabled = 1; bss->conf->mesh = MESH_ENABLED; bss->conf->ap_max_inactivity = wpa_s->conf->mesh_max_inactivity; + bss->conf->mesh_fwding = wpa_s->conf->mesh_fwding; if (ieee80211_is_dfs(ssid->frequency, wpa_s->hw.modes, wpa_s->hw.num_modes) && wpa_s->conf->country[0]) { @@ -686,6 +688,10 @@ int wpa_supplicant_join_mesh(struct wpa_supplicant *wpa_s, } params->conf.peer_link_timeout = wpa_s->conf->mesh_max_inactivity; + /* Always explicitely set forwarding to on or off for now */ + params->conf.flags |= WPA_DRIVER_MESH_CONF_FLAG_FORWARDING; + params->conf.forwarding = ssid->mesh_fwding; + os_free(wpa_s->mesh_params); wpa_s->mesh_params = params; if (wpa_supplicant_mesh_init(wpa_s, ssid, ¶ms->freq)) { diff --git a/contrib/wpa/wpa_supplicant/mesh_mpm.c b/contrib/wpa/wpa_supplicant/mesh_mpm.c index 38f0d641a03b..2eb9a7ef6182 100644 --- a/contrib/wpa/wpa_supplicant/mesh_mpm.c +++ b/contrib/wpa/wpa_supplicant/mesh_mpm.c @@ -306,9 +306,10 @@ static void mesh_mpm_send_plink_action(struct wpa_supplicant *wpa_s, info = (bss->num_plinks > 63 ? 63 : bss->num_plinks) << 1; /* TODO: Add Connected to Mesh Gate/AS subfields */ wpabuf_put_u8(buf, info); - /* always forwarding & accepting plinks for now */ + /* Set forwarding based on configuration and always accept + * plinks for now */ wpabuf_put_u8(buf, MESH_CAP_ACCEPT_ADDITIONAL_PEER | - MESH_CAP_FORWARDING); + (conf->mesh_fwding ? MESH_CAP_FORWARDING : 0)); } else { /* Peer closing frame */ /* IE: Mesh ID */ wpabuf_put_u8(buf, WLAN_EID_MESH_ID); diff --git a/contrib/wpa/wpa_supplicant/notify.c b/contrib/wpa/wpa_supplicant/notify.c index fe5e072c24c2..821c916c153f 100644 --- a/contrib/wpa/wpa_supplicant/notify.c +++ b/contrib/wpa/wpa_supplicant/notify.c @@ -19,6 +19,7 @@ #include "rsn_supp/wpa.h" #include "fst/fst.h" #include "crypto/tls.h" +#include "bss.h" #include "driver_i.h" #include "scan.h" #include "p2p_supplicant.h" @@ -943,3 +944,32 @@ void wpas_notify_mesh_peer_disconnected(struct wpa_supplicant *wpa_s, } #endif /* CONFIG_MESH */ + + +#ifdef CONFIG_INTERWORKING + +void wpas_notify_interworking_ap_added(struct wpa_supplicant *wpa_s, + struct wpa_bss *bss, + struct wpa_cred *cred, int excluded, + const char *type, int bh, int bss_load, + int conn_capab) +{ + wpa_msg(wpa_s, MSG_INFO, "%s" MACSTR " type=%s%s%s%s id=%d priority=%d sp_priority=%d", + excluded ? INTERWORKING_EXCLUDED : INTERWORKING_AP, + MAC2STR(bss->bssid), type, + bh ? " below_min_backhaul=1" : "", + bss_load ? " over_max_bss_load=1" : "", + conn_capab ? " conn_capab_missing=1" : "", + cred->id, cred->priority, cred->sp_priority); + + wpas_dbus_signal_interworking_ap_added(wpa_s, bss, cred, type, excluded, + bh, bss_load, conn_capab); +} + + +void wpas_notify_interworking_select_done(struct wpa_supplicant *wpa_s) +{ + wpas_dbus_signal_interworking_select_done(wpa_s); +} + +#endif /* CONFIG_INTERWORKING */ diff --git a/contrib/wpa/wpa_supplicant/notify.h b/contrib/wpa/wpa_supplicant/notify.h index e843aa124b39..c46e7986e3b3 100644 --- a/contrib/wpa/wpa_supplicant/notify.h +++ b/contrib/wpa/wpa_supplicant/notify.h @@ -15,6 +15,7 @@ struct wps_credential; struct wps_event_m2d; struct wps_event_fail; struct tls_cert_data; +struct wpa_cred; int wpas_notify_supplicant_initialized(struct wpa_global *global); void wpas_notify_supplicant_deinitialized(struct wpa_global *global); @@ -156,5 +157,11 @@ void wpas_notify_mesh_peer_connected(struct wpa_supplicant *wpa_s, const u8 *peer_addr); void wpas_notify_mesh_peer_disconnected(struct wpa_supplicant *wpa_s, const u8 *peer_addr, u16 reason_code); +void wpas_notify_interworking_ap_added(struct wpa_supplicant *wpa_s, + struct wpa_bss *bss, + struct wpa_cred *cred, int excluded, + const char *type, int bh, int bss_load, + int conn_capab); +void wpas_notify_interworking_select_done(struct wpa_supplicant *wpa_s); #endif /* NOTIFY_H */ diff --git a/contrib/wpa/wpa_supplicant/sme.c b/contrib/wpa/wpa_supplicant/sme.c index f2c42ff354e7..1dc7001a7305 100644 --- a/contrib/wpa/wpa_supplicant/sme.c +++ b/contrib/wpa/wpa_supplicant/sme.c @@ -13,7 +13,6 @@ #include "common/ieee802_11_defs.h" #include "common/ieee802_11_common.h" #include "common/ocv.h" -#include "common/hw_features_common.h" #include "eapol_supp/eapol_supp_sm.h" #include "common/wpa_common.h" #include "common/sae.h" @@ -138,6 +137,12 @@ static struct wpabuf * sme_auth_build_sae_commit(struct wpa_supplicant *wpa_s, } bss = wpa_bss_get_bssid_latest(wpa_s, bssid); + if (!bss) { + wpa_printf(MSG_DEBUG, + "SAE: BSS not available, update scan result to get BSS"); + wpa_supplicant_update_scan_results(wpa_s); + bss = wpa_bss_get_bssid_latest(wpa_s, bssid); + } if (bss) { const u8 *rsnxe; @@ -2380,14 +2385,13 @@ static void sme_send_2040_bss_coex(struct wpa_supplicant *wpa_s, } -int sme_proc_obss_scan(struct wpa_supplicant *wpa_s, - struct wpa_scan_results *scan_res) +int sme_proc_obss_scan(struct wpa_supplicant *wpa_s) { + struct wpa_bss *bss; const u8 *ie; + u16 ht_cap; u8 chan_list[P2P_MAX_CHANNELS], channel; u8 num_channels = 0, num_intol = 0, i; - size_t j; - int pri_freq, sec_freq; if (!wpa_s->sme.sched_obss_scan) return 0; @@ -2415,36 +2419,22 @@ int sme_proc_obss_scan(struct wpa_supplicant *wpa_s, os_memset(chan_list, 0, sizeof(chan_list)); - pri_freq = wpa_s->assoc_freq; - - switch (wpa_s->sme.ht_sec_chan) { - case HT_SEC_CHAN_ABOVE: - sec_freq = pri_freq + 20; - break; - case HT_SEC_CHAN_BELOW: - sec_freq = pri_freq - 20; - break; - case HT_SEC_CHAN_UNKNOWN: - default: - wpa_msg(wpa_s, MSG_WARNING, - "Undefined secondary channel: drop OBSS scan results"); - return 1; - } - - for (j = 0; j < scan_res->num; j++) { - struct wpa_scan_res *bss = scan_res->res[j]; - enum hostapd_hw_mode mode; - int res; - + dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) { /* Skip other band bss */ + enum hostapd_hw_mode mode; mode = ieee80211_freq_to_chan(bss->freq, &channel); if (mode != HOSTAPD_MODE_IEEE80211G && mode != HOSTAPD_MODE_IEEE80211B) continue; - res = check_bss_coex_40mhz(bss, pri_freq, sec_freq); - if (res) { - if (res == 2) + ie = wpa_bss_get_ie(bss, WLAN_EID_HT_CAP); + ht_cap = (ie && (ie[1] == 26)) ? WPA_GET_LE16(ie + 2) : 0; + wpa_printf(MSG_DEBUG, "SME OBSS scan BSS " MACSTR + " freq=%u chan=%u ht_cap=0x%x", + MAC2STR(bss->bssid), bss->freq, channel, ht_cap); + + if (!ht_cap || (ht_cap & HT_CAP_INFO_40MHZ_INTOLERANT)) { + if (ht_cap & HT_CAP_INFO_40MHZ_INTOLERANT) num_intol++; /* Check whether the channel is already considered */ @@ -2583,6 +2573,12 @@ void sme_sched_obss_scan(struct wpa_supplicant *wpa_s, int enable) ssid == NULL || ssid->mode != WPAS_MODE_INFRA) return; +#ifdef CONFIG_HT_OVERRIDES + /* No need for OBSS scan if HT40 is explicitly disabled */ + if (ssid->disable_ht40) + return; +#endif /* CONFIG_HT_OVERRIDES */ + if (!wpa_s->hw.modes) return; diff --git a/contrib/wpa/wpa_supplicant/sme.h b/contrib/wpa/wpa_supplicant/sme.h index ecbc16dacd9d..c797d2e9e796 100644 --- a/contrib/wpa/wpa_supplicant/sme.h +++ b/contrib/wpa/wpa_supplicant/sme.h @@ -37,8 +37,7 @@ void sme_disassoc_while_authenticating(struct wpa_supplicant *wpa_s, void sme_clear_on_disassoc(struct wpa_supplicant *wpa_s); void sme_deinit(struct wpa_supplicant *wpa_s); -int sme_proc_obss_scan(struct wpa_supplicant *wpa_s, - struct wpa_scan_results *scan_res); +int sme_proc_obss_scan(struct wpa_supplicant *wpa_s); void sme_sched_obss_scan(struct wpa_supplicant *wpa_s, int enable); void sme_external_auth_trigger(struct wpa_supplicant *wpa_s, union wpa_event_data *data); @@ -113,8 +112,7 @@ static inline void sme_deinit(struct wpa_supplicant *wpa_s) { } -static inline int sme_proc_obss_scan(struct wpa_supplicant *wpa_s, - struct wpa_scan_results *scan_res) +static inline int sme_proc_obss_scan(struct wpa_supplicant *wpa_s) { return 0; } diff --git a/contrib/wpa/wpa_supplicant/wpa_cli.c b/contrib/wpa/wpa_supplicant/wpa_cli.c index 075d587be2f1..5bbc4535e364 100644 --- a/contrib/wpa/wpa_supplicant/wpa_cli.c +++ b/contrib/wpa/wpa_supplicant/wpa_cli.c @@ -1591,6 +1591,7 @@ static const char * const cred_fields[] = { "min_dl_bandwidth_roaming", "min_ul_bandwidth_roaming", "max_bss_load", "req_conn_capab", "ocsp", "sim_num", "realm", "username", "password", "ca_cert", "client_cert", "private_key", "private_key_passwd", "imsi", + "ca_cert_id", "cert_id", "key_id", "engine_id", "engine", "milenage", "domain_suffix_match", "domain", "phase1", "phase2", "roaming_consortium", "required_roaming_consortium", "excluded_ssid", "roaming_partner", "provisioning_sp" diff --git a/contrib/wpa/wpa_supplicant/wpa_supplicant.c b/contrib/wpa/wpa_supplicant/wpa_supplicant.c index 71bf95f951a1..53b44035f16e 100644 --- a/contrib/wpa/wpa_supplicant/wpa_supplicant.c +++ b/contrib/wpa/wpa_supplicant/wpa_supplicant.c @@ -4513,6 +4513,82 @@ void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s, /** + * wpas_remove_cred - Remove the specified credential and all the network + * entries created based on the removed credential + * @wpa_s: wpa_supplicant structure for a network interface + * @cred: The credential to remove + * Returns: 0 on success, -1 on failure + */ +int wpas_remove_cred(struct wpa_supplicant *wpa_s, struct wpa_cred *cred) +{ + struct wpa_ssid *ssid, *next; + int id; + + if (!cred) { + wpa_printf(MSG_DEBUG, "Could not find cred"); + return -1; + } + + id = cred->id; + if (wpa_config_remove_cred(wpa_s->conf, id) < 0) { + wpa_printf(MSG_DEBUG, "Could not find cred %d", id); + return -1; + } + + wpa_msg(wpa_s, MSG_INFO, CRED_REMOVED "%d", id); + + /* Remove any network entry created based on the removed credential */ + ssid = wpa_s->conf->ssid; + while (ssid) { + next = ssid->next; + + if (ssid->parent_cred == cred) { + wpa_printf(MSG_DEBUG, + "Remove network id %d since it used the removed credential", + ssid->id); + if (wpa_supplicant_remove_network(wpa_s, ssid->id) == + -1) { + wpa_printf(MSG_DEBUG, + "Could not find network id=%d", + ssid->id); + } + } + + ssid = next; + } + + return 0; +} + + +/** + * wpas_remove_cred - Remove all the Interworking credentials + * @wpa_s: wpa_supplicant structure for a network interface + * Returns: 0 on success, -1 on failure + */ +int wpas_remove_all_creds(struct wpa_supplicant *wpa_s) +{ + int res, ret = 0; + struct wpa_cred *cred, *prev; + + cred = wpa_s->conf->cred; + while (cred) { + prev = cred; + cred = cred->next; + res = wpas_remove_cred(wpa_s, prev); + if (res < 0) { + wpa_printf(MSG_DEBUG, + "Removal of all credentials failed - failed to remove credential id=%d", + prev->id); + ret = -1; + } + } + + return ret; +} + + +/** * wpas_set_pkcs11_engine_and_module_path - Set PKCS #11 engine and module path * @wpa_s: wpa_supplicant structure for a network interface * @pkcs11_engine_path: PKCS #11 engine path or NULL diff --git a/contrib/wpa/wpa_supplicant/wpa_supplicant.conf b/contrib/wpa/wpa_supplicant/wpa_supplicant.conf index fa257f3dec1b..6619d6ba7fb1 100644 --- a/contrib/wpa/wpa_supplicant/wpa_supplicant.conf +++ b/contrib/wpa/wpa_supplicant/wpa_supplicant.conf @@ -150,6 +150,9 @@ ap_scan=1 # This timeout value is used in mesh STA to clean up inactive stations. #mesh_max_inactivity=300 +# Enable 802.11s layer-2 routing and forwarding (dot11MeshForwarding) +#mesh_fwding=1 + # cert_in_cb - Whether to include a peer certificate dump in events # This controls whether peer certificates for authentication server and # its certificate chain are included in EAP peer certificate events. This is diff --git a/contrib/wpa/wpa_supplicant/wpa_supplicant_i.h b/contrib/wpa/wpa_supplicant/wpa_supplicant_i.h index cbc955159bbe..5fa765fda25c 100644 --- a/contrib/wpa/wpa_supplicant/wpa_supplicant_i.h +++ b/contrib/wpa/wpa_supplicant/wpa_supplicant_i.h @@ -38,6 +38,7 @@ struct wpa_bss; struct wpa_scan_results; struct hostapd_hw_modes; struct wpa_driver_associate_params; +struct wpa_cred; /* * Forward declarations of private structures used within the ctrl_iface @@ -1578,6 +1579,8 @@ void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid); void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid); +int wpas_remove_cred(struct wpa_supplicant *wpa_s, struct wpa_cred *cred); +int wpas_remove_all_creds(struct wpa_supplicant *wpa_s); int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s, const char *pkcs11_engine_path, const char *pkcs11_module_path); |
