18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP peer method: EAP-TNC (Trusted Network Connect) 38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2007, Jouni Malinen <j@w1.fi> 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license. 6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details. 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h" 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h" 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_i.h" 13014a3ff83915745d57480e99b47e281a82143c79Dmitry Shmidt#include "eap_config.h" 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "tncc.h" 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct eap_tnc_data { 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum { WAIT_START, PROC_MSG, WAIT_FRAG_ACK, DONE, FAIL } state; 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tncc_data *tncc; 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *in_buf; 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *out_buf; 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t out_used; 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t fragment_size; 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* EAP-TNC Flags */ 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define EAP_TNC_FLAGS_LENGTH_INCLUDED 0x80 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define EAP_TNC_FLAGS_MORE_FRAGMENTS 0x40 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define EAP_TNC_FLAGS_START 0x20 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define EAP_TNC_VERSION_MASK 0x07 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define EAP_TNC_VERSION 1 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void * eap_tnc_init(struct eap_sm *sm) 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_tnc_data *data; 39014a3ff83915745d57480e99b47e281a82143c79Dmitry Shmidt struct eap_peer_config *config = eap_get_config(sm); 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data = os_zalloc(sizeof(*data)); 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data == NULL) 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = WAIT_START; 45014a3ff83915745d57480e99b47e281a82143c79Dmitry Shmidt if (config && config->fragment_size) 46014a3ff83915745d57480e99b47e281a82143c79Dmitry Shmidt data->fragment_size = config->fragment_size; 47014a3ff83915745d57480e99b47e281a82143c79Dmitry Shmidt else 48014a3ff83915745d57480e99b47e281a82143c79Dmitry Shmidt data->fragment_size = 1300; 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->tncc = tncc_init(); 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->tncc == NULL) { 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data); 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data; 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_tnc_deinit(struct eap_sm *sm, void *priv) 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_tnc_data *data = priv; 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->in_buf); 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->out_buf); 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tncc_deinit(data->tncc); 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data); 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_tnc_build_frag_ack(u8 id, u8 code) 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *msg; 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TNC, 1, code, id); 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (msg == NULL) { 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "EAP-TNC: Failed to allocate memory " 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "for fragment ack"); 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(msg, EAP_TNC_VERSION); /* Flags */ 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TNC: Send fragment ack"); 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return msg; 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_tnc_build_msg(struct eap_tnc_data *data, 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method_ret *ret, u8 id) 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *resp; 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 flags; 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t send_len, plen; 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = FALSE; 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TNC: Generating Response"); 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->allowNotifications = TRUE; 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt flags = EAP_TNC_VERSION; 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt send_len = wpabuf_len(data->out_buf) - data->out_used; 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (1 + send_len > data->fragment_size) { 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt send_len = data->fragment_size - 1; 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt flags |= EAP_TNC_FLAGS_MORE_FRAGMENTS; 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->out_used == 0) { 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt flags |= EAP_TNC_FLAGS_LENGTH_INCLUDED; 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt send_len -= 4; 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt plen = 1 + send_len; 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (flags & EAP_TNC_FLAGS_LENGTH_INCLUDED) 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt plen += 4; 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TNC, plen, 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_CODE_RESPONSE, id); 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (resp == NULL) 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(resp, flags); /* Flags */ 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (flags & EAP_TNC_FLAGS_LENGTH_INCLUDED) 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be32(resp, wpabuf_len(data->out_buf)); 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_data(resp, wpabuf_head_u8(data->out_buf) + data->out_used, 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt send_len); 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->out_used += send_len; 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->methodState = METHOD_MAY_CONT; 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->decision = DECISION_FAIL; 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->out_used == wpabuf_len(data->out_buf)) { 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TNC: Sending out %lu bytes " 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(message sent completely)", 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) send_len); 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->out_buf); 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->out_buf = NULL; 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->out_used = 0; 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TNC: Sending out %lu bytes " 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(%lu more to send)", (unsigned long) send_len, 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) wpabuf_len(data->out_buf) - 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->out_used); 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = WAIT_FRAG_ACK; 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return resp; 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int eap_tnc_process_cont(struct eap_tnc_data *data, 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *buf, size_t len) 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Process continuation of a pending message */ 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len > wpabuf_tailroom(data->in_buf)) { 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TNC: Fragment overflow"); 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = FAIL; 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_data(data->in_buf, buf, len); 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TNC: Received %lu bytes, waiting for " 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "%lu bytes more", (unsigned long) len, 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) wpabuf_tailroom(data->in_buf)); 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_tnc_process_fragment(struct eap_tnc_data *data, 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method_ret *ret, 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 id, u8 flags, 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 message_length, 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *buf, size_t len) 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Process a fragment that is not the last one of the message */ 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->in_buf == NULL && !(flags & EAP_TNC_FLAGS_LENGTH_INCLUDED)) { 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TNC: No Message Length field in a " 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "fragmented packet"); 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->in_buf == NULL) { 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* First fragment of the message */ 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->in_buf = wpabuf_alloc(message_length); 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->in_buf == NULL) { 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TNC: No memory for " 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "message"); 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_data(data->in_buf, buf, len); 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TNC: Received %lu bytes in first " 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "fragment, waiting for %lu bytes more", 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) len, 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) wpabuf_tailroom(data->in_buf)); 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_tnc_build_frag_ack(id, EAP_CODE_RESPONSE); 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_tnc_process(struct eap_sm *sm, void *priv, 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method_ret *ret, 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *reqData) 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_tnc_data *data = priv; 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *resp; 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, *end; 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *rpos, *rpos1; 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len, rlen; 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t imc_len; 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *start_buf, *end_buf; 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t start_len, end_len; 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int tncs_done = 0; 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 flags, id; 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 message_length = 0; 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf tmpbuf; 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_TNC, reqData, &len); 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL) { 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-TNC: Invalid frame (pos=%p len=%lu)", 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos, (unsigned long) len); 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt id = eap_get_id(reqData); 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = pos + len; 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len == 0) 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt flags = 0; /* fragment ack */ 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt flags = *pos++; 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len > 0 && (flags & EAP_TNC_VERSION_MASK) != EAP_TNC_VERSION) { 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TNC: Unsupported version %d", 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt flags & EAP_TNC_VERSION_MASK); 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (flags & EAP_TNC_FLAGS_LENGTH_INCLUDED) { 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (end - pos < 4) { 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TNC: Message underflow"); 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt message_length = WPA_GET_BE32(pos); 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 4; 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 251623d63a3a443027e50efdaaec027befcc3882527Dmitry Shmidt if (message_length < (u32) (end - pos) || 252623d63a3a443027e50efdaaec027befcc3882527Dmitry Shmidt message_length > 75000) { 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TNC: Invalid Message " 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Length (%d; %ld remaining in this msg)", 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt message_length, (long) (end - pos)); 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TNC: Received packet: Flags 0x%x " 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Message Length %u", flags, message_length); 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state == WAIT_FRAG_ACK) { 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len > 1) { 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TNC: Unexpected payload in " 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "WAIT_FRAG_ACK state"); 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TNC: Fragment acknowledged"); 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = PROC_MSG; 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_tnc_build_msg(data, ret, id); 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->in_buf && eap_tnc_process_cont(data, pos, end - pos) < 0) { 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (flags & EAP_TNC_FLAGS_MORE_FRAGMENTS) { 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_tnc_process_fragment(data, ret, id, flags, 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt message_length, pos, 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end - pos); 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->in_buf == NULL) { 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Wrap unfragmented messages as wpabuf without extra copy */ 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_set(&tmpbuf, pos, end - pos); 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->in_buf = &tmpbuf; 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state == WAIT_START) { 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!(flags & EAP_TNC_FLAGS_START)) { 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TNC: Server did not use " 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "start flag in the first message"); 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tncc_init_connection(data->tncc); 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = PROC_MSG; 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum tncc_process_res res; 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (flags & EAP_TNC_FLAGS_START) { 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TNC: Server used start " 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "flag again"); 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = tncc_process_if_tnccs(data->tncc, 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_head(data->in_buf), 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_len(data->in_buf)); 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (res) { 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case TNCCS_PROCESS_ERROR: 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto fail; 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case TNCCS_PROCESS_OK_NO_RECOMMENDATION: 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case TNCCS_RECOMMENDATION_ERROR: 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TNC: No " 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "TNCCS-Recommendation received"); 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case TNCCS_RECOMMENDATION_ALLOW: 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->msg_ctx, MSG_INFO, 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "TNC: Recommendation = allow"); 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tncs_done = 1; 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case TNCCS_RECOMMENDATION_NONE: 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->msg_ctx, MSG_INFO, 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "TNC: Recommendation = none"); 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tncs_done = 1; 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case TNCCS_RECOMMENDATION_ISOLATE: 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->msg_ctx, MSG_INFO, 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "TNC: Recommendation = isolate"); 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tncs_done = 1; 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->in_buf != &tmpbuf) 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_free(data->in_buf); 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->in_buf = NULL; 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = FALSE; 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->methodState = METHOD_MAY_CONT; 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->decision = DECISION_UNCOND_SUCC; 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->allowNotifications = TRUE; 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tncs_done) { 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TNC, 1, 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_CODE_RESPONSE, eap_get_id(reqData)); 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (resp == NULL) 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_u8(resp, EAP_TNC_VERSION); 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-TNC: TNCS done - reply with an " 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "empty ACK message"); 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return resp; 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt imc_len = tncc_total_send_len(data->tncc); 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt start_buf = tncc_if_tnccs_start(data->tncc); 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (start_buf == NULL) 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt start_len = os_strlen(start_buf); 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end_buf = tncc_if_tnccs_end(); 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (end_buf == NULL) { 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(start_buf); 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end_len = os_strlen(end_buf); 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rlen = start_len + imc_len + end_len; 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp = wpabuf_alloc(rlen); 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (resp == NULL) { 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(start_buf); 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(end_buf); 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_data(resp, start_buf, start_len); 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(start_buf); 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rpos1 = wpabuf_put(resp, 0); 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rpos = tncc_copy_send_buf(data->tncc, rpos1); 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put(resp, rpos - rpos1); 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_data(resp, end_buf, end_len); 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(end_buf); 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-TNC: Response", 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_head(resp), wpabuf_len(resp)); 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->out_buf = resp; 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = PROC_MSG; 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_tnc_build_msg(data, ret, id); 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtfail: 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->in_buf == &tmpbuf) 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->in_buf = NULL; 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_peer_tnc_register(void) 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method *eap; 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_VENDOR_IETF, EAP_TYPE_TNC, "TNC"); 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap == NULL) 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->init = eap_tnc_init; 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->deinit = eap_tnc_deinit; 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->process = eap_tnc_process; 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4231d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt return eap_peer_method_register(eap); 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 425