static struct wpabuf * ndef_build_record(u8 flags, void *type, u8 type_length, void *id, u8 id_length, void *payload, u32 payload_length) { struct wpabuf *record; size_t total_len; int short_record; u8 local_flag; short_record = payload_length < 256 ? 1 : 0; total_len = 2; /* flag + type length */ /* payload length */ total_len += short_record ? sizeof(u8) : sizeof(u32); if (id_length > 0) total_len += 1; total_len += type_length + id_length + payload_length; record = wpabuf_alloc(total_len); if (record == NULL) { wpa_printf(MSG_ERROR, "NDEF : Failed to allocate " "record for build"); return NULL; } local_flag = flags; if (id_length > 0) local_flag |= FLAG_ID_LENGTH_PRESENT; if (short_record) local_flag |= FLAG_SHORT_RECORD; wpabuf_put_u8(record, local_flag); wpabuf_put_u8(record, type_length); if (short_record) wpabuf_put_u8(record, payload_length); else wpabuf_put_be32(record, payload_length); if (id_length > 0) wpabuf_put_u8(record, id_length); wpabuf_put_data(record, type, type_length); wpabuf_put_data(record, id, id_length); wpabuf_put_data(record, payload, payload_length); return record; }
static struct wpabuf * eap_tlv_build_nak(int id, u16 nak_type) { struct wpabuf *msg; msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TLV, 10, EAP_CODE_RESPONSE, id); if (msg == NULL) return NULL; wpabuf_put_u8(msg, 0x80); /* Mandatory */ wpabuf_put_u8(msg, EAP_TLV_NAK_TLV); wpabuf_put_be16(msg, 6); /* Length */ wpabuf_put_be32(msg, 0); /* Vendor-Id */ wpabuf_put_be16(msg, nak_type); /* NAK-Type */ return msg; }
/** * wps_build_probe_req_ie - Build WPS IE for Probe Request * @pbc: Whether searching for PBC mode APs * @dev: Device attributes * @uuid: Own UUID * @req_type: Value for Request Type attribute * Returns: WPS IE or %NULL on failure * * The caller is responsible for freeing the buffer. */ struct wpabuf * wps_build_probe_req_ie(int pbc, struct wps_device_data *dev, const u8 *uuid, enum wps_request_type req_type) { struct wpabuf *ie; u8 *len; u16 methods; wpa_printf(MSG_DEBUG, "WPS: Building WPS IE for Probe Request"); ie = wpabuf_alloc(200); if (ie == NULL) return NULL; wpabuf_put_u8(ie, WLAN_EID_VENDOR_SPECIFIC); len = wpabuf_put(ie, 1); wpabuf_put_be32(ie, WPS_DEV_OUI_WFA); if (pbc) methods = WPS_CONFIG_PUSHBUTTON; else methods = WPS_CONFIG_LABEL | WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD; if (wps_build_version(ie) || wps_build_req_type(ie, req_type) || wps_build_config_methods(ie, methods) || wps_build_uuid_e(ie, uuid) || wps_build_primary_dev_type(dev, ie) || wps_build_rf_bands(dev, ie) || wps_build_assoc_state(NULL, ie) || wps_build_config_error(ie, WPS_CFG_NO_ERROR) || wps_build_dev_password_id(ie, pbc ? DEV_PW_PUSHBUTTON : DEV_PW_DEFAULT)) { wpabuf_free(ie); return NULL; } *len = wpabuf_len(ie) - 2; return ie; }
static struct wpabuf * p2p_build_sd_query(u16 update_indic, struct wpabuf *tlvs) { struct wpabuf *buf; u8 *len_pos; buf = gas_anqp_build_initial_req(0, 100 + wpabuf_len(tlvs)); if (buf == NULL) return NULL; /* ANQP Query Request Frame */ len_pos = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC); wpabuf_put_be32(buf, P2P_IE_VENDOR_TYPE); wpabuf_put_le16(buf, update_indic); /* Service Update Indicator */ wpabuf_put_buf(buf, tlvs); gas_anqp_set_element_len(buf, len_pos); gas_anqp_set_len(buf); return buf; }
static struct wpabuf * eap_eke_build_fail(struct eap_eke_data *data, struct eap_method_ret *ret, u8 id, u32 failure_code) { struct wpabuf *resp; wpa_printf(MSG_DEBUG, "EAP-EKE: Sending EAP-EKE-Failure/Response - code=0x%x", failure_code); resp = eap_eke_build_msg(data, id, 4, EAP_EKE_FAILURE); if (resp) wpabuf_put_be32(resp, failure_code); os_memset(data->dh_priv, 0, sizeof(data->dh_priv)); eap_eke_session_clean(&data->sess); eap_eke_state(data, FAILURE); ret->methodState = METHOD_DONE; ret->decision = DECISION_FAIL; ret->allowNotifications = FALSE; return resp; }
struct wpabuf * tncs_build_soh_request(void) { struct wpabuf *buf; /* * Build a SoH Request TLV (to be used inside SoH EAP Extensions * Method) */ buf = wpabuf_alloc(8 + 4); if (buf == NULL) return NULL; /* Vendor-Specific TLV (Microsoft) - SoH Request */ wpabuf_put_be16(buf, EAP_TLV_VENDOR_SPECIFIC_TLV); /* TLV Type */ wpabuf_put_be16(buf, 8); /* Length */ wpabuf_put_be32(buf, EAP_VENDOR_MICROSOFT); /* Vendor_Id */ wpabuf_put_be16(buf, 0x02); /* TLV Type - SoH Request TLV */ wpabuf_put_be16(buf, 0); /* Length */ return buf; }
/** * wps_build_assoc_resp_ie - Build WPS IE for (Re)Association Response * Returns: WPS IE or %NULL on failure * * The caller is responsible for freeing the buffer. */ struct wpabuf *wps_build_assoc_resp_ie(void) { struct wpabuf *ie; u8 *len; wpa_printf(MSG_DEBUG, "WPS: Building WPS IE for (Re)Association " "Response"); ie = wpabuf_alloc(100); if (ie == NULL) { return NULL; } wpabuf_put_u8(ie, WLAN_EID_VENDOR_SPECIFIC); len = wpabuf_put(ie, 1); wpabuf_put_be32(ie, WPS_DEV_OUI_WFA); if (wps_build_version(ie) || wps_build_resp_type(ie, WPS_RESP_AP) || wps_build_wfa_ext(ie, 0, NULL, 0)) { wpabuf_free(ie); return NULL; } *len = wpabuf_len(ie) - 2; return ie; }
/** * wps_build_assoc_req_ie - Build WPS IE for (Re)Association Request * @req_type: Value for Request Type attribute * Returns: WPS IE or %NULL on failure * * The caller is responsible for freeing the buffer. */ struct wpabuf * wps_build_assoc_req_ie(enum wps_request_type req_type) { struct wpabuf *ie; u8 *len; wpa_printf(MSG_DEBUG, "WPS: Building WPS IE for (Re)Association " "Request"); ie = wpabuf_alloc(100); if (ie == NULL) return NULL; wpabuf_put_u8(ie, WLAN_EID_VENDOR_SPECIFIC); len = wpabuf_put(ie, 1); wpabuf_put_be32(ie, WPS_DEV_OUI_WFA); if (wps_build_version(ie) || wps_build_req_type(ie, req_type)) { wpabuf_free(ie); return NULL; } *len = wpabuf_len(ie) - 2; return ie; }
void p2p_build_wps_ie(struct p2p_data *p2p, struct wpabuf *buf, u16 pw_id, int all_attr) { u8 *len; int i; wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC); len = wpabuf_put(buf, 1); wpabuf_put_be32(buf, WPS_DEV_OUI_WFA); wps_build_version(buf); if (all_attr) { wpabuf_put_be16(buf, ATTR_WPS_STATE); wpabuf_put_be16(buf, 1); wpabuf_put_u8(buf, WPS_STATE_NOT_CONFIGURED); } /* Device Password ID */ wpabuf_put_be16(buf, ATTR_DEV_PASSWORD_ID); wpabuf_put_be16(buf, 2); wpa_printf(MSG_DEBUG, "P2P: WPS IE Device Password ID: %d", pw_id); wpabuf_put_be16(buf, pw_id); if (all_attr) { size_t nlen; wpabuf_put_be16(buf, ATTR_RESPONSE_TYPE); wpabuf_put_be16(buf, 1); wpabuf_put_u8(buf, WPS_RESP_ENROLLEE_INFO); #if 0 /* FIX */ wps_build_uuid_e(buf, reg->wps->uuid); wps_build_manufacturer(dev, buf); wps_build_model_name(dev, buf); wps_build_model_number(dev, buf); wps_build_serial_number(dev, buf); #endif wpabuf_put_be16(buf, ATTR_PRIMARY_DEV_TYPE); wpabuf_put_be16(buf, WPS_DEV_TYPE_LEN); wpabuf_put_data(buf, p2p->cfg->pri_dev_type, WPS_DEV_TYPE_LEN); wpabuf_put_be16(buf, ATTR_DEV_NAME); nlen = p2p->cfg->dev_name ? os_strlen(p2p->cfg->dev_name) : 0; wpabuf_put_be16(buf, nlen); if (p2p->cfg->dev_name) wpabuf_put_data(buf, p2p->cfg->dev_name, nlen); wpabuf_put_be16(buf, ATTR_CONFIG_METHODS); wpabuf_put_be16(buf, 2); wpabuf_put_be16(buf, 0); /* FIX: ? */ } wps_build_wfa_ext(buf, 0, NULL, 0); if (all_attr && p2p->cfg->num_sec_dev_types) { wpabuf_put_be16(buf, ATTR_SECONDARY_DEV_TYPE_LIST); wpabuf_put_be16(buf, WPS_DEV_TYPE_LEN * p2p->cfg->num_sec_dev_types); wpabuf_put_data(buf, p2p->cfg->sec_dev_type, WPS_DEV_TYPE_LEN * p2p->cfg->num_sec_dev_types); } /* Add the WPS vendor extensions */ for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) { if (p2p->wps_vendor_ext[i] == NULL) break; if (wpabuf_tailroom(buf) < 4 + wpabuf_len(p2p->wps_vendor_ext[i])) continue; wpabuf_put_be16(buf, ATTR_VENDOR_EXT); wpabuf_put_be16(buf, wpabuf_len(p2p->wps_vendor_ext[i])); wpabuf_put_buf(buf, p2p->wps_vendor_ext[i]); } p2p_buf_update_ie_hdr(buf, len); }
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_ikev2_build_msg(struct eap_ikev2_data *data, struct eap_method_ret *ret, u8 id) { struct wpabuf *resp; u8 flags; size_t send_len, plen, icv_len = 0; ret->ignore = FALSE; wpa_printf(MSG_DEBUG, "EAP-IKEV2: Generating Response"); ret->allowNotifications = TRUE; 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; } } #ifdef CCNS_PL /* Some issues figuring out the length of the message if Message Length * field not included?! */ if (!(flags & IKEV2_FLAGS_LENGTH_INCLUDED)) flags |= IKEV2_FLAGS_LENGTH_INCLUDED; #endif /* CCNS_PL */ 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; } resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IKEV2, plen, EAP_CODE_RESPONSE, id); if (resp == NULL) return NULL; wpabuf_put_u8(resp, flags); /* Flags */ if (flags & IKEV2_FLAGS_LENGTH_INCLUDED) wpabuf_put_be32(resp, wpabuf_len(data->out_buf)); wpabuf_put_data(resp, 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(resp); size_t len = wpabuf_len(resp); ikev2_integ_hash(data->ikev2.proposal.integ, data->ikev2.keys.SK_ar, data->ikev2.keys.SK_integ_len, msg, len, wpabuf_put(resp, icv_len)); } ret->methodState = METHOD_MAY_CONT; ret->decision = DECISION_FAIL; 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; switch (data->ikev2.state) { case SA_AUTH: /* SA_INIT was sent out, so message have to be * integrity protected from now on. */ data->keys_ready = 1; break; case IKEV2_DONE: ret->methodState = METHOD_DONE; if (data->state == FAIL) break; ret->decision = DECISION_COND_SUCC; wpa_printf(MSG_DEBUG, "EAP-IKEV2: Authentication " "completed successfully"); if (eap_ikev2_peer_keymat(data)) break; eap_ikev2_state(data, DONE); break; case IKEV2_FAILED: wpa_printf(MSG_DEBUG, "EAP-IKEV2: Authentication " "failed"); ret->methodState = METHOD_DONE; ret->decision = DECISION_FAIL; break; default: break; } } 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 resp; }
int p2p_build_wps_ie(struct p2p_data *p2p, struct wpabuf *buf, int pw_id, int all_attr) { u8 *len; int i; if (wpabuf_tailroom(buf) < 6) return -1; wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC); len = wpabuf_put(buf, 1); wpabuf_put_be32(buf, WPS_DEV_OUI_WFA); if (wps_build_version(buf) < 0) return -1; if (all_attr) { if (wpabuf_tailroom(buf) < 5) return -1; wpabuf_put_be16(buf, ATTR_WPS_STATE); wpabuf_put_be16(buf, 1); wpabuf_put_u8(buf, WPS_STATE_NOT_CONFIGURED); } if (pw_id >= 0) { if (wpabuf_tailroom(buf) < 6) return -1; /* Device Password ID */ wpabuf_put_be16(buf, ATTR_DEV_PASSWORD_ID); wpabuf_put_be16(buf, 2); wpa_printf(MSG_DEBUG, "P2P: WPS IE Device Password ID: %d", pw_id); wpabuf_put_be16(buf, pw_id); } if (all_attr) { if (wpabuf_tailroom(buf) < 5) return -1; wpabuf_put_be16(buf, ATTR_RESPONSE_TYPE); wpabuf_put_be16(buf, 1); wpabuf_put_u8(buf, WPS_RESP_ENROLLEE_INFO); if (wps_build_uuid_e(buf, p2p->cfg->uuid) < 0 || p2p_add_wps_string(buf, ATTR_MANUFACTURER, p2p->cfg->manufacturer) < 0 || p2p_add_wps_string(buf, ATTR_MODEL_NAME, p2p->cfg->model_name) < 0 || p2p_add_wps_string(buf, ATTR_MODEL_NUMBER, p2p->cfg->model_number) < 0 || p2p_add_wps_string(buf, ATTR_SERIAL_NUMBER, p2p->cfg->serial_number) < 0) return -1; if (wpabuf_tailroom(buf) < 4 + WPS_DEV_TYPE_LEN) return -1; wpabuf_put_be16(buf, ATTR_PRIMARY_DEV_TYPE); wpabuf_put_be16(buf, WPS_DEV_TYPE_LEN); wpabuf_put_data(buf, p2p->cfg->pri_dev_type, WPS_DEV_TYPE_LEN); if (p2p_add_wps_string(buf, ATTR_DEV_NAME, p2p->cfg->dev_name) < 0) return -1; if (wpabuf_tailroom(buf) < 6) return -1; wpabuf_put_be16(buf, ATTR_CONFIG_METHODS); wpabuf_put_be16(buf, 2); wpabuf_put_be16(buf, p2p->cfg->config_methods); } if (wps_build_wfa_ext(buf, 0, NULL, 0) < 0) return -1; if (all_attr && p2p->cfg->num_sec_dev_types) { if (wpabuf_tailroom(buf) < 4 + WPS_DEV_TYPE_LEN * p2p->cfg->num_sec_dev_types) return -1; wpabuf_put_be16(buf, ATTR_SECONDARY_DEV_TYPE_LIST); wpabuf_put_be16(buf, WPS_DEV_TYPE_LEN * p2p->cfg->num_sec_dev_types); wpabuf_put_data(buf, p2p->cfg->sec_dev_type, WPS_DEV_TYPE_LEN * p2p->cfg->num_sec_dev_types); } /* Add the WPS vendor extensions */ for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) { if (p2p->wps_vendor_ext[i] == NULL) break; if (wpabuf_tailroom(buf) < 4 + wpabuf_len(p2p->wps_vendor_ext[i])) continue; wpabuf_put_be16(buf, ATTR_VENDOR_EXT); wpabuf_put_be16(buf, wpabuf_len(p2p->wps_vendor_ext[i])); wpabuf_put_buf(buf, p2p->wps_vendor_ext[i]); } p2p_buf_update_ie_hdr(buf, len); return 0; }
static struct wpabuf * eap_fast_build_pac(struct eap_sm *sm, struct eap_fast_data *data) { u8 pac_key[EAP_FAST_PAC_KEY_LEN]; u8 *pac_buf, *pac_opaque; struct wpabuf *buf; u8 *pos; size_t buf_len, srv_id_info_len, pac_len; struct eap_tlv_hdr *pac_tlv; struct pac_tlv_hdr *pac_info; struct eap_tlv_result_tlv *result; struct os_time now; if (random_get_bytes(pac_key, EAP_FAST_PAC_KEY_LEN) < 0 || os_get_time(&now) < 0) return NULL; wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: Generated PAC-Key", pac_key, EAP_FAST_PAC_KEY_LEN); pac_len = (2 + EAP_FAST_PAC_KEY_LEN) + (2 + 4) + (2 + sm->identity_len) + 8; pac_buf = os_malloc(pac_len); if (pac_buf == NULL) return NULL; srv_id_info_len = os_strlen(data->srv_id_info); pos = pac_buf; *pos++ = PAC_OPAQUE_TYPE_KEY; *pos++ = EAP_FAST_PAC_KEY_LEN; os_memcpy(pos, pac_key, EAP_FAST_PAC_KEY_LEN); pos += EAP_FAST_PAC_KEY_LEN; *pos++ = PAC_OPAQUE_TYPE_LIFETIME; *pos++ = 4; WPA_PUT_BE32(pos, now.sec + data->pac_key_lifetime); pos += 4; if (sm->identity) { *pos++ = PAC_OPAQUE_TYPE_IDENTITY; *pos++ = sm->identity_len; os_memcpy(pos, sm->identity, sm->identity_len); pos += sm->identity_len; } pac_len = pos - pac_buf; while (pac_len % 8) { *pos++ = PAC_OPAQUE_TYPE_PAD; pac_len++; } pac_opaque = os_malloc(pac_len + 8); if (pac_opaque == NULL) { os_free(pac_buf); return NULL; } if (aes_wrap(data->pac_opaque_encr, sizeof(data->pac_opaque_encr), pac_len / 8, pac_buf, pac_opaque) < 0) { os_free(pac_buf); os_free(pac_opaque); return NULL; } os_free(pac_buf); pac_len += 8; wpa_hexdump(MSG_DEBUG, "EAP-FAST: PAC-Opaque", pac_opaque, pac_len); buf_len = sizeof(*pac_tlv) + sizeof(struct pac_tlv_hdr) + EAP_FAST_PAC_KEY_LEN + sizeof(struct pac_tlv_hdr) + pac_len + data->srv_id_len + srv_id_info_len + 100 + sizeof(*result); buf = wpabuf_alloc(buf_len); if (buf == NULL) { os_free(pac_opaque); return NULL; } /* Result TLV */ wpa_printf(MSG_DEBUG, "EAP-FAST: Add Result TLV (status=SUCCESS)"); result = wpabuf_put(buf, sizeof(*result)); WPA_PUT_BE16((u8 *) &result->tlv_type, EAP_TLV_TYPE_MANDATORY | EAP_TLV_RESULT_TLV); WPA_PUT_BE16((u8 *) &result->length, 2); WPA_PUT_BE16((u8 *) &result->status, EAP_TLV_RESULT_SUCCESS); /* PAC TLV */ wpa_printf(MSG_DEBUG, "EAP-FAST: Add PAC TLV"); pac_tlv = wpabuf_put(buf, sizeof(*pac_tlv)); pac_tlv->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY | EAP_TLV_PAC_TLV); /* PAC-Key */ eap_fast_put_tlv(buf, PAC_TYPE_PAC_KEY, pac_key, EAP_FAST_PAC_KEY_LEN); /* PAC-Opaque */ eap_fast_put_tlv(buf, PAC_TYPE_PAC_OPAQUE, pac_opaque, pac_len); os_free(pac_opaque); /* PAC-Info */ pac_info = wpabuf_put(buf, sizeof(*pac_info)); pac_info->type = host_to_be16(PAC_TYPE_PAC_INFO); /* PAC-Lifetime (inside PAC-Info) */ eap_fast_put_tlv_hdr(buf, PAC_TYPE_CRED_LIFETIME, 4); wpabuf_put_be32(buf, now.sec + data->pac_key_lifetime); /* A-ID (inside PAC-Info) */ eap_fast_put_tlv(buf, PAC_TYPE_A_ID, data->srv_id, data->srv_id_len); /* Note: headers may be misaligned after A-ID */ if (sm->identity) { eap_fast_put_tlv(buf, PAC_TYPE_I_ID, sm->identity, sm->identity_len); } /* A-ID-Info (inside PAC-Info) */ eap_fast_put_tlv(buf, PAC_TYPE_A_ID_INFO, data->srv_id_info, srv_id_info_len); /* PAC-Type (inside PAC-Info) */ eap_fast_put_tlv_hdr(buf, PAC_TYPE_PAC_TYPE, 2); wpabuf_put_be16(buf, PAC_TYPE_TUNNEL_PAC); /* Update PAC-Info and PAC TLV Length fields */ pos = wpabuf_put(buf, 0); pac_info->len = host_to_be16(pos - (u8 *) (pac_info + 1)); pac_tlv->length = host_to_be16(pos - (u8 *) (pac_tlv + 1)); return buf; }
/** * 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_tls_msg_alloc(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 * tncc_build_soh(int ver) { struct wpabuf *buf; u8 *tlv_len, *tlv_len2, *outer_len, *inner_len, *ssoh_len, *end; u8 correlation_id[24]; /* TODO: get correct name */ char *machinename = "*****@*****.**"; if (os_get_random(correlation_id, sizeof(correlation_id))) return NULL; wpa_hexdump(MSG_DEBUG, "TNC: SoH Correlation ID", correlation_id, sizeof(correlation_id)); buf = wpabuf_alloc(200); if (buf == NULL) return NULL; /* Vendor-Specific TLV (Microsoft) - SoH */ wpabuf_put_be16(buf, EAP_TLV_VENDOR_SPECIFIC_TLV); /* TLV Type */ tlv_len = wpabuf_put(buf, 2); /* Length */ wpabuf_put_be32(buf, EAP_VENDOR_MICROSOFT); /* Vendor_Id */ wpabuf_put_be16(buf, 0x01); /* TLV Type - SoH TLV */ tlv_len2 = wpabuf_put(buf, 2); /* Length */ /* SoH Header */ wpabuf_put_be16(buf, EAP_TLV_VENDOR_SPECIFIC_TLV); /* Outer Type */ outer_len = wpabuf_put(buf, 2); wpabuf_put_be32(buf, EAP_VENDOR_MICROSOFT); /* IANA SMI Code */ wpabuf_put_be16(buf, ver); /* Inner Type */ inner_len = wpabuf_put(buf, 2); if (ver == 2) { /* SoH Mode Sub-Header */ /* Outer Type */ wpabuf_put_be16(buf, EAP_TLV_VENDOR_SPECIFIC_TLV); wpabuf_put_be16(buf, 4 + 24 + 1 + 1); /* Length */ wpabuf_put_be32(buf, EAP_VENDOR_MICROSOFT); /* IANA SMI Code */ /* Value: */ wpabuf_put_data(buf, correlation_id, sizeof(correlation_id)); wpabuf_put_u8(buf, 0x01); /* Intent Flag - Request */ wpabuf_put_u8(buf, 0x00); /* Content-Type Flag */ } /* SSoH TLV */ /* System-Health-Id */ wpabuf_put_be16(buf, 0x0002); /* Type */ wpabuf_put_be16(buf, 4); /* Length */ wpabuf_put_be32(buf, 79616); /* Vendor-Specific Attribute */ wpabuf_put_be16(buf, EAP_TLV_VENDOR_SPECIFIC_TLV); ssoh_len = wpabuf_put(buf, 2); wpabuf_put_be32(buf, EAP_VENDOR_MICROSOFT); /* IANA SMI Code */ /* MS-Packet-Info */ wpabuf_put_u8(buf, SSOH_MS_PACKET_INFO); /* Note: IF-TNCCS-SOH v1.0 r8 claims this field to be: * Reserved(4 bits) r(1 bit) Vers(3 bits), but Windows XP * SP3 seems to be sending 0x11 for SSoH, i.e., r(request/response) bit * would not be in the specified location. * [MS-SOH] 4.0.2: Reserved(3 bits) r(1 bit) Vers(4 bits) */ wpabuf_put_u8(buf, 0x11); /* r=request, vers=1 */ /* MS-Machine-Inventory */ /* TODO: get correct values; 0 = not applicable for OS */ wpabuf_put_u8(buf, SSOH_MS_MACHINE_INVENTORY); wpabuf_put_be32(buf, 0); /* osVersionMajor */ wpabuf_put_be32(buf, 0); /* osVersionMinor */ wpabuf_put_be32(buf, 0); /* osVersionBuild */ wpabuf_put_be16(buf, 0); /* spVersionMajor */ wpabuf_put_be16(buf, 0); /* spVersionMinor */ wpabuf_put_be16(buf, 0); /* procArch */ /* MS-MachineName */ wpabuf_put_u8(buf, SSOH_MS_MACHINENAME); wpabuf_put_be16(buf, os_strlen(machinename) + 1); wpabuf_put_data(buf, machinename, os_strlen(machinename) + 1); /* MS-CorrelationId */ wpabuf_put_u8(buf, SSOH_MS_CORRELATIONID); wpabuf_put_data(buf, correlation_id, sizeof(correlation_id)); /* MS-Quarantine-State */ wpabuf_put_u8(buf, SSOH_MS_QUARANTINE_STATE); wpabuf_put_be16(buf, 1); /* Flags: ExtState=0, f=0, qState=1 */ wpabuf_put_be32(buf, 0xffffffff); /* ProbTime (hi) */ wpabuf_put_be32(buf, 0xffffffff); /* ProbTime (lo) */ wpabuf_put_be16(buf, 1); /* urlLenInBytes */ wpabuf_put_u8(buf, 0); /* null termination for the url */ /* MS-Machine-Inventory-Ex */ wpabuf_put_u8(buf, SSOH_MS_MACHINE_INVENTORY_EX); wpabuf_put_be32(buf, 0); /* Reserved * (note: Windows XP SP3 uses 0xdecafbad) */ wpabuf_put_u8(buf, 1); /* ProductType: Client */ /* Update SSoH Length */ end = wpabuf_put(buf, 0); WPA_PUT_BE16(ssoh_len, end - ssoh_len - 2); /* TODO: SoHReportEntry TLV (zero or more) */ /* Update length fields */ end = wpabuf_put(buf, 0); WPA_PUT_BE16(tlv_len, end - tlv_len - 2); WPA_PUT_BE16(tlv_len2, end - tlv_len2 - 2); WPA_PUT_BE16(outer_len, end - outer_len - 2); WPA_PUT_BE16(inner_len, end - inner_len - 2); return buf; }