123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288 |
- #include "includes.h"
- #include "common.h"
- #include "eap_defs.h"
- #include "eap_common.h"
- int eap_hdr_len_valid(const struct wpabuf *msg, size_t min_payload)
- {
- const struct eap_hdr *hdr;
- size_t len;
- if (msg == NULL)
- return 0;
- hdr = wpabuf_head(msg);
- if (wpabuf_len(msg) < sizeof(*hdr)) {
- wpa_printf(MSG_INFO, "EAP: Too short EAP frame");
- return 0;
- }
- len = be_to_host16(hdr->length);
- if (len < sizeof(*hdr) + min_payload || len > wpabuf_len(msg)) {
- wpa_printf(MSG_INFO, "EAP: Invalid EAP length");
- return 0;
- }
- return 1;
- }
- const u8 * eap_hdr_validate(int vendor, EapType eap_type,
- const struct wpabuf *msg, size_t *plen)
- {
- const struct eap_hdr *hdr;
- const u8 *pos;
- size_t len;
- if (!eap_hdr_len_valid(msg, 1))
- return NULL;
- hdr = wpabuf_head(msg);
- len = be_to_host16(hdr->length);
- pos = (const u8 *) (hdr + 1);
- if (*pos == EAP_TYPE_EXPANDED) {
- int exp_vendor;
- u32 exp_type;
- if (len < sizeof(*hdr) + 8) {
- wpa_printf(MSG_INFO, "EAP: Invalid expanded EAP "
- "length");
- return NULL;
- }
- pos++;
- exp_vendor = WPA_GET_BE24(pos);
- pos += 3;
- exp_type = WPA_GET_BE32(pos);
- pos += 4;
- if (exp_vendor != vendor || exp_type != (u32) eap_type) {
- wpa_printf(MSG_INFO, "EAP: Invalid expanded frame "
- "type");
- return NULL;
- }
- *plen = len - sizeof(*hdr) - 8;
- return pos;
- } else {
- if (vendor != EAP_VENDOR_IETF || *pos != eap_type) {
- wpa_printf(MSG_INFO, "EAP: Invalid frame type");
- return NULL;
- }
- *plen = len - sizeof(*hdr) - 1;
- return pos + 1;
- }
- }
- struct wpabuf * eap_msg_alloc(int vendor, EapType type, size_t payload_len,
- u8 code, u8 identifier)
- {
- struct wpabuf *buf;
- struct eap_hdr *hdr;
- size_t len;
- len = sizeof(struct eap_hdr) + (vendor == EAP_VENDOR_IETF ? 1 : 8) +
- payload_len;
- buf = wpabuf_alloc(len);
- if (buf == NULL)
- return NULL;
- hdr = wpabuf_put(buf, sizeof(*hdr));
- hdr->code = code;
- hdr->identifier = identifier;
- hdr->length = host_to_be16(len);
- if (vendor == EAP_VENDOR_IETF) {
- wpabuf_put_u8(buf, type);
- } else {
- wpabuf_put_u8(buf, EAP_TYPE_EXPANDED);
- wpabuf_put_be24(buf, vendor);
- wpabuf_put_be32(buf, type);
- }
- return buf;
- }
- void eap_update_len(struct wpabuf *msg)
- {
- struct eap_hdr *hdr;
- hdr = wpabuf_mhead(msg);
- if (wpabuf_len(msg) < sizeof(*hdr))
- return;
- hdr->length = host_to_be16(wpabuf_len(msg));
- }
- u8 eap_get_id(const struct wpabuf *msg)
- {
- const struct eap_hdr *eap;
- if (wpabuf_len(msg) < sizeof(*eap))
- return 0;
- eap = wpabuf_head(msg);
- return eap->identifier;
- }
- EapType eap_get_type(const struct wpabuf *msg)
- {
- if (wpabuf_len(msg) < sizeof(struct eap_hdr) + 1)
- return EAP_TYPE_NONE;
- return ((const u8 *) wpabuf_head(msg))[sizeof(struct eap_hdr)];
- }
- #ifdef CONFIG_ERP
- int erp_parse_tlvs(const u8 *pos, const u8 *end, struct erp_tlvs *tlvs,
- int stop_at_keyname)
- {
- os_memset(tlvs, 0, sizeof(*tlvs));
- while (pos < end) {
- u8 tlv_type, tlv_len;
- tlv_type = *pos++;
- switch (tlv_type) {
- case EAP_ERP_TV_RRK_LIFETIME:
- case EAP_ERP_TV_RMSK_LIFETIME:
-
- if (pos + 4 > end) {
- wpa_printf(MSG_DEBUG, "EAP: Too short TV");
- return -1;
- }
- pos += 4;
- break;
- case EAP_ERP_TLV_DOMAIN_NAME:
- case EAP_ERP_TLV_KEYNAME_NAI:
- case EAP_ERP_TLV_CRYPTOSUITES:
- case EAP_ERP_TLV_AUTHORIZATION_INDICATION:
- case EAP_ERP_TLV_CALLED_STATION_ID:
- case EAP_ERP_TLV_CALLING_STATION_ID:
- case EAP_ERP_TLV_NAS_IDENTIFIER:
- case EAP_ERP_TLV_NAS_IP_ADDRESS:
- case EAP_ERP_TLV_NAS_IPV6_ADDRESS:
- if (pos >= end) {
- wpa_printf(MSG_DEBUG, "EAP: Too short TLV");
- return -1;
- }
- tlv_len = *pos++;
- if (tlv_len > (unsigned) (end - pos)) {
- wpa_printf(MSG_DEBUG, "EAP: Truncated TLV");
- return -1;
- }
- if (tlv_type == EAP_ERP_TLV_KEYNAME_NAI) {
- if (tlvs->keyname) {
- wpa_printf(MSG_DEBUG,
- "EAP: More than one keyName-NAI");
- return -1;
- }
- tlvs->keyname = pos;
- tlvs->keyname_len = tlv_len;
- if (stop_at_keyname)
- return 0;
- } else if (tlv_type == EAP_ERP_TLV_DOMAIN_NAME) {
- tlvs->domain = pos;
- tlvs->domain_len = tlv_len;
- }
- pos += tlv_len;
- break;
- default:
- if (tlv_type >= 128 && tlv_type <= 191) {
-
- if (pos >= end) {
- wpa_printf(MSG_DEBUG,
- "EAP: Too short TLV");
- return -1;
- }
- tlv_len = *pos++;
- if (tlv_len > (unsigned) (end - pos)) {
- wpa_printf(MSG_DEBUG,
- "EAP: Truncated TLV");
- return -1;
- }
- pos += tlv_len;
- break;
- }
- wpa_printf(MSG_DEBUG, "EAP: Unknown TV/TLV type %u",
- tlv_type);
- pos = end;
- break;
- }
- }
- return 0;
- }
- #endif
|