int hostapd_init_wps(struct hostapd_data *hapd, struct hostapd_bss_config *conf) { struct wps_context *wps; struct wps_registrar_config cfg; if (conf->wps_state == 0) { hostapd_wps_clear_ies(hapd); return 0; } wps = os_zalloc(sizeof(*wps)); if (wps == NULL) return -1; wps->cred_cb = hostapd_wps_cred_cb; wps->event_cb = hostapd_wps_event_cb; wps->cb_ctx = hapd; os_memset(&cfg, 0, sizeof(cfg)); wps->wps_state = hapd->conf->wps_state; wps->ap_setup_locked = hapd->conf->ap_setup_locked; if (is_nil_uuid(hapd->conf->uuid)) { const u8 *uuid; uuid = get_own_uuid(hapd->iface); if (uuid) { os_memcpy(wps->uuid, uuid, UUID_LEN); #if 0 //peter-jc To follow MR0 wpa_hexdump modification wpa_hexdump(MSG_DEBUG, "WPS: Clone UUID from another " "interface", wps->uuid, UUID_LEN); #endif } else { uuid_gen_mac_addr(hapd->own_addr, wps->uuid); #if 0 //peter-jc To follow MR0 wpa_hexdump modification wpa_hexdump(MSG_DEBUG, "WPS: UUID based on MAC " "address", wps->uuid, UUID_LEN); #endif } } else { os_memcpy(wps->uuid, hapd->conf->uuid, UUID_LEN); #if 0 //peter-jc To follow MR0 wpa_hexdump modification wpa_hexdump(MSG_DEBUG, "WPS: Use configured UUID", wps->uuid, UUID_LEN); #endif } wps->ssid_len = hapd->conf->ssid.ssid_len; os_memcpy(wps->ssid, hapd->conf->ssid.ssid, wps->ssid_len); wps->ap = 1; os_memcpy(wps->dev.mac_addr, hapd->own_addr, ETH_ALEN); wps->dev.device_name = hapd->conf->device_name ? os_strdup(hapd->conf->device_name) : NULL; wps->dev.manufacturer = hapd->conf->manufacturer ? os_strdup(hapd->conf->manufacturer) : NULL; wps->dev.model_name = hapd->conf->model_name ? os_strdup(hapd->conf->model_name) : NULL; wps->dev.model_number = hapd->conf->model_number ? os_strdup(hapd->conf->model_number) : NULL; wps->dev.serial_number = hapd->conf->serial_number ? os_strdup(hapd->conf->serial_number) : NULL; wps->config_methods = wps_config_methods_str2bin(hapd->conf->config_methods); #ifdef CONFIG_WPS2 if ((wps->config_methods & (WPS_CONFIG_DISPLAY | WPS_CONFIG_VIRT_DISPLAY | WPS_CONFIG_PHY_DISPLAY)) == WPS_CONFIG_DISPLAY) { wpa_printf(MSG_INFO, "WPS: Converting display to " "virtual_display for WPS 2.0 compliance"); wps->config_methods |= WPS_CONFIG_VIRT_DISPLAY; } if ((wps->config_methods & (WPS_CONFIG_PUSHBUTTON | WPS_CONFIG_VIRT_PUSHBUTTON | WPS_CONFIG_PHY_PUSHBUTTON)) == WPS_CONFIG_PUSHBUTTON) { wpa_printf(MSG_INFO, "WPS: Converting push_button to " "virtual_push_button for WPS 2.0 compliance"); wps->config_methods |= WPS_CONFIG_VIRT_PUSHBUTTON; } #endif /* CONFIG_WPS2 */ os_memcpy(wps->dev.pri_dev_type, hapd->conf->device_type, WPS_DEV_TYPE_LEN); if (hostapd_wps_set_vendor_ext(hapd, wps) < 0) { os_free(wps); return -1; } wps->dev.os_version = WPA_GET_BE32(hapd->conf->os_version); if (conf->wps_rf_bands) { wps->dev.rf_bands = conf->wps_rf_bands; } else { wps->dev.rf_bands = hapd->iconf->hw_mode == HOSTAPD_MODE_IEEE80211A ? WPS_RF_50GHZ : WPS_RF_24GHZ; /* FIX: dualband AP */ } if (conf->wpa & WPA_PROTO_RSN) { if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) wps->auth_types |= WPS_AUTH_WPA2PSK; if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) wps->auth_types |= WPS_AUTH_WPA2; if (conf->rsn_pairwise & WPA_CIPHER_CCMP) wps->encr_types |= WPS_ENCR_AES; if (conf->rsn_pairwise & WPA_CIPHER_TKIP) wps->encr_types |= WPS_ENCR_TKIP; } if (conf->wpa & WPA_PROTO_WPA) { if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) wps->auth_types |= WPS_AUTH_WPAPSK; if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) wps->auth_types |= WPS_AUTH_WPA; if (conf->wpa_pairwise & WPA_CIPHER_CCMP) wps->encr_types |= WPS_ENCR_AES; if (conf->wpa_pairwise & WPA_CIPHER_TKIP) wps->encr_types |= WPS_ENCR_TKIP; } if (conf->ssid.security_policy == SECURITY_PLAINTEXT) { wps->encr_types |= WPS_ENCR_NONE; wps->auth_types |= WPS_AUTH_OPEN; } else if (conf->ssid.security_policy == SECURITY_STATIC_WEP) { wps->encr_types |= WPS_ENCR_WEP; if (conf->auth_algs & WPA_AUTH_ALG_OPEN) wps->auth_types |= WPS_AUTH_OPEN; if (conf->auth_algs & WPA_AUTH_ALG_SHARED) wps->auth_types |= WPS_AUTH_SHARED; } else if (conf->ssid.security_policy == SECURITY_IEEE_802_1X) { wps->auth_types |= WPS_AUTH_OPEN; if (conf->default_wep_key_len) wps->encr_types |= WPS_ENCR_WEP; else wps->encr_types |= WPS_ENCR_NONE; } if (conf->ssid.wpa_psk_file) { /* Use per-device PSKs */ } else if (conf->ssid.wpa_passphrase) { wps->network_key = (u8 *) os_strdup(conf->ssid.wpa_passphrase); wps->network_key_len = os_strlen(conf->ssid.wpa_passphrase); } else if (conf->ssid.wpa_psk) { wps->network_key = os_malloc(2 * PMK_LEN + 1); if (wps->network_key == NULL) { os_free(wps); return -1; } wpa_snprintf_hex((char *) wps->network_key, 2 * PMK_LEN + 1, conf->ssid.wpa_psk->psk, PMK_LEN); wps->network_key_len = 2 * PMK_LEN; } else if (conf->ssid.wep.keys_set && conf->ssid.wep.key[0]) { wps->network_key = os_malloc(conf->ssid.wep.len[0]); if (wps->network_key == NULL) { os_free(wps); return -1; } os_memcpy(wps->network_key, conf->ssid.wep.key[0], conf->ssid.wep.len[0]); wps->network_key_len = conf->ssid.wep.len[0]; } if (conf->ssid.wpa_psk) { os_memcpy(wps->psk, conf->ssid.wpa_psk->psk, PMK_LEN); wps->psk_set = 1; } if (conf->wps_state == WPS_STATE_NOT_CONFIGURED) { /* Override parameters to enable security by default */ wps->auth_types = WPS_AUTH_WPA2PSK | WPS_AUTH_WPAPSK; wps->encr_types = WPS_ENCR_AES | WPS_ENCR_TKIP; } wps->ap_settings = conf->ap_settings; wps->ap_settings_len = conf->ap_settings_len; cfg.new_psk_cb = hostapd_wps_new_psk_cb; cfg.set_ie_cb = hostapd_wps_set_ie_cb; cfg.pin_needed_cb = hostapd_wps_pin_needed_cb; cfg.reg_success_cb = hostapd_wps_reg_success_cb; cfg.enrollee_seen_cb = hostapd_wps_enrollee_seen_cb; cfg.cb_ctx = hapd; cfg.skip_cred_build = conf->skip_cred_build; cfg.extra_cred = conf->extra_cred; cfg.extra_cred_len = conf->extra_cred_len; cfg.disable_auto_conf = (hapd->conf->wps_cred_processing == 1) && conf->skip_cred_build; if (conf->ssid.security_policy == SECURITY_STATIC_WEP) cfg.static_wep_only = 1; cfg.dualband = interface_count(hapd->iface) > 1; if (cfg.dualband) wpa_printf(MSG_DEBUG, "WPS: Dualband AP"); wps->registrar = wps_registrar_init(wps, &cfg); if (wps->registrar == NULL) { wpa_printf(MSG_ERROR, "Failed to initialize WPS Registrar"); os_free(wps->network_key); os_free(wps); return -1; } #ifdef CONFIG_WPS_UPNP wps->friendly_name = hapd->conf->friendly_name; wps->manufacturer_url = hapd->conf->manufacturer_url; wps->model_description = hapd->conf->model_description; wps->model_url = hapd->conf->model_url; wps->upc = hapd->conf->upc; #endif /* CONFIG_WPS_UPNP */ hostapd_register_probereq_cb(hapd, hostapd_wps_probe_req_rx, hapd); hapd->wps = wps; return 0; }
struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path) { struct wpa_ctrl *ctrl; static int counter = 0; int ret; size_t res; int tries = 0; ctrl = os_malloc(sizeof(*ctrl)); if (ctrl == NULL) return NULL; os_memset(ctrl, 0, sizeof(*ctrl)); ctrl->s = socket(PF_UNIX, SOCK_DGRAM, 0); if (ctrl->s < 0) { os_free(ctrl); return NULL; } ctrl->local.sun_family = AF_UNIX; counter++; try_again: ret = os_snprintf(ctrl->local.sun_path, sizeof(ctrl->local.sun_path), CONFIG_CTRL_IFACE_CLIENT_DIR "/" CONFIG_CTRL_IFACE_CLIENT_PREFIX "%d-%d", (int) getpid(), counter); if (ret < 0 || (size_t) ret >= sizeof(ctrl->local.sun_path)) { close(ctrl->s); os_free(ctrl); return NULL; } tries++; if (bind(ctrl->s, (struct sockaddr *) &ctrl->local, sizeof(ctrl->local)) < 0) { if (errno == EADDRINUSE && tries < 2) { /* * getpid() returns unique identifier for this instance * of wpa_ctrl, so the existing socket file must have * been left by unclean termination of an earlier run. * Remove the file and try again. */ unlink(ctrl->local.sun_path); goto try_again; } close(ctrl->s); os_free(ctrl); return NULL; } #ifdef ANDROID chmod(ctrl->local.sun_path, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); chown(ctrl->local.sun_path, AID_SYSTEM, AID_WIFI); /* * If the ctrl_path isn't an absolute pathname, assume that * it's the name of a socket in the Android reserved namespace. * Otherwise, it's a normal UNIX domain socket appearing in the * filesystem. */ if (ctrl_path != NULL && *ctrl_path != '/') { char buf[21]; os_snprintf(buf, sizeof(buf), "wpa_%s", ctrl_path); if (socket_local_client_connect( ctrl->s, buf, ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_DGRAM) < 0) { close(ctrl->s); unlink(ctrl->local.sun_path); os_free(ctrl); return NULL; } return ctrl; } #endif /* ANDROID */ ctrl->dest.sun_family = AF_UNIX; res = os_strlcpy(ctrl->dest.sun_path, ctrl_path, sizeof(ctrl->dest.sun_path)); if (res >= sizeof(ctrl->dest.sun_path)) { close(ctrl->s); os_free(ctrl); return NULL; } if (connect(ctrl->s, (struct sockaddr *) &ctrl->dest, sizeof(ctrl->dest)) < 0) { close(ctrl->s); unlink(ctrl->local.sun_path); os_free(ctrl); return NULL; } return ctrl; }
void eloop_run(void) { fd_set *rfds, *wfds, *efds; int res; struct timeval _tv; struct os_time tv, now; rfds = os_malloc(sizeof(*rfds)); wfds = os_malloc(sizeof(*wfds)); efds = os_malloc(sizeof(*efds)); if (rfds == NULL || wfds == NULL || efds == NULL) { printf("eloop_run - malloc failed\n"); goto out; } while (!eloop.terminate && (eloop.timeout || eloop.readers.count > 0 || eloop.writers.count > 0 || eloop.exceptions.count > 0)) { if (eloop.timeout) { os_get_time(&now); if (os_time_before(&now, &eloop.timeout->time)) os_time_sub(&eloop.timeout->time, &now, &tv); else tv.sec = tv.usec = 0; #if 0 printf("next timeout in %lu.%06lu sec\n", tv.sec, tv.usec); #endif _tv.tv_sec = tv.sec; _tv.tv_usec = tv.usec; } eloop_sock_table_set_fds(&eloop.readers, rfds); eloop_sock_table_set_fds(&eloop.writers, wfds); eloop_sock_table_set_fds(&eloop.exceptions, efds); res = select(eloop.max_sock + 1, rfds, wfds, efds, eloop.timeout ? &_tv : NULL); if (res < 0 && errno != EINTR && errno != 0) { perror("select"); goto out; } eloop_process_pending_signals(); /* check if some registered timeouts have occurred */ if (eloop.timeout) { struct eloop_timeout *tmp; os_get_time(&now); if (!os_time_before(&now, &eloop.timeout->time)) { tmp = eloop.timeout; eloop.timeout = eloop.timeout->next; tmp->handler(tmp->eloop_data, tmp->user_data); os_free(tmp); } } if (res <= 0) continue; eloop_sock_table_dispatch(&eloop.readers, rfds); eloop_sock_table_dispatch(&eloop.writers, wfds); eloop_sock_table_dispatch(&eloop.exceptions, efds); } out: os_free(rfds); os_free(wfds); os_free(efds); }
int ieee802_11_build_ap_params(struct hostapd_data *hapd, struct wpa_driver_ap_params *params) { struct ieee80211_mgmt *head = NULL; u8 *tail = NULL; size_t head_len = 0, tail_len = 0; u8 *resp = NULL; size_t resp_len = 0; #ifdef NEED_AP_MLME u16 capab_info; u8 *pos, *tailpos; #define BEACON_HEAD_BUF_SIZE 256 #define BEACON_TAIL_BUF_SIZE 512 head = os_zalloc(BEACON_HEAD_BUF_SIZE); tail_len = BEACON_TAIL_BUF_SIZE; #ifdef CONFIG_WPS if (hapd->conf->wps_state && hapd->wps_beacon_ie) tail_len += wpabuf_len(hapd->wps_beacon_ie); #endif /* CONFIG_WPS */ #ifdef CONFIG_P2P if (hapd->p2p_beacon_ie) tail_len += wpabuf_len(hapd->p2p_beacon_ie); #endif /* CONFIG_P2P */ if (hapd->conf->vendor_elements) tail_len += wpabuf_len(hapd->conf->vendor_elements); tailpos = tail = os_malloc(tail_len); if (head == NULL || tail == NULL) { wpa_printf(MSG_ERROR, "Failed to set beacon data"); os_free(head); os_free(tail); return -1; } head->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, WLAN_FC_STYPE_BEACON); head->duration = host_to_le16(0); os_memset(head->da, 0xff, ETH_ALEN); os_memcpy(head->sa, hapd->own_addr, ETH_ALEN); os_memcpy(head->bssid, hapd->own_addr, ETH_ALEN); head->u.beacon.beacon_int = host_to_le16(hapd->iconf->beacon_int); /* hardware or low-level driver will setup seq_ctrl and timestamp */ capab_info = hostapd_own_capab_info(hapd, NULL, 0); head->u.beacon.capab_info = host_to_le16(capab_info); pos = &head->u.beacon.variable[0]; /* SSID */ *pos++ = WLAN_EID_SSID; if (hapd->conf->ignore_broadcast_ssid == 2) { /* clear the data, but keep the correct length of the SSID */ *pos++ = hapd->conf->ssid.ssid_len; os_memset(pos, 0, hapd->conf->ssid.ssid_len); pos += hapd->conf->ssid.ssid_len; } else if (hapd->conf->ignore_broadcast_ssid) { *pos++ = 0; /* empty SSID */ } else { *pos++ = hapd->conf->ssid.ssid_len; os_memcpy(pos, hapd->conf->ssid.ssid, hapd->conf->ssid.ssid_len); pos += hapd->conf->ssid.ssid_len; } /* Supported rates */ pos = hostapd_eid_supp_rates(hapd, pos); /* DS Params */ pos = hostapd_eid_ds_params(hapd, pos); head_len = pos - (u8 *) head; tailpos = hostapd_eid_country(hapd, tailpos, tail + BEACON_TAIL_BUF_SIZE - tailpos); /* Power Constraint element */ tailpos = hostapd_eid_pwr_constraint(hapd, tailpos); /* ERP Information element */ tailpos = hostapd_eid_erp_info(hapd, tailpos); /* Extended supported rates */ tailpos = hostapd_eid_ext_supp_rates(hapd, tailpos); /* RSN, MDIE, WPA */ tailpos = hostapd_eid_wpa(hapd, tailpos, tail + BEACON_TAIL_BUF_SIZE - tailpos); tailpos = hostapd_eid_bss_load(hapd, tailpos, tail + BEACON_TAIL_BUF_SIZE - tailpos); #ifdef CONFIG_IEEE80211N tailpos = hostapd_eid_ht_capabilities(hapd, tailpos); tailpos = hostapd_eid_ht_operation(hapd, tailpos); #endif /* CONFIG_IEEE80211N */ tailpos = hostapd_eid_ext_capab(hapd, tailpos); /* * TODO: Time Advertisement element should only be included in some * DTIM Beacon frames. */ tailpos = hostapd_eid_time_adv(hapd, tailpos); tailpos = hostapd_eid_interworking(hapd, tailpos); tailpos = hostapd_eid_adv_proto(hapd, tailpos); tailpos = hostapd_eid_roaming_consortium(hapd, tailpos); tailpos = hostapd_add_csa_elems(hapd, tailpos, tail, &hapd->cs_c_off_beacon); #ifdef CONFIG_IEEE80211AC tailpos = hostapd_eid_vht_capabilities(hapd, tailpos); tailpos = hostapd_eid_vht_operation(hapd, tailpos); #endif /* CONFIG_IEEE80211AC */ /* Wi-Fi Alliance WMM */ tailpos = hostapd_eid_wmm(hapd, tailpos); #ifdef CONFIG_WPS if (hapd->conf->wps_state && hapd->wps_beacon_ie) { os_memcpy(tailpos, wpabuf_head(hapd->wps_beacon_ie), wpabuf_len(hapd->wps_beacon_ie)); tailpos += wpabuf_len(hapd->wps_beacon_ie); } #endif /* CONFIG_WPS */ #ifdef CONFIG_P2P if ((hapd->conf->p2p & P2P_ENABLED) && hapd->p2p_beacon_ie) { os_memcpy(tailpos, wpabuf_head(hapd->p2p_beacon_ie), wpabuf_len(hapd->p2p_beacon_ie)); tailpos += wpabuf_len(hapd->p2p_beacon_ie); } #endif /* CONFIG_P2P */ #ifdef CONFIG_P2P_MANAGER if ((hapd->conf->p2p & (P2P_MANAGE | P2P_ENABLED | P2P_GROUP_OWNER)) == P2P_MANAGE) tailpos = hostapd_eid_p2p_manage(hapd, tailpos); #endif /* CONFIG_P2P_MANAGER */ #ifdef CONFIG_HS20 tailpos = hostapd_eid_hs20_indication(hapd, tailpos); tailpos = hostapd_eid_osen(hapd, tailpos); #endif /* CONFIG_HS20 */ if (hapd->conf->vendor_elements) { os_memcpy(tailpos, wpabuf_head(hapd->conf->vendor_elements), wpabuf_len(hapd->conf->vendor_elements)); tailpos += wpabuf_len(hapd->conf->vendor_elements); } tail_len = tailpos > tail ? tailpos - tail : 0; resp = hostapd_probe_resp_offloads(hapd, &resp_len); #endif /* NEED_AP_MLME */ os_memset(params, 0, sizeof(*params)); params->head = (u8 *) head; params->head_len = head_len; params->tail = tail; params->tail_len = tail_len; params->proberesp = resp; params->proberesp_len = resp_len; params->dtim_period = hapd->conf->dtim_period; params->beacon_int = hapd->iconf->beacon_int; params->basic_rates = hapd->iface->basic_rates; params->ssid = hapd->conf->ssid.ssid; params->ssid_len = hapd->conf->ssid.ssid_len; params->pairwise_ciphers = hapd->conf->wpa_pairwise | hapd->conf->rsn_pairwise; params->group_cipher = hapd->conf->wpa_group; params->key_mgmt_suites = hapd->conf->wpa_key_mgmt; params->auth_algs = hapd->conf->auth_algs; params->wpa_version = hapd->conf->wpa; params->privacy = hapd->conf->ssid.wep.keys_set || hapd->conf->wpa || (hapd->conf->ieee802_1x && (hapd->conf->default_wep_key_len || hapd->conf->individual_wep_key_len)); switch (hapd->conf->ignore_broadcast_ssid) { case 0: params->hide_ssid = NO_SSID_HIDING; break; case 1: params->hide_ssid = HIDDEN_SSID_ZERO_LEN; break; case 2: params->hide_ssid = HIDDEN_SSID_ZERO_CONTENTS; break; } params->isolate = hapd->conf->isolate; #ifdef NEED_AP_MLME params->cts_protect = !!(ieee802_11_erp_info(hapd) & ERP_INFO_USE_PROTECTION); params->preamble = hapd->iface->num_sta_no_short_preamble == 0 && hapd->iconf->preamble == SHORT_PREAMBLE; if (hapd->iface->current_mode && hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G) params->short_slot_time = hapd->iface->num_sta_no_short_slot_time > 0 ? 0 : 1; else params->short_slot_time = -1; if (!hapd->iconf->ieee80211n || hapd->conf->disable_11n) params->ht_opmode = -1; else params->ht_opmode = hapd->iface->ht_op_mode; #endif /* NEED_AP_MLME */ params->interworking = hapd->conf->interworking; if (hapd->conf->interworking && !is_zero_ether_addr(hapd->conf->hessid)) params->hessid = hapd->conf->hessid; params->access_network_type = hapd->conf->access_network_type; params->ap_max_inactivity = hapd->conf->ap_max_inactivity; #ifdef CONFIG_HS20 params->disable_dgaf = hapd->conf->disable_dgaf; if (hapd->conf->osen) { params->privacy = 1; params->osen = 1; } #endif /* CONFIG_HS20 */ return 0; }
u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn, const u8 *in_data, size_t in_len, size_t *out_len, u8 **appl_data, size_t *appl_data_len) { struct tls_global *global = ssl_ctx; DWORD sspi_flags, sspi_flags_out; SecBufferDesc inbuf, outbuf; SecBuffer inbufs[2], outbufs[1]; SECURITY_STATUS status; TimeStamp ts_expiry; u8 *out_buf = NULL; if (appl_data) *appl_data = NULL; if (conn->start) { return tls_conn_hs_clienthello(global, conn, out_len); } wpa_printf(MSG_DEBUG, "SChannel: %d bytes handshake data to process", in_len); sspi_flags = ISC_REQ_REPLAY_DETECT | ISC_REQ_CONFIDENTIALITY | ISC_RET_EXTENDED_ERROR | ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_MANUAL_CRED_VALIDATION; /* Input buffer for Schannel */ inbufs[0].pvBuffer = (u8 *) in_data; inbufs[0].cbBuffer = in_len; inbufs[0].BufferType = SECBUFFER_TOKEN; /* Place for leftover data from Schannel */ inbufs[1].pvBuffer = NULL; inbufs[1].cbBuffer = 0; inbufs[1].BufferType = SECBUFFER_EMPTY; inbuf.cBuffers = 2; inbuf.pBuffers = inbufs; inbuf.ulVersion = SECBUFFER_VERSION; /* Output buffer for Schannel */ outbufs[0].pvBuffer = NULL; outbufs[0].cbBuffer = 0; outbufs[0].BufferType = SECBUFFER_TOKEN; outbuf.cBuffers = 1; outbuf.pBuffers = outbufs; outbuf.ulVersion = SECBUFFER_VERSION; #ifdef UNICODE status = global->sspi->InitializeSecurityContextW( &conn->creds, &conn->context, NULL, sspi_flags, 0, SECURITY_NATIVE_DREP, &inbuf, 0, NULL, &outbuf, &sspi_flags_out, &ts_expiry); #else /* UNICODE */ status = global->sspi->InitializeSecurityContextA( &conn->creds, &conn->context, NULL, sspi_flags, 0, SECURITY_NATIVE_DREP, &inbuf, 0, NULL, &outbuf, &sspi_flags_out, &ts_expiry); #endif /* UNICODE */ wpa_printf(MSG_MSGDUMP, "Schannel: InitializeSecurityContext -> " "status=%d inlen[0]=%d intype[0]=%d inlen[1]=%d " "intype[1]=%d outlen[0]=%d", (int) status, (int) inbufs[0].cbBuffer, (int) inbufs[0].BufferType, (int) inbufs[1].cbBuffer, (int) inbufs[1].BufferType, (int) outbufs[0].cbBuffer); if (status == SEC_E_OK || status == SEC_I_CONTINUE_NEEDED || (FAILED(status) && (sspi_flags_out & ISC_RET_EXTENDED_ERROR))) { if (outbufs[0].cbBuffer != 0 && outbufs[0].pvBuffer) { wpa_hexdump(MSG_MSGDUMP, "SChannel - output", outbufs[0].pvBuffer, outbufs[0].cbBuffer); *out_len = outbufs[0].cbBuffer; out_buf = os_malloc(*out_len); if (out_buf) os_memcpy(out_buf, outbufs[0].pvBuffer, *out_len); global->sspi->FreeContextBuffer(outbufs[0].pvBuffer); outbufs[0].pvBuffer = NULL; if (out_buf == NULL) return NULL; } } switch (status) { case SEC_E_INCOMPLETE_MESSAGE: wpa_printf(MSG_DEBUG, "Schannel: SEC_E_INCOMPLETE_MESSAGE"); break; case SEC_I_CONTINUE_NEEDED: wpa_printf(MSG_DEBUG, "Schannel: SEC_I_CONTINUE_NEEDED"); break; case SEC_E_OK: /* TODO: verify server certificate chain */ wpa_printf(MSG_DEBUG, "Schannel: SEC_E_OK - Handshake " "completed successfully"); conn->established = 1; tls_get_eap(global, conn); /* Need to return something to get final TLS ACK. */ if (out_buf == NULL) out_buf = os_malloc(1); if (inbufs[1].BufferType == SECBUFFER_EXTRA) { wpa_hexdump(MSG_MSGDUMP, "SChannel - Encrypted " "application data", inbufs[1].pvBuffer, inbufs[1].cbBuffer); if (appl_data) { *appl_data_len = outbufs[1].cbBuffer; appl_data = os_malloc(*appl_data_len); if (appl_data) os_memcpy(appl_data, outbufs[1].pvBuffer, *appl_data_len); } global->sspi->FreeContextBuffer(inbufs[1].pvBuffer); inbufs[1].pvBuffer = NULL; } break; case SEC_I_INCOMPLETE_CREDENTIALS: wpa_printf(MSG_DEBUG, "Schannel: SEC_I_INCOMPLETE_CREDENTIALS"); break; case SEC_E_WRONG_PRINCIPAL: wpa_printf(MSG_DEBUG, "Schannel: SEC_E_WRONG_PRINCIPAL"); break; case SEC_E_INTERNAL_ERROR: wpa_printf(MSG_DEBUG, "Schannel: SEC_E_INTERNAL_ERROR"); break; } if (FAILED(status)) { wpa_printf(MSG_DEBUG, "Schannel: Handshake failed " "(out_buf=%p)", out_buf); conn->failed++; global->sspi->DeleteSecurityContext(&conn->context); return out_buf; } if (inbufs[1].BufferType == SECBUFFER_EXTRA) { /* TODO: Can this happen? What to do with this data? */ wpa_hexdump(MSG_MSGDUMP, "SChannel - Leftover data", inbufs[1].pvBuffer, inbufs[1].cbBuffer); global->sspi->FreeContextBuffer(inbufs[1].pvBuffer); inbufs[1].pvBuffer = NULL; } return out_buf; }
u8 * tls_send_client_hello(struct tlsv1_client *conn, size_t *out_len) { u8 *hello, *end, *pos, *hs_length, *hs_start, *rhdr; struct os_time now; size_t len, i; wpa_printf(MSG_DEBUG, "TLSv1: Send ClientHello"); *out_len = 0; os_get_time(&now); WPA_PUT_BE32(conn->client_random, now.sec); if (random_get_bytes(conn->client_random + 4, TLS_RANDOM_LEN - 4)) { wpa_printf(MSG_ERROR, "TLSv1: Could not generate " "client_random"); return NULL; } wpa_hexdump(MSG_MSGDUMP, "TLSv1: client_random", conn->client_random, TLS_RANDOM_LEN); len = 100 + conn->num_cipher_suites * 2 + conn->client_hello_ext_len; hello = os_malloc(len); if (hello == NULL) return NULL; end = hello + len; rhdr = hello; pos = rhdr + TLS_RECORD_HEADER_LEN; /* opaque fragment[TLSPlaintext.length] */ /* Handshake */ hs_start = pos; /* HandshakeType msg_type */ *pos++ = TLS_HANDSHAKE_TYPE_CLIENT_HELLO; /* uint24 length (to be filled) */ hs_length = pos; pos += 3; /* body - ClientHello */ /* ProtocolVersion client_version */ WPA_PUT_BE16(pos, TLS_VERSION); pos += 2; /* Random random: uint32 gmt_unix_time, opaque random_bytes */ os_memcpy(pos, conn->client_random, TLS_RANDOM_LEN); pos += TLS_RANDOM_LEN; /* SessionID session_id */ *pos++ = conn->session_id_len; os_memcpy(pos, conn->session_id, conn->session_id_len); pos += conn->session_id_len; /* CipherSuite cipher_suites<2..2^16-1> */ WPA_PUT_BE16(pos, 2 * conn->num_cipher_suites); pos += 2; for (i = 0; i < conn->num_cipher_suites; i++) { WPA_PUT_BE16(pos, conn->cipher_suites[i]); pos += 2; } /* CompressionMethod compression_methods<1..2^8-1> */ *pos++ = 1; *pos++ = TLS_COMPRESSION_NULL; if (conn->client_hello_ext) { os_memcpy(pos, conn->client_hello_ext, conn->client_hello_ext_len); pos += conn->client_hello_ext_len; } WPA_PUT_BE24(hs_length, pos - hs_length - 3); tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, rhdr, end - rhdr, hs_start, pos - hs_start, out_len) < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to create TLS record"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); os_free(hello); return NULL; } conn->state = SERVER_HELLO; return hello; }
static struct wpabuf * eap_aka_process_challenge(struct eap_sm *sm, struct eap_aka_data *data, u8 id, const struct wpabuf *reqData, struct eap_sim_attrs *attr) { const u8 *identity; size_t identity_len; int res; struct eap_sim_attrs eattr; wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Challenge"); if (attr->checkcode && eap_aka_verify_checkcode(data, attr->checkcode, attr->checkcode_len)) { wpa_printf(MSG_WARNING, "EAP-AKA: Invalid AT_CHECKCODE in the " "message"); return eap_aka_client_error(data, id, EAP_AKA_UNABLE_TO_PROCESS_PACKET); } #ifdef EAP_AKA_PRIME if (data->eap_method == EAP_TYPE_AKA_PRIME) { if (!attr->kdf_input || attr->kdf_input_len == 0) { wpa_printf(MSG_WARNING, "EAP-AKA': Challenge message " "did not include non-empty AT_KDF_INPUT"); /* Fail authentication as if AUTN had been incorrect */ return eap_aka_authentication_reject(data, id); } os_free(data->network_name); data->network_name = os_malloc(attr->kdf_input_len); if (data->network_name == NULL) { wpa_printf(MSG_WARNING, "EAP-AKA': No memory for " "storing Network Name"); return eap_aka_authentication_reject(data, id); } os_memcpy(data->network_name, attr->kdf_input, attr->kdf_input_len); data->network_name_len = attr->kdf_input_len; wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA': Network Name " "(AT_KDF_INPUT)", data->network_name, data->network_name_len); /* TODO: check Network Name per 3GPP.33.402 */ if (!eap_aka_prime_kdf_valid(data, attr)) return eap_aka_authentication_reject(data, id); if (attr->kdf[0] != EAP_AKA_PRIME_KDF) return eap_aka_prime_kdf_neg(data, id, attr); data->kdf = EAP_AKA_PRIME_KDF; wpa_printf(MSG_DEBUG, "EAP-AKA': KDF %d selected", data->kdf); } if (data->eap_method == EAP_TYPE_AKA && attr->bidding) { u16 flags = WPA_GET_BE16(attr->bidding); if ((flags & EAP_AKA_BIDDING_FLAG_D) && eap_allowed_method(sm, EAP_VENDOR_IETF, EAP_TYPE_AKA_PRIME)) { wpa_printf(MSG_WARNING, "EAP-AKA: Bidding down from " "AKA' to AKA detected"); /* Fail authentication as if AUTN had been incorrect */ return eap_aka_authentication_reject(data, id); } } #endif /* EAP_AKA_PRIME */ data->reauth = 0; if (!attr->mac || !attr->rand || !attr->autn) { wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message " "did not include%s%s%s", !attr->mac ? " AT_MAC" : "", !attr->rand ? " AT_RAND" : "", !attr->autn ? " AT_AUTN" : ""); return eap_aka_client_error(data, id, EAP_AKA_UNABLE_TO_PROCESS_PACKET); } os_memcpy(data->rand, attr->rand, EAP_AKA_RAND_LEN); os_memcpy(data->autn, attr->autn, EAP_AKA_AUTN_LEN); res = eap_aka_umts_auth(sm, data); if (res == -1) { wpa_printf(MSG_WARNING, "EAP-AKA: UMTS authentication " "failed (AUTN)"); return eap_aka_authentication_reject(data, id); } else if (res == -2) { wpa_printf(MSG_WARNING, "EAP-AKA: UMTS authentication " "failed (AUTN seq# -> AUTS)"); return eap_aka_synchronization_failure(data, id); } else if (res > 0) { wpa_printf(MSG_DEBUG, "EAP-AKA: Wait for external USIM processing"); return NULL; } else if (res) { wpa_printf(MSG_WARNING, "EAP-AKA: UMTS authentication failed"); return eap_aka_client_error(data, id, EAP_AKA_UNABLE_TO_PROCESS_PACKET); } #ifdef EAP_AKA_PRIME if (data->eap_method == EAP_TYPE_AKA_PRIME) { /* Note: AUTN = (SQN ^ AK) || AMF || MAC which gives us the * needed 6-octet SQN ^ AK for CK',IK' derivation */ u16 amf = WPA_GET_BE16(data->autn + 6); if (!(amf & 0x8000)) { wpa_printf(MSG_WARNING, "EAP-AKA': AMF separation bit " "not set (AMF=0x%4x)", amf); return eap_aka_authentication_reject(data, id); } eap_aka_prime_derive_ck_ik_prime(data->ck, data->ik, data->autn, data->network_name, data->network_name_len); } #endif /* EAP_AKA_PRIME */ if (data->last_eap_identity) { identity = data->last_eap_identity; identity_len = data->last_eap_identity_len; } else if (data->pseudonym) { identity = data->pseudonym; identity_len = data->pseudonym_len; } else identity = eap_get_config_identity(sm, &identity_len); wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA: Selected identity for MK " "derivation", identity, identity_len); if (data->eap_method == EAP_TYPE_AKA_PRIME) { eap_aka_prime_derive_keys(identity, identity_len, data->ik, data->ck, data->k_encr, data->k_aut, data->k_re, data->msk, data->emsk); } else { eap_aka_derive_mk(identity, identity_len, data->ik, data->ck, data->mk); eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, data->msk, data->emsk); } if (eap_aka_verify_mac(data, reqData, attr->mac, (u8 *) "", 0)) { wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message " "used invalid AT_MAC"); return eap_aka_client_error(data, id, EAP_AKA_UNABLE_TO_PROCESS_PACKET); } /* Old reauthentication identity must not be used anymore. In * other words, if no new identities are received, full * authentication will be used on next reauthentication (using * pseudonym identity or permanent identity). */ eap_aka_clear_identities(sm, data, CLEAR_REAUTH_ID | CLEAR_EAP_ID); if (attr->encr_data) { u8 *decrypted; decrypted = eap_sim_parse_encr(data->k_encr, attr->encr_data, attr->encr_data_len, attr->iv, &eattr, 0); if (decrypted == NULL) { return eap_aka_client_error( data, id, EAP_AKA_UNABLE_TO_PROCESS_PACKET); } eap_aka_learn_ids(sm, data, &eattr); os_free(decrypted); } if (data->result_ind && attr->result_ind) data->use_result_ind = 1; if (data->state != FAILURE) { eap_aka_state(data, data->use_result_ind ? RESULT_SUCCESS : SUCCESS); } data->num_id_req = 0; data->num_notification = 0; /* RFC 4187 specifies that counter is initialized to one after * fullauth, but initializing it to zero makes it easier to implement * reauth verification. */ data->counter = 0; return eap_aka_response_challenge(data, id); }
static int eap_ttls_phase2_request_chap(struct eap_sm *sm, struct eap_ttls_data *data, struct eap_method_ret *ret, u8 **resp, size_t *resp_len) { struct wpa_ssid *config = eap_get_config(sm); u8 *buf, *pos, *challenge; const u8 *addr[3]; size_t len[3]; wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 CHAP Request"); pos = buf = os_malloc(config->identity_len + 1000); if (buf == NULL) { wpa_printf(MSG_ERROR, "EAP-TTLS/CHAP: Failed to allocate memory"); return -1; } /* User-Name */ pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_USER_NAME, 0, 1, config->identity, config->identity_len); /* CHAP-Challenge */ challenge = eap_ttls_implicit_challenge( sm, data, EAP_TTLS_CHAP_CHALLENGE_LEN + 1); if (challenge == NULL) { os_free(buf); wpa_printf(MSG_ERROR, "EAP-TTLS/CHAP: Failed to derive " "implicit challenge"); return -1; } pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_CHAP_CHALLENGE, 0, 1, challenge, EAP_TTLS_CHAP_CHALLENGE_LEN); /* CHAP-Password */ pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_CHAP_PASSWORD, 0, 1, 1 + EAP_TTLS_CHAP_PASSWORD_LEN); data->ident = challenge[EAP_TTLS_CHAP_CHALLENGE_LEN]; *pos++ = data->ident; /* MD5(Ident + Password + Challenge) */ addr[0] = &data->ident; len[0] = 1; addr[1] = config->password; len[1] = config->password_len; addr[2] = challenge; len[2] = EAP_TTLS_CHAP_CHALLENGE_LEN; md5_vector(3, addr, len, pos); wpa_hexdump_ascii(MSG_DEBUG, "EAP-TTLS: CHAP username", config->identity, config->identity_len); wpa_hexdump_ascii_key(MSG_DEBUG, "EAP-TTLS: CHAP password", config->password, config->password_len); wpa_hexdump(MSG_DEBUG, "EAP-TTLS: CHAP implicit challenge", challenge, EAP_TTLS_CHAP_CHALLENGE_LEN); wpa_hexdump(MSG_DEBUG, "EAP-TTLS: CHAP password", pos, EAP_TTLS_CHAP_PASSWORD_LEN); pos += EAP_TTLS_CHAP_PASSWORD_LEN; os_free(challenge); AVP_PAD(buf, pos); *resp = buf; *resp_len = pos - buf; if (data->ttls_version > 0) { /* EAP-TTLSv1 uses TLS/IA FinalPhaseFinished to report success, * so do not allow connection to be terminated yet. */ ret->methodState = METHOD_CONT; ret->decision = DECISION_COND_SUCC; } else { /* EAP-TTLS/CHAP does not provide tunneled success * notification, so assume that Phase2 succeeds. */ ret->methodState = METHOD_DONE; ret->decision = DECISION_COND_SUCC; } return 0; }
/* A new device is handled by the server, do the init operations in order to make the device usable */ int export_device(const exa_uuid_t *uuid, char *device_path) { device_t *dev; int i, err; /* If device was already exported, do nothing */ if (find_device_from_uuid(uuid) != NULL) return EXA_SUCCESS; dev = os_malloc(sizeof(struct device)); if (dev == NULL) { err = -NBD_ERR_MALLOC_FAILED; goto error; } dev->handle = NULL; err = -CMD_EXP_ERR_OPEN_DEVICE; dev->handle = exa_rdev_handle_alloc(device_path); if (dev->handle == NULL) goto error; err = get_nb_sectors(device_path, &dev->size_in_sectors); if (err != EXA_SUCCESS) goto error; uuid_copy(&dev->uuid, uuid); strlcpy(dev->path, device_path, sizeof(dev->path)); for (i = 0; i < NBMAX_DISKS_PER_NODE; i++) if (nbd_server.devices[i] == NULL) break; if (i >= NBMAX_DISKS_PER_NODE) { exalog_error("maximum number of exportable devices exceeded"); err = -NBD_ERR_NB_RDEVS_CREATED; } dev->dev_index = i; dev->exit_thread = false; nbd_init_list(&nbd_server.list_root, &dev->disk_queue); /* resource needed to lock/unlock a zone */ os_sem_init (&dev->lock_sem_disk, 0); /* launch disk thread (TD) */ if (!exathread_create_named(&nbd_server.td_pid[dev->dev_index], NBD_THREAD_STACK_SIZE + MIN_THREAD_STACK_SIZE, exa_td_main, dev, "TD_thread")) { os_sem_destroy(&dev->lock_sem_disk); err = -NBD_ERR_THREAD_CREATION; goto error; } nbd_server.devices[dev->dev_index] = dev; return EXA_SUCCESS; error: if (dev != NULL) { if (dev->handle != NULL) exa_rdev_handle_free(dev->handle); os_free(dev); } return err; }
static int eap_ttls_phase2_request_mschapv2(struct eap_sm *sm, struct eap_ttls_data *data, struct eap_method_ret *ret, u8 **resp, size_t *resp_len) { struct wpa_ssid *config = eap_get_config(sm); u8 *buf, *pos, *challenge, *username, *peer_challenge; size_t username_len, i; wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 MSCHAPV2 Request"); /* MSCHAPv2 does not include optional domain name in the * challenge-response calculation, so remove domain prefix * (if present). */ username = config->identity; username_len = config->identity_len; pos = username; for (i = 0; i < username_len; i++) { if (username[i] == '\\') { username_len -= i + 1; username += i + 1; break; } } pos = buf = os_malloc(config->identity_len + 1000); if (buf == NULL) { wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAPV2: Failed to allocate memory"); return -1; } /* User-Name */ pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_USER_NAME, 0, 1, config->identity, config->identity_len); /* MS-CHAP-Challenge */ challenge = eap_ttls_implicit_challenge( sm, data, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN + 1); if (challenge == NULL) { os_free(buf); wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAPV2: Failed to derive " "implicit challenge"); return -1; } peer_challenge = challenge + 1 + EAP_TTLS_MSCHAPV2_CHALLENGE_LEN; pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_MS_CHAP_CHALLENGE, RADIUS_VENDOR_ID_MICROSOFT, 1, challenge, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN); /* MS-CHAP2-Response */ pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_MS_CHAP2_RESPONSE, RADIUS_VENDOR_ID_MICROSOFT, 1, EAP_TTLS_MSCHAPV2_RESPONSE_LEN); data->ident = challenge[EAP_TTLS_MSCHAPV2_CHALLENGE_LEN]; *pos++ = data->ident; *pos++ = 0; /* Flags */ os_memcpy(pos, peer_challenge, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN); pos += EAP_TTLS_MSCHAPV2_CHALLENGE_LEN; os_memset(pos, 0, 8); /* Reserved, must be zero */ pos += 8; wpa_hexdump(MSG_DEBUG, "EAP-TTLS: MSCHAPV2: implicit auth_challenge", challenge, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN); wpa_hexdump(MSG_DEBUG, "EAP-TTLS: MSCHAPV2: peer_challenge", peer_challenge, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN); wpa_hexdump_ascii(MSG_DEBUG, "EAP-TTLS: MSCHAPV2 username", username, username_len); wpa_hexdump_ascii_key(MSG_DEBUG, "EAP-TTLS: MSCHAPV2 password", config->password, config->password_len); generate_nt_response(challenge, peer_challenge, username, username_len, config->password, config->password_len, pos); wpa_hexdump(MSG_DEBUG, "EAP-TTLS: MSCHAPV2 response", pos, 24); generate_authenticator_response(config->password, config->password_len, peer_challenge, challenge, username, username_len, pos, data->auth_response); data->auth_response_valid = 1; if (data->ttls_version > 0) { u8 pw_hash[16], pw_hash_hash[16], master_key[16]; u8 session_key[2 * MSCHAPV2_KEY_LEN]; nt_password_hash(config->password, config->password_len, pw_hash); hash_nt_password_hash(pw_hash, pw_hash_hash); get_master_key(pw_hash_hash, pos /* nt_response */, master_key); get_asymetric_start_key(master_key, session_key, MSCHAPV2_KEY_LEN, 0, 0); get_asymetric_start_key(master_key, session_key + MSCHAPV2_KEY_LEN, MSCHAPV2_KEY_LEN, 1, 0); eap_ttls_ia_permute_inner_secret(sm, data, session_key, sizeof(session_key)); } pos += 24; os_free(challenge); AVP_PAD(buf, pos); *resp = buf; *resp_len = pos - buf; if (sm->workaround && data->ttls_version == 0) { /* At least FreeRADIUS seems to be terminating * EAP-TTLS/MSHCAPV2 without the expected MS-CHAP-v2 Success * packet. */ wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: EAP workaround - " "allow success without tunneled response"); ret->methodState = METHOD_MAY_CONT; ret->decision = DECISION_COND_SUCC; } return 0; }
static int eap_ttls_phase2_request_mschap(struct eap_sm *sm, struct eap_ttls_data *data, struct eap_method_ret *ret, u8 **resp, size_t *resp_len) { struct wpa_ssid *config = eap_get_config(sm); u8 *buf, *pos, *challenge; wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 MSCHAP Request"); pos = buf = os_malloc(config->identity_len + 1000); if (buf == NULL) { wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAP: Failed to allocate memory"); return -1; } /* User-Name */ pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_USER_NAME, 0, 1, config->identity, config->identity_len); /* MS-CHAP-Challenge */ challenge = eap_ttls_implicit_challenge( sm, data, EAP_TTLS_MSCHAP_CHALLENGE_LEN + 1); if (challenge == NULL) { os_free(buf); wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAP: Failed to derive " "implicit challenge"); return -1; } pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_MS_CHAP_CHALLENGE, RADIUS_VENDOR_ID_MICROSOFT, 1, challenge, EAP_TTLS_MSCHAP_CHALLENGE_LEN); /* MS-CHAP-Response */ pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_MS_CHAP_RESPONSE, RADIUS_VENDOR_ID_MICROSOFT, 1, EAP_TTLS_MSCHAP_RESPONSE_LEN); data->ident = challenge[EAP_TTLS_MSCHAP_CHALLENGE_LEN]; *pos++ = data->ident; *pos++ = 1; /* Flags: Use NT style passwords */ os_memset(pos, 0, 24); /* LM-Response */ pos += 24; nt_challenge_response(challenge, config->password, config->password_len, pos); /* NT-Response */ wpa_hexdump_ascii_key(MSG_DEBUG, "EAP-TTLS: MSCHAP password", config->password, config->password_len); wpa_hexdump(MSG_DEBUG, "EAP-TTLS: MSCHAP implicit challenge", challenge, EAP_TTLS_MSCHAP_CHALLENGE_LEN); wpa_hexdump(MSG_DEBUG, "EAP-TTLS: MSCHAP response", pos, 24); pos += 24; os_free(challenge); AVP_PAD(buf, pos); *resp = buf; *resp_len = pos - buf; if (data->ttls_version > 0) { /* EAP-TTLSv1 uses TLS/IA FinalPhaseFinished to report success, * so do not allow connection to be terminated yet. */ ret->methodState = METHOD_CONT; ret->decision = DECISION_COND_SUCC; } else { /* EAP-TTLS/MSCHAP does not provide tunneled success * notification, so assume that Phase2 succeeds. */ ret->methodState = METHOD_DONE; ret->decision = DECISION_COND_SUCC; } return 0; }
return res; } static u8 * eap_ttls_build_phase_finished(struct eap_sm *sm, struct eap_ttls_data *data, int id, int final, size_t *reqDataLen) { int len; struct eap_hdr *req; u8 *pos; const int max_len = 300; len = sizeof(struct eap_hdr) + 2 + max_len; req = os_malloc(len); if (req == NULL) return NULL; req->code = EAP_CODE_RESPONSE; req->identifier = id; pos = (u8 *) (req + 1); *pos++ = EAP_TYPE_TTLS; *pos++ = data->ttls_version; len = tls_connection_ia_send_phase_finished(sm->ssl_ctx, data->ssl.conn, final, pos, max_len); if (len < 0) { os_free(req);
static int hostapd_prepare_rates(struct hostapd_data *hapd, struct hostapd_hw_modes *mode) { int i, num_basic_rates = 0; int basic_rates_a[] = { 60, 120, 240, -1 }; int basic_rates_b[] = { 10, 20, -1 }; int basic_rates_g[] = { 10, 20, 55, 110, -1 }; int *basic_rates; if (hapd->iconf->basic_rates) basic_rates = hapd->iconf->basic_rates; else switch (mode->mode) { case HOSTAPD_MODE_IEEE80211A: basic_rates = basic_rates_a; break; case HOSTAPD_MODE_IEEE80211B: basic_rates = basic_rates_b; break; case HOSTAPD_MODE_IEEE80211G: basic_rates = basic_rates_g; break; default: return -1; } if (hostapd_set_rate_sets(hapd, hapd->iconf->supported_rates, basic_rates, mode->mode)) { wpa_printf(MSG_ERROR, "Failed to update rate sets in kernel " "module"); } os_free(hapd->iface->current_rates); hapd->iface->num_rates = 0; hapd->iface->current_rates = os_malloc(mode->num_rates * sizeof(struct hostapd_rate_data)); if (!hapd->iface->current_rates) { wpa_printf(MSG_ERROR, "Failed to allocate memory for rate " "table."); return -1; } for (i = 0; i < mode->num_rates; i++) { struct hostapd_rate_data *rate; if (hapd->iconf->supported_rates && !hostapd_rate_found(hapd->iconf->supported_rates, mode->rates[i].rate)) continue; rate = &hapd->iface->current_rates[hapd->iface->num_rates]; os_memcpy(rate, &mode->rates[i], sizeof(struct hostapd_rate_data)); if (hostapd_rate_found(basic_rates, rate->rate)) { rate->flags |= HOSTAPD_RATE_BASIC; num_basic_rates++; } else rate->flags &= ~HOSTAPD_RATE_BASIC; wpa_printf(MSG_DEBUG, "RATE[%d] rate=%d flags=0x%x", hapd->iface->num_rates, rate->rate, rate->flags); hapd->iface->num_rates++; } if (hapd->iface->num_rates == 0 || num_basic_rates == 0) { wpa_printf(MSG_ERROR, "No rates remaining in supported/basic " "rate sets (%d,%d).", hapd->iface->num_rates, num_basic_rates); return -1; } return 0; }
static int hostapd_mgmt_rx(struct hostapd_data *hapd, struct rx_mgmt *rx_mgmt) { struct hostapd_iface *iface = hapd->iface; const struct ieee80211_hdr *hdr; const u8 *bssid; struct hostapd_frame_info fi; int ret; #ifdef CONFIG_TESTING_OPTIONS if (hapd->ext_mgmt_frame_handling) { size_t hex_len = 2 * rx_mgmt->frame_len + 1; char *hex = os_malloc(hex_len); if (hex) { wpa_snprintf_hex(hex, hex_len, rx_mgmt->frame, rx_mgmt->frame_len); wpa_msg(hapd->msg_ctx, MSG_INFO, "MGMT-RX %s", hex); os_free(hex); } return 1; } #endif /* CONFIG_TESTING_OPTIONS */ hdr = (const struct ieee80211_hdr *) rx_mgmt->frame; bssid = get_hdr_bssid(hdr, rx_mgmt->frame_len); if (bssid == NULL) return 0; hapd = get_hapd_bssid(iface, bssid); if (hapd == NULL) { u16 fc; fc = le_to_host16(hdr->frame_control); /* * Drop frames to unknown BSSIDs except for Beacon frames which * could be used to update neighbor information. */ if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT && WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_BEACON) hapd = iface->bss[0]; else return 0; } os_memset(&fi, 0, sizeof(fi)); fi.datarate = rx_mgmt->datarate; fi.ssi_signal = rx_mgmt->ssi_signal; if (hapd == HAPD_BROADCAST) { size_t i; ret = 0; for (i = 0; i < iface->num_bss; i++) { /* if bss is set, driver will call this function for * each bss individually. */ if (rx_mgmt->drv_priv && (iface->bss[i]->drv_priv != rx_mgmt->drv_priv)) continue; if (ieee802_11_mgmt(iface->bss[i], rx_mgmt->frame, rx_mgmt->frame_len, &fi) > 0) ret = 1; } } else ret = ieee802_11_mgmt(hapd, rx_mgmt->frame, rx_mgmt->frame_len, &fi); random_add_randomness(&fi, sizeof(fi)); return ret; }
/** * eap_gpsk_derive_keys - Derive EAP-GPSK keys * @psk: Pre-shared key * @psk_len: Length of psk in bytes * @vendor: CSuite/Vendor * @specifier: CSuite/Specifier * @rand_peer: 32-byte RAND_Peer * @rand_server: 32-byte RAND_Server * @id_peer: ID_Peer * @id_peer_len: Length of ID_Peer * @id_server: ID_Server * @id_server_len: Length of ID_Server * @msk: Buffer for 64-byte MSK * @emsk: Buffer for 64-byte EMSK * @sk: Buffer for SK (at least EAP_GPSK_MAX_SK_LEN bytes) * @sk_len: Buffer for returning length of SK * @pk: Buffer for PK (at least EAP_GPSK_MAX_PK_LEN bytes) * @pk_len: Buffer for returning length of PK * Returns: 0 on success, -1 on failure */ int eap_gpsk_derive_keys(const u8 *psk, size_t psk_len, int vendor, int specifier, const u8 *rand_peer, const u8 *rand_server, const u8 *id_peer, size_t id_peer_len, const u8 *id_server, size_t id_server_len, u8 *msk, u8 *emsk, u8 *sk, size_t *sk_len, u8 *pk, size_t *pk_len) { u8 *seed, *pos; size_t seed_len; int ret; wpa_printf(MSG_DEBUG, "EAP-GPSK: Deriving keys (%d:%d)", vendor, specifier); if (vendor != EAP_GPSK_VENDOR_IETF) return -1; wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: PSK", psk, psk_len); /* Seed = RAND_Peer || ID_Peer || RAND_Server || ID_Server */ seed_len = 2 * EAP_GPSK_RAND_LEN + id_server_len + id_peer_len; seed = os_malloc(seed_len); if (seed == NULL) { wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to allocate memory " "for key derivation"); return -1; } pos = seed; os_memcpy(pos, rand_peer, EAP_GPSK_RAND_LEN); pos += EAP_GPSK_RAND_LEN; os_memcpy(pos, id_peer, id_peer_len); pos += id_peer_len; os_memcpy(pos, rand_server, EAP_GPSK_RAND_LEN); pos += EAP_GPSK_RAND_LEN; os_memcpy(pos, id_server, id_server_len); pos += id_server_len; wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Seed", seed, seed_len); switch (specifier) { case EAP_GPSK_CIPHER_AES: ret = eap_gpsk_derive_keys_aes(psk, psk_len, seed, seed_len, msk, emsk, sk, sk_len, pk, pk_len); break; #ifdef EAP_GPSK_SHA256 case EAP_GPSK_CIPHER_SHA256: ret = eap_gpsk_derive_keys_sha256(psk, psk_len, seed, seed_len, msk, emsk, sk, sk_len); break; #endif /* EAP_GPSK_SHA256 */ default: wpa_printf(MSG_DEBUG, "EAP-GPSK: Unknown cipher %d:%d used in " "key derivation", vendor, specifier); ret = -1; break; } os_free(seed); return ret; }
static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid) { struct hostapd_iface *ifmsh; struct hostapd_data *bss; struct hostapd_config *conf; struct mesh_conf *mconf; int basic_rates_erp[] = { 10, 20, 55, 60, 110, 120, 240, -1 }; static int default_groups[] = { 19, 20, 21, 25, 26, -1 }; size_t len; int rate_len; if (!wpa_s->conf->user_mpm) { /* not much for us to do here */ wpa_msg(wpa_s, MSG_WARNING, "user_mpm is not enabled in configuration"); return 0; } wpa_s->ifmsh = ifmsh = os_zalloc(sizeof(*wpa_s->ifmsh)); if (!ifmsh) return -ENOMEM; ifmsh->drv_flags = wpa_s->drv_flags; ifmsh->num_bss = 1; ifmsh->bss = os_calloc(wpa_s->ifmsh->num_bss, sizeof(struct hostapd_data *)); if (!ifmsh->bss) goto out_free; ifmsh->bss[0] = bss = os_zalloc(sizeof(struct hostapd_data)); if (!bss) goto out_free; os_memcpy(bss->own_addr, wpa_s->own_addr, ETH_ALEN); bss->driver = wpa_s->driver; bss->drv_priv = wpa_s->drv_priv; bss->iface = ifmsh; bss->mesh_sta_free_cb = mesh_mpm_free_sta; wpa_s->assoc_freq = ssid->frequency; wpa_s->current_ssid = ssid; /* setup an AP config for auth processing */ conf = hostapd_config_defaults(); if (!conf) goto out_free; bss->conf = *conf->bss; bss->conf->start_disabled = 1; bss->conf->mesh = MESH_ENABLED; bss->conf->ap_max_inactivity = wpa_s->conf->mesh_max_inactivity; bss->iconf = conf; ifmsh->conf = conf; ifmsh->bss[0]->max_plinks = wpa_s->conf->max_peer_links; os_strlcpy(bss->conf->iface, wpa_s->ifname, sizeof(bss->conf->iface)); mconf = mesh_config_create(ssid); if (!mconf) goto out_free; ifmsh->mconf = mconf; /* need conf->hw_mode for supported rates. */ if (ssid->frequency == 0) { conf->hw_mode = HOSTAPD_MODE_IEEE80211G; conf->channel = 1; } else { conf->hw_mode = ieee80211_freq_to_chan(ssid->frequency, &conf->channel); } if (conf->hw_mode == NUM_HOSTAPD_MODES) { wpa_printf(MSG_ERROR, "Unsupported mesh mode frequency: %d MHz", ssid->frequency); goto out_free; } if (ssid->mesh_basic_rates == NULL) { /* * XXX: Hack! This is so an MPM which correctly sets the ERP * mandatory rates as BSSBasicRateSet doesn't reject us. We * could add a new hw_mode HOSTAPD_MODE_IEEE80211G_ERP, but * this is way easier. This also makes our BSSBasicRateSet * advertised in beacons match the one in peering frames, sigh. */ if (conf->hw_mode == HOSTAPD_MODE_IEEE80211G) { conf->basic_rates = os_malloc(sizeof(basic_rates_erp)); if (!conf->basic_rates) goto out_free; os_memcpy(conf->basic_rates, basic_rates_erp, sizeof(basic_rates_erp)); } } else { rate_len = 0; while (1) { if (ssid->mesh_basic_rates[rate_len] < 1) break; rate_len++; } conf->basic_rates = os_calloc(rate_len + 1, sizeof(int)); if (conf->basic_rates == NULL) goto out_free; os_memcpy(conf->basic_rates, ssid->mesh_basic_rates, rate_len * sizeof(int)); conf->basic_rates[rate_len] = -1; } if (hostapd_setup_interface(ifmsh)) { wpa_printf(MSG_ERROR, "Failed to initialize hostapd interface for mesh"); return -1; } if (wpa_drv_init_mesh(wpa_s)) { wpa_msg(wpa_s, MSG_ERROR, "Failed to init mesh in driver"); return -1; } if (mconf->security != MESH_CONF_SEC_NONE) { if (ssid->passphrase == NULL) { wpa_printf(MSG_ERROR, "mesh: Passphrase for SAE not configured"); goto out_free; } bss->conf->wpa = ssid->proto; bss->conf->wpa_key_mgmt = ssid->key_mgmt; if (wpa_s->conf->sae_groups && wpa_s->conf->sae_groups[0] > 0) { wpas_mesh_copy_groups(bss, wpa_s); } else { bss->conf->sae_groups = os_malloc(sizeof(default_groups)); if (!bss->conf->sae_groups) goto out_free; os_memcpy(bss->conf->sae_groups, default_groups, sizeof(default_groups)); } len = os_strlen(ssid->passphrase); bss->conf->ssid.wpa_passphrase = dup_binstr(ssid->passphrase, len); wpa_s->mesh_rsn = mesh_rsn_auth_init(wpa_s, mconf); if (!wpa_s->mesh_rsn) goto out_free; } wpa_supplicant_conf_ap_ht(wpa_s, ssid, conf); return 0; out_free: wpa_supplicant_mesh_deinit(wpa_s); return -ENOMEM; }
static int tlsv1_key_x_anon_dh(struct tlsv1_client *conn, u8 **pos, u8 *end) { /* ClientDiffieHellmanPublic */ u8 *csecret, *csecret_start, *dh_yc, *shared; size_t csecret_len, dh_yc_len, shared_len; csecret_len = conn->dh_p_len; csecret = os_malloc(csecret_len); if (csecret == NULL) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate " "memory for Yc (Diffie-Hellman)"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); return -1; } if (random_get_bytes(csecret, csecret_len)) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to get random " "data for Diffie-Hellman"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); os_free(csecret); return -1; } if (os_memcmp(csecret, conn->dh_p, csecret_len) > 0) csecret[0] = 0; /* make sure Yc < p */ csecret_start = csecret; while (csecret_len > 1 && *csecret_start == 0) { csecret_start++; csecret_len--; } wpa_hexdump_key(MSG_DEBUG, "TLSv1: DH client's secret value", csecret_start, csecret_len); /* Yc = g^csecret mod p */ dh_yc_len = conn->dh_p_len; dh_yc = os_malloc(dh_yc_len); if (dh_yc == NULL) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate " "memory for Diffie-Hellman"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); os_free(csecret); return -1; } if (crypto_mod_exp(conn->dh_g, conn->dh_g_len, csecret_start, csecret_len, conn->dh_p, conn->dh_p_len, dh_yc, &dh_yc_len)) { tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); os_free(csecret); os_free(dh_yc); return -1; } wpa_hexdump(MSG_DEBUG, "TLSv1: DH Yc (client's public value)", dh_yc, dh_yc_len); WPA_PUT_BE16(*pos, dh_yc_len); *pos += 2; if (*pos + dh_yc_len > end) { wpa_printf(MSG_DEBUG, "TLSv1: Not enough room in the " "message buffer for Yc"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); os_free(csecret); os_free(dh_yc); return -1; } os_memcpy(*pos, dh_yc, dh_yc_len); *pos += dh_yc_len; os_free(dh_yc); shared_len = conn->dh_p_len; shared = os_malloc(shared_len); if (shared == NULL) { wpa_printf(MSG_DEBUG, "TLSv1: Could not allocate memory for " "DH"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); os_free(csecret); return -1; } /* shared = Ys^csecret mod p */ if (crypto_mod_exp(conn->dh_ys, conn->dh_ys_len, csecret_start, csecret_len, conn->dh_p, conn->dh_p_len, shared, &shared_len)) { tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); os_free(csecret); os_free(shared); return -1; } wpa_hexdump_key(MSG_DEBUG, "TLSv1: Shared secret from DH key exchange", shared, shared_len); os_memset(csecret_start, 0, csecret_len); os_free(csecret); if (tls_derive_keys(conn, shared, shared_len)) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive keys"); tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); os_free(shared); return -1; } os_memset(shared, 0, shared_len); os_free(shared); tlsv1_client_free_dh(conn); return 0; }
static int mesh_attr_text(const u8 *ies, size_t ies_len, char *buf, char *end) { struct ieee802_11_elems elems; char *mesh_id, *pos = buf; u8 *bss_basic_rate_set; int bss_basic_rate_set_len, ret, i; if (ieee802_11_parse_elems(ies, ies_len, &elems, 0) == ParseFailed) return -1; if (elems.mesh_id_len < 1) return 0; mesh_id = os_malloc(elems.mesh_id_len + 1); if (mesh_id == NULL) return -1; os_memcpy(mesh_id, elems.mesh_id, elems.mesh_id_len); mesh_id[elems.mesh_id_len] = '\0'; ret = os_snprintf(pos, end - pos, "mesh_id=%s\n", mesh_id); os_free(mesh_id); if (os_snprintf_error(end - pos, ret)) return pos - buf; pos += ret; if (elems.mesh_config_len > 6) { ret = os_snprintf(pos, end - pos, "active_path_selection_protocol_id=0x%02x\n" "active_path_selection_metric_id=0x%02x\n" "congestion_control_mode_id=0x%02x\n" "synchronization_method_id=0x%02x\n" "authentication_protocol_id=0x%02x\n" "mesh_formation_info=0x%02x\n" "mesh_capability=0x%02x\n", elems.mesh_config[0], elems.mesh_config[1], elems.mesh_config[2], elems.mesh_config[3], elems.mesh_config[4], elems.mesh_config[5], elems.mesh_config[6]); if (os_snprintf_error(end - pos, ret)) return pos - buf; pos += ret; } bss_basic_rate_set = os_malloc(elems.supp_rates_len + elems.ext_supp_rates_len); if (bss_basic_rate_set == NULL) return -1; bss_basic_rate_set_len = 0; for (i = 0; i < elems.supp_rates_len; i++) { if (elems.supp_rates[i] & 0x80) { bss_basic_rate_set[bss_basic_rate_set_len++] = (elems.supp_rates[i] & 0x7f) * 5; } } for (i = 0; i < elems.ext_supp_rates_len; i++) { if (elems.ext_supp_rates[i] & 0x80) { bss_basic_rate_set[bss_basic_rate_set_len++] = (elems.ext_supp_rates[i] & 0x7f) * 5; } } if (bss_basic_rate_set_len > 0) { ret = os_snprintf(pos, end - pos, "bss_basic_rate_set=%d", bss_basic_rate_set[0]); if (os_snprintf_error(end - pos, ret)) return pos - buf; pos += ret; for (i = 1; i < bss_basic_rate_set_len; i++) { ret = os_snprintf(pos, end - pos, " %d", bss_basic_rate_set[i]); if (os_snprintf_error(end - pos, ret)) return pos - buf; pos += ret; } ret = os_snprintf(pos, end - pos, "\n"); if (os_snprintf_error(end - pos, ret)) return pos - buf; pos += ret; } os_free(bss_basic_rate_set); return pos - buf; }
static int eap_aka_learn_ids(struct eap_sm *sm, struct eap_aka_data *data, struct eap_sim_attrs *attr) { if (attr->next_pseudonym) { const u8 *identity = NULL; size_t identity_len = 0; const u8 *realm = NULL; size_t realm_len = 0; wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA: (encr) AT_NEXT_PSEUDONYM", attr->next_pseudonym, attr->next_pseudonym_len); os_free(data->pseudonym); /* Look for the realm of the permanent identity */ identity = eap_get_config_identity(sm, &identity_len); if (identity) { for (realm = identity, realm_len = identity_len; realm_len > 0; realm_len--, realm++) { if (*realm == '@') break; } } data->pseudonym = os_malloc(attr->next_pseudonym_len + realm_len); if (data->pseudonym == NULL) { wpa_printf(MSG_INFO, "EAP-AKA: (encr) No memory for " "next pseudonym"); data->pseudonym_len = 0; return -1; } os_memcpy(data->pseudonym, attr->next_pseudonym, attr->next_pseudonym_len); if (realm_len) { os_memcpy(data->pseudonym + attr->next_pseudonym_len, realm, realm_len); } data->pseudonym_len = attr->next_pseudonym_len + realm_len; eap_set_anon_id(sm, data->pseudonym, data->pseudonym_len); } if (attr->next_reauth_id) { os_free(data->reauth_id); data->reauth_id = os_malloc(attr->next_reauth_id_len); if (data->reauth_id == NULL) { wpa_printf(MSG_INFO, "EAP-AKA: (encr) No memory for " "next reauth_id"); data->reauth_id_len = 0; return -1; } os_memcpy(data->reauth_id, attr->next_reauth_id, attr->next_reauth_id_len); data->reauth_id_len = attr->next_reauth_id_len; wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA: (encr) AT_NEXT_REAUTH_ID", data->reauth_id, data->reauth_id_len); } return 0; }
void c_copyOut ( c_type type, c_object o, c_voidp *data) { c_long i,size; c_type t,subType; if (data == NULL) { OS_REPORT(OS_ERROR,"Database misc",0, "c_copyOut: no destination specified"); return; } if (o == NULL) { *data = NULL; return; } t = c_typeActualType(type); size = c_typeSize(t); if (size == 0) { OS_REPORT(OS_WARNING,"Database misc",0, "c_copyOut: zero sized type specified"); *data = NULL; return; } if (*data == NULL) { *data = (c_voidp)os_malloc(size); } if (c_baseObject(t)->kind == M_COLLECTION) { switch(c_collectionType(t)->kind) { case C_STRING: *data = os_strdup((c_char *)o); break; case C_LIST: case C_BAG: case C_SET: case C_MAP: case C_DICTIONARY: OS_REPORT(OS_WARNING,"Database misc",0, "c_copyOut: ODL collections unsupported"); assert(FALSE); break; case C_ARRAY: size = c_collectionType(t)->maxSize; if (size > 0) { subType = c_collectionType(t)->subType; for (i=0;i<size;i++) { c_copyIn(subType, ((c_voidp *)o)[i], &((c_voidp *)(*data))[i]); } } else { OS_REPORT(OS_WARNING,"Database misc",0, "c_copyOut: dynamic sized arrays unsupported"); } case C_SEQUENCE: OS_REPORT(OS_WARNING,"Database misc",0, "c_copyOut: sequences unsupported"); assert(FALSE); break; default: OS_REPORT_1(OS_ERROR,"Database misc",0, "c_copyOut: unknown collection kind (%d)", c_collectionType(t)->kind); assert(FALSE); break; } } else if (c_typeIsRef(t)) { memcpy(*data,*(void**)o,size); extractReferences(t,*(void**)o,*data); } else { memcpy(*data,o,size); extractReferences(t,o,*data); } }
void handle_probe_req(struct hostapd_data *hapd, const struct ieee80211_mgmt *mgmt, size_t len, int ssi_signal) { u8 *resp; struct ieee802_11_elems elems; const u8 *ie; size_t ie_len; struct sta_info *sta = NULL; size_t i, resp_len; int noack; enum ssid_match_result res; int iterate = 0; ie = mgmt->u.probe_req.variable; if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req)) return; ie_len = len - (IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req)); for (i = 0; hapd->probereq_cb && i < hapd->num_probereq_cb; i++) if (hapd->probereq_cb[i].cb(hapd->probereq_cb[i].ctx, mgmt->sa, mgmt->da, mgmt->bssid, ie, ie_len, ssi_signal) > 0) return; if (!hapd->iconf->send_probe_response) return; if (ieee802_11_parse_elems(ie, ie_len, &elems, 0) == ParseFailed) { wpa_printf(MSG_DEBUG, "Could not parse ProbeReq from " MACSTR, MAC2STR(mgmt->sa)); return; } if ((!elems.ssid || !elems.supp_rates)) { wpa_printf(MSG_DEBUG, "STA " MACSTR " sent probe request " "without SSID or supported rates element", MAC2STR(mgmt->sa)); return; } #ifdef CONFIG_P2P if (hapd->p2p && elems.wps_ie) { struct wpabuf *wps; wps = ieee802_11_vendor_ie_concat(ie, ie_len, WPS_DEV_OUI_WFA); if (wps && !p2p_group_match_dev_type(hapd->p2p_group, wps)) { wpa_printf(MSG_MSGDUMP, "P2P: Ignore Probe Request " "due to mismatch with Requested Device " "Type"); wpabuf_free(wps); return; } wpabuf_free(wps); } if (hapd->p2p && elems.p2p) { struct wpabuf *p2p; p2p = ieee802_11_vendor_ie_concat(ie, ie_len, P2P_IE_VENDOR_TYPE); if (p2p && !p2p_group_match_dev_id(hapd->p2p_group, p2p)) { wpa_printf(MSG_MSGDUMP, "P2P: Ignore Probe Request " "due to mismatch with Device ID"); wpabuf_free(p2p); return; } wpabuf_free(p2p); } #endif /* CONFIG_P2P */ if (hapd->conf->ignore_broadcast_ssid && elems.ssid_len == 0 && elems.ssid_list_len == 0 && !hapd->iconf->enable_mana) { wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR " for " "broadcast SSID ignored", MAC2STR(mgmt->sa)); return; } sta = ap_get_sta(hapd, mgmt->sa); #ifdef CONFIG_P2P if ((hapd->conf->p2p & P2P_GROUP_OWNER) && elems.ssid_len == P2P_WILDCARD_SSID_LEN && os_memcmp(elems.ssid, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) == 0) { /* Process P2P Wildcard SSID like Wildcard SSID */ elems.ssid_len = 0; } #endif /* CONFIG_P2P */ res = ssid_match(hapd, elems.ssid, elems.ssid_len, elems.ssid_list, elems.ssid_list_len); // todo handle ssid_list see ssid_match for code // todo change emit code below (global flag?) if (res == EXACT_SSID_MATCH) { //Probed for configured address if (hapd->iconf->enable_mana) { wpa_printf(MSG_INFO,"MANA - Directed probe request for actual/legitimate SSID '%s' from " MACSTR "",wpa_ssid_txt(elems.ssid, elems.ssid_len),MAC2STR(mgmt->sa)); } if (sta) { sta->ssid_probe = &hapd->conf->ssid; sta->ssid_probe_mana = &hapd->conf->ssid; } } else if (res == NO_SSID_MATCH) { //Probed for unseen SSID wpa_printf(MSG_INFO,"MANA - Directed probe request for foreign SSID '%s' from " MACSTR "",wpa_ssid_txt(elems.ssid, elems.ssid_len),MAC2STR(mgmt->sa)); if (hapd->iconf->enable_mana) { if (sta) { // Make hostapd think they probed for us, necessary for security policy sta->ssid_probe = &hapd->conf->ssid; // Store what was actually probed for sta->ssid_probe_mana = (struct hostapd_ssid*)os_malloc(sizeof(struct hostapd_ssid)); os_memcpy(sta->ssid_probe_mana,&hapd->conf->ssid,sizeof(hapd->conf->ssid)); os_memcpy(sta->ssid_probe_mana->ssid, elems.ssid, elems.ssid_len); sta->ssid_probe_mana->ssid[elems.ssid_len] = '\0'; sta->ssid_probe_mana->ssid_len = elems.ssid_len; } if (hapd->iconf->mana_loud) { // Check if the SSID probed for is in the hash for this STA struct mana_ssid *d = NULL; HASH_FIND_STR(mana_ssidhash, wpa_ssid_txt(elems.ssid, elems.ssid_len), d); if (d == NULL) { wpa_printf(MSG_DEBUG, "MANA - Adding SSID %s(%d) for STA " MACSTR " to the hash.", wpa_ssid_txt(elems.ssid, elems.ssid_len), elems.ssid_len, MAC2STR(mgmt->sa)); d = (struct mana_ssid*)os_malloc(sizeof(struct mana_ssid)); os_memcpy(d->ssid_txt, wpa_ssid_txt(elems.ssid, elems.ssid_len), elems.ssid_len+1); os_memcpy(d->ssid, elems.ssid, elems.ssid_len); d->ssid_len = elems.ssid_len; //os_memcpy(d->sta_addr, mgmt->sa, ETH_ALEN); HASH_ADD_STR(mana_ssidhash, ssid_txt, d); log_ssid(elems.ssid, elems.ssid_len, mgmt->sa); } } else { //Not loud mode, Check if the STA probing is in our hash struct mana_mac *newsta = NULL; //char strmac[18]; //snprintf(strmac, sizeof(strmac), MACSTR, MAC2STR(mgmt->sa)); HASH_FIND(hh,mana_machash, mgmt->sa, 6, newsta); if (newsta == NULL) { //MAC not seen before adding to hash wpa_printf(MSG_DEBUG, "MANA - Adding SSID %s(%d) for STA " MACSTR " to the hash.", wpa_ssid_txt(elems.ssid, elems.ssid_len), elems.ssid_len, MAC2STR(mgmt->sa)); //Add STA newsta = (struct mana_mac*)os_malloc(sizeof(struct mana_mac)); os_memcpy(newsta->sta_addr, mgmt->sa, ETH_ALEN); //os_memcpy(newsta->mac_txt, strmac, sizeof(strmac)); newsta->ssids = NULL; HASH_ADD(hh,mana_machash, sta_addr, 6, newsta); //Add SSID to subhash struct mana_ssid *newssid = os_malloc(sizeof(struct mana_ssid)); os_memcpy(newssid->ssid_txt, wpa_ssid_txt(elems.ssid, elems.ssid_len), elems.ssid_len+1); os_memcpy(newssid->ssid, elems.ssid, elems.ssid_len); newssid->ssid_len = elems.ssid_len; HASH_ADD_STR(newsta->ssids, ssid_txt, newssid); log_ssid(elems.ssid, elems.ssid_len, mgmt->sa); } else { //Seen MAC, check if SSID is new // Check if the SSID probed for is in the hash for this STA struct mana_ssid *newssid = NULL; HASH_FIND_STR(newsta->ssids, wpa_ssid_txt(elems.ssid, elems.ssid_len), newssid); if (newssid == NULL) { //SSID not found, add to sub hash newssid = (struct mana_ssid*)os_malloc(sizeof(struct mana_ssid)); os_memcpy(newssid->ssid_txt, wpa_ssid_txt(elems.ssid, elems.ssid_len), elems.ssid_len+1); os_memcpy(newssid->ssid, elems.ssid, elems.ssid_len); newssid->ssid_len = elems.ssid_len; HASH_ADD_STR(newsta->ssids, ssid_txt, newssid); log_ssid(elems.ssid, elems.ssid_len, mgmt->sa); } } } } else { //No SSID Match and no Mana behave as normal if (!(mgmt->da[0] & 0x01)) { wpa_printf(MSG_DEBUG, "Probe Request from " MACSTR " for foreign SSID '%s' (DA " MACSTR ")%s", MAC2STR(mgmt->sa), wpa_ssid_txt(elems.ssid, elems.ssid_len), MAC2STR(mgmt->da), elems.ssid_list ? " (SSID list)" : ""); } return; } } else { //Probed for wildcard i.e. WILDCARD_SSID_MATCH if (hapd->iconf->enable_mana) { wpa_printf(MSG_DEBUG,"MANA - Broadcast probe request from " MACSTR "",MAC2STR(mgmt->sa)); iterate = 1; //iterate through hash emitting multiple probe responses } if (sta) sta->ssid_probe = &hapd->conf->ssid; } #ifdef CONFIG_INTERWORKING if (hapd->conf->interworking && elems.interworking && elems.interworking_len >= 1) { u8 ant = elems.interworking[0] & 0x0f; if (ant != INTERWORKING_ANT_WILDCARD && ant != hapd->conf->access_network_type) { wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR " for mismatching ANT %u ignored", MAC2STR(mgmt->sa), ant); return; } } if (hapd->conf->interworking && elems.interworking && (elems.interworking_len == 7 || elems.interworking_len == 9)) { const u8 *hessid; if (elems.interworking_len == 7) hessid = elems.interworking + 1; else hessid = elems.interworking + 1 + 2; if (!is_broadcast_ether_addr(hessid) && os_memcmp(hessid, hapd->conf->hessid, ETH_ALEN) != 0) { wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR " for mismatching HESSID " MACSTR " ignored", MAC2STR(mgmt->sa), MAC2STR(hessid)); return; } } #endif /* CONFIG_INTERWORKING */ #ifdef CONFIG_P2P if ((hapd->conf->p2p & P2P_GROUP_OWNER) && supp_rates_11b_only(&elems)) { /* Indicates support for 11b rates only */ wpa_printf(MSG_EXCESSIVE, "P2P: Ignore Probe Request from " MACSTR " with only 802.11b rates", MAC2STR(mgmt->sa)); return; } #endif /* CONFIG_P2P */ /* TODO: verify that supp_rates contains at least one matching rate * with AP configuration */ #ifdef CONFIG_TESTING_OPTIONS if (hapd->iconf->ignore_probe_probability > 0.0 && drand48() < hapd->iconf->ignore_probe_probability) { wpa_printf(MSG_INFO, "TESTING: ignoring probe request from " MACSTR, MAC2STR(mgmt->sa)); return; } #endif /* CONFIG_TESTING_OPTIONS */ resp = hostapd_gen_probe_resp(hapd, sta, elems.ssid, elems.ssid_len, mgmt, elems.p2p != NULL, &resp_len); if (resp == NULL) return; /* * If this is a broadcast probe request, apply no ack policy to avoid * excessive retries. */ noack = !!(res == WILDCARD_SSID_MATCH && is_broadcast_ether_addr(mgmt->da)); if (hostapd_drv_send_mlme(hapd, resp, resp_len, noack) < 0) wpa_printf(MSG_INFO, "handle_probe_req: send failed"); os_free(resp); if (iterate) { // Only iterate through the hash if this is set struct ieee80211_mgmt *resp2; size_t resp2_len; struct mana_ssid *k; if (hapd->iconf->mana_loud) { for ( k = mana_ssidhash; k != NULL; k = (struct mana_ssid*)(k->hh.next)) { wpa_printf(MSG_DEBUG, "MANA - Attempting to generate LOUD Broadcast response : %s (%zu) for STA " MACSTR, k->ssid_txt, k->ssid_len, MAC2STR(mgmt->sa)); resp2 = (struct ieee80211_mgmt*)hostapd_gen_probe_resp(hapd, sta, k->ssid, k->ssid_len, mgmt, elems.p2p != NULL, &resp2_len); if (resp2 == NULL) { wpa_printf(MSG_ERROR, "MANA - Could not generate SSID response for %s (%zu)", k->ssid_txt, k->ssid_len); } else { wpa_printf(MSG_DEBUG, "MANA - Successfully generated SSID response for %s (len %zu) to station : " MACSTR, k->ssid_txt, k->ssid_len, MAC2STR(resp2->da)); if (hostapd_drv_send_mlme(hapd, resp2, resp2_len, noack) < 0) { wpa_printf(MSG_ERROR, "MANA - Failed sending prove response for SSID %s (%zu)", k->ssid_txt, k->ssid_len); } os_free(resp2); } } } else { //Not loud mode, only send for one mac struct mana_mac *newsta = NULL; char strmac[18]; snprintf(strmac, sizeof(strmac), MACSTR, MAC2STR(mgmt->sa)); HASH_FIND(hh, mana_machash, mgmt->sa, 6, newsta); if (newsta != NULL) { for ( k = newsta->ssids; k != NULL; k = (struct mana_ssid*)(k->hh.next)) { wpa_printf(MSG_INFO, "MANA - Attempting to generated Broadcast response : %s (%zu) for STA %s", k->ssid_txt, k->ssid_len, strmac); resp2 = (struct ieee80211_mgmt*)hostapd_gen_probe_resp(hapd, sta, k->ssid, k->ssid_len, mgmt, elems.p2p != NULL, &resp2_len); if (resp2 == NULL) { wpa_printf(MSG_ERROR, "MANA - Could not generate SSID response for %s (%zu)", k->ssid_txt, k->ssid_len); } else { wpa_printf(MSG_DEBUG, "MANA - Successfully generated SSID response for %s (len %zu) to station : " MACSTR, k->ssid_txt, k->ssid_len, MAC2STR(resp2->da)); if (hostapd_drv_send_mlme(hapd, resp2, resp2_len, noack) < 0) { wpa_printf(MSG_ERROR, "MANA - Failed sending prove response for SSID %s (%zu)", k->ssid_txt, k->ssid_len); } os_free(resp2); } } } } } wpa_printf(MSG_EXCESSIVE, "STA " MACSTR " sent probe request for %s " "SSID", MAC2STR(mgmt->sa), elems.ssid_len == 0 ? "broadcast" : "our"); }
int radius_msg_add_mppe_keys(struct radius_msg *msg, const u8 *req_authenticator, const u8 *secret, size_t secret_len, const u8 *send_key, size_t send_key_len, const u8 *recv_key, size_t recv_key_len) { struct radius_attr_hdr *attr; u32 vendor_id = htonl(RADIUS_VENDOR_ID_MICROSOFT); u8 *buf; struct radius_attr_vendor *vhdr; u8 *pos; size_t elen; int hlen; u16 salt; hlen = sizeof(vendor_id) + sizeof(*vhdr) + 2; /* MS-MPPE-Send-Key */ buf = os_malloc(hlen + send_key_len + 16); if (buf == NULL) { return 0; } pos = buf; os_memcpy(pos, &vendor_id, sizeof(vendor_id)); pos += sizeof(vendor_id); vhdr = (struct radius_attr_vendor *) pos; vhdr->vendor_type = RADIUS_VENDOR_ATTR_MS_MPPE_SEND_KEY; pos = (u8 *) (vhdr + 1); salt = os_random() | 0x8000; WPA_PUT_BE16(pos, salt); pos += 2; encrypt_ms_key(send_key, send_key_len, salt, req_authenticator, secret, secret_len, pos, &elen); vhdr->vendor_length = hlen + elen - sizeof(vendor_id); attr = radius_msg_add_attr(msg, RADIUS_ATTR_VENDOR_SPECIFIC, buf, hlen + elen); os_free(buf); if (attr == NULL) { return 0; } /* MS-MPPE-Recv-Key */ buf = os_malloc(hlen + send_key_len + 16); if (buf == NULL) { return 0; } pos = buf; os_memcpy(pos, &vendor_id, sizeof(vendor_id)); pos += sizeof(vendor_id); vhdr = (struct radius_attr_vendor *) pos; vhdr->vendor_type = RADIUS_VENDOR_ATTR_MS_MPPE_RECV_KEY; pos = (u8 *) (vhdr + 1); salt ^= 1; WPA_PUT_BE16(pos, salt); pos += 2; encrypt_ms_key(recv_key, recv_key_len, salt, req_authenticator, secret, secret_len, pos, &elen); vhdr->vendor_length = hlen + elen - sizeof(vendor_id); attr = radius_msg_add_attr(msg, RADIUS_ATTR_VENDOR_SPECIFIC, buf, hlen + elen); os_free(buf); if (attr == NULL) { return 0; } return 1; }
static u8 * tls_conn_hs_clienthello(struct tls_global *global, struct tls_connection *conn, size_t *out_len) { DWORD sspi_flags, sspi_flags_out; SecBufferDesc outbuf; SecBuffer outbufs[1]; SECURITY_STATUS status; TimeStamp ts_expiry; sspi_flags = ISC_REQ_REPLAY_DETECT | ISC_REQ_CONFIDENTIALITY | ISC_RET_EXTENDED_ERROR | ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_MANUAL_CRED_VALIDATION; wpa_printf(MSG_DEBUG, "%s: Generating ClientHello", __func__); outbufs[0].pvBuffer = NULL; outbufs[0].BufferType = SECBUFFER_TOKEN; outbufs[0].cbBuffer = 0; outbuf.cBuffers = 1; outbuf.pBuffers = outbufs; outbuf.ulVersion = SECBUFFER_VERSION; #ifdef UNICODE status = global->sspi->InitializeSecurityContextW( &conn->creds, NULL, NULL /* server name */, sspi_flags, 0, SECURITY_NATIVE_DREP, NULL, 0, &conn->context, &outbuf, &sspi_flags_out, &ts_expiry); #else /* UNICODE */ status = global->sspi->InitializeSecurityContextA( &conn->creds, NULL, NULL /* server name */, sspi_flags, 0, SECURITY_NATIVE_DREP, NULL, 0, &conn->context, &outbuf, &sspi_flags_out, &ts_expiry); #endif /* UNICODE */ if (status != SEC_I_CONTINUE_NEEDED) { wpa_printf(MSG_ERROR, "%s: InitializeSecurityContextA " "failed - 0x%x", __func__, (unsigned int) status); return NULL; } if (outbufs[0].cbBuffer != 0 && outbufs[0].pvBuffer) { u8 *buf; wpa_hexdump(MSG_MSGDUMP, "SChannel - ClientHello", outbufs[0].pvBuffer, outbufs[0].cbBuffer); conn->start = 0; *out_len = outbufs[0].cbBuffer; buf = os_malloc(*out_len); if (buf == NULL) return NULL; os_memcpy(buf, outbufs[0].pvBuffer, *out_len); global->sspi->FreeContextBuffer(outbufs[0].pvBuffer); return buf; } wpa_printf(MSG_ERROR, "SChannel: Failed to generate ClientHello"); return NULL; }
/** * radius_msg_get_tunnel_password - Parse RADIUS attribute Tunnel-Password * @msg: Received RADIUS message * @keylen: Length of returned password * @secret: RADIUS shared secret * @secret_len: Length of secret * @sent_msg: Sent RADIUS message * Returns: pointer to password (free with os_free) or %NULL */ char * radius_msg_get_tunnel_password(struct radius_msg *msg, int *keylen, const u8 *secret, size_t secret_len, struct radius_msg *sent_msg) { u8 *buf = NULL; size_t buflen; const u8 *salt; u8 *str; const u8 *addr[3]; size_t len[3]; u8 hash[16]; u8 *pos; size_t i; struct radius_attr_hdr *attr; const u8 *data; size_t dlen; const u8 *fdata = NULL; /* points to found item */ size_t fdlen = -1; char *ret = NULL; /* find attribute with lowest tag and check it */ for (i = 0; i < msg->attr_used; i++) { attr = radius_get_attr_hdr(msg, i); if (attr == NULL || attr->type != RADIUS_ATTR_TUNNEL_PASSWORD) { continue; } if (attr->length <= 5) continue; data = (const u8 *) (attr + 1); dlen = attr->length - sizeof(*attr); if (dlen <= 3 || dlen % 16 != 3) continue; if (fdata != NULL && fdata[0] <= data[0]) continue; fdata = data; fdlen = dlen; } if (fdata == NULL) goto out; /* alloc writable memory for decryption */ buf = os_malloc(fdlen); if (buf == NULL) goto out; os_memcpy(buf, fdata, fdlen); buflen = fdlen; /* init pointers */ salt = buf + 1; str = buf + 3; /* decrypt blocks */ pos = buf + buflen - 16; /* last block */ while (pos >= str + 16) { /* all but the first block */ addr[0] = secret; len[0] = secret_len; addr[1] = pos - 16; len[1] = 16; md5_vector(2, addr, len, hash); for (i = 0; i < 16; i++) pos[i] ^= hash[i]; pos -= 16; } /* decrypt first block */ if (str != pos) goto out; addr[0] = secret; len[0] = secret_len; addr[1] = sent_msg->hdr->authenticator; len[1] = 16; addr[2] = salt; len[2] = 2; md5_vector(3, addr, len, hash); for (i = 0; i < 16; i++) pos[i] ^= hash[i]; /* derive plaintext length from first subfield */ *keylen = (unsigned char) str[0]; if ((u8 *) (str + *keylen) >= (u8 *) (buf + buflen)) { /* decryption error - invalid key length */ goto out; } if (*keylen == 0) { /* empty password */ goto out; } /* copy passphrase into new buffer */ ret = os_malloc(*keylen); if (ret) os_memcpy(ret, str + 1, *keylen); out: /* return new buffer */ os_free(buf); return ret; }
int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len, void (*msg_cb)(char *msg, size_t len)) { struct timeval tv; int res; fd_set rfds; const char *_cmd; char *cmd_buf = NULL; size_t _cmd_len; #ifdef CONFIG_CTRL_IFACE_UDP if (ctrl->cookie) { char *pos; _cmd_len = os_strlen(ctrl->cookie) + 1 + cmd_len; cmd_buf = os_malloc(_cmd_len); if (cmd_buf == NULL) return -1; _cmd = cmd_buf; pos = cmd_buf; os_strlcpy(pos, ctrl->cookie, _cmd_len); pos += os_strlen(ctrl->cookie); *pos++ = ' '; os_memcpy(pos, cmd, cmd_len); } else #endif /* CONFIG_CTRL_IFACE_UDP */ { _cmd = cmd; _cmd_len = cmd_len; } if (send(ctrl->s, _cmd, _cmd_len, 0) < 0) { os_free(cmd_buf); return -1; } os_free(cmd_buf); for (;;) { tv.tv_sec = 10; tv.tv_usec = 0; FD_ZERO(&rfds); FD_SET(ctrl->s, &rfds); res = select(ctrl->s + 1, &rfds, NULL, NULL, &tv); if (res < 0) return res; if (FD_ISSET(ctrl->s, &rfds)) { res = recv(ctrl->s, reply, *reply_len, 0); if (res < 0) return res; if (res > 0 && reply[0] == '<') { /* This is an unsolicited message from * wpa_supplicant, not the reply to the * request. Use msg_cb to report this to the * caller. */ if (msg_cb) { /* Make sure the message is nul * terminated. */ if ((size_t) res == *reply_len) res = (*reply_len) - 1; reply[res] = '\0'; msg_cb(reply, res); } continue; } *reply_len = res; break; } else { return -2; } } return 0; }
static u8 * decrypt_ms_key(const u8 *key, size_t len, const u8 *req_authenticator, const u8 *secret, size_t secret_len, size_t *reslen) { u8 *plain, *ppos, *res; const u8 *pos; size_t left, plen; u8 hash[MD5_MAC_LEN]; int i, first = 1; const u8 *addr[3]; size_t elen[3]; /* key: 16-bit salt followed by encrypted key info */ if (len < 2 + 16) return NULL; pos = key + 2; left = len - 2; if (left % 16) { printf("Invalid ms key len %lu\n", (unsigned long) left); return NULL; } plen = left; ppos = plain = os_malloc(plen); if (plain == NULL) return NULL; plain[0] = 0; while (left > 0) { /* b(1) = MD5(Secret + Request-Authenticator + Salt) * b(i) = MD5(Secret + c(i - 1)) for i > 1 */ addr[0] = secret; elen[0] = secret_len; if (first) { addr[1] = req_authenticator; elen[1] = MD5_MAC_LEN; addr[2] = key; elen[2] = 2; /* Salt */ } else { addr[1] = pos - MD5_MAC_LEN; elen[1] = MD5_MAC_LEN; } md5_vector(first ? 3 : 2, addr, elen, hash); first = 0; for (i = 0; i < MD5_MAC_LEN; i++) *ppos++ = *pos++ ^ hash[i]; left -= MD5_MAC_LEN; } if (plain[0] == 0 || plain[0] > plen - 1) { printf("Failed to decrypt MPPE key\n"); os_free(plain); return NULL; } res = os_malloc(plain[0]); if (res == NULL) { os_free(plain); return NULL; } os_memcpy(res, plain + 1, plain[0]); if (reslen) *reslen = plain[0]; os_free(plain); return res; }
static void eap_sake_process_challenge(struct eap_sm *sm, struct eap_sake_data *data, const struct wpabuf *respData, const u8 *payload, size_t payloadlen) { struct eap_sake_parse_attr attr; u8 mic_p[EAP_SAKE_MIC_LEN]; if (data->state != CHALLENGE) return; wpa_printf(MSG_DEBUG, "EAP-SAKE: Received Response/Challenge"); if (eap_sake_parse_attributes(payload, payloadlen, &attr)) return; if (!attr.rand_p || !attr.mic_p) { wpa_printf(MSG_INFO, "EAP-SAKE: Response/Challenge did not " "include AT_RAND_P or AT_MIC_P"); return; } os_memcpy(data->rand_p, attr.rand_p, EAP_SAKE_RAND_LEN); os_free(data->peerid); data->peerid = NULL; data->peerid_len = 0; if (attr.peerid) { data->peerid = os_malloc(attr.peerid_len); if (data->peerid == NULL) return; os_memcpy(data->peerid, attr.peerid, attr.peerid_len); data->peerid_len = attr.peerid_len; } if (sm->user == NULL || sm->user->password == NULL || sm->user->password_len != 2 * EAP_SAKE_ROOT_SECRET_LEN) { wpa_printf(MSG_INFO, "EAP-SAKE: Plaintext password with " "%d-byte key not configured", 2 * EAP_SAKE_ROOT_SECRET_LEN); data->state = FAILURE; return; } eap_sake_derive_keys(sm->user->password, sm->user->password + EAP_SAKE_ROOT_SECRET_LEN, data->rand_s, data->rand_p, (u8 *) &data->tek, data->msk, data->emsk); eap_sake_compute_mic(data->tek.auth, data->rand_s, data->rand_p, data->serverid, data->serverid_len, data->peerid, data->peerid_len, 1, wpabuf_head(respData), wpabuf_len(respData), attr.mic_p, mic_p); if (os_memcmp(attr.mic_p, mic_p, EAP_SAKE_MIC_LEN) != 0) { wpa_printf(MSG_INFO, "EAP-SAKE: Incorrect AT_MIC_P"); eap_sake_state(data, FAILURE); return; } eap_sake_state(data, CONFIRM); }
static int eap_gpsk_derive_keys_helper(u32 csuite_specifier, u8 *kdf_out, size_t kdf_out_len, const u8 *psk, size_t psk_len, const u8 *seed, size_t seed_len, u8 *msk, u8 *emsk, u8 *sk, size_t sk_len, u8 *pk, size_t pk_len) { u8 mk[32], *pos, *data; size_t data_len, mk_len; int (*gkdf)(const u8 *_psk, const u8 *_data, size_t _data_len, u8 *buf, size_t len); gkdf = NULL; switch (csuite_specifier) { case EAP_GPSK_CIPHER_AES: gkdf = eap_gpsk_gkdf_cmac; mk_len = 16; break; #ifdef EAP_GPSK_SHA256 case EAP_GPSK_CIPHER_SHA256: gkdf = eap_gpsk_gkdf_sha256; mk_len = SHA256_MAC_LEN; break; #endif /* EAP_GPSK_SHA256 */ default: return -1; } if (psk_len < mk_len) return -1; data_len = 2 + psk_len + 6 + seed_len; data = os_malloc(data_len); if (data == NULL) return -1; pos = data; WPA_PUT_BE16(pos, psk_len); pos += 2; os_memcpy(pos, psk, psk_len); pos += psk_len; WPA_PUT_BE32(pos, EAP_GPSK_VENDOR_IETF); /* CSuite/Vendor = IETF */ pos += 4; WPA_PUT_BE16(pos, csuite_specifier); /* CSuite/Specifier */ pos += 2; os_memcpy(pos, seed, seed_len); /* inputString */ wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: Data to MK derivation", data, data_len); if (gkdf(psk, data, data_len, mk, mk_len) < 0) { os_free(data); return -1; } os_free(data); wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: MK", mk, mk_len); if (gkdf(mk, seed, seed_len, kdf_out, kdf_out_len) < 0) return -1; pos = kdf_out; wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: MSK", pos, EAP_MSK_LEN); os_memcpy(msk, pos, EAP_MSK_LEN); pos += EAP_MSK_LEN; wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: EMSK", pos, EAP_EMSK_LEN); os_memcpy(emsk, pos, EAP_EMSK_LEN); pos += EAP_EMSK_LEN; wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: SK", pos, sk_len); os_memcpy(sk, pos, sk_len); pos += sk_len; if (pk) { wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: PK", pos, pk_len); os_memcpy(pk, pos, pk_len); } return 0; }
int sandbox_write_state(struct sandbox_state *state, const char *fname) { struct sandbox_state_io *io; bool got_err; int size; int ret; int fd; /* Create a state FDT if we don't have one */ if (!state->state_fdt) { size = 0x4000; state->state_fdt = os_malloc(size); if (!state->state_fdt) { puts("No memory to create FDT\n"); return -ENOMEM; } ret = fdt_create_empty_tree(state->state_fdt, size); if (ret < 0) { printf("Cannot create empty state FDT: %s\n", fdt_strerror(ret)); ret = -EIO; goto err_create; } } /* Call all the state write funtcions */ got_err = false; io = ll_entry_start(struct sandbox_state_io, state_io); ret = 0; for (; io < ll_entry_end(struct sandbox_state_io, state_io); io++) { ret = sandbox_write_state_node(state, io); if (ret == -EIO) break; else if (ret) got_err = true; } if (ret == -EIO) { printf("Could not write sandbox state\n"); goto err_create; } ret = fdt_pack(state->state_fdt); if (ret < 0) { printf("Cannot pack state FDT: %s\n", fdt_strerror(ret)); ret = -EINVAL; goto err_create; } size = fdt_totalsize(state->state_fdt); fd = os_open(fname, OS_O_WRONLY | OS_O_CREAT); if (fd < 0) { printf("Cannot open sandbox state file '%s'\n", fname); ret = -EIO; goto err_create; } if (os_write(fd, state->state_fdt, size) != size) { printf("Cannot write sandbox state file '%s'\n", fname); ret = -EIO; goto err_write; } os_close(fd); debug("Wrote sandbox state to '%s'%s\n", fname, got_err ? " (with errors)" : ""); return 0; err_write: os_close(fd); err_create: os_free(state->state_fdt); return ret; }
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; }