static void update_channel_utilization(void *eloop_data, void *user_data) { struct hostapd_data *hapd = eloop_data; unsigned int sec, usec; int err; struct hostapd_iface *iface = hapd->iface; if (!(hapd->beacon_set_done && hapd->started)) return; err = hostapd_drv_get_survey(hapd, hapd->iface->freq); if (err) { wpa_printf(MSG_ERROR, "BSS Load: Failed to get survey data"); return; } ieee802_11_set_beacon(hapd); if (get_bss_load_update_timeout(hapd, &sec, &usec) < 0) return; if (hapd->conf->chan_util_avg_period) { iface->chan_util_samples_sum += iface->channel_utilization; iface->chan_util_num_sample_periods += hapd->conf->bss_load_update_period; if (iface->chan_util_num_sample_periods >= hapd->conf->chan_util_avg_period) { iface->chan_util_average = iface->chan_util_samples_sum / (iface->chan_util_num_sample_periods / hapd->conf->bss_load_update_period); iface->chan_util_samples_sum = 0; iface->chan_util_num_sample_periods = 0; } } eloop_register_timeout(sec, usec, update_channel_utilization, hapd, NULL); }
static void hostapd_cli_ping(void *eloop_ctx, void *timeout_ctx) { if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) { printf("Connection to hostapd lost - trying to reconnect\n"); hostapd_cli_close_connection(); } if (!ctrl_conn) { ctrl_conn = hostapd_cli_open_connection(ctrl_ifname); if (ctrl_conn) { printf("Connection to hostapd re-established\n"); if (wpa_ctrl_attach(ctrl_conn) == 0) { hostapd_cli_attached = 1; } else { printf("Warning: Failed to attach to " "hostapd.\n"); } } } if (ctrl_conn) hostapd_cli_recv_pending(ctrl_conn, 1, 0); eloop_register_timeout(ping_interval, 0, hostapd_cli_ping, NULL, NULL); }
int radius_client_init(struct wpa_supplicant *wpa_s) { wpa_s->radius = malloc(sizeof(struct radius_client_data)); if (wpa_s->radius == NULL) return -1; memset(wpa_s->radius, 0, sizeof(struct radius_client_data)); wpa_s->radius->auth_serv_sock = wpa_s->radius->acct_serv_sock = -1; if (wpa_s->auth_server && radius_client_init_auth(wpa_s)) return -1; if (wpa_s->acct_server && radius_client_init_acct(wpa_s)) return -1; if (wpa_s->radius_retry_primary_interval) eloop_register_timeout(wpa_s->radius_retry_primary_interval, 0, radius_retry_primary_timer, wpa_s, NULL); return 0; }
static void radius_retry_primary_timer(void *eloop_ctx, void *timeout_ctx) { struct radius_client_data *radius = eloop_ctx; struct hostapd_radius_servers *conf = radius->conf; struct hostapd_radius_server *oserv; if (radius->auth_sock >= 0 && conf->auth_servers && conf->auth_server != conf->auth_servers) { oserv = conf->auth_server; conf->auth_server = conf->auth_servers; if (radius_change_server(radius, conf->auth_server, oserv, radius->auth_serv_sock, radius->auth_serv_sock6, 1) < 0) { conf->auth_server = oserv; radius_change_server(radius, oserv, conf->auth_server, radius->auth_serv_sock, radius->auth_serv_sock6, 1); } } if (radius->acct_sock >= 0 && conf->acct_servers && conf->acct_server != conf->acct_servers) { oserv = conf->acct_server; conf->acct_server = conf->acct_servers; if (radius_change_server(radius, conf->acct_server, oserv, radius->acct_serv_sock, radius->acct_serv_sock6, 0) < 0) { conf->acct_server = oserv; radius_change_server(radius, oserv, conf->acct_server, radius->acct_serv_sock, radius->acct_serv_sock6, 0); } } if (conf->retry_primary_interval) eloop_register_timeout(conf->retry_primary_interval, 0, radius_retry_primary_timer, radius, NULL); }
/* httpread_create -- start a new reading session making use of eloop. * The new instance will use the socket descriptor for reading (until * it gets a file and not after) but will not close the socket, even * when the instance is destroyed (the application must do that). * Return NULL on error. * * Provided that httpread_create successfully returns a handle, * the callback fnc is called to handle httpread_event events. * The caller should do destroy on any errors or unknown events. * * Pass max_bytes == 0 to not read body at all (required for e.g. * reply to HEAD request). */ struct httpread * httpread_create( int sd, /* descriptor of TCP socket to read from */ void (*cb)(struct httpread *handle, void *cookie, enum httpread_event e), /* call on event */ void *cookie, /* pass to callback */ int max_bytes, /* maximum body size else abort it */ int timeout_seconds /* 0; or total duration timeout period */ ) { struct httpread *h = NULL; h = os_zalloc(sizeof(*h)); if (h == NULL) goto fail; h->sd = sd; h->cb = cb; h->cookie = cookie; h->max_bytes = max_bytes; h->timeout_seconds = timeout_seconds; if (timeout_seconds > 0 && eloop_register_timeout(timeout_seconds, 0, httpread_timeout_handler, NULL, h)) { /* No way to recover (from malloc failure) */ goto fail; } if (eloop_register_sock(sd, EVENT_TYPE_READ, httpread_read_handler, NULL, h)) { /* No way to recover (from malloc failure) */ goto fail; } return h; fail: /* Error */ httpread_destroy(h); return NULL; }
/* The rekeying function: generate a new broadcast WEP key, rotate * the key index, and direct Key Transmit State Machines of all of the * authenticators to send a new key to the authenticated stations. */ static void hostapd_rotate_wep(void *eloop_ctx, void *timeout_ctx) { struct sta_info *s; hostapd *hapd = eloop_ctx; if (hapd->default_wep_key) free(hapd->default_wep_key); if (hapd->default_wep_key_idx >= 3) hapd->default_wep_key_idx = hapd->conf->individual_wep_key_len > 0 ? 1 : 0; else hapd->default_wep_key_idx++; hostapd_set_broadcast_wep(hapd); for (s = hapd->sta_list; s != NULL; s = s->next) ieee802_1x_notify_key_available(s->eapol_sm, 1); if (HOSTAPD_DEBUG_COND(HOSTAPD_DEBUG_MINIMAL)) { hostapd_hexdump("New WEP key generated", hapd->default_wep_key, hapd->conf->default_wep_key_len); } /* TODO: Could setup key for RX here, but change default TX keyid only * after new broadcast key has been sent to all stations. */ if (hostapd_set_encryption(hapd->driver.data, "WEP", NULL, hapd->default_wep_key_idx, hapd->default_wep_key, hapd->conf->default_wep_key_len)) { printf("Could not set WEP encryption.\n"); } if (hapd->conf->wep_rekeying_period > 0) eloop_register_timeout(hapd->conf->wep_rekeying_period, 0, hostapd_rotate_wep, hapd, NULL); }
int wpas_wps_start_reg(struct wpa_supplicant *wpa_s, const u8 *bssid, const char *pin, struct wps_new_ap_settings *settings) { struct wpa_ssid *ssid; char val[200]; char *pos, *end; int res; if (!pin) return -1; wpas_clear_wps(wpa_s); ssid = wpas_wps_add_network(wpa_s, 1, bssid); if (ssid == NULL) return -1; pos = val; end = pos + sizeof(val); res = os_snprintf(pos, end - pos, "\"pin=%s", pin); if (res < 0 || res >= end - pos) return -1; pos += res; if (settings) { res = os_snprintf(pos, end - pos, " new_ssid=%s new_auth=%s " "new_encr=%s new_key=%s", settings->ssid_hex, settings->auth, settings->encr, settings->key_hex); if (res < 0 || res >= end - pos) return -1; pos += res; } res = os_snprintf(pos, end - pos, "\""); if (res < 0 || res >= end - pos) return -1; wpa_config_set(ssid, "phase1", val, 0); eloop_register_timeout(WPS_PBC_WALK_TIME, 0, wpas_wps_timeout, wpa_s, NULL); wpas_wps_reassoc(wpa_s, ssid); return 0; }
/* initiate new SAE authentication with sta */ int mesh_rsn_auth_sae_sta(struct wpa_supplicant *wpa_s, struct sta_info *sta) { struct hostapd_data *hapd = wpa_s->ifmsh->bss[0]; struct wpa_ssid *ssid = wpa_s->current_ssid; unsigned int rnd; int ret; if (!ssid) { wpa_msg(wpa_s, MSG_DEBUG, "AUTH: No current_ssid known to initiate new SAE"); return -1; } if (!sta->sae) { sta->sae = os_zalloc(sizeof(*sta->sae)); if (sta->sae == NULL) return -1; } if (mesh_rsn_build_sae_commit(wpa_s, ssid, sta)) return -1; wpa_msg(wpa_s, MSG_DEBUG, "AUTH: started authentication with SAE peer: " MACSTR, MAC2STR(sta->addr)); wpa_supplicant_set_state(wpa_s, WPA_AUTHENTICATING); ret = auth_sae_init_committed(hapd, sta); if (ret) return ret; eloop_cancel_timeout(mesh_auth_timer, wpa_s, sta); rnd = rand() % MESH_AUTH_TIMEOUT; eloop_register_timeout(MESH_AUTH_TIMEOUT + rnd, 0, mesh_auth_timer, wpa_s, sta); return 0; }
void sme_disassoc_while_authenticating(struct wpa_supplicant *wpa_s, const u8 *prev_pending_bssid) { /* * Android to provide a "Scanning always available" since in Android 4.3 * to have a backround scan for Google's location service and other apps * scan for networks even Wi-Fi is off. It is default enabled that when * user switch Wi-Fi radio on/off quickly and Wi-Fi wouldn't reconnet * back to remembered AP due to rejection from sme_authenticate() which * would check if connect_work existed or not. If it is disabled, * no such issue since wpa_supplicant would be killed and restart when * Wi-Fi enabled. * wpa_supplicant_mark_disassoc() would set to WPA_DISCONNECTED before * being here. */ if (wpa_s->connect_work && wpa_s->wpa_state == WPA_DISCONNECTED) { wpa_dbg(wpa_s, MSG_DEBUG, "SME: reset " "connect_work when disconnection"); wpas_connect_work_done(wpa_s); } /* * mac80211-workaround to force deauth on failed auth cmd, * requires us to remain in authenticating state to allow the * second authentication attempt to be continued properly. */ wpa_dbg(wpa_s, MSG_DEBUG, "SME: Allow pending authentication " "to proceed after disconnection event"); wpa_supplicant_set_state(wpa_s, WPA_AUTHENTICATING); os_memcpy(wpa_s->pending_bssid, prev_pending_bssid, ETH_ALEN); /* * Re-arm authentication timer in case auth fails for whatever reason. */ eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL); eloop_register_timeout(SME_AUTH_TIMEOUT, 0, sme_auth_timer, wpa_s, NULL); }
static void iapp_process_add_notify(struct iapp_data *iapp, struct sockaddr_in *from, struct iapp_hdr *hdr, int len) { struct iapp_add_notify *add = (struct iapp_add_notify *) (hdr + 1); struct sta_info *sta; if (len != sizeof(*add)) { printf("Invalid IAPP-ADD packet length %d (expected %lu)\n", len, (unsigned long) sizeof(*add)); return; } sta = ap_get_sta(iapp->hapd, add->mac_addr); /* IAPP-ADD.indication(MAC Address, Sequence Number) */ hostapd_logger(iapp->hapd, add->mac_addr, HOSTAPD_MODULE_IAPP, HOSTAPD_LEVEL_INFO, "Received IAPP ADD-notify (seq# %d) from %s:%d%s", be_to_host16(add->seq_num), inet_ntoa(from->sin_addr), ntohs(from->sin_port), sta ? "" : " (STA not found)"); if (!sta) return; /* TODO: could use seq_num to try to determine whether last association * to this AP is newer than the one advertised in IAPP-ADD. Although, * this is not really a reliable verification. */ hostapd_logger(iapp->hapd, add->mac_addr, HOSTAPD_MODULE_IAPP, HOSTAPD_LEVEL_DEBUG, "Removing STA due to IAPP ADD-notify"); sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_AUTHORIZED); eloop_cancel_timeout(ap_handle_timer, iapp->hapd, sta); eloop_register_timeout(0, 0, ap_handle_timer, iapp->hapd, sta); sta->timeout_next = STA_REMOVE; }
static void sme_sa_query_timer(void *eloop_ctx, void *timeout_ctx) { struct wpa_supplicant *wpa_s = eloop_ctx; unsigned int timeout, sec, usec; u8 *trans_id, *nbuf; if (wpa_s->sme.sa_query_count > 0 && sme_check_sa_query_timeout(wpa_s)) return; nbuf = os_realloc_array(wpa_s->sme.sa_query_trans_id, wpa_s->sme.sa_query_count + 1, WLAN_SA_QUERY_TR_ID_LEN); if (nbuf == NULL) return; if (wpa_s->sme.sa_query_count == 0) { /* Starting a new SA Query procedure */ os_get_reltime(&wpa_s->sme.sa_query_start); } trans_id = nbuf + wpa_s->sme.sa_query_count * WLAN_SA_QUERY_TR_ID_LEN; wpa_s->sme.sa_query_trans_id = nbuf; wpa_s->sme.sa_query_count++; if (os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN) < 0) { wpa_printf(MSG_DEBUG, "Could not generate SA Query ID"); return; } timeout = sa_query_retry_timeout; sec = ((timeout / 1000) * 1024) / 1000; usec = (timeout % 1000) * 1024; eloop_register_timeout(sec, usec, sme_sa_query_timer, wpa_s, NULL); wpa_dbg(wpa_s, MSG_DEBUG, "SME: Association SA Query attempt %d", wpa_s->sme.sa_query_count); sme_send_sa_query_req(wpa_s, trans_id); }
static void ap_sa_query_timer(void *eloop_ctx, void *timeout_ctx) { struct hostapd_data *hapd = eloop_ctx; struct sta_info *sta = timeout_ctx; unsigned int timeout, sec, usec; u8 *trans_id, *nbuf; if (sta->sa_query_count > 0 && ap_check_sa_query_timeout(hapd, sta)) return; nbuf = os_realloc(sta->sa_query_trans_id, (sta->sa_query_count + 1) * WLAN_SA_QUERY_TR_ID_LEN); if (nbuf == NULL) return; if (sta->sa_query_count == 0) { /* Starting a new SA Query procedure */ os_get_time(&sta->sa_query_start); } trans_id = nbuf + sta->sa_query_count * WLAN_SA_QUERY_TR_ID_LEN; sta->sa_query_trans_id = nbuf; sta->sa_query_count++; os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN); timeout = hapd->conf->assoc_sa_query_retry_timeout; sec = ((timeout / 1000) * 1024) / 1000; usec = (timeout % 1000) * 1024; eloop_register_timeout(sec, usec, ap_sa_query_timer, hapd, sta); hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_DEBUG, "association SA Query attempt %d", sta->sa_query_count); #ifdef NEED_AP_MLME ieee802_11_send_sa_query_req(hapd, sta->addr, trans_id); #endif /* NEED_AP_MLME */ }
int upnp_er_set_selected_registrar(struct wps_registrar *reg, struct subscription *s, const struct wpabuf *msg) { struct wps_parse_attr attr; wpa_hexdump_buf(MSG_MSGDUMP, "WPS: SetSelectedRegistrar attributes", msg); if (wps_parse_msg(msg, &attr) < 0) return -1; if (!wps_version_supported(attr.version)) { wpa_printf(MSG_DEBUG, "WPS: Unsupported SetSelectedRegistrar " "version 0x%x", attr.version ? *attr.version : 0); return -1; } s->reg = reg; eloop_cancel_timeout(upnp_er_set_selected_timeout, s, NULL); if (attr.selected_registrar == NULL || *attr.selected_registrar == 0) { wpa_printf(MSG_DEBUG, "WPS: SetSelectedRegistrar: Disable " "Selected Registrar"); s->selected_registrar = 0; } else { s->selected_registrar = 1; s->dev_password_id = attr.dev_password_id ? WPA_GET_BE16(attr.dev_password_id) : DEV_PW_DEFAULT; s->config_methods = attr.sel_reg_config_methods ? WPA_GET_BE16(attr.sel_reg_config_methods) : -1; eloop_register_timeout(WPS_PBC_WALK_TIME, 0, upnp_er_set_selected_timeout, s, NULL); } wps_registrar_selected_registrar_changed(reg); return 0; }
void wrapd_wpa_s_ctrl_iface_process(struct wrap_demon *aptr, char *msg) { if (os_strncmp(msg + WPA_S_MSG_ADDR_OFF, "CTRL-EVENT-DISCONNECTED ", 24) == 0) { aptr->mpsta_conn = 0; wrapd_disconn_all(aptr); } else if (os_strncmp(msg + WPA_S_MSG_ADDR_OFF, "CTRL-EVENT-CONNECTED ", 21) == 0) { aptr->mpsta_conn = 1; if ((NULL == wrapd_hostapd_conn) || (0 == aptr->do_timer) ){ wrapd_conn_all(aptr); } else { if (0 == aptr->in_timer) { eloop_register_timeout(1, 0, wrapd_conn_timer, aptr, NULL); aptr->in_timer = 1; } } } else { //wrapd_printf("Unknow msg(%s)", msg); } }
static void ieee80211_tkip_countermeasures_start(struct hostapd_data *hapd) { struct sta_info *sta; hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_INFO, "TKIP countermeasures initiated"); if (hapd->wpa_auth) hapd->wpa_auth->dot11RSNATKIPCounterMeasuresInvoked++; hapd->tkip_countermeasures = 1; hostapd_set_countermeasures(hapd, 1); wpa_gtk_rekey(hapd); eloop_cancel_timeout(ieee80211_tkip_countermeasures_stop, hapd, NULL); eloop_register_timeout(60, 0, ieee80211_tkip_countermeasures_stop, hapd, NULL); for (sta = hapd->sta_list; sta != NULL; sta = sta->next) { hostapd_sta_deauth(hapd, sta->addr, WLAN_REASON_MICHAEL_MIC_FAILURE); sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_AUTHORIZED); hostapd_sta_remove(hapd, sta->addr); } }
static void wpa_supplicant_wps_event_m2d(struct wpa_supplicant *wpa_s, struct wps_event_m2d *m2d) { wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_M2D "dev_password_id=%d config_error=%d", m2d->dev_password_id, m2d->config_error); wpas_notify_wps_event_m2d(wpa_s, m2d); #ifdef CONFIG_P2P if (wpa_s->parent && wpa_s->parent != wpa_s) { wpa_msg(wpa_s->parent, MSG_INFO, WPS_EVENT_M2D "dev_password_id=%d config_error=%d", m2d->dev_password_id, m2d->config_error); } if (m2d->config_error == WPS_CFG_MULTIPLE_PBC_DETECTED) { /* * Notify P2P from eloop timeout to avoid issues with the * interface getting removed while processing a message. */ eloop_register_timeout(0, 0, wpas_wps_pbc_overlap_cb, wpa_s, NULL); } #endif /* CONFIG_P2P */ }
int wpas_wps_start_pin(struct wpa_supplicant *wpa_s, const u8 *bssid, const char *pin) { struct wpa_ssid *ssid; char val[128]; unsigned int rpin = 0; wpas_clear_wps(wpa_s); ssid = wpas_wps_add_network(wpa_s, 0, bssid); if (ssid == NULL) return -1; if (pin) os_snprintf(val, sizeof(val), "\"pin=%s\"", pin); else { rpin = wps_generate_pin(); os_snprintf(val, sizeof(val), "\"pin=%08d\"", rpin); } wpa_config_set(ssid, "phase1", val, 0); eloop_register_timeout(WPS_PBC_WALK_TIME, 0, wpas_wps_timeout, wpa_s, NULL); wpas_wps_reassoc(wpa_s, ssid); return rpin; }
static void sme_obss_scan_timeout(void *eloop_ctx, void *timeout_ctx) { struct wpa_supplicant *wpa_s = eloop_ctx; struct wpa_driver_scan_params params; if (!wpa_s->current_bss) { wpa_printf(MSG_DEBUG, "SME OBSS: Ignore scan request"); return; } os_memset(¶ms, 0, sizeof(params)); wpa_setband_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211G, ¶ms); wpa_printf(MSG_DEBUG, "SME OBSS: Request an OBSS scan"); if (wpa_supplicant_trigger_scan(wpa_s, ¶ms)) wpa_printf(MSG_DEBUG, "SME OBSS: Failed to trigger scan"); else wpa_s->sme.sched_obss_scan = 1; os_free(params.freqs); eloop_register_timeout(wpa_s->sme.obss_scan_int, 0, sme_obss_scan_timeout, wpa_s, NULL); }
static void ap_ht40_scan_retry(void *eloop_data, void *user_data) { #define HT2040_COEX_SCAN_RETRY 15 struct hostapd_iface *iface = eloop_data; struct wpa_driver_scan_params params; int ret; os_memset(¶ms, 0, sizeof(params)); if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G) ieee80211n_scan_channels_2g4(iface, ¶ms); else ieee80211n_scan_channels_5g(iface, ¶ms); ret = hostapd_driver_scan(iface->bss[0], ¶ms); iface->num_ht40_scan_tries++; os_free(params.freqs); if (ret == -EBUSY && iface->num_ht40_scan_tries < HT2040_COEX_SCAN_RETRY) { wpa_printf(MSG_ERROR, "Failed to request a scan of neighboring BSSes ret=%d (%s) - try to scan again (attempt %d)", ret, strerror(-ret), iface->num_ht40_scan_tries); eloop_register_timeout(1, 0, ap_ht40_scan_retry, iface, NULL); return; } if (ret == 0) { iface->scan_cb = ieee80211n_check_scan; return; } wpa_printf(MSG_DEBUG, "Failed to request a scan in device, bringing up in HT20 mode"); iface->conf->secondary_channel = 0; iface->conf->ht_capab &= ~HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET; hostapd_setup_interface_complete(iface, 0); }
static int ieee80211n_check_40mhz(struct hostapd_iface *iface) { struct wpa_driver_scan_params params; int ret; if (!iface->conf->secondary_channel) { return 0; /* HT40 not used */ } hostapd_set_state(iface, HAPD_IFACE_HT_SCAN); wpa_printf(MSG_DEBUG, "Scan for neighboring BSSes prior to enabling " "40 MHz channel"); os_memset(¶ms, 0, sizeof(params)); if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G) { ieee80211n_scan_channels_2g4(iface, ¶ms); } else { ieee80211n_scan_channels_5g(iface, ¶ms); } ret = hostapd_driver_scan(iface->bss[0], ¶ms); os_free(params.freqs); if (ret == -EBUSY) { wpa_printf(MSG_ERROR, "Failed to request a scan of neighboring BSSes ret=%d (%s) - try to scan again", ret, strerror(-ret)); iface->num_ht40_scan_tries = 1; eloop_cancel_timeout(ap_ht40_scan_retry, iface, NULL); eloop_register_timeout(1, 0, ap_ht40_scan_retry, iface, NULL); return 1; } if (ret < 0) { wpa_printf(MSG_ERROR, "Failed to request a scan of neighboring BSSes ret=%d (%s)", ret, strerror(-ret)); return -1; } iface->scan_cb = ieee80211n_check_scan; return 1; }
struct sta_info * ap_sta_add(struct hostapd_data *hapd, const u8 *addr) { struct sta_info *sta; sta = ap_get_sta(hapd, addr); if (sta) return sta; wpa_printf(MSG_DEBUG, " New STA"); if (hapd->num_sta >= hapd->conf->max_num_sta) { /* FIX: might try to remove some old STAs first? */ wpa_printf(MSG_DEBUG, "no more room for new STAs (%d/%d)", hapd->num_sta, hapd->conf->max_num_sta); return NULL; } sta = os_zalloc(sizeof(struct sta_info)); if (sta == NULL) { wpa_printf(MSG_ERROR, "malloc failed"); return NULL; } sta->acct_interim_interval = hapd->conf->acct_interim_interval; /* initialize STA info data */ eloop_register_timeout(hapd->conf->ap_max_inactivity, 0, ap_handle_timer, hapd, sta); os_memcpy(sta->addr, addr, ETH_ALEN); sta->next = hapd->sta_list; hapd->sta_list = sta; hapd->num_sta++; ap_sta_hash_add(hapd, sta); sta->ssid = &hapd->conf->ssid; ap_sta_remove_in_other_bss(hapd, sta); return sta; }
static void wpa_supplicant_event_michael_mic_failure(struct wpa_supplicant *wpa_s, union wpa_event_data *data) { int pairwise; struct os_time t; wpa_msg(wpa_s, MSG_WARNING, "Michael MIC failure detected"); pairwise = (data && data->michael_mic_failure.unicast); wpa_sm_key_request(wpa_s->wpa, 1, pairwise); os_get_time(&t); if (wpa_s->last_michael_mic_error && t.sec - wpa_s->last_michael_mic_error <= 60) { /* initialize countermeasures */ wpa_s->countermeasures = 1; wpa_msg(wpa_s, MSG_WARNING, "TKIP countermeasures started"); /* * Need to wait for completion of request frame. We do not get * any callback for the message completion, so just wait a * short while and hope for the best. */ os_sleep(0, 10000); wpa_drv_set_countermeasures(wpa_s, 1); wpa_supplicant_deauthenticate(wpa_s, REASON_MICHAEL_MIC_FAILURE); eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL); eloop_register_timeout(60, 0, wpa_supplicant_stop_countermeasures, wpa_s, NULL); /* TODO: mark the AP rejected for 60 second. STA is * allowed to associate with another AP.. */ } wpa_s->last_michael_mic_error = t.sec; }
/** * eapol_port_timers_tick - Port Timers state machine * @eloop_ctx: struct eapol_state_machine * * @timeout_ctx: Not used * * This statemachine is implemented as a function that will be called * once a second as a registered event loop timeout. */ static void eapol_port_timers_tick(void *eloop_ctx, void *timeout_ctx) { struct eapol_state_machine *state = timeout_ctx; if (state->aWhile > 0) { state->aWhile--; if (state->aWhile == 0) { wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR " - aWhile --> 0", MAC2STR(state->addr)); } } if (state->quietWhile > 0) { state->quietWhile--; if (state->quietWhile == 0) { wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR " - quietWhile --> 0", MAC2STR(state->addr)); } } if (state->reAuthWhen > 0) { state->reAuthWhen--; if (state->reAuthWhen == 0) { wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR " - reAuthWhen --> 0", MAC2STR(state->addr)); } } if (state->eap_if->retransWhile > 0) { state->eap_if->retransWhile--; if (state->eap_if->retransWhile == 0) { wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR " - (EAP) retransWhile --> 0", MAC2STR(state->addr)); } } eapol_sm_step_run(state); eloop_register_timeout(1, 0, eapol_port_timers_tick, eloop_ctx, state); }
static void wps_er_sta_process(struct wps_er_sta *sta, struct wpabuf *msg, enum wsc_op_code op_code) { enum wps_process_res res; res = wps_process_msg(sta->wps, op_code, msg); if (res == WPS_CONTINUE) { struct wpabuf *next = wps_get_msg(sta->wps, &op_code); if (next) wps_er_sta_send_msg(sta, next); } else { wpa_printf(MSG_DEBUG, "WPS ER: Protocol run %s with the " "enrollee (res=%d)", res == WPS_DONE ? "succeeded" : "failed", res); wps_deinit(sta->wps); sta->wps = NULL; if (res == WPS_DONE) { /* Remove the STA entry after short timeout */ eloop_cancel_timeout(wps_er_sta_timeout, sta, NULL); eloop_register_timeout(10, 0, wps_er_sta_timeout, sta, NULL); } } }
static void wrapd_conn_timer(void *eloop_ctx, void *timeout_ctx) { struct wrap_demon *aptr = (struct wrap_demon *)eloop_ctx; struct proxy_sta *psta = NULL; int i, sec; static int cnt = 0; if (0 == aptr->mpsta_conn) { wrapd_printf("stop conn cause 0 == aptr->mpsta_conn"); goto conn_done; } for (i = 0; i < WRAP_MAX_PSTA_NUM; i ++) { psta = &aptr->psta[i]; if ((psta->added) && (0 == psta->connected)) { wrapd_psta_conn(aptr, i); if (cnt < 15) sec = (i/3) * 2 + 1; else sec = 6; wrapd_printf("<========delay %ds to connect PSTA %d========>", sec, i); eloop_register_timeout(sec, 0, wrapd_conn_timer, aptr, NULL); aptr->in_timer = 1; cnt ++; return; } } wrapd_printf("%d connected",cnt); conn_done: cnt = 0; aptr->in_timer = 0; eloop_cancel_timeout(wrapd_conn_timer, aptr, NULL); }
static int wpa_supplicant_process_smk_m45( struct wpa_sm *sm, const unsigned char *src_addr, const struct wpa_eapol_key *key, size_t extra_len, int ver) { struct wpa_peerkey *peerkey; struct wpa_eapol_ie_parse kde; u32 lifetime; struct os_time now; if (!sm->peerkey_enabled || sm->proto != WPA_PROTO_RSN) { wpa_printf(MSG_DEBUG, "RSN: SMK handshake not allowed for " "the current network"); return -1; } if (wpa_supplicant_parse_ies((const u8 *) (key + 1), extra_len, &kde) < 0) { wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK M4/M5"); return -1; } if (kde.mac_addr == NULL || kde.mac_addr_len < ETH_ALEN || kde.nonce == NULL || kde.nonce_len < WPA_NONCE_LEN || kde.smk == NULL || kde.smk_len < PMK_LEN + WPA_NONCE_LEN || kde.lifetime == NULL || kde.lifetime_len < 4) { wpa_printf(MSG_INFO, "RSN: No MAC Address, Nonce, SMK, or " "Lifetime KDE in SMK M4/M5"); return -1; } for (peerkey = sm->peerkey; peerkey; peerkey = peerkey->next) { if (os_memcmp(peerkey->addr, kde.mac_addr, ETH_ALEN) == 0 && os_memcmp(peerkey->initiator ? peerkey->inonce : peerkey->pnonce, key->key_nonce, WPA_NONCE_LEN) == 0) break; } if (peerkey == NULL) { wpa_printf(MSG_INFO, "RSN: No matching SMK handshake found " "for SMK M4/M5: peer " MACSTR, MAC2STR(kde.mac_addr)); return -1; } if (peerkey->initiator) { if (wpa_supplicant_process_smk_m5(sm, src_addr, key, ver, peerkey, &kde) < 0) return -1; } else { if (wpa_supplicant_process_smk_m4(peerkey, &kde) < 0) return -1; } os_memcpy(peerkey->smk, kde.smk, PMK_LEN); peerkey->smk_complete = 1; wpa_hexdump_key(MSG_DEBUG, "RSN: SMK", peerkey->smk, PMK_LEN); lifetime = WPA_GET_BE32(kde.lifetime); wpa_printf(MSG_DEBUG, "RSN: SMK lifetime %u seconds", lifetime); if (lifetime > 1000000000) lifetime = 1000000000; /* avoid overflowing expiration time */ peerkey->lifetime = lifetime; os_get_time(&now); peerkey->expiration = now.sec + lifetime; eloop_register_timeout(lifetime, 0, wpa_supplicant_smk_timeout, sm, peerkey); if (peerkey->initiator) { rsn_smkid(peerkey->smk, peerkey->pnonce, peerkey->addr, peerkey->inonce, sm->own_addr, peerkey->smkid, peerkey->use_sha256); wpa_supplicant_send_stk_1_of_4(sm, peerkey); } else { rsn_smkid(peerkey->smk, peerkey->pnonce, sm->own_addr, peerkey->inonce, peerkey->addr, peerkey->smkid, peerkey->use_sha256); } wpa_hexdump(MSG_DEBUG, "RSN: SMKID", peerkey->smkid, PMKID_LEN); return 0; }
static void gas_server_send_resp(struct gas_server *gas, struct gas_server_handler *handler, const u8 *da, int freq, u8 dialog_token, struct wpabuf *query_resp) { size_t max_len = (freq > 56160) ? 928 : 1400; size_t hdr_len = 24 + 2 + 5 + 3 + handler->adv_proto_id_len + 2; size_t resp_frag_len; struct wpabuf *resp; u16 comeback_delay; struct gas_server_response *response; if (!query_resp) return; response = os_zalloc(sizeof(*response)); if (!response) return; wpa_printf(MSG_DEBUG, "DPP: Allocated GAS response @%p", response); response->freq = freq; response->handler = handler; os_memcpy(response->dst, da, ETH_ALEN); response->dialog_token = dialog_token; if (hdr_len + wpabuf_len(query_resp) > max_len) { /* Need to use comeback to initiate fragmentation */ comeback_delay = 1; resp_frag_len = 0; } else { /* Full response fits into the initial response */ comeback_delay = 0; resp_frag_len = wpabuf_len(query_resp); } resp = gas_build_initial_resp(dialog_token, WLAN_STATUS_SUCCESS, comeback_delay, handler->adv_proto_id_len + resp_frag_len); if (!resp) { gas_server_free_response(response); return; } /* Advertisement Protocol element */ wpabuf_put_u8(resp, WLAN_EID_ADV_PROTO); wpabuf_put_u8(resp, 1 + handler->adv_proto_id_len); /* Length */ wpabuf_put_u8(resp, 0x7f); /* Advertisement Protocol ID */ wpabuf_put_data(resp, handler->adv_proto_id, handler->adv_proto_id_len); /* Query Response Length */ wpabuf_put_le16(resp, resp_frag_len); if (!comeback_delay) wpabuf_put_buf(resp, query_resp); if (comeback_delay) { wpa_printf(MSG_DEBUG, "GAS: Need to fragment query response"); } else { wpa_printf(MSG_DEBUG, "GAS: Full query response fits in the GAS Initial Response frame"); } response->offset = resp_frag_len; response->resp = query_resp; dl_list_add(&gas->responses, &response->list); gas->tx(gas->ctx, freq, da, resp, comeback_delay ? 2000 : 0); wpabuf_free(resp); eloop_register_timeout(GAS_QUERY_TIMEOUT, 0, gas_server_response_timeout, response, NULL); }
void sme_authenticate(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, struct wpa_ssid *ssid) { struct wpa_driver_auth_params params; struct wpa_ssid *old_ssid; #ifdef CONFIG_IEEE80211R const u8 *ie; #endif /* CONFIG_IEEE80211R */ #ifdef CONFIG_IEEE80211R const u8 *md = NULL; #endif /* CONFIG_IEEE80211R */ int i, bssid_changed; #if defined(ANDROID_P2P) && defined(WIFI_EAGLE) int freq = 0; #endif /* ANDROID_P2P && WIFI_EAGLE */ if (bss == NULL) { wpa_msg(wpa_s, MSG_ERROR, "SME: No scan result available for " "the network"); return; } wpa_s->current_bss = bss; os_memset(¶ms, 0, sizeof(params)); wpa_s->reassociate = 0; params.freq = bss->freq; params.bssid = bss->bssid; params.ssid = bss->ssid; params.ssid_len = bss->ssid_len; params.p2p = ssid->p2p_group; if (wpa_s->sme.ssid_len != params.ssid_len || os_memcmp(wpa_s->sme.ssid, params.ssid, params.ssid_len) != 0) wpa_s->sme.prev_bssid_set = 0; wpa_s->sme.freq = params.freq; os_memcpy(wpa_s->sme.ssid, params.ssid, params.ssid_len); wpa_s->sme.ssid_len = params.ssid_len; params.auth_alg = WPA_AUTH_ALG_OPEN; #ifdef IEEE8021X_EAPOL if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) { if (ssid->leap) { if (ssid->non_leap == 0) params.auth_alg = WPA_AUTH_ALG_LEAP; else params.auth_alg |= WPA_AUTH_ALG_LEAP; } } #endif /* IEEE8021X_EAPOL */ wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", params.auth_alg); if (ssid->auth_alg) { params.auth_alg = ssid->auth_alg; wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: " "0x%x", params.auth_alg); } for (i = 0; i < NUM_WEP_KEYS; i++) { if (ssid->wep_key_len[i]) params.wep_key[i] = ssid->wep_key[i]; params.wep_key_len[i] = ssid->wep_key_len[i]; } params.wep_tx_keyidx = ssid->wep_tx_keyidx; bssid_changed = !is_zero_ether_addr(wpa_s->bssid); os_memset(wpa_s->bssid, 0, ETH_ALEN); os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN); if (bssid_changed) wpas_notify_bssid_changed(wpa_s); if ((wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) || wpa_bss_get_ie(bss, WLAN_EID_RSN)) && wpa_key_mgmt_wpa(ssid->key_mgmt)) { int try_opportunistic; try_opportunistic = ssid->proactive_key_caching && (ssid->proto & WPA_PROTO_RSN); if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid, wpa_s->current_ssid, try_opportunistic) == 0) eapol_sm_notify_pmkid_attempt(wpa_s->eapol, 1); wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie); if (wpa_supplicant_set_suites(wpa_s, bss, ssid, wpa_s->sme.assoc_req_ie, &wpa_s->sme.assoc_req_ie_len)) { wpa_msg(wpa_s, MSG_WARNING, "SME: Failed to set WPA " "key management and encryption suites"); return; } } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) { /* * Both WPA and non-WPA IEEE 802.1X enabled in configuration - * use non-WPA since the scan results did not indicate that the * AP is using WPA or WPA2. */ wpa_supplicant_set_non_wpa_policy(wpa_s, ssid); wpa_s->sme.assoc_req_ie_len = 0; } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) { wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie); if (wpa_supplicant_set_suites(wpa_s, NULL, ssid, wpa_s->sme.assoc_req_ie, &wpa_s->sme.assoc_req_ie_len)) { wpa_msg(wpa_s, MSG_WARNING, "SME: Failed to set WPA " "key management and encryption suites (no " "scan results)"); return; } #ifdef CONFIG_WPS } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) { struct wpabuf *wps_ie; wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid)); if (wps_ie && wpabuf_len(wps_ie) <= sizeof(wpa_s->sme.assoc_req_ie)) { wpa_s->sme.assoc_req_ie_len = wpabuf_len(wps_ie); os_memcpy(wpa_s->sme.assoc_req_ie, wpabuf_head(wps_ie), wpa_s->sme.assoc_req_ie_len); } else wpa_s->sme.assoc_req_ie_len = 0; wpabuf_free(wps_ie); wpa_supplicant_set_non_wpa_policy(wpa_s, ssid); #endif /* CONFIG_WPS */ } else { wpa_supplicant_set_non_wpa_policy(wpa_s, ssid); wpa_s->sme.assoc_req_ie_len = 0; } #ifdef CONFIG_IEEE80211R ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN); if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN) md = ie + 2; wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0); if (md) { /* Prepare for the next transition */ wpa_ft_prepare_auth_request(wpa_s->wpa, ie); } if (md && wpa_key_mgmt_ft(ssid->key_mgmt)) { if (wpa_s->sme.assoc_req_ie_len + 5 < sizeof(wpa_s->sme.assoc_req_ie)) { struct rsn_mdie *mdie; u8 *pos = wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len; *pos++ = WLAN_EID_MOBILITY_DOMAIN; *pos++ = sizeof(*mdie); mdie = (struct rsn_mdie *) pos; os_memcpy(mdie->mobility_domain, md, MOBILITY_DOMAIN_ID_LEN); mdie->ft_capab = md[MOBILITY_DOMAIN_ID_LEN]; wpa_s->sme.assoc_req_ie_len += 5; } if (wpa_s->sme.ft_used && os_memcmp(md, wpa_s->sme.mobility_domain, 2) == 0 && wpa_sm_has_ptk(wpa_s->wpa)) { wpa_dbg(wpa_s, MSG_DEBUG, "SME: Trying to use FT " "over-the-air"); params.auth_alg = WPA_AUTH_ALG_FT; params.ie = wpa_s->sme.ft_ies; params.ie_len = wpa_s->sme.ft_ies_len; } } #endif /* CONFIG_IEEE80211R */ #ifdef CONFIG_IEEE80211W wpa_s->sme.mfp = ssid->ieee80211w; if (ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION) { const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN); struct wpa_ie_data _ie; if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &_ie) == 0 && _ie.capabilities & (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) { wpa_dbg(wpa_s, MSG_DEBUG, "SME: Selected AP supports " "MFP: require MFP"); wpa_s->sme.mfp = MGMT_FRAME_PROTECTION_REQUIRED; } } #endif /* CONFIG_IEEE80211W */ #ifdef CONFIG_P2P if (wpa_s->global->p2p) { u8 *pos; size_t len; int res; pos = wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len; len = sizeof(wpa_s->sme.assoc_req_ie) - wpa_s->sme.assoc_req_ie_len; res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len, ssid->p2p_group); if (res >= 0) wpa_s->sme.assoc_req_ie_len += res; } #endif /* CONFIG_P2P */ #ifdef CONFIG_HS20 if (wpa_s->conf->hs20) { struct wpabuf *hs20; hs20 = wpabuf_alloc(20); if (hs20) { wpas_hs20_add_indication(hs20); os_memcpy(wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len, wpabuf_head(hs20), wpabuf_len(hs20)); wpa_s->sme.assoc_req_ie_len += wpabuf_len(hs20); wpabuf_free(hs20); } } #endif /* CONFIG_HS20 */ #ifdef CONFIG_INTERWORKING if (wpa_s->conf->interworking) { u8 *pos = wpa_s->sme.assoc_req_ie; if (wpa_s->sme.assoc_req_ie_len > 0 && pos[0] == WLAN_EID_RSN) pos += 2 + pos[1]; os_memmove(pos + 6, pos, wpa_s->sme.assoc_req_ie_len - (pos - wpa_s->sme.assoc_req_ie)); wpa_s->sme.assoc_req_ie_len += 6; *pos++ = WLAN_EID_EXT_CAPAB; *pos++ = 4; *pos++ = 0x00; *pos++ = 0x00; *pos++ = 0x00; *pos++ = 0x80; /* Bit 31 - Interworking */ } #endif /* CONFIG_INTERWORKING */ wpa_supplicant_cancel_sched_scan(wpa_s); wpa_supplicant_cancel_scan(wpa_s); wpa_msg(wpa_s, MSG_INFO, "SME: Trying to authenticate with " MACSTR " (SSID='%s' freq=%d MHz)", MAC2STR(params.bssid), wpa_ssid_txt(params.ssid, params.ssid_len), params.freq); wpa_clear_keys(wpa_s, bss->bssid); wpa_supplicant_set_state(wpa_s, WPA_AUTHENTICATING); old_ssid = wpa_s->current_ssid; wpa_s->current_ssid = ssid; wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid); wpa_supplicant_initiate_eapol(wpa_s); if (old_ssid != wpa_s->current_ssid) wpas_notify_network_changed(wpa_s); wpa_s->sme.auth_alg = params.auth_alg; #if defined(ANDROID_P2P) && defined(WIFI_EAGLE) /* If multichannel concurrency is not supported, check for any frequency * conflict and take appropriate action. */ wpa_printf(MSG_DEBUG, "%s EAGLE: Priority choose", __func__); if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MULTI_CHANNEL_CONCURRENT) && ((freq = wpa_drv_shared_freq(wpa_s)) > 0) && (freq != params.freq)) { wpa_printf(MSG_DEBUG, "Shared interface with conflicting frequency found (%d != %d)" , freq, params.freq); if (wpas_p2p_handle_frequency_conflicts(wpa_s, params.freq) < 0) { /* Handling conflicts failed. Disable the current connect req and * notify the userspace to take appropriate action */ wpa_printf(MSG_DEBUG, "proiritize is not set. Notifying user space to handle the case"); wpa_supplicant_disable_network(wpa_s, ssid); wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_FREQ_CONFLICT " id=%d", ssid->id); os_memset(wpa_s->pending_bssid, 0, ETH_ALEN); return; } } #endif /* ANDROID_P2P && WIFI_EAGLE */ if (wpa_drv_authenticate(wpa_s, ¶ms) < 0) { wpa_msg(wpa_s, MSG_INFO, "SME: Authentication request to the " "driver failed"); wpas_connection_failed(wpa_s, bss->bssid); wpa_supplicant_mark_disassoc(wpa_s); return; } eloop_register_timeout(SME_AUTH_TIMEOUT, 0, sme_auth_timer, wpa_s, NULL); /* * Association will be started based on the authentication event from * the driver. */ }
static int hapd_wps_cred_cb(struct hostapd_data *hapd, void *ctx) { const struct wps_credential *cred = ctx; FILE *oconf, *nconf; size_t len, i; char *tmp_fname; char buf[1024]; int multi_bss; int wpa; if (hapd->wps == NULL) return 0; wpa_hexdump_key(MSG_DEBUG, "WPS: Received Credential attribute", cred->cred_attr, cred->cred_attr_len); wpa_printf(MSG_DEBUG, "WPS: Received new AP Settings"); wpa_hexdump_ascii(MSG_DEBUG, "WPS: SSID", cred->ssid, cred->ssid_len); wpa_printf(MSG_DEBUG, "WPS: Authentication Type 0x%x", cred->auth_type); wpa_printf(MSG_DEBUG, "WPS: Encryption Type 0x%x", cred->encr_type); wpa_printf(MSG_DEBUG, "WPS: Network Key Index %d", cred->key_idx); wpa_hexdump_key(MSG_DEBUG, "WPS: Network Key", cred->key, cred->key_len); wpa_printf(MSG_DEBUG, "WPS: MAC Address " MACSTR, MAC2STR(cred->mac_addr)); if ((hapd->conf->wps_cred_processing == 1 || hapd->conf->wps_cred_processing == 2) && cred->cred_attr) { hapd_new_ap_event(hapd, cred->cred_attr, cred->cred_attr_len); } else if (hapd->conf->wps_cred_processing == 1 || hapd->conf->wps_cred_processing == 2) { struct wpabuf *attr; attr = wpabuf_alloc(200); if (attr && wps_build_credential_wrap(attr, cred) == 0) hapd_new_ap_event(hapd, wpabuf_head_u8(attr), wpabuf_len(attr)); wpabuf_free(attr); } else wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_NEW_AP_SETTINGS); if (hapd->conf->wps_cred_processing == 1) return 0; os_memcpy(hapd->wps->ssid, cred->ssid, cred->ssid_len); hapd->wps->ssid_len = cred->ssid_len; hapd->wps->encr_types = cred->encr_type; hapd->wps->auth_types = cred->auth_type; if (cred->key_len == 0) { os_free(hapd->wps->network_key); hapd->wps->network_key = NULL; hapd->wps->network_key_len = 0; } else { if (hapd->wps->network_key == NULL || hapd->wps->network_key_len < cred->key_len) { hapd->wps->network_key_len = 0; os_free(hapd->wps->network_key); hapd->wps->network_key = os_malloc(cred->key_len); if (hapd->wps->network_key == NULL) return -1; } hapd->wps->network_key_len = cred->key_len; os_memcpy(hapd->wps->network_key, cred->key, cred->key_len); } hapd->wps->wps_state = WPS_STATE_CONFIGURED; if (hapd->iface->config_fname == NULL) return 0; len = os_strlen(hapd->iface->config_fname) + 5; tmp_fname = os_malloc(len); if (tmp_fname == NULL) return -1; os_snprintf(tmp_fname, len, "%s-new", hapd->iface->config_fname); oconf = fopen(hapd->iface->config_fname, "r"); if (oconf == NULL) { wpa_printf(MSG_WARNING, "WPS: Could not open current " "configuration file"); os_free(tmp_fname); return -1; } nconf = fopen(tmp_fname, "w"); if (nconf == NULL) { wpa_printf(MSG_WARNING, "WPS: Could not write updated " "configuration file"); os_free(tmp_fname); fclose(oconf); return -1; } fprintf(nconf, "# WPS configuration - START\n"); fprintf(nconf, "wps_state=2\n"); if (is_hex(cred->ssid, cred->ssid_len)) { fprintf(nconf, "ssid2="); for (i = 0; i < cred->ssid_len; i++) fprintf(nconf, "%02x", cred->ssid[i]); fprintf(nconf, "\n"); } else { fprintf(nconf, "ssid="); for (i = 0; i < cred->ssid_len; i++) fputc(cred->ssid[i], nconf); fprintf(nconf, "\n"); } if ((cred->auth_type & (WPS_AUTH_WPA2 | WPS_AUTH_WPA2PSK)) && (cred->auth_type & (WPS_AUTH_WPA | WPS_AUTH_WPAPSK))) wpa = 3; else if (cred->auth_type & (WPS_AUTH_WPA2 | WPS_AUTH_WPA2PSK)) wpa = 2; else if (cred->auth_type & (WPS_AUTH_WPA | WPS_AUTH_WPAPSK)) wpa = 1; else wpa = 0; if (wpa) { char *prefix; fprintf(nconf, "wpa=%d\n", wpa); fprintf(nconf, "wpa_key_mgmt="); prefix = ""; if (cred->auth_type & (WPS_AUTH_WPA2 | WPS_AUTH_WPA)) { fprintf(nconf, "WPA-EAP"); prefix = " "; } if (cred->auth_type & (WPS_AUTH_WPA2PSK | WPS_AUTH_WPAPSK)) fprintf(nconf, "%sWPA-PSK", prefix); fprintf(nconf, "\n"); fprintf(nconf, "wpa_pairwise="); prefix = ""; if (cred->encr_type & WPS_ENCR_AES) { fprintf(nconf, "CCMP"); prefix = " "; } if (cred->encr_type & WPS_ENCR_TKIP) { fprintf(nconf, "%sTKIP", prefix); } fprintf(nconf, "\n"); if (cred->key_len >= 8 && cred->key_len < 64) { fprintf(nconf, "wpa_passphrase="); for (i = 0; i < cred->key_len; i++) fputc(cred->key[i], nconf); fprintf(nconf, "\n"); } else if (cred->key_len == 64) { fprintf(nconf, "wpa_psk="); for (i = 0; i < cred->key_len; i++) fputc(cred->key[i], nconf); fprintf(nconf, "\n"); } else { wpa_printf(MSG_WARNING, "WPS: Invalid key length %lu " "for WPA/WPA2", (unsigned long) cred->key_len); } fprintf(nconf, "auth_algs=1\n"); } else { if ((cred->auth_type & WPS_AUTH_OPEN) && (cred->auth_type & WPS_AUTH_SHARED)) fprintf(nconf, "auth_algs=3\n"); else if (cred->auth_type & WPS_AUTH_SHARED) fprintf(nconf, "auth_algs=2\n"); else fprintf(nconf, "auth_algs=1\n"); if (cred->encr_type & WPS_ENCR_WEP && cred->key_idx <= 4) { int key_idx = cred->key_idx; if (key_idx) key_idx--; fprintf(nconf, "wep_default_key=%d\n", key_idx); fprintf(nconf, "wep_key%d=", key_idx); if (cred->key_len == 10 || cred->key_len == 26) { /* WEP key as a hex string */ for (i = 0; i < cred->key_len; i++) fputc(cred->key[i], nconf); } else { /* Raw WEP key; convert to hex */ for (i = 0; i < cred->key_len; i++) fprintf(nconf, "%02x", cred->key[i]); } fprintf(nconf, "\n"); } } fprintf(nconf, "# WPS configuration - END\n"); multi_bss = 0; while (fgets(buf, sizeof(buf), oconf)) { if (os_strncmp(buf, "bss=", 4) == 0) multi_bss = 1; if (!multi_bss && (str_starts(buf, "ssid=") || str_starts(buf, "ssid2=") || str_starts(buf, "auth_algs=") || str_starts(buf, "wep_default_key=") || str_starts(buf, "wep_key") || str_starts(buf, "wps_state=") || str_starts(buf, "wpa=") || str_starts(buf, "wpa_psk=") || str_starts(buf, "wpa_pairwise=") || str_starts(buf, "rsn_pairwise=") || str_starts(buf, "wpa_key_mgmt=") || str_starts(buf, "wpa_passphrase="))) { fprintf(nconf, "#WPS# %s", buf); } else fprintf(nconf, "%s", buf); } fclose(nconf); fclose(oconf); if (rename(tmp_fname, hapd->iface->config_fname) < 0) { wpa_printf(MSG_WARNING, "WPS: Failed to rename the updated " "configuration file: %s", strerror(errno)); os_free(tmp_fname); return -1; } os_free(tmp_fname); /* Schedule configuration reload after short period of time to allow * EAP-WSC to be finished. */ eloop_register_timeout(0, 100000, wps_reload_config, hapd->iface, NULL); wpa_printf(MSG_DEBUG, "WPS: AP configuration updated"); return 0; }
void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode, const u8 *bssid, u16 auth_type) { struct wpa_driver_associate_params params; struct ieee802_11_elems elems; #ifdef CONFIG_HT_OVERRIDES struct ieee80211_ht_capabilities htcaps; struct ieee80211_ht_capabilities htcaps_mask; #endif /* CONFIG_HT_OVERRIDES */ os_memset(¶ms, 0, sizeof(params)); params.bssid = bssid; params.ssid = wpa_s->sme.ssid; params.ssid_len = wpa_s->sme.ssid_len; params.freq = wpa_s->sme.freq; params.bg_scan_period = wpa_s->current_ssid ? wpa_s->current_ssid->bg_scan_period : -1; params.wpa_ie = wpa_s->sme.assoc_req_ie_len ? wpa_s->sme.assoc_req_ie : NULL; params.wpa_ie_len = wpa_s->sme.assoc_req_ie_len; params.pairwise_suite = cipher_suite2driver(wpa_s->pairwise_cipher); params.group_suite = cipher_suite2driver(wpa_s->group_cipher); #ifdef CONFIG_HT_OVERRIDES os_memset(&htcaps, 0, sizeof(htcaps)); os_memset(&htcaps_mask, 0, sizeof(htcaps_mask)); params.htcaps = (u8 *) &htcaps; params.htcaps_mask = (u8 *) &htcaps_mask; wpa_supplicant_apply_ht_overrides(wpa_s, wpa_s->current_ssid, ¶ms); #endif /* CONFIG_HT_OVERRIDES */ #ifdef CONFIG_IEEE80211R if (auth_type == WLAN_AUTH_FT && wpa_s->sme.ft_ies) { params.wpa_ie = wpa_s->sme.ft_ies; params.wpa_ie_len = wpa_s->sme.ft_ies_len; } #endif /* CONFIG_IEEE80211R */ params.mode = mode; params.mgmt_frame_protection = wpa_s->sme.mfp; if (wpa_s->sme.prev_bssid_set) params.prev_bssid = wpa_s->sme.prev_bssid; wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR " (SSID='%s' freq=%d MHz)", MAC2STR(params.bssid), params.ssid ? wpa_ssid_txt(params.ssid, params.ssid_len) : "", params.freq); wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING); if (params.wpa_ie == NULL || ieee802_11_parse_elems(params.wpa_ie, params.wpa_ie_len, &elems, 0) < 0) { wpa_dbg(wpa_s, MSG_DEBUG, "SME: Could not parse own IEs?!"); os_memset(&elems, 0, sizeof(elems)); } if (elems.rsn_ie) { params.wpa_proto = WPA_PROTO_RSN; wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, elems.rsn_ie - 2, elems.rsn_ie_len + 2); } else if (elems.wpa_ie) { params.wpa_proto = WPA_PROTO_WPA; wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, elems.wpa_ie - 2, elems.wpa_ie_len + 2); } else wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0); if (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group) params.p2p = 1; if (wpa_s->parent->set_sta_uapsd) params.uapsd = wpa_s->parent->sta_uapsd; else params.uapsd = -1; if (wpa_drv_associate(wpa_s, ¶ms) < 0) { wpa_msg(wpa_s, MSG_INFO, "SME: Association request to the " "driver failed"); wpas_connection_failed(wpa_s, wpa_s->pending_bssid); wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); os_memset(wpa_s->pending_bssid, 0, ETH_ALEN); return; } eloop_register_timeout(SME_ASSOC_TIMEOUT, 0, sme_assoc_timer, wpa_s, NULL); }