int eap_sim_msg_add_encr_end(struct eap_sim_msg *msg, u8 *k_encr, int attr_pad) { size_t encr_len; if (msg == NULL || k_encr == NULL || msg->iv == 0 || msg->encr == 0) return -1; encr_len = wpabuf_len(msg->buf) - msg->encr - 4; if (encr_len % 16) { u8 *pos; int pad_len = 16 - (encr_len % 16); if (pad_len < 4) { wpa_printf(MSG_WARNING, "EAP-SIM: " "eap_sim_msg_add_encr_end - invalid pad_len" " %d", pad_len); return -1; } wpa_printf(MSG_DEBUG, " *AT_PADDING"); pos = eap_sim_msg_add(msg, attr_pad, 0, NULL, pad_len - 4); if (pos == NULL) return -1; os_memset(pos + 4, 0, pad_len - 4); encr_len += pad_len; } wpa_printf(MSG_DEBUG, " (AT_ENCR_DATA data len %lu)", (unsigned long) encr_len); wpabuf_mhead_u8(msg->buf)[msg->encr + 1] = encr_len / 4 + 1; return aes_128_cbc_encrypt(k_encr, wpabuf_head_u8(msg->buf) + msg->iv, wpabuf_mhead_u8(msg->buf) + msg->encr + 4, encr_len); }
/** * gas_anqp_set_len - Set Query Request/Response Length * @buf: GAS message * * This function is used to update the Query Request/Response Length field once * the payload has been filled. */ void gas_anqp_set_len(struct wpabuf *buf) { u8 action; size_t offset; u8 *len; if (buf == NULL || wpabuf_len(buf) < 2) return; action = *(wpabuf_head_u8(buf) + 1); switch (action) { case WLAN_PA_GAS_INITIAL_REQ: offset = 3 + 4; break; case WLAN_PA_GAS_INITIAL_RESP: offset = 7 + 4; break; case WLAN_PA_GAS_COMEBACK_RESP: offset = 8 + 4; break; default: return; } if (wpabuf_len(buf) < offset + 2) return; len = wpabuf_mhead_u8(buf) + offset; WPA_PUT_LE16(len, (u8 *) wpabuf_put(buf, 0) - len - 2); }
static int gas_query_tx(struct gas_query *gas, struct gas_query_pending *query, struct wpabuf *req, unsigned int wait_time) { int res, prot = pmf_in_use(gas->wpa_s, query->addr); const u8 *bssid; const u8 wildcard_bssid[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; wpa_printf(MSG_DEBUG, "GAS: Send action frame to " MACSTR " len=%u " "freq=%d prot=%d", MAC2STR(query->addr), (unsigned int) wpabuf_len(req), query->freq, prot); if (prot) { u8 *categ = wpabuf_mhead_u8(req); *categ = WLAN_ACTION_PROTECTED_DUAL; } os_get_reltime(&query->last_oper); if (gas->wpa_s->max_remain_on_chan && wait_time > gas->wpa_s->max_remain_on_chan) wait_time = gas->wpa_s->max_remain_on_chan; if (!gas->wpa_s->conf->gas_address3 || (gas->wpa_s->current_ssid && gas->wpa_s->wpa_state >= WPA_ASSOCIATED && os_memcmp(query->addr, gas->wpa_s->bssid, ETH_ALEN) == 0)) bssid = query->addr; else bssid = wildcard_bssid; res = offchannel_send_action(gas->wpa_s, query->freq, query->addr, gas->wpa_s->own_addr, bssid, wpabuf_head(req), wpabuf_len(req), wait_time, gas_query_tx_status, 0); if (res == 0) query->offchannel_tx_started = 1; return res; }
static int gas_query_tx(struct gas_query *gas, struct gas_query_pending *query, struct wpabuf *req) { unsigned int wait_time; int res, prot = pmf_in_use(gas->wpa_s, query->addr); wpa_printf(MSG_DEBUG, "GAS: Send action frame to " MACSTR " len=%u " "freq=%d prot=%d", MAC2STR(query->addr), (unsigned int) wpabuf_len(req), query->freq, prot); if (prot) { u8 *categ = wpabuf_mhead_u8(req); *categ = WLAN_ACTION_PROTECTED_DUAL; } os_get_reltime(&query->last_oper); wait_time = 1000; if (gas->wpa_s->max_remain_on_chan && wait_time > gas->wpa_s->max_remain_on_chan) wait_time = gas->wpa_s->max_remain_on_chan; res = offchannel_send_action(gas->wpa_s, query->freq, query->addr, gas->wpa_s->own_addr, query->addr, wpabuf_head(req), wpabuf_len(req), wait_time, gas_query_tx_status, 0); if (res == 0) query->offchannel_tx_started = 1; return res; }
static void gas_query_rx_comeback_timeout(void *eloop_data, void *user_ctx) { struct gas_query *gas = eloop_data; struct gas_query_pending *query = user_ctx; int dialog_token; wpa_printf(MSG_DEBUG, "GAS: No response to comeback request received (retry=%u)", query->retry); if (gas->current != query || query->retry) return; dialog_token = gas_query_new_dialog_token(gas, query->addr); if (dialog_token < 0) return; wpa_printf(MSG_DEBUG, "GAS: Retry GAS query due to comeback response timeout"); query->retry = 1; query->dialog_token = dialog_token; *(wpabuf_mhead_u8(query->req) + 2) = dialog_token; query->wait_comeback = 0; query->next_frag_id = 0; wpabuf_free(query->adv_proto); query->adv_proto = NULL; eloop_cancel_timeout(gas_query_tx_comeback_timeout, gas, query); eloop_cancel_timeout(gas_query_timeout, gas, query); gas_query_tx_initial_req(gas, query); }
void * wpabuf_put(struct wpabuf *buf, size_t len) { void *tmp = wpabuf_mhead_u8(buf) + wpabuf_len(buf); buf->used += len; if (buf->used > buf->size) { wpabuf_overflow(buf, len); } return tmp; }
/** * dh_init - Initialize Diffie-Hellman handshake * @dh: Selected Diffie-Hellman group * @priv: Pointer for returning Diffie-Hellman private key * Returns: Diffie-Hellman public value */ struct wpabuf * dh_init(const struct dh_group *dh, struct wpabuf **priv) { struct wpabuf *pv; size_t pv_len; int retval = 1; if (dh == NULL) return NULL; wpabuf_free(*priv); *priv = wpabuf_alloc(dh->prime_len); if (*priv == NULL) return NULL; if(get_dh_small()) { /* Use small DH secret (1) to reduce calculation time on AP */ if(!memset(wpabuf_put(*priv, 1), 1, 1)) retval = 0; } else { if(os_get_random(wpabuf_put(*priv, dh->prime_len), dh->prime_len)) retval = 0; } if(!retval) { wpabuf_free(*priv); *priv = NULL; return NULL; } if (os_memcmp(wpabuf_head(*priv), dh->prime, dh->prime_len) > 0) { /* Make sure private value is smaller than prime */ *(wpabuf_mhead_u8(*priv)) = 0; } wpa_hexdump_buf_key(/*MSG_INFO*/ MSG_DEBUG, "DH: private value", *priv); pv_len = dh->prime_len; pv = wpabuf_alloc(pv_len); if (pv == NULL) return NULL; if (crypto_mod_exp(dh->generator, dh->generator_len, wpabuf_head(*priv), wpabuf_len(*priv), dh->prime, dh->prime_len, wpabuf_mhead(pv), &pv_len) < 0) { wpabuf_free(pv); wpa_printf(MSG_INFO, "DH: crypto_mod_exp failed"); return NULL; } wpabuf_put(pv, pv_len); wpa_hexdump_buf(MSG_DEBUG, "DH: public value", pv); return pv; }
/** * gas_query_req - Request a GAS query * @gas: GAS query data from gas_query_init() * @dst: Destination MAC address for the query * @freq: Frequency (in MHz) for the channel on which to send the query * @req: GAS query payload (to be freed by gas_query module in case of success * return) * @cb: Callback function for reporting GAS query result and response * @ctx: Context pointer to use with the @cb call * Returns: dialog token (>= 0) on success or -1 on failure */ int gas_query_req(struct gas_query *gas, const u8 *dst, int freq, struct wpabuf *req, void (*cb)(void *ctx, const u8 *dst, u8 dialog_token, enum gas_query_result result, const struct wpabuf *adv_proto, const struct wpabuf *resp, u16 status_code), void *ctx) { struct gas_query_pending *query; int dialog_token; static int next_start = 0; if (wpabuf_len(req) < 3) return -1; for (dialog_token = 0; dialog_token < 256; dialog_token++) { if (gas_query_dialog_token_available( gas, dst, (next_start + dialog_token) % 256)) break; } if (dialog_token == 256) return -1; /* Too many pending queries */ dialog_token = (next_start + dialog_token) % 256; next_start = (dialog_token + 1) % 256; query = os_zalloc(sizeof(*query)); if (query == NULL) return -1; query->gas = gas; os_memcpy(query->addr, dst, ETH_ALEN); query->dialog_token = dialog_token; query->freq = freq; query->cb = cb; query->ctx = ctx; query->req = req; dl_list_add(&gas->pending, &query->list); *(wpabuf_mhead_u8(req) + 2) = dialog_token; wpa_msg(gas->wpa_s, MSG_INFO, GAS_QUERY_START "addr=" MACSTR " dialog_token=%u freq=%d", MAC2STR(query->addr), query->dialog_token, query->freq); if (radio_add_work(gas->wpa_s, freq, "gas-query", 0, gas_query_start_cb, query) < 0) { gas_query_free(query, 1); return -1; } return dialog_token; }
void wpabuf_printf(struct wpabuf *buf, char *fmt, ...) { va_list ap; void *tmp = wpabuf_mhead_u8(buf) + wpabuf_len(buf); int res; va_start(ap, fmt); res = vsnprintf(tmp, buf->size - buf->used, fmt, ap); va_end(ap); if (res < 0 || (size_t) res >= buf->size - buf->used) wpabuf_overflow(buf, res); buf->used += res; }
int hostapd_update_time_adv(struct hostapd_data *hapd) { const int elen = 2 + 1 + 10 + 5 + 1; struct os_time t; struct os_tm tm; u8 *pos; if (hapd->conf->time_advertisement != 2) return 0; if (os_get_time(&t) < 0 || os_gmtime(t.sec, &tm) < 0) return -1; if (!hapd->time_adv) { hapd->time_adv = wpabuf_alloc(elen); if (hapd->time_adv == NULL) return -1; pos = wpabuf_put(hapd->time_adv, elen); } else pos = wpabuf_mhead_u8(hapd->time_adv); *pos++ = WLAN_EID_TIME_ADVERTISEMENT; *pos++ = 1 + 10 + 5 + 1; *pos++ = 2; /* UTC time at which the TSF timer is 0 */ /* Time Value at TSF 0 */ /* FIX: need to calculate this based on the current TSF value */ WPA_PUT_LE16(pos, tm.year); /* Year */ pos += 2; *pos++ = tm.month; /* Month */ *pos++ = tm.day; /* Day of month */ *pos++ = tm.hour; /* Hours */ *pos++ = tm.min; /* Minutes */ *pos++ = tm.sec; /* Seconds */ WPA_PUT_LE16(pos, 0); /* Milliseconds (not used) */ pos += 2; *pos++ = 0; /* Reserved */ /* Time Error */ /* TODO: fill in an estimate on the error */ *pos++ = 0; *pos++ = 0; *pos++ = 0; *pos++ = 0; *pos++ = 0; *pos++ = hapd->time_update_counter++; return 0; }
int gas_query_req(struct gas_query *gas, const u8 *dst, int freq, struct wpabuf *req, void (*cb)(void *ctx, const u8 *dst, u8 dialog_token, enum gas_query_result result, const struct wpabuf *adv_proto, const struct wpabuf *resp, u16 status_code), void *ctx) { struct gas_query_pending *query; int dialog_token; if (wpabuf_len(req) < 3) return -1; for (dialog_token = 0; dialog_token < 256; dialog_token++) { if (gas_query_dialog_token_available(gas, dst, dialog_token)) break; } if (dialog_token == 256) return -1; /* Too many pending queries */ query = os_zalloc(sizeof(*query)); if (query == NULL) return -1; os_memcpy(query->addr, dst, ETH_ALEN); query->dialog_token = dialog_token; query->freq = freq; query->cb = cb; query->ctx = ctx; dl_list_add(&gas->pending, &query->list); *(wpabuf_mhead_u8(req) + 2) = dialog_token; wpa_printf(MSG_DEBUG, "GAS: Starting request for " MACSTR " dialog_token %u", MAC2STR(dst), dialog_token); if (gas_query_tx(gas, query, req) < 0) { wpa_printf(MSG_DEBUG, "GAS: Failed to send Action frame to " MACSTR, MAC2STR(query->addr)); os_free(query); return -1; } eloop_register_timeout(GAS_QUERY_TIMEOUT, 0, gas_query_timeout, gas, query); return dialog_token; }
/** * gas_query_req - Request a GAS query * @gas: GAS query data from gas_query_init() * @dst: Destination MAC address for the query * @freq: Frequency (in MHz) for the channel on which to send the query * @req: GAS query payload (to be freed by gas_query module in case of success * return) * @cb: Callback function for reporting GAS query result and response * @ctx: Context pointer to use with the @cb call * Returns: dialog token (>= 0) on success or -1 on failure */ int gas_query_req(struct gas_query *gas, const u8 *dst, int freq, struct wpabuf *req, void (*cb)(void *ctx, const u8 *dst, u8 dialog_token, enum gas_query_result result, const struct wpabuf *adv_proto, const struct wpabuf *resp, u16 status_code), void *ctx) { struct gas_query_pending *query; int dialog_token; if (wpabuf_len(req) < 3) return -1; dialog_token = gas_query_new_dialog_token(gas, dst); if (dialog_token < 0) return -1; query = os_zalloc(sizeof(*query)); if (query == NULL) return -1; query->gas = gas; os_memcpy(query->addr, dst, ETH_ALEN); query->dialog_token = dialog_token; query->freq = freq; query->cb = cb; query->ctx = ctx; query->req = req; dl_list_add(&gas->pending, &query->list); *(wpabuf_mhead_u8(req) + 2) = dialog_token; wpa_msg(gas->wpa_s, MSG_INFO, GAS_QUERY_START "addr=" MACSTR " dialog_token=%u freq=%d", MAC2STR(query->addr), query->dialog_token, query->freq); if (radio_add_work(gas->wpa_s, freq, "gas-query", 0, gas_query_start_cb, query) < 0) { query->req = NULL; /* caller will free this in error case */ gas_query_free(query, 1); return -1; } return dialog_token; }
/** * dh_init - Initialize Diffie-Hellman handshake * @dh: Selected Diffie-Hellman group * @priv: Pointer for returning Diffie-Hellman private key * Returns: Diffie-Hellman public value */ struct wpabuf * dh_init(const struct dh_group *dh, struct wpabuf **priv) { struct wpabuf *pv; size_t pv_len; if (dh == NULL) return NULL; wpabuf_free(*priv); *priv = wpabuf_alloc(dh->prime_len); if (*priv == NULL) return NULL; if (random_get_bytes(wpabuf_put(*priv, dh->prime_len), dh->prime_len)) { wpabuf_free(*priv); *priv = NULL; return NULL; } if (os_memcmp(wpabuf_head(*priv), dh->prime, dh->prime_len) > 0) { /* Make sure private value is smaller than prime */ *(wpabuf_mhead_u8(*priv)) = 0; } wpa_hexdump_buf_key(MSG_DEBUG, "DH: private value", *priv); pv_len = dh->prime_len; pv = wpabuf_alloc(pv_len); if (pv == NULL) return NULL; if (crypto_mod_exp(dh->generator, dh->generator_len, wpabuf_head(*priv), wpabuf_len(*priv), dh->prime, dh->prime_len, wpabuf_mhead(pv), &pv_len) < 0) { wpabuf_free(pv); wpa_printf(MSG_INFO, "DH: crypto_mod_exp failed"); return NULL; } wpabuf_put(pv, pv_len); wpa_hexdump_buf(MSG_DEBUG, "DH: public value", pv); return pv; }
int eap_sim_msg_add_encr_start(struct eap_sim_msg *msg, u8 attr_iv, u8 attr_encr) { u8 *pos = eap_sim_msg_add(msg, attr_iv, 0, NULL, EAP_SIM_IV_LEN); if (pos == NULL) return -1; msg->iv = (pos - wpabuf_head_u8(msg->buf)) + 4; if (random_get_bytes(wpabuf_mhead_u8(msg->buf) + msg->iv, EAP_SIM_IV_LEN)) { msg->iv = 0; return -1; } pos = eap_sim_msg_add(msg, attr_encr, 0, NULL, 0); if (pos == NULL) { msg->iv = 0; return -1; } msg->encr = pos - wpabuf_head_u8(msg->buf); return 0; }
static Boolean eap_pax_check(struct eap_sm *sm, void *priv, struct wpabuf *respData) { struct eap_pax_data *data = priv; struct eap_pax_hdr *resp; const u8 *pos; size_t len, mlen; u8 icvbuf[EAP_PAX_ICV_LEN], *icv; pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PAX, respData, &len); if (pos == NULL || len < sizeof(*resp)) { wpa_printf(MSG_INFO, "EAP-PAX: Invalid frame"); return TRUE; } mlen = sizeof(struct eap_hdr) + 1 + len; resp = (struct eap_pax_hdr *) pos; wpa_printf(MSG_DEBUG, "EAP-PAX: received frame: op_code 0x%x " "flags 0x%x mac_id 0x%x dh_group_id 0x%x " "public_key_id 0x%x", resp->op_code, resp->flags, resp->mac_id, resp->dh_group_id, resp->public_key_id); wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: received payload", (u8 *) (resp + 1), len - sizeof(*resp) - EAP_PAX_ICV_LEN); if (data->state == PAX_STD_1 && resp->op_code != EAP_PAX_OP_STD_2) { wpa_printf(MSG_DEBUG, "EAP-PAX: Expected PAX_STD-2 - " "ignore op %d", resp->op_code); return TRUE; } if (data->state == PAX_STD_3 && resp->op_code != EAP_PAX_OP_ACK) { wpa_printf(MSG_DEBUG, "EAP-PAX: Expected PAX-ACK - " "ignore op %d", resp->op_code); return TRUE; } if (resp->op_code != EAP_PAX_OP_STD_2 && resp->op_code != EAP_PAX_OP_ACK) { wpa_printf(MSG_DEBUG, "EAP-PAX: Unknown op_code 0x%x", resp->op_code); } if (data->mac_id != resp->mac_id) { wpa_printf(MSG_DEBUG, "EAP-PAX: Expected MAC ID 0x%x, " "received 0x%x", data->mac_id, resp->mac_id); return TRUE; } if (resp->dh_group_id != EAP_PAX_DH_GROUP_NONE) { wpa_printf(MSG_INFO, "EAP-PAX: Expected DH Group ID 0x%x, " "received 0x%x", EAP_PAX_DH_GROUP_NONE, resp->dh_group_id); return TRUE; } if (resp->public_key_id != EAP_PAX_PUBLIC_KEY_NONE) { wpa_printf(MSG_INFO, "EAP-PAX: Expected Public Key ID 0x%x, " "received 0x%x", EAP_PAX_PUBLIC_KEY_NONE, resp->public_key_id); return TRUE; } if (resp->flags & EAP_PAX_FLAGS_MF) { /* TODO: add support for reassembling fragments */ wpa_printf(MSG_INFO, "EAP-PAX: fragmentation not supported"); return TRUE; } if (resp->flags & EAP_PAX_FLAGS_CE) { wpa_printf(MSG_INFO, "EAP-PAX: Unexpected CE flag"); return TRUE; } if (data->keys_set) { if (len - sizeof(*resp) < EAP_PAX_ICV_LEN) { wpa_printf(MSG_INFO, "EAP-PAX: No ICV in the packet"); return TRUE; } icv = wpabuf_mhead_u8(respData) + mlen - EAP_PAX_ICV_LEN; wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ICV", icv, EAP_PAX_ICV_LEN); eap_pax_mac(data->mac_id, data->ick, EAP_PAX_ICK_LEN, wpabuf_mhead(respData), wpabuf_len(respData) - EAP_PAX_ICV_LEN, NULL, 0, NULL, 0, icvbuf); if (os_memcmp_const(icvbuf, icv, EAP_PAX_ICV_LEN) != 0) { wpa_printf(MSG_INFO, "EAP-PAX: Invalid ICV"); wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: Expected ICV", icvbuf, EAP_PAX_ICV_LEN); return TRUE; } } return FALSE; }
int wps_build_public_key(struct wps_data *wps, struct wpabuf *msg) { struct wpabuf *pubkey; wpa_printf(MSG_DEBUG, "WPS: * Public Key"); wpabuf_free(wps->dh_privkey); //if (wps->dev_pw_id != DEV_PW_DEFAULT && wps->wps->dh_privkey) { if (wps->wps->dh_privkey) { wpa_printf(MSG_DEBUG, "WPS: Using pre-configured DH keys"); wps->dh_privkey = wpabuf_dup(wps->wps->dh_privkey); wps->dh_ctx = wps->wps->dh_ctx; wps->wps->dh_ctx = NULL; pubkey = wpabuf_dup(wps->wps->dh_pubkey); } else { wpa_printf(MSG_DEBUG, "WPS: Generate new DH keys"); wps->dh_privkey = NULL; dh5_free(wps->dh_ctx); wps->dh_ctx = dh5_init(&wps->dh_privkey, &pubkey); pubkey = wpabuf_zeropad(pubkey, 192); } if (wps->dh_ctx == NULL || wps->dh_privkey == NULL || pubkey == NULL) { wpa_printf(MSG_DEBUG, "WPS: Failed to initialize " "Diffie-Hellman handshake"); wpabuf_free(pubkey); return -1; } wpabuf_put_be16(msg, ATTR_PUBLIC_KEY); wpabuf_put_be16(msg, wpabuf_len(pubkey)); wpabuf_put_buf(msg, pubkey); if (wps->registrar) { wpabuf_free(wps->dh_pubkey_r); wps->dh_pubkey_r = pubkey; unsigned char *v; v = wpabuf_mhead_u8(pubkey); memset(pixie_pkr, 0, sizeof (pixie_pkr)); if (get_debug() == 4) { //verbose (-vvv) printf("[P] PKR: "); } int pixiecnt = 0; for (; pixiecnt < 192; pixiecnt++) { if (get_debug() == 4) { //verbose (-vvv) printf("%02x", v[pixiecnt]); } sprintf(cmd_pixie_aux, "%02x", v[pixiecnt]); strcat(pixie_pkr, cmd_pixie_aux); if (pixiecnt != 191) { if (get_debug() == 4) { //verbose (-vvv) printf(":"); } strcat(pixie_pkr, ":"); } } if (get_debug() == 4) { //verbose (-vvv) printf("\n"); } } else { wpabuf_free(wps->dh_pubkey_e); wps->dh_pubkey_e = pubkey; } return 0; }
static struct radius_attr_hdr * radius_get_attr_hdr(struct radius_msg *msg, int idx) { return (struct radius_attr_hdr *) (wpabuf_mhead_u8(msg->buf) + msg->attr_pos[idx]); }
/** * radius_msg_parse - Parse a RADIUS message * @data: RADIUS message to be parsed * @len: Length of data buffer in octets * Returns: Parsed RADIUS message or %NULL on failure * * This parses a RADIUS message and makes a copy of its data. The caller is * responsible for freeing the returned data with radius_msg_free(). */ struct radius_msg * radius_msg_parse(const u8 *data, size_t len) { struct radius_msg *msg; struct radius_hdr *hdr; struct radius_attr_hdr *attr; size_t msg_len; unsigned char *pos, *end; if (data == NULL || len < sizeof(*hdr)) return NULL; hdr = (struct radius_hdr *) data; msg_len = ntohs(hdr->length); if (msg_len < sizeof(*hdr) || msg_len > len) { wpa_printf(MSG_INFO, "RADIUS: Invalid message length"); return NULL; } if (msg_len < len) { wpa_printf(MSG_DEBUG, "RADIUS: Ignored %lu extra bytes after " "RADIUS message", (unsigned long) len - msg_len); } msg = os_zalloc(sizeof(*msg)); if (msg == NULL) return NULL; msg->buf = wpabuf_alloc_copy(data, msg_len); if (msg->buf == NULL || radius_msg_initialize(msg)) { radius_msg_free(msg); return NULL; } msg->hdr = wpabuf_mhead(msg->buf); /* parse attributes */ pos = wpabuf_mhead_u8(msg->buf) + sizeof(struct radius_hdr); end = wpabuf_mhead_u8(msg->buf) + wpabuf_len(msg->buf); while (pos < end) { if ((size_t) (end - pos) < sizeof(*attr)) goto fail; attr = (struct radius_attr_hdr *) pos; if (pos + attr->length > end || attr->length < sizeof(*attr)) goto fail; /* TODO: check that attr->length is suitable for attr->type */ if (radius_msg_add_attr_to_array(msg, attr)) goto fail; pos += attr->length; } return msg; fail: radius_msg_free(msg); return NULL; }
static void convert_to_protected_dual(struct wpabuf *msg) { u8 *categ = wpabuf_mhead_u8(msg); *categ = WLAN_ACTION_PROTECTED_DUAL; }