static int eap_fast_use_pac_opaque(struct eap_sm *sm, struct eap_fast_data *data, struct eap_fast_pac *pac) { u8 *tlv; size_t tlv_len, olen; struct eap_tlv_hdr *ehdr; olen = pac->pac_opaque_len; tlv_len = sizeof(*ehdr) + olen; tlv = os_malloc(tlv_len); if (tlv) { ehdr = (struct eap_tlv_hdr *) tlv; ehdr->tlv_type = host_to_be16(PAC_TYPE_PAC_OPAQUE); ehdr->length = host_to_be16(olen); os_memcpy(ehdr + 1, pac->pac_opaque, olen); } if (tlv == NULL || tls_connection_client_hello_ext(sm->ssl_ctx, data->ssl.conn, TLS_EXT_PAC_OPAQUE, tlv, tlv_len) < 0) { wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to add PAC-Opaque TLS " "extension"); os_free(tlv); return -1; } os_free(tlv); return 0; }
int radius_msg_finish(struct radius_msg *msg, const u8 *secret, size_t secret_len) { if (secret) { u8 auth[MD5_MAC_LEN]; struct radius_attr_hdr *attr; os_memset(auth, 0, MD5_MAC_LEN); attr = radius_msg_add_attr(msg, RADIUS_ATTR_MESSAGE_AUTHENTICATOR, auth, MD5_MAC_LEN); if (attr == NULL) { wpa_printf(MSG_WARNING, "RADIUS: Could not add " "Message-Authenticator"); return -1; } msg->hdr->length = host_to_be16(wpabuf_len(msg->buf)); hmac_md5(secret, secret_len, wpabuf_head(msg->buf), wpabuf_len(msg->buf), (u8 *) (attr + 1)); } else msg->hdr->length = host_to_be16(wpabuf_len(msg->buf)); if (wpabuf_len(msg->buf) > 0xffff) { wpa_printf(MSG_WARNING, "RADIUS: Too long message (%lu)", (unsigned long) wpabuf_len(msg->buf)); return -1; } return 0; }
void eap_fast_put_tlv_hdr(struct wpabuf *buf, u16 type, u16 len) { struct pac_tlv_hdr hdr; hdr.type = host_to_be16(type); hdr.len = host_to_be16(len); wpabuf_put_data(buf, &hdr, sizeof(hdr)); }
static void wpa_smk_send_error(struct wpa_authenticator *wpa_auth, struct wpa_state_machine *sm, const u8 *peer, u16 mui, u16 error_type) { u8 kde[2 + RSN_SELECTOR_LEN + ETH_ALEN + 2 + RSN_SELECTOR_LEN + sizeof(struct rsn_error_kde)]; u8 *pos; struct rsn_error_kde error; wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, "Sending SMK Error"); pos = kde; if (peer) { pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peer, ETH_ALEN, NULL, 0); } error.mui = host_to_be16(mui); error.error_type = host_to_be16(error_type); pos = wpa_add_kde(pos, RSN_KEY_DATA_ERROR, (u8 *) &error, sizeof(error), NULL, 0); __wpa_send_eapol(wpa_auth, sm, WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC | WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_ERROR, NULL, NULL, kde, pos - kde, 0, 0, 0); }
static struct wpabuf * eap_peapv2_tlv_eap_payload(struct wpabuf *buf) { struct wpabuf *e; struct eap_tlv_hdr *tlv; if (buf == NULL) return NULL; /* Encapsulate EAP packet in EAP-Payload TLV */ wpa_printf(MSG_DEBUG, "EAP-PEAPv2: Add EAP-Payload TLV"); e = wpabuf_alloc(sizeof(*tlv) + wpabuf_len(buf)); if (e == NULL) { wpa_printf(MSG_DEBUG, "EAP-PEAPv2: Failed to allocate memory " "for TLV encapsulation"); wpabuf_free(buf); return NULL; } tlv = wpabuf_put(e, sizeof(*tlv)); tlv->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY | EAP_TLV_EAP_PAYLOAD_TLV); tlv->length = host_to_be16(wpabuf_len(buf)); wpabuf_put_buf(e, buf); wpabuf_free(buf); return e; }
static void iapp_send_add(struct iapp_data *iapp, u8 *mac_addr, u16 seq_num) { char buf[128]; struct iapp_hdr *hdr; struct iapp_add_notify *add; struct sockaddr_in addr; /* Send IAPP ADD-notify to remove possible association from other APs */ hdr = (struct iapp_hdr *) buf; hdr->version = IAPP_VERSION; hdr->command = IAPP_CMD_ADD_notify; hdr->identifier = host_to_be16(iapp->identifier++); hdr->length = host_to_be16(sizeof(*hdr) + sizeof(*add)); add = (struct iapp_add_notify *) (hdr + 1); add->addr_len = ETH_ALEN; add->reserved = 0; os_memcpy(add->mac_addr, mac_addr, ETH_ALEN); add->seq_num = host_to_be16(seq_num); os_memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = iapp->multicast.s_addr; addr.sin_port = htons(IAPP_UDP_PORT); if (sendto(iapp->udp_sock, buf, (char *) (add + 1) - buf, 0, (struct sockaddr *) &addr, sizeof(addr)) < 0) perror("sendto[IAPP-ADD]"); }
static int wpa_supplicant_send_smk_error(struct wpa_sm *sm, const u8 *dst, const u8 *peer, u16 mui, u16 error_type, int ver) { size_t rlen; struct wpa_eapol_key *err; struct rsn_error_kde error; u8 *rbuf, *pos; size_t kde_len; u16 key_info; kde_len = 2 + RSN_SELECTOR_LEN + sizeof(error); if (peer) kde_len += 2 + RSN_SELECTOR_LEN + ETH_ALEN; rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, sizeof(*err) + kde_len, &rlen, (void *) &err); if (rbuf == NULL) return -1; err->type = EAPOL_KEY_TYPE_RSN; key_info = ver | WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_MIC | WPA_KEY_INFO_SECURE | WPA_KEY_INFO_ERROR | WPA_KEY_INFO_REQUEST; WPA_PUT_BE16(err->key_info, key_info); WPA_PUT_BE16(err->key_length, 0); os_memcpy(err->replay_counter, sm->request_counter, WPA_REPLAY_COUNTER_LEN); inc_byte_array(sm->request_counter, WPA_REPLAY_COUNTER_LEN); WPA_PUT_BE16(err->key_data_length, (u16) kde_len); pos = (u8 *) (err + 1); if (peer) { /* Peer MAC Address KDE */ pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peer, ETH_ALEN); } /* Error KDE */ error.mui = host_to_be16(mui); error.error_type = host_to_be16(error_type); wpa_add_kde(pos, RSN_KEY_DATA_ERROR, (u8 *) &error, sizeof(error)); if (peer) { wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key SMK Error (peer " MACSTR " mui %d error_type %d)", MAC2STR(peer), mui, error_type); } else { wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key SMK Error " "(mui %d error_type %d)", mui, error_type); } wpa_eapol_key_send(sm, sm->ptk.kck, ver, dst, ETH_P_EAPOL, rbuf, rlen, err->key_mic); return 0; }
static struct wpabuf * eap_fast_tlv_nak(int vendor_id, int tlv_type) { struct wpabuf *buf; struct eap_tlv_nak_tlv *nak; buf = wpabuf_alloc(sizeof(*nak)); if (buf == NULL) return NULL; nak = wpabuf_put(buf, sizeof(*nak)); nak->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY | EAP_TLV_NAK_TLV); nak->length = host_to_be16(6); nak->vendor_id = host_to_be32(vendor_id); nak->nak_type = host_to_be16(tlv_type); return buf; }
static void iapp_send_layer2_update(struct iapp_data *iapp, u8 *addr) { struct iapp_layer2_update msg; /* Send Level 2 Update Frame to update forwarding tables in layer 2 * bridge devices */ /* 802.2 Type 1 Logical Link Control (LLC) Exchange Identifier (XID) * Update response frame; IEEE Std 802.2-1998, 5.4.1.2.1 */ os_memset(msg.da, 0xff, ETH_ALEN); os_memcpy(msg.sa, addr, ETH_ALEN); msg.len = host_to_be16(6); msg.dsap = 0; /* NULL DSAP address */ msg.ssap = 0x01; /* NULL SSAP address, CR Bit: Response */ msg.control = 0xaf; /* XID response lsb.1111F101. * F=0 (no poll command; unsolicited frame) */ msg.xid_info[0] = 0x81; /* XID format identifier */ msg.xid_info[1] = 1; /* LLC types/classes: Type 1 LLC */ msg.xid_info[2] = 1 << 1; /* XID sender's receive window size (RW) * FIX: what is correct RW with 802.11? */ if (send(iapp->packet_sock, &msg, sizeof(msg), 0) < 0) perror("send[L2 Update]"); }
/** * eap_msg_alloc - Allocate a buffer for an EAP message * @vendor: Vendor-Id (0 = IETF) * @type: EAP type * @len: Buffer for returning message length * @payload_len: Payload length in bytes (data after Type) * @code: Message Code (EAP_CODE_*) * @identifier: Identifier * @payload: Pointer to payload pointer that will be set to point to the * beginning of the payload or %NULL if payload pointer is not needed * Returns: Pointer to the allocated message buffer or %NULL on error * * This function can be used to allocate a buffer for an EAP message and fill * in the EAP header. This function is automatically using expanded EAP header * if the selected Vendor-Id is not IETF. In other words, most EAP methods do * not need to separately select which header type to use when using this * function to allocate the message buffers. */ struct eap_hdr * eap_msg_alloc(int vendor, EapType type, size_t *len, size_t payload_len, u8 code, u8 identifier, u8 **payload) { struct eap_hdr *hdr; u8 *pos; *len = sizeof(struct eap_hdr) + (vendor == EAP_VENDOR_IETF ? 1 : 8) + payload_len; hdr = malloc(*len); if (hdr) { hdr->code = code; hdr->identifier = identifier; hdr->length = host_to_be16(*len); pos = (u8 *) (hdr + 1); if (vendor == EAP_VENDOR_IETF) { *pos++ = type; } else { *pos++ = EAP_TYPE_EXPANDED; WPA_PUT_BE24(pos, vendor); pos += 3; WPA_PUT_BE32(pos, type); pos += 4; } if (payload) *payload = pos; } return hdr; }
void rsn_preauth_send(struct hostapd_data *hapd, struct sta_info *sta, u8 *buf, size_t len) { struct rsn_preauth_interface *piface; struct l2_ethhdr *ethhdr; piface = hapd->preauth_iface; while (piface) { if (piface == sta->preauth_iface) break; piface = piface->next; } if (piface == NULL) { wpa_printf(MSG_DEBUG, "RSN: Could not find pre-authentication " "interface for " MACSTR, MAC2STR(sta->addr)); return; } ethhdr = os_malloc(sizeof(*ethhdr) + len); if (ethhdr == NULL) return; os_memcpy(ethhdr->h_dest, sta->addr, ETH_ALEN); os_memcpy(ethhdr->h_source, hapd->own_addr, ETH_ALEN); ethhdr->h_proto = host_to_be16(ETH_P_PREAUTH); os_memcpy(ethhdr + 1, buf, len); if (l2_packet_send(piface->l2, sta->addr, ETH_P_PREAUTH, (u8 *) ethhdr, sizeof(*ethhdr) + len) < 0) { wpa_printf(MSG_ERROR, "Failed to send preauth packet using " "l2_packet_send\n"); } os_free(ethhdr); }
static int wpa_driver_test_send_eapol(void *priv, const u8 *dest, u16 proto, const u8 *data, size_t data_len) { struct wpa_driver_test_data *drv = priv; struct msghdr msg; struct iovec io[3]; struct l2_ethhdr eth; wpa_hexdump(MSG_MSGDUMP, "test_send_eapol TX frame", data, data_len); memset(ð, 0, sizeof(eth)); memcpy(eth.h_dest, dest, ETH_ALEN); memcpy(eth.h_source, drv->own_addr, ETH_ALEN); eth.h_proto = host_to_be16(proto); io[0].iov_base = "EAPOL "; io[0].iov_len = 6; io[1].iov_base = (u8 *) ð io[1].iov_len = sizeof(eth); io[2].iov_base = (u8 *) data; io[2].iov_len = data_len; memset(&msg, 0, sizeof(msg)); msg.msg_iov = io; msg.msg_iovlen = 3; msg.msg_name = &drv->hostapd_addr; msg.msg_namelen = sizeof(drv->hostapd_addr); if (sendmsg(drv->test_socket, &msg, 0) < 0) { perror("sendmsg(test_socket)"); return -1; } return 0; }
static u8 * eap_peap_encrypt(struct eap_sm *sm, struct eap_peap_data *data, int id, u8 *plain, size_t plain_len, size_t *out_len) { int res; u8 *pos; struct eap_hdr *req; /* TODO: add support for fragmentation, if needed. This will need to * add TLS Message Length field, if the frame is fragmented. */ req = malloc(sizeof(struct eap_hdr) + 2 + data->ssl.tls_out_limit); if (req == NULL) return NULL; req->code = EAP_CODE_REQUEST; req->identifier = id; pos = (u8 *) (req + 1); *pos++ = EAP_TYPE_PEAP; *pos++ = data->peap_version; res = tls_connection_encrypt(sm->ssl_ctx, data->ssl.conn, plain, plain_len, pos, data->ssl.tls_out_limit); if (res < 0) { wpa_printf(MSG_INFO, "EAP-PEAP: Failed to encrypt Phase 2 " "data"); free(req); return NULL; } *out_len = sizeof(struct eap_hdr) + 2 + res; req->length = host_to_be16(*out_len); return (u8 *) req; }
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; }
static u8 * wpa_alloc_eapol(const struct wpa_supplicant *wpa_s, u8 type, const void *data, u16 data_len, size_t *msg_len, void **data_pos) { struct ieee802_1x_hdr *hdr; *msg_len = sizeof(*hdr) + data_len; hdr = os_malloc(*msg_len); if (hdr == NULL) return NULL; hdr->version = wpa_s->conf->eapol_version; hdr->type = type; hdr->length = host_to_be16(data_len); if (data) os_memcpy(hdr + 1, data, data_len); else os_memset(hdr + 1, 0, data_len); if (data_pos) *data_pos = hdr + 1; return (u8 *) hdr; }
struct wpabuf * eap_sim_msg_finish(struct eap_sim_msg *msg, const u8 *k_aut, const u8 *extra, size_t extra_len) { struct eap_hdr *eap; struct wpabuf *buf; if (msg == NULL) return NULL; eap = wpabuf_mhead(msg->buf); eap->length = host_to_be16(wpabuf_len(msg->buf)); #if defined(EAP_AKA_PRIME) || defined(EAP_SERVER_AKA_PRIME) if (k_aut && msg->mac && msg->type == EAP_TYPE_AKA_PRIME) { eap_sim_add_mac_sha256(k_aut, (u8 *) wpabuf_head(msg->buf), wpabuf_len(msg->buf), (u8 *) wpabuf_mhead(msg->buf) + msg->mac, extra, extra_len); } else #endif /* EAP_AKA_PRIME || EAP_SERVER_AKA_PRIME */ if (k_aut && msg->mac) { eap_sim_add_mac(k_aut, (u8 *) wpabuf_head(msg->buf), wpabuf_len(msg->buf), (u8 *) wpabuf_mhead(msg->buf) + msg->mac, extra, extra_len); } buf = msg->buf; os_free(msg); return buf; }
static u8 * eap_tlv_buildReq(struct eap_sm *sm, void *priv, int id, size_t *reqDataLen) { struct eap_hdr *req; u8 *pos; u16 status; if (sm->tlv_request == TLV_REQ_SUCCESS) { status = EAP_TLV_RESULT_SUCCESS; } else { status = EAP_TLV_RESULT_FAILURE; } *reqDataLen = sizeof(struct eap_hdr) + 1 + 6; req = VM_MALLOC(*reqDataLen); if (req == NULL) return NULL; req->code = EAP_CODE_REQUEST; req->identifier = id; req->length = host_to_be16(*reqDataLen); pos = (u8 *) (req + 1); *pos++ = EAP_TYPE_TLV; *pos++ = 0x80; /* Mandatory */ *pos++ = EAP_TLV_RESULT_TLV; /* Length */ *pos++ = 0; *pos++ = 2; /* Status */ *pos++ = status >> 8; *pos++ = status & 0xff; return (u8 *) req; }
static u8 * supp_alloc_eapol(void *ctx, u8 type, const void *data, u16 data_len, size_t *msg_len, void **data_pos) { struct ieee802_1x_hdr *hdr; wpa_printf(MSG_DEBUG, "SUPP: %s(type=%d data_len=%d)", __func__, type, data_len); *msg_len = sizeof(*hdr) + data_len; hdr = os_malloc(*msg_len); if (hdr == NULL) return NULL; hdr->version = 2; hdr->type = type; hdr->length = host_to_be16(data_len); if (data) os_memcpy(hdr + 1, data, data_len); else os_memset(hdr + 1, 0, data_len); if (data_pos) *data_pos = hdr + 1; return (u8 *) hdr; }
static int eap_ttls_phase2_nak(struct eap_ttls_data *data, struct eap_hdr *hdr, u8 **resp, size_t *resp_len) { struct eap_hdr *resp_hdr; u8 *pos = (u8 *) (hdr + 1); size_t i; /* TODO: add support for expanded Nak */ wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 Request: Nak type=%d", *pos); wpa_hexdump(MSG_DEBUG, "EAP-TTLS: Allowed Phase2 EAP types", (u8 *) data->phase2_eap_types, data->num_phase2_eap_types * sizeof(struct eap_method_type)); *resp_len = sizeof(struct eap_hdr) + 1; *resp = os_malloc(*resp_len + data->num_phase2_eap_types); if (*resp == NULL) return -1; resp_hdr = (struct eap_hdr *) (*resp); resp_hdr->code = EAP_CODE_RESPONSE; resp_hdr->identifier = hdr->identifier; pos = (u8 *) (resp_hdr + 1); *pos++ = EAP_TYPE_NAK; for (i = 0; i < data->num_phase2_eap_types; i++) { if (data->phase2_eap_types[i].vendor == EAP_VENDOR_IETF && data->phase2_eap_types[i].method < 256) { (*resp_len)++; *pos++ = data->phase2_eap_types[i].method; } } resp_hdr->length = host_to_be16(*resp_len); return 0; }
static struct wpabuf * eap_peap_build_phase2_term(struct eap_sm *sm, struct eap_peap_data *data, u8 id, int success) { struct wpabuf *encr_req, msgbuf; size_t req_len; struct eap_hdr *hdr; req_len = sizeof(*hdr); hdr = os_zalloc(req_len); if (hdr == NULL) return NULL; hdr->code = success ? EAP_CODE_SUCCESS : EAP_CODE_FAILURE; hdr->identifier = id; hdr->length = host_to_be16(req_len); wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 data", (u8 *) hdr, req_len); wpabuf_set(&msgbuf, hdr, req_len); encr_req = eap_server_tls_encrypt(sm, &data->ssl, &msgbuf); os_free(hdr); return encr_req; }
static int radius_server_reject(struct radius_server_data *data, struct radius_client *client, struct radius_msg *request, struct sockaddr *from, socklen_t fromlen, const char *from_addr, int from_port) { struct radius_msg *msg; int ret = 0; struct eap_hdr eapfail; struct wpabuf *buf; struct radius_hdr *hdr = radius_msg_get_hdr(request); RADIUS_DEBUG("Reject invalid request from %s:%d", from_addr, from_port); msg = radius_msg_new(RADIUS_CODE_ACCESS_REJECT, hdr->identifier); if (msg == NULL) { return -1; } os_memset(&eapfail, 0, sizeof(eapfail)); eapfail.code = EAP_CODE_FAILURE; eapfail.identifier = 0; eapfail.length = host_to_be16(sizeof(eapfail)); if (!radius_msg_add_eap(msg, (u8 *) &eapfail, sizeof(eapfail))) { RADIUS_DEBUG("Failed to add EAP-Message attribute"); } if (radius_msg_copy_attr(msg, request, RADIUS_ATTR_PROXY_STATE) < 0) { RADIUS_DEBUG("Failed to copy Proxy-State attribute(s)"); radius_msg_free(msg); return -1; } if (radius_msg_finish_srv(msg, (u8 *) client->shared_secret, client->shared_secret_len, hdr->authenticator) < 0) { RADIUS_DEBUG("Failed to add Message-Authenticator attribute"); } if (wpa_debug_level <= MSG_MSGDUMP) { radius_msg_dump(msg); } data->counters.access_rejects++; client->counters.access_rejects++; buf = radius_msg_get_buf(msg); if (sendto(data->auth_sock, wpabuf_head(buf), wpabuf_len(buf), 0, (struct sockaddr *) from, sizeof(*from)) < 0) { wpa_printf(MSG_INFO, "sendto[RADIUS SRV]: %s", strerror(errno)); ret = -1; } radius_msg_free(msg); return ret; }
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)); }
static int hostapd_wpa_auth_send_ether(void *ctx, const u8 *dst, u16 proto, const u8 *data, size_t data_len) { struct hostapd_data *hapd = ctx; struct l2_ethhdr *buf; int ret; #ifdef CONFIG_TESTING_OPTIONS if (hapd->ext_eapol_frame_io && proto == ETH_P_EAPOL) { size_t hex_len = 2 * data_len + 1; char *hex = os_malloc(hex_len); if (hex == NULL) return -1; wpa_snprintf_hex(hex, hex_len, data, data_len); wpa_msg(hapd->msg_ctx, MSG_INFO, "EAPOL-TX " MACSTR " %s", MAC2STR(dst), hex); os_free(hex); return 0; } #endif /* CONFIG_TESTING_OPTIONS */ #ifdef CONFIG_IEEE80211R if (proto == ETH_P_RRB && hapd->iface->interfaces && hapd->iface->interfaces->for_each_interface) { int res; struct wpa_auth_ft_iface_iter_data idata; idata.src_hapd = hapd; idata.dst = dst; idata.data = data; idata.data_len = data_len; res = hapd->iface->interfaces->for_each_interface( hapd->iface->interfaces, hostapd_wpa_auth_ft_iter, &idata); if (res == 1) return data_len; } #endif /* CONFIG_IEEE80211R */ if (hapd->driver && hapd->driver->send_ether) return hapd->driver->send_ether(hapd->drv_priv, dst, hapd->own_addr, proto, data, data_len); if (hapd->l2 == NULL) return -1; buf = os_malloc(sizeof(*buf) + data_len); if (buf == NULL) return -1; os_memcpy(buf->h_dest, dst, ETH_ALEN); os_memcpy(buf->h_source, hapd->own_addr, ETH_ALEN); buf->h_proto = host_to_be16(proto); os_memcpy(buf + 1, data, data_len); ret = l2_packet_send(hapd->l2, dst, proto, (u8 *) buf, sizeof(*buf) + data_len); os_free(buf); return ret; }
static struct wpabuf * eap_fast_tlv_result(int status, int intermediate) { struct wpabuf *buf; struct eap_tlv_intermediate_result_tlv *result; buf = wpabuf_alloc(sizeof(*result)); if (buf == NULL) return NULL; wpa_printf(MSG_DEBUG, "EAP-FAST: Add %sResult TLV(status=%d)", intermediate ? "Intermediate " : "", status); result = wpabuf_put(buf, sizeof(*result)); result->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY | (intermediate ? EAP_TLV_INTERMEDIATE_RESULT_TLV : EAP_TLV_RESULT_TLV)); result->length = host_to_be16(2); result->status = host_to_be16(status); return buf; }
static u8 * eap_mschapv2_failure(struct eap_sm *sm, struct eap_mschapv2_data *data, struct eap_method_ret *ret, const struct eap_mschapv2_hdr *req, size_t *respDataLen) { struct eap_mschapv2_hdr *resp; const u8 *msdata = (const u8 *) (req + 1); char *buf; int len = be_to_host16(req->length) - sizeof(*req); int retry = 0; wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Received failure"); wpa_hexdump_ascii(MSG_DEBUG, "EAP-MSCHAPV2: Failure data", msdata, len); buf = malloc(len + 1); if (buf) { memcpy(buf, msdata, len); buf[len] = '\0'; retry = eap_mschapv2_failure_txt(sm, data, buf); free(buf); } ret->ignore = FALSE; ret->methodState = METHOD_DONE; ret->decision = DECISION_FAIL; ret->allowNotifications = FALSE; if (data->prev_error == ERROR_PASSWD_EXPIRED && data->passwd_change_version == 3) { struct wpa_ssid *config = eap_get_config(sm); if (config && config->new_password) return eap_mschapv2_change_password(sm, data, ret, req, respDataLen); if (config && config->pending_req_new_password) return NULL; } else if (retry && data->prev_error == ERROR_AUTHENTICATION_FAILURE) { /* TODO: could try to retry authentication, e.g, after having * changed the username/password. In this case, EAP MS-CHAP-v2 * Failure Response would not be sent here. */ return NULL; } *respDataLen = 6; resp = malloc(6); if (resp == NULL) { return NULL; } resp->code = EAP_CODE_RESPONSE; resp->identifier = req->identifier; resp->length = host_to_be16(6); resp->type = EAP_TYPE_MSCHAPV2; resp->op_code = MSCHAPV2_OP_FAILURE; return (u8 *) resp; }
static u8 * eap_mschapv2_success(struct eap_sm *sm, struct eap_mschapv2_data *data, struct eap_method_ret *ret, struct eap_mschapv2_hdr *req, size_t *respDataLen) { struct eap_mschapv2_hdr *resp; u8 *pos, recv_response[20]; int len, left; wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Received success"); len = be_to_host16(req->length); pos = (u8 *) (req + 1); if (!data->auth_response_valid || len < sizeof(*req) + 42 || pos[0] != 'S' || pos[1] != '=' || hexstr2bin((char *) (pos + 2), recv_response, 20) || memcmp(data->auth_response, recv_response, 20) != 0) { wpa_printf(MSG_WARNING, "EAP-MSCHAPV2: Invalid authenticator " "response in success request"); ret->methodState = METHOD_DONE; ret->decision = DECISION_FAIL; return NULL; } pos += 42; left = len - sizeof(*req) - 42; while (left > 0 && *pos == ' ') { pos++; left--; } wpa_hexdump_ascii(MSG_DEBUG, "EAP-MSCHAPV2: Success message", pos, left); wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Authentication succeeded"); *respDataLen = 6; resp = malloc(6); if (resp == NULL) { wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Failed to allocate " "buffer for success response"); ret->ignore = TRUE; return NULL; } resp->code = EAP_CODE_RESPONSE; resp->identifier = req->identifier; resp->length = host_to_be16(6); resp->type = EAP_TYPE_MSCHAPV2; resp->op_code = MSCHAPV2_OP_SUCCESS; ret->methodState = METHOD_DONE; ret->decision = DECISION_UNCOND_SUCC; ret->allowNotifications = FALSE; data->success = 1; return (u8 *) resp; }
static struct wpabuf * eap_fast_tlv_pac_ack(void) { struct wpabuf *buf; struct eap_tlv_result_tlv *res; struct eap_tlv_pac_ack_tlv *ack; buf = wpabuf_alloc(sizeof(*res) + sizeof(*ack)); if (buf == NULL) return NULL; wpa_printf(MSG_DEBUG, "EAP-FAST: Add PAC TLV (ack)"); ack = wpabuf_put(buf, sizeof(*ack)); ack->tlv_type = host_to_be16(EAP_TLV_PAC_TLV | EAP_TLV_TYPE_MANDATORY); ack->length = host_to_be16(sizeof(*ack) - sizeof(struct eap_tlv_hdr)); ack->pac_type = host_to_be16(PAC_TYPE_PAC_ACKNOWLEDGEMENT); ack->pac_len = host_to_be16(2); ack->result = host_to_be16(EAP_TLV_RESULT_SUCCESS); return buf; }
static u8 * eap_leap_process_success(struct eap_sm *sm, void *priv, struct eap_method_ret *ret, const u8 *reqData, size_t reqDataLen, size_t *respDataLen) { struct eap_leap_data *data = priv; struct wpa_ssid *config = eap_get_config(sm); const struct eap_hdr *req; struct eap_hdr *resp; u8 *pos; wpa_printf(MSG_DEBUG, "EAP-LEAP: Processing EAP-Success"); if (data->state != LEAP_WAIT_SUCCESS) { wpa_printf(MSG_INFO, "EAP-LEAP: EAP-Success received in " "unexpected state (%d) - ignored", data->state); ret->ignore = TRUE; return NULL; } req = (const struct eap_hdr *) reqData; *respDataLen = sizeof(struct eap_hdr) + 1 + 3 + LEAP_CHALLENGE_LEN + config->identity_len; resp = malloc(*respDataLen); if (resp == NULL) return NULL; resp->code = EAP_CODE_REQUEST; resp->identifier = req->identifier; resp->length = host_to_be16(*respDataLen); pos = (u8 *) (resp + 1); *pos++ = EAP_TYPE_LEAP; *pos++ = LEAP_VERSION; *pos++ = 0; /* unused */ *pos++ = LEAP_CHALLENGE_LEN; if (hostapd_get_rand(pos, LEAP_CHALLENGE_LEN)) { wpa_printf(MSG_WARNING, "EAP-LEAP: Failed to read random data " "for challenge"); free(resp); ret->ignore = TRUE; return NULL; } memcpy(data->ap_challenge, pos, LEAP_CHALLENGE_LEN); wpa_hexdump(MSG_MSGDUMP, "EAP-LEAP: Challenge to AP/AS", pos, LEAP_CHALLENGE_LEN); pos += LEAP_CHALLENGE_LEN; memcpy(pos, config->identity, config->identity_len); data->state = LEAP_WAIT_RESPONSE; return (u8 *) resp; }
static void eapol_auth_tx_canned_eap(struct eapol_state_machine *sm, int success) { struct eap_hdr eap; os_memset(&eap, 0, sizeof(eap)); eap.code = success ? EAP_CODE_SUCCESS : EAP_CODE_FAILURE; eap.identifier = ++sm->last_eap_id; eap.length = host_to_be16(sizeof(eap)); eapol_auth_vlogger(sm->eapol, sm->addr, EAPOL_LOGGER_DEBUG, "Sending canned EAP packet %s (identifier %d)", success ? "SUCCESS" : "FAILURE", eap.identifier); sm->eapol->cb.eapol_send(sm->eapol->conf.ctx, sm->sta, IEEE802_1X_TYPE_EAP_PACKET, (u8 *)&eap, sizeof(eap)); sm->dot1xAuthEapolFramesTx++; }
static void eap_fast_write_crypto_binding( struct eap_tlv_crypto_binding_tlv *rbind, struct eap_tlv_crypto_binding_tlv *_bind, const u8 *cmk) { rbind->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY | EAP_TLV_CRYPTO_BINDING_TLV); rbind->length = host_to_be16(sizeof(*rbind) - sizeof(struct eap_tlv_hdr)); rbind->version = EAP_FAST_VERSION; rbind->received_version = _bind->version; rbind->subtype = EAP_TLV_CRYPTO_BINDING_SUBTYPE_RESPONSE; os_memcpy(rbind->nonce, _bind->nonce, sizeof(_bind->nonce)); inc_byte_array(rbind->nonce, sizeof(rbind->nonce)); hmac_sha1(cmk, EAP_FAST_CMK_LEN, (u8 *) rbind, sizeof(*rbind), rbind->compound_mac); wpa_printf(MSG_DEBUG, "EAP-FAST: Reply Crypto-Binding TLV: Version %d " "Received Version %d SubType %d", rbind->version, rbind->received_version, rbind->subtype); wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: NONCE", rbind->nonce, sizeof(rbind->nonce)); wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Compound MAC", rbind->compound_mac, sizeof(rbind->compound_mac)); }