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