/** * eap_tls_process_output - Process outgoing TLS message * @data: Data for TLS processing * @eap_type: EAP type (EAP_TYPE_TLS, EAP_TYPE_PEAP, ...) * @peap_version: Version number for EAP-PEAP/TTLS * @id: EAP identifier for the response * @ret: Return value to use on success * @out_data: Buffer for returning the allocated output buffer * Returns: ret (0 or 1) on success, -1 on failure */ static int eap_tls_process_output(struct eap_ssl_data *data, EapType eap_type, int peap_version, u8 id, int ret, struct wpabuf **out_data) { size_t len; u8 *flags; int more_fragments, length_included; if (data->tls_out == NULL) return -1; len = wpabuf_len(data->tls_out) - data->tls_out_pos; wpa_printf(MSG_DEBUG, "SSL: %lu bytes left to be sent out (of total " "%lu bytes)", (unsigned long) len, (unsigned long) wpabuf_len(data->tls_out)); /* * Limit outgoing message to the configured maximum size. Fragment * message if needed. */ if (len > data->tls_out_limit) { more_fragments = 1; len = data->tls_out_limit; wpa_printf(MSG_DEBUG, "SSL: sending %lu bytes, more fragments " "will follow", (unsigned long) len); } else more_fragments = 0; length_included = data->tls_out_pos == 0 && (wpabuf_len(data->tls_out) > data->tls_out_limit || data->include_tls_length); if (!length_included && eap_type == EAP_TYPE_PEAP && peap_version == 0 && !tls_connection_established(data->eap->ssl_ctx, data->conn)) { /* * Windows Server 2008 NPS really wants to have the TLS Message * length included in phase 0 even for unfragmented frames or * it will get very confused with Compound MAC calculation and * Outer TLVs. */ length_included = 1; } *out_data = eap_msg_alloc(EAP_VENDOR_IETF, eap_type, 1 + length_included * 4 + len, EAP_CODE_RESPONSE, id); if (*out_data == NULL) return -1; flags = wpabuf_put(*out_data, 1); *flags = peap_version; if (more_fragments) *flags |= EAP_TLS_FLAGS_MORE_FRAGMENTS; if (length_included) { *flags |= EAP_TLS_FLAGS_LENGTH_INCLUDED; wpabuf_put_be32(*out_data, wpabuf_len(data->tls_out)); } wpabuf_put_data(*out_data, wpabuf_head_u8(data->tls_out) + data->tls_out_pos, len); data->tls_out_pos += len; if (!more_fragments) eap_peer_tls_reset_output(data); return ret; }
static struct wpabuf * eap_ikev2_build_msg(struct eap_ikev2_data *data, u8 id) { struct wpabuf *req; u8 flags; size_t send_len, plen, icv_len = 0; wpa_printf(MSG_DEBUG, "EAP-IKEV2: Generating Request"); flags = 0; send_len = wpabuf_len(data->out_buf) - data->out_used; if (1 + send_len > data->fragment_size) { send_len = data->fragment_size - 1; flags |= IKEV2_FLAGS_MORE_FRAGMENTS; if (data->out_used == 0) { flags |= IKEV2_FLAGS_LENGTH_INCLUDED; send_len -= 4; } } plen = 1 + send_len; if (flags & IKEV2_FLAGS_LENGTH_INCLUDED) plen += 4; if (data->keys_ready) { const struct ikev2_integ_alg *integ; wpa_printf(MSG_DEBUG, "EAP-IKEV2: Add Integrity Checksum " "Data"); flags |= IKEV2_FLAGS_ICV_INCLUDED; integ = ikev2_get_integ(data->ikev2.proposal.integ); if (integ == NULL) { wpa_printf(MSG_DEBUG, "EAP-IKEV2: Unknown INTEG " "transform / cannot generate ICV"); return NULL; } icv_len = integ->hash_len; plen += icv_len; } req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IKEV2, plen, EAP_CODE_REQUEST, id); if (req == NULL) return NULL; wpabuf_put_u8(req, flags); /* Flags */ if (flags & IKEV2_FLAGS_LENGTH_INCLUDED) wpabuf_put_be32(req, wpabuf_len(data->out_buf)); wpabuf_put_data(req, wpabuf_head_u8(data->out_buf) + data->out_used, send_len); data->out_used += send_len; if (flags & IKEV2_FLAGS_ICV_INCLUDED) { const u8 *msg = wpabuf_head(req); size_t len = wpabuf_len(req); ikev2_integ_hash(data->ikev2.proposal.integ, data->ikev2.keys.SK_ai, data->ikev2.keys.SK_integ_len, msg, len, wpabuf_put(req, icv_len)); } if (data->out_used == wpabuf_len(data->out_buf)) { wpa_printf(MSG_DEBUG, "EAP-IKEV2: Sending out %lu bytes " "(message sent completely)", (unsigned long) send_len); wpabuf_free(data->out_buf); data->out_buf = NULL; data->out_used = 0; } else { wpa_printf(MSG_DEBUG, "EAP-IKEV2: Sending out %lu bytes " "(%lu more to send)", (unsigned long) send_len, (unsigned long) wpabuf_len(data->out_buf) - data->out_used); eap_ikev2_state(data, WAIT_FRAG_ACK); } return req; }
static struct wpabuf * eap_gtc_process(struct eap_sm *sm, void *priv, struct eap_method_ret *ret, const struct wpabuf *reqData) { struct eap_gtc_data *data = priv; struct wpabuf *resp; const u8 *pos, *password, *identity; size_t password_len, identity_len, len, plen; int otp; u8 id; pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GTC, reqData, &len); if (pos == NULL) { ret->ignore = TRUE; return NULL; } id = eap_get_id(reqData); wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-GTC: Request message", pos, len); if (data->prefix && (len < 10 || os_memcmp(pos, "CHALLENGE=", 10) != 0)) { wpa_printf(MSG_DEBUG, "EAP-GTC: Challenge did not start with " "expected prefix"); /* Send an empty response in order to allow tunneled * acknowledgement of the failure. This will also cover the * error case which seems to use EAP-MSCHAPv2 like error * reporting with EAP-GTC inside EAP-FAST tunnel. */ resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GTC, 0, EAP_CODE_RESPONSE, id); return resp; } password = eap_get_config_otp(sm, &password_len); if (password) otp = 1; else { password = eap_get_config_password(sm, &password_len); otp = 0; } if (password == NULL) { wpa_printf(MSG_INFO, "EAP-GTC: Password not configured"); eap_sm_request_otp(sm, (const char *) pos, len); ret->ignore = TRUE; return NULL; } ret->ignore = FALSE; ret->methodState = data->prefix ? METHOD_MAY_CONT : METHOD_DONE; ret->decision = DECISION_COND_SUCC; ret->allowNotifications = FALSE; plen = password_len; identity = eap_get_config_identity(sm, &identity_len); if (identity == NULL) return NULL; if (data->prefix) plen += 9 + identity_len + 1; resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GTC, plen, EAP_CODE_RESPONSE, id); if (resp == NULL) return NULL; if (data->prefix) { wpabuf_put_data(resp, "RESPONSE=", 9); wpabuf_put_data(resp, identity, identity_len); wpabuf_put_u8(resp, '\0'); } wpabuf_put_data(resp, password, password_len); wpa_hexdump_ascii_key(MSG_MSGDUMP, "EAP-GTC: Response", wpabuf_head_u8(resp) + sizeof(struct eap_hdr) + 1, plen); if (otp) { wpa_printf(MSG_DEBUG, "EAP-GTC: Forgetting used password"); eap_clear_config_otp(sm); } return resp; }
static struct wpabuf * eap_mschapv2_challenge_reply( struct eap_sm *sm, struct eap_mschapv2_data *data, u8 id, u8 mschapv2_id, const u8 *auth_challenge) { struct wpabuf *resp; struct eap_mschapv2_hdr *ms; u8 *peer_challenge; int ms_len; struct ms_response *r; size_t identity_len, password_len; const u8 *identity, *password; int pwhash; wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Generating Challenge Response"); identity = eap_get_config_identity(sm, &identity_len); password = eap_get_config_password2(sm, &password_len, &pwhash); if (identity == NULL || password == NULL) return NULL; ms_len = sizeof(*ms) + 1 + sizeof(*r) + identity_len; resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, ms_len, EAP_CODE_RESPONSE, id); if (resp == NULL) return NULL; ms = wpabuf_put(resp, sizeof(*ms)); ms->op_code = MSCHAPV2_OP_RESPONSE; ms->mschapv2_id = mschapv2_id; if (data->prev_error) { /* * TODO: this does not seem to be enough when processing two * or more failure messages. IAS did not increment mschapv2_id * in its own packets, but it seemed to expect the peer to * increment this for all packets(?). */ ms->mschapv2_id++; } WPA_PUT_BE16(ms->ms_length, ms_len); wpabuf_put_u8(resp, sizeof(*r)); /* Value-Size */ /* Response */ r = wpabuf_put(resp, sizeof(*r)); peer_challenge = r->peer_challenge; if (data->peer_challenge) { wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: peer_challenge generated " "in Phase 1"); peer_challenge = data->peer_challenge; os_memset(r->peer_challenge, 0, MSCHAPV2_CHAL_LEN); } else if (random_get_bytes(peer_challenge, MSCHAPV2_CHAL_LEN)) { wpabuf_free(resp); return NULL; } os_memset(r->reserved, 0, 8); if (data->auth_challenge) { wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: auth_challenge generated " "in Phase 1"); auth_challenge = data->auth_challenge; } if (mschapv2_derive_response(identity, identity_len, password, password_len, pwhash, auth_challenge, peer_challenge, r->nt_response, data->auth_response, data->master_key)) { wpa_printf(MSG_ERROR, "EAP-MSCHAPV2: Failed to derive " "response"); wpabuf_free(resp); return NULL; } data->auth_response_valid = 1; data->master_key_valid = 1; r->flags = 0; /* reserved, must be zero */ wpabuf_put_data(resp, identity, identity_len); wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: TX identifier %d mschapv2_id %d " "(response)", id, ms->mschapv2_id); return resp; }
/*----------------------------------------------------------------------------- Routine Name: wpa_driver_tista_set_probe_req_ie Routine Description: set probe request ie for WSC mode change Arguments: priv - pointer to private data structure ies - probe_req_ie data ies_len - ie data length Return Value: actual buffer length - success, -1 - failure -----------------------------------------------------------------------------*/ static int wpa_driver_tista_set_probe_req_ie(void *priv, const u8* ies, size_t ies_len) { struct wpa_driver_ti_data *drv = (struct wpa_driver_ti_data *)priv; #ifdef CONFIG_WPS TWscMode WscModeStruct; TI_CHECK_DRIVER( drv->driver_is_loaded, -1 ); if ((!ies || (0 == ies_len)) && (NULL == drv->probe_req_ie)) { return 0; } if (ies && drv->probe_req_ie) { size_t len = wpabuf_len(drv->probe_req_ie); u8* data = (u8*)wpabuf_head(drv->probe_req_ie); if ((ies_len == len) && (0 == os_memcmp(ies, data, ies_len))) { return 0; } } os_memset(&WscModeStruct, 0, sizeof(TWscMode)); if (!ies || (0 == ies_len)) { WscModeStruct.WSCMode = TIWLN_SIMPLE_CONFIG_OFF; } else { const size_t head_len = 6; /* probeReqIe head: dd xx 00 50 f2 04 */ u8 *pos, *end; u16 password_id = 0; size_t min_len = 0; pos = (u8*)ies + head_len; /* Find the WSC mode in probe_req_ie by password_id */ end = (u8*)ies + ies_len; while (pos < end) { if (ATTR_DEV_PASSWORD_ID == WPA_GET_BE16(pos)) { password_id = WPA_GET_BE16(pos+4); break; } pos += (4 + WPA_GET_BE16(pos+2)); } WscModeStruct.WSCMode = (DEV_PW_PUSHBUTTON == password_id)?TIWLN_SIMPLE_CONFIG_PBC_METHOD:TIWLN_SIMPLE_CONFIG_PIN_METHOD; pos = (u8*)ies + head_len; min_len = ies_len - head_len; if (min_len > sizeof(WscModeStruct.probeReqWSCIE)) { min_len = sizeof(WscModeStruct.probeReqWSCIE); } os_memcpy(WscModeStruct.probeReqWSCIE, pos, min_len); } wpa_hexdump(MSG_DEBUG, "SetProbeReqIe:WscModeStruct", (u8*)&WscModeStruct, sizeof(TWscMode)); if(0 == wpa_driver_tista_private_send(priv, SITE_MGR_SIMPLE_CONFIG_MODE, (void*)&WscModeStruct, sizeof(TWscMode), NULL, 0)) { /* Update the cached probe req ie */ wpabuf_free(drv->probe_req_ie); drv->probe_req_ie = NULL; if (ies && ies_len) { drv->probe_req_ie = wpabuf_alloc(sizeof(WscModeStruct.probeReqWSCIE)); if (drv->probe_req_ie) { wpabuf_put_data(drv->probe_req_ie, ies, ies_len); } } } else { wpa_printf(MSG_ERROR, "ERROR - Failed to set wsc mode!"); return -1; } #endif return 0; }