static struct wpabuf * eap_ikev2_buildReq(struct eap_sm *sm, void *priv, u8 id) { struct eap_ikev2_data *data = priv; switch (data->state) { case MSG: if (data->out_buf == NULL) { data->out_buf = ikev2_initiator_build(&data->ikev2); if (data->out_buf == NULL) { wpa_printf(MSG_DEBUG, "EAP-IKEV2: Failed to " "generate IKEv2 message"); return NULL; } data->out_used = 0; } /* pass through */ case WAIT_FRAG_ACK: return eap_ikev2_build_msg(data, id); case FRAG_ACK: return eap_ikev2_build_frag_ack(id, EAP_CODE_REQUEST); default: wpa_printf(MSG_DEBUG, "EAP-IKEV2: Unexpected state %d in " "buildReq", data->state); return NULL; } }
static struct wpabuf * eap_ikev2_process(struct eap_sm *sm, void *priv, struct eap_method_ret *ret, const struct wpabuf *reqData) { struct eap_ikev2_data *data = priv; const u8 *start, *pos, *end; size_t len; u8 flags, id; u32 message_length = 0; struct wpabuf tmpbuf; pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_IKEV2, reqData, &len); if (pos == NULL) { ret->ignore = TRUE; return NULL; } id = eap_get_id(reqData); start = pos; end = start + len; if (len == 0) flags = 0; /* fragment ack */ else flags = *pos++; if (eap_ikev2_process_icv(data, reqData, flags, pos, &end) < 0) { ret->ignore = TRUE; return NULL; } if (flags & IKEV2_FLAGS_LENGTH_INCLUDED) { if (end - pos < 4) { wpa_printf(MSG_DEBUG, "EAP-IKEV2: Message underflow"); ret->ignore = TRUE; return NULL; } message_length = WPA_GET_BE32(pos); pos += 4; if (message_length < (u32) (end - pos)) { wpa_printf(MSG_DEBUG, "EAP-IKEV2: Invalid Message " "Length (%d; %ld remaining in this msg)", message_length, (long) (end - pos)); ret->ignore = TRUE; return NULL; } } wpa_printf(MSG_DEBUG, "EAP-IKEV2: Received packet: Flags 0x%x " "Message Length %u", flags, message_length); if (data->state == WAIT_FRAG_ACK) { #ifdef CCNS_PL if (len > 1) /* Empty Flags field included in ACK */ #else /* CCNS_PL */ if (len != 0) #endif /* CCNS_PL */ { wpa_printf(MSG_DEBUG, "EAP-IKEV2: Unexpected payload " "in WAIT_FRAG_ACK state"); ret->ignore = TRUE; return NULL; } wpa_printf(MSG_DEBUG, "EAP-IKEV2: Fragment acknowledged"); eap_ikev2_state(data, PROC_MSG); return eap_ikev2_build_msg(data, ret, id); } if (data->in_buf && eap_ikev2_process_cont(data, pos, end - pos) < 0) { ret->ignore = TRUE; return NULL; } if (flags & IKEV2_FLAGS_MORE_FRAGMENTS) { return eap_ikev2_process_fragment(data, ret, id, flags, message_length, pos, end - pos); } if (data->in_buf == NULL) { /* Wrap unfragmented messages as wpabuf without extra copy */ wpabuf_set(&tmpbuf, pos, end - pos); data->in_buf = &tmpbuf; } if (ikev2_responder_process(&data->ikev2, data->in_buf) < 0) { if (data->in_buf == &tmpbuf) data->in_buf = NULL; eap_ikev2_state(data, FAIL); return NULL; } if (data->in_buf != &tmpbuf) wpabuf_free(data->in_buf); data->in_buf = NULL; if (data->out_buf == NULL) { data->out_buf = ikev2_responder_build(&data->ikev2); if (data->out_buf == NULL) { wpa_printf(MSG_DEBUG, "EAP-IKEV2: Failed to generate " "IKEv2 message"); return NULL; } data->out_used = 0; } eap_ikev2_state(data, PROC_MSG); return eap_ikev2_build_msg(data, ret, id); }