tncc.c 30 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319
  1. /*
  2. * EAP-TNC - TNCC (IF-IMC and IF-TNCCS)
  3. * Copyright (c) 2007, Jouni Malinen <j@w1.fi>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2 as
  7. * published by the Free Software Foundation.
  8. *
  9. * Alternatively, this software may be distributed under the terms of BSD
  10. * license.
  11. *
  12. * See README and COPYING for more details.
  13. */
  14. #include "includes.h"
  15. #ifndef CONFIG_NATIVE_WINDOWS
  16. #include <dlfcn.h>
  17. #endif /* CONFIG_NATIVE_WINDOWS */
  18. #include "common.h"
  19. #include "base64.h"
  20. #include "tncc.h"
  21. #include "eap_common/eap_tlv_common.h"
  22. #include "eap_common/eap_defs.h"
  23. #ifdef UNICODE
  24. #define TSTR "%S"
  25. #else /* UNICODE */
  26. #define TSTR "%s"
  27. #endif /* UNICODE */
  28. #define TNC_CONFIG_FILE "/etc/tnc_config"
  29. #define TNC_WINREG_PATH TEXT("SOFTWARE\\Trusted Computing Group\\TNC\\IMCs")
  30. #define IF_TNCCS_START \
  31. "<?xml version=\"1.0\"?>\n" \
  32. "<TNCCS-Batch BatchId=\"%d\" Recipient=\"TNCS\" " \
  33. "xmlns=\"http://www.trustedcomputinggroup.org/IWG/TNC/1_0/IF_TNCCS#\" " \
  34. "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " \
  35. "xsi:schemaLocation=\"http://www.trustedcomputinggroup.org/IWG/TNC/1_0/" \
  36. "IF_TNCCS#https://www.trustedcomputinggroup.org/XML/SCHEMA/TNCCS_1.0.xsd\">\n"
  37. #define IF_TNCCS_END "\n</TNCCS-Batch>"
  38. /* TNC IF-IMC */
  39. typedef unsigned long TNC_UInt32;
  40. typedef unsigned char *TNC_BufferReference;
  41. typedef TNC_UInt32 TNC_IMCID;
  42. typedef TNC_UInt32 TNC_ConnectionID;
  43. typedef TNC_UInt32 TNC_ConnectionState;
  44. typedef TNC_UInt32 TNC_RetryReason;
  45. typedef TNC_UInt32 TNC_MessageType;
  46. typedef TNC_MessageType *TNC_MessageTypeList;
  47. typedef TNC_UInt32 TNC_VendorID;
  48. typedef TNC_UInt32 TNC_MessageSubtype;
  49. typedef TNC_UInt32 TNC_Version;
  50. typedef TNC_UInt32 TNC_Result;
  51. typedef TNC_Result (*TNC_TNCC_BindFunctionPointer)(
  52. TNC_IMCID imcID,
  53. char *functionName,
  54. void **pOutfunctionPointer);
  55. #define TNC_RESULT_SUCCESS 0
  56. #define TNC_RESULT_NOT_INITIALIZED 1
  57. #define TNC_RESULT_ALREADY_INITIALIZED 2
  58. #define TNC_RESULT_NO_COMMON_VERSION 3
  59. #define TNC_RESULT_CANT_RETRY 4
  60. #define TNC_RESULT_WONT_RETRY 5
  61. #define TNC_RESULT_INVALID_PARAMETER 6
  62. #define TNC_RESULT_CANT_RESPOND 7
  63. #define TNC_RESULT_ILLEGAL_OPERATION 8
  64. #define TNC_RESULT_OTHER 9
  65. #define TNC_RESULT_FATAL 10
  66. #define TNC_CONNECTION_STATE_CREATE 0
  67. #define TNC_CONNECTION_STATE_HANDSHAKE 1
  68. #define TNC_CONNECTION_STATE_ACCESS_ALLOWED 2
  69. #define TNC_CONNECTION_STATE_ACCESS_ISOLATED 3
  70. #define TNC_CONNECTION_STATE_ACCESS_NONE 4
  71. #define TNC_CONNECTION_STATE_DELETE 5
  72. #define TNC_IFIMC_VERSION_1 1
  73. #define TNC_VENDORID_ANY ((TNC_VendorID) 0xffffff)
  74. #define TNC_SUBTYPE_ANY ((TNC_MessageSubtype) 0xff)
  75. /* TNCC-TNCS Message Types */
  76. #define TNC_TNCCS_RECOMMENDATION 0x00000001
  77. #define TNC_TNCCS_ERROR 0x00000002
  78. #define TNC_TNCCS_PREFERREDLANGUAGE 0x00000003
  79. #define TNC_TNCCS_REASONSTRINGS 0x00000004
  80. struct tnc_if_imc {
  81. struct tnc_if_imc *next;
  82. char *name;
  83. char *path;
  84. void *dlhandle; /* from dlopen() */
  85. TNC_IMCID imcID;
  86. TNC_ConnectionID connectionID;
  87. TNC_MessageTypeList supported_types;
  88. size_t num_supported_types;
  89. u8 *imc_send;
  90. size_t imc_send_len;
  91. /* Functions implemented by IMCs (with TNC_IMC_ prefix) */
  92. TNC_Result (*Initialize)(
  93. TNC_IMCID imcID,
  94. TNC_Version minVersion,
  95. TNC_Version maxVersion,
  96. TNC_Version *pOutActualVersion);
  97. TNC_Result (*NotifyConnectionChange)(
  98. TNC_IMCID imcID,
  99. TNC_ConnectionID connectionID,
  100. TNC_ConnectionState newState);
  101. TNC_Result (*BeginHandshake)(
  102. TNC_IMCID imcID,
  103. TNC_ConnectionID connectionID);
  104. TNC_Result (*ReceiveMessage)(
  105. TNC_IMCID imcID,
  106. TNC_ConnectionID connectionID,
  107. TNC_BufferReference messageBuffer,
  108. TNC_UInt32 messageLength,
  109. TNC_MessageType messageType);
  110. TNC_Result (*BatchEnding)(
  111. TNC_IMCID imcID,
  112. TNC_ConnectionID connectionID);
  113. TNC_Result (*Terminate)(TNC_IMCID imcID);
  114. TNC_Result (*ProvideBindFunction)(
  115. TNC_IMCID imcID,
  116. TNC_TNCC_BindFunctionPointer bindFunction);
  117. };
  118. struct tncc_data {
  119. struct tnc_if_imc *imc;
  120. unsigned int last_batchid;
  121. };
  122. #define TNC_MAX_IMC_ID 10
  123. static struct tnc_if_imc *tnc_imc[TNC_MAX_IMC_ID] = { NULL };
  124. /* TNCC functions that IMCs can call */
  125. TNC_Result TNC_TNCC_ReportMessageTypes(
  126. TNC_IMCID imcID,
  127. TNC_MessageTypeList supportedTypes,
  128. TNC_UInt32 typeCount)
  129. {
  130. TNC_UInt32 i;
  131. struct tnc_if_imc *imc;
  132. wpa_printf(MSG_DEBUG, "TNC: TNC_TNCC_ReportMessageTypes(imcID=%lu "
  133. "typeCount=%lu)",
  134. (unsigned long) imcID, (unsigned long) typeCount);
  135. for (i = 0; i < typeCount; i++) {
  136. wpa_printf(MSG_DEBUG, "TNC: supportedTypes[%lu] = %lu",
  137. i, supportedTypes[i]);
  138. }
  139. if (imcID >= TNC_MAX_IMC_ID || tnc_imc[imcID] == NULL)
  140. return TNC_RESULT_INVALID_PARAMETER;
  141. imc = tnc_imc[imcID];
  142. os_free(imc->supported_types);
  143. imc->supported_types =
  144. os_malloc(typeCount * sizeof(TNC_MessageTypeList));
  145. if (imc->supported_types == NULL)
  146. return TNC_RESULT_FATAL;
  147. os_memcpy(imc->supported_types, supportedTypes,
  148. typeCount * sizeof(TNC_MessageTypeList));
  149. imc->num_supported_types = typeCount;
  150. return TNC_RESULT_SUCCESS;
  151. }
  152. TNC_Result TNC_TNCC_SendMessage(
  153. TNC_IMCID imcID,
  154. TNC_ConnectionID connectionID,
  155. TNC_BufferReference message,
  156. TNC_UInt32 messageLength,
  157. TNC_MessageType messageType)
  158. {
  159. struct tnc_if_imc *imc;
  160. unsigned char *b64;
  161. size_t b64len;
  162. wpa_printf(MSG_DEBUG, "TNC: TNC_TNCC_SendMessage(imcID=%lu "
  163. "connectionID=%lu messageType=%lu)",
  164. imcID, connectionID, messageType);
  165. wpa_hexdump_ascii(MSG_DEBUG, "TNC: TNC_TNCC_SendMessage",
  166. message, messageLength);
  167. if (imcID >= TNC_MAX_IMC_ID || tnc_imc[imcID] == NULL)
  168. return TNC_RESULT_INVALID_PARAMETER;
  169. b64 = base64_encode(message, messageLength, &b64len);
  170. if (b64 == NULL)
  171. return TNC_RESULT_FATAL;
  172. imc = tnc_imc[imcID];
  173. os_free(imc->imc_send);
  174. imc->imc_send_len = 0;
  175. imc->imc_send = os_zalloc(b64len + 100);
  176. if (imc->imc_send == NULL) {
  177. os_free(b64);
  178. return TNC_RESULT_OTHER;
  179. }
  180. imc->imc_send_len =
  181. os_snprintf((char *) imc->imc_send, b64len + 100,
  182. "<IMC-IMV-Message><Type>%08X</Type>"
  183. "<Base64>%s</Base64></IMC-IMV-Message>",
  184. (unsigned int) messageType, b64);
  185. os_free(b64);
  186. return TNC_RESULT_SUCCESS;
  187. }
  188. TNC_Result TNC_TNCC_RequestHandshakeRetry(
  189. TNC_IMCID imcID,
  190. TNC_ConnectionID connectionID,
  191. TNC_RetryReason reason)
  192. {
  193. wpa_printf(MSG_DEBUG, "TNC: TNC_TNCC_RequestHandshakeRetry");
  194. if (imcID >= TNC_MAX_IMC_ID || tnc_imc[imcID] == NULL)
  195. return TNC_RESULT_INVALID_PARAMETER;
  196. /*
  197. * TODO: trigger a call to eapol_sm_request_reauth(). This would
  198. * require that the IMC continues to be loaded in memory afer
  199. * authentication..
  200. */
  201. return TNC_RESULT_SUCCESS;
  202. }
  203. TNC_Result TNC_9048_LogMessage(TNC_IMCID imcID, TNC_UInt32 severity,
  204. const char *message)
  205. {
  206. wpa_printf(MSG_DEBUG, "TNC: TNC_9048_LogMessage(imcID=%lu "
  207. "severity==%lu message='%s')",
  208. imcID, severity, message);
  209. return TNC_RESULT_SUCCESS;
  210. }
  211. TNC_Result TNC_9048_UserMessage(TNC_IMCID imcID, TNC_ConnectionID connectionID,
  212. const char *message)
  213. {
  214. wpa_printf(MSG_DEBUG, "TNC: TNC_9048_UserMessage(imcID=%lu "
  215. "connectionID==%lu message='%s')",
  216. imcID, connectionID, message);
  217. return TNC_RESULT_SUCCESS;
  218. }
  219. TNC_Result TNC_TNCC_BindFunction(
  220. TNC_IMCID imcID,
  221. char *functionName,
  222. void **pOutfunctionPointer)
  223. {
  224. wpa_printf(MSG_DEBUG, "TNC: TNC_TNCC_BindFunction(imcID=%lu, "
  225. "functionName='%s')", (unsigned long) imcID, functionName);
  226. if (imcID >= TNC_MAX_IMC_ID || tnc_imc[imcID] == NULL)
  227. return TNC_RESULT_INVALID_PARAMETER;
  228. if (pOutfunctionPointer == NULL)
  229. return TNC_RESULT_INVALID_PARAMETER;
  230. if (os_strcmp(functionName, "TNC_TNCC_ReportMessageTypes") == 0)
  231. *pOutfunctionPointer = TNC_TNCC_ReportMessageTypes;
  232. else if (os_strcmp(functionName, "TNC_TNCC_SendMessage") == 0)
  233. *pOutfunctionPointer = TNC_TNCC_SendMessage;
  234. else if (os_strcmp(functionName, "TNC_TNCC_RequestHandshakeRetry") ==
  235. 0)
  236. *pOutfunctionPointer = TNC_TNCC_RequestHandshakeRetry;
  237. else if (os_strcmp(functionName, "TNC_9048_LogMessage") == 0)
  238. *pOutfunctionPointer = TNC_9048_LogMessage;
  239. else if (os_strcmp(functionName, "TNC_9048_UserMessage") == 0)
  240. *pOutfunctionPointer = TNC_9048_UserMessage;
  241. else
  242. *pOutfunctionPointer = NULL;
  243. return TNC_RESULT_SUCCESS;
  244. }
  245. static void * tncc_get_sym(void *handle, char *func)
  246. {
  247. void *fptr;
  248. #ifdef CONFIG_NATIVE_WINDOWS
  249. #ifdef _WIN32_WCE
  250. fptr = GetProcAddressA(handle, func);
  251. #else /* _WIN32_WCE */
  252. fptr = GetProcAddress(handle, func);
  253. #endif /* _WIN32_WCE */
  254. #else /* CONFIG_NATIVE_WINDOWS */
  255. fptr = dlsym(handle, func);
  256. #endif /* CONFIG_NATIVE_WINDOWS */
  257. return fptr;
  258. }
  259. static int tncc_imc_resolve_funcs(struct tnc_if_imc *imc)
  260. {
  261. void *handle = imc->dlhandle;
  262. /* Mandatory IMC functions */
  263. imc->Initialize = tncc_get_sym(handle, "TNC_IMC_Initialize");
  264. if (imc->Initialize == NULL) {
  265. wpa_printf(MSG_ERROR, "TNC: IMC does not export "
  266. "TNC_IMC_Initialize");
  267. return -1;
  268. }
  269. imc->BeginHandshake = tncc_get_sym(handle, "TNC_IMC_BeginHandshake");
  270. if (imc->BeginHandshake == NULL) {
  271. wpa_printf(MSG_ERROR, "TNC: IMC does not export "
  272. "TNC_IMC_BeginHandshake");
  273. return -1;
  274. }
  275. imc->ProvideBindFunction =
  276. tncc_get_sym(handle, "TNC_IMC_ProvideBindFunction");
  277. if (imc->ProvideBindFunction == NULL) {
  278. wpa_printf(MSG_ERROR, "TNC: IMC does not export "
  279. "TNC_IMC_ProvideBindFunction");
  280. return -1;
  281. }
  282. /* Optional IMC functions */
  283. imc->NotifyConnectionChange =
  284. tncc_get_sym(handle, "TNC_IMC_NotifyConnectionChange");
  285. imc->ReceiveMessage = tncc_get_sym(handle, "TNC_IMC_ReceiveMessage");
  286. imc->BatchEnding = tncc_get_sym(handle, "TNC_IMC_BatchEnding");
  287. imc->Terminate = tncc_get_sym(handle, "TNC_IMC_Terminate");
  288. return 0;
  289. }
  290. static int tncc_imc_initialize(struct tnc_if_imc *imc)
  291. {
  292. TNC_Result res;
  293. TNC_Version imc_ver;
  294. wpa_printf(MSG_DEBUG, "TNC: Calling TNC_IMC_Initialize for IMC '%s'",
  295. imc->name);
  296. res = imc->Initialize(imc->imcID, TNC_IFIMC_VERSION_1,
  297. TNC_IFIMC_VERSION_1, &imc_ver);
  298. wpa_printf(MSG_DEBUG, "TNC: TNC_IMC_Initialize: res=%lu imc_ver=%lu",
  299. (unsigned long) res, (unsigned long) imc_ver);
  300. return res == TNC_RESULT_SUCCESS ? 0 : -1;
  301. }
  302. static int tncc_imc_terminate(struct tnc_if_imc *imc)
  303. {
  304. TNC_Result res;
  305. if (imc->Terminate == NULL)
  306. return 0;
  307. wpa_printf(MSG_DEBUG, "TNC: Calling TNC_IMC_Terminate for IMC '%s'",
  308. imc->name);
  309. res = imc->Terminate(imc->imcID);
  310. wpa_printf(MSG_DEBUG, "TNC: TNC_IMC_Terminate: %lu",
  311. (unsigned long) res);
  312. return res == TNC_RESULT_SUCCESS ? 0 : -1;
  313. }
  314. static int tncc_imc_provide_bind_function(struct tnc_if_imc *imc)
  315. {
  316. TNC_Result res;
  317. wpa_printf(MSG_DEBUG, "TNC: Calling TNC_IMC_ProvideBindFunction for "
  318. "IMC '%s'", imc->name);
  319. res = imc->ProvideBindFunction(imc->imcID, TNC_TNCC_BindFunction);
  320. wpa_printf(MSG_DEBUG, "TNC: TNC_IMC_ProvideBindFunction: res=%lu",
  321. (unsigned long) res);
  322. return res == TNC_RESULT_SUCCESS ? 0 : -1;
  323. }
  324. static int tncc_imc_notify_connection_change(struct tnc_if_imc *imc,
  325. TNC_ConnectionState state)
  326. {
  327. TNC_Result res;
  328. if (imc->NotifyConnectionChange == NULL)
  329. return 0;
  330. wpa_printf(MSG_DEBUG, "TNC: Calling TNC_IMC_NotifyConnectionChange(%d)"
  331. " for IMC '%s'", (int) state, imc->name);
  332. res = imc->NotifyConnectionChange(imc->imcID, imc->connectionID,
  333. state);
  334. wpa_printf(MSG_DEBUG, "TNC: TNC_IMC_NotifyConnectionChange: %lu",
  335. (unsigned long) res);
  336. return res == TNC_RESULT_SUCCESS ? 0 : -1;
  337. }
  338. static int tncc_imc_begin_handshake(struct tnc_if_imc *imc)
  339. {
  340. TNC_Result res;
  341. wpa_printf(MSG_DEBUG, "TNC: Calling TNC_IMC_BeginHandshake for IMC "
  342. "'%s'", imc->name);
  343. res = imc->BeginHandshake(imc->imcID, imc->connectionID);
  344. wpa_printf(MSG_DEBUG, "TNC: TNC_IMC_BeginHandshake: %lu",
  345. (unsigned long) res);
  346. return res == TNC_RESULT_SUCCESS ? 0 : -1;
  347. }
  348. static int tncc_load_imc(struct tnc_if_imc *imc)
  349. {
  350. if (imc->path == NULL) {
  351. wpa_printf(MSG_DEBUG, "TNC: No IMC configured");
  352. return -1;
  353. }
  354. wpa_printf(MSG_DEBUG, "TNC: Opening IMC: %s (%s)",
  355. imc->name, imc->path);
  356. #ifdef CONFIG_NATIVE_WINDOWS
  357. #ifdef UNICODE
  358. {
  359. TCHAR *lib = wpa_strdup_tchar(imc->path);
  360. if (lib == NULL)
  361. return -1;
  362. imc->dlhandle = LoadLibrary(lib);
  363. os_free(lib);
  364. }
  365. #else /* UNICODE */
  366. imc->dlhandle = LoadLibrary(imc->path);
  367. #endif /* UNICODE */
  368. if (imc->dlhandle == NULL) {
  369. wpa_printf(MSG_ERROR, "TNC: Failed to open IMC '%s' (%s): %d",
  370. imc->name, imc->path, (int) GetLastError());
  371. return -1;
  372. }
  373. #else /* CONFIG_NATIVE_WINDOWS */
  374. imc->dlhandle = dlopen(imc->path, RTLD_LAZY);
  375. if (imc->dlhandle == NULL) {
  376. wpa_printf(MSG_ERROR, "TNC: Failed to open IMC '%s' (%s): %s",
  377. imc->name, imc->path, dlerror());
  378. return -1;
  379. }
  380. #endif /* CONFIG_NATIVE_WINDOWS */
  381. if (tncc_imc_resolve_funcs(imc) < 0) {
  382. wpa_printf(MSG_ERROR, "TNC: Failed to resolve IMC functions");
  383. return -1;
  384. }
  385. if (tncc_imc_initialize(imc) < 0 ||
  386. tncc_imc_provide_bind_function(imc) < 0) {
  387. wpa_printf(MSG_ERROR, "TNC: Failed to initialize IMC");
  388. return -1;
  389. }
  390. return 0;
  391. }
  392. static void tncc_unload_imc(struct tnc_if_imc *imc)
  393. {
  394. tncc_imc_terminate(imc);
  395. tnc_imc[imc->imcID] = NULL;
  396. if (imc->dlhandle) {
  397. #ifdef CONFIG_NATIVE_WINDOWS
  398. FreeLibrary(imc->dlhandle);
  399. #else /* CONFIG_NATIVE_WINDOWS */
  400. dlclose(imc->dlhandle);
  401. #endif /* CONFIG_NATIVE_WINDOWS */
  402. }
  403. os_free(imc->name);
  404. os_free(imc->path);
  405. os_free(imc->supported_types);
  406. os_free(imc->imc_send);
  407. }
  408. static int tncc_supported_type(struct tnc_if_imc *imc, unsigned int type)
  409. {
  410. size_t i;
  411. unsigned int vendor, subtype;
  412. if (imc == NULL || imc->supported_types == NULL)
  413. return 0;
  414. vendor = type >> 8;
  415. subtype = type & 0xff;
  416. for (i = 0; i < imc->num_supported_types; i++) {
  417. unsigned int svendor, ssubtype;
  418. svendor = imc->supported_types[i] >> 8;
  419. ssubtype = imc->supported_types[i] & 0xff;
  420. if ((vendor == svendor || svendor == TNC_VENDORID_ANY) &&
  421. (subtype == ssubtype || ssubtype == TNC_SUBTYPE_ANY))
  422. return 1;
  423. }
  424. return 0;
  425. }
  426. static void tncc_send_to_imcs(struct tncc_data *tncc, unsigned int type,
  427. const u8 *msg, size_t len)
  428. {
  429. struct tnc_if_imc *imc;
  430. TNC_Result res;
  431. wpa_hexdump_ascii(MSG_MSGDUMP, "TNC: Message to IMC(s)", msg, len);
  432. for (imc = tncc->imc; imc; imc = imc->next) {
  433. if (imc->ReceiveMessage == NULL ||
  434. !tncc_supported_type(imc, type))
  435. continue;
  436. wpa_printf(MSG_DEBUG, "TNC: Call ReceiveMessage for IMC '%s'",
  437. imc->name);
  438. res = imc->ReceiveMessage(imc->imcID, imc->connectionID,
  439. (TNC_BufferReference) msg, len,
  440. type);
  441. wpa_printf(MSG_DEBUG, "TNC: ReceiveMessage: %lu",
  442. (unsigned long) res);
  443. }
  444. }
  445. void tncc_init_connection(struct tncc_data *tncc)
  446. {
  447. struct tnc_if_imc *imc;
  448. for (imc = tncc->imc; imc; imc = imc->next) {
  449. tncc_imc_notify_connection_change(
  450. imc, TNC_CONNECTION_STATE_CREATE);
  451. tncc_imc_notify_connection_change(
  452. imc, TNC_CONNECTION_STATE_HANDSHAKE);
  453. os_free(imc->imc_send);
  454. imc->imc_send = NULL;
  455. imc->imc_send_len = 0;
  456. tncc_imc_begin_handshake(imc);
  457. }
  458. }
  459. size_t tncc_total_send_len(struct tncc_data *tncc)
  460. {
  461. struct tnc_if_imc *imc;
  462. size_t len = 0;
  463. for (imc = tncc->imc; imc; imc = imc->next)
  464. len += imc->imc_send_len;
  465. return len;
  466. }
  467. u8 * tncc_copy_send_buf(struct tncc_data *tncc, u8 *pos)
  468. {
  469. struct tnc_if_imc *imc;
  470. for (imc = tncc->imc; imc; imc = imc->next) {
  471. if (imc->imc_send == NULL)
  472. continue;
  473. os_memcpy(pos, imc->imc_send, imc->imc_send_len);
  474. pos += imc->imc_send_len;
  475. os_free(imc->imc_send);
  476. imc->imc_send = NULL;
  477. imc->imc_send_len = 0;
  478. }
  479. return pos;
  480. }
  481. char * tncc_if_tnccs_start(struct tncc_data *tncc)
  482. {
  483. char *buf = os_malloc(1000);
  484. if (buf == NULL)
  485. return NULL;
  486. tncc->last_batchid++;
  487. os_snprintf(buf, 1000, IF_TNCCS_START, tncc->last_batchid);
  488. return buf;
  489. }
  490. char * tncc_if_tnccs_end(void)
  491. {
  492. char *buf = os_malloc(100);
  493. if (buf == NULL)
  494. return NULL;
  495. os_snprintf(buf, 100, IF_TNCCS_END);
  496. return buf;
  497. }
  498. static void tncc_notify_recommendation(struct tncc_data *tncc,
  499. enum tncc_process_res res)
  500. {
  501. TNC_ConnectionState state;
  502. struct tnc_if_imc *imc;
  503. switch (res) {
  504. case TNCCS_RECOMMENDATION_ALLOW:
  505. state = TNC_CONNECTION_STATE_ACCESS_ALLOWED;
  506. break;
  507. case TNCCS_RECOMMENDATION_NONE:
  508. state = TNC_CONNECTION_STATE_ACCESS_NONE;
  509. break;
  510. case TNCCS_RECOMMENDATION_ISOLATE:
  511. state = TNC_CONNECTION_STATE_ACCESS_ISOLATED;
  512. break;
  513. default:
  514. state = TNC_CONNECTION_STATE_ACCESS_NONE;
  515. break;
  516. }
  517. for (imc = tncc->imc; imc; imc = imc->next)
  518. tncc_imc_notify_connection_change(imc, state);
  519. }
  520. static int tncc_get_type(char *start, unsigned int *type)
  521. {
  522. char *pos = os_strstr(start, "<Type>");
  523. if (pos == NULL)
  524. return -1;
  525. pos += 6;
  526. *type = strtoul(pos, NULL, 16);
  527. return 0;
  528. }
  529. static unsigned char * tncc_get_base64(char *start, size_t *decoded_len)
  530. {
  531. char *pos, *pos2;
  532. unsigned char *decoded;
  533. pos = os_strstr(start, "<Base64>");
  534. if (pos == NULL)
  535. return NULL;
  536. pos += 8;
  537. pos2 = os_strstr(pos, "</Base64>");
  538. if (pos2 == NULL)
  539. return NULL;
  540. *pos2 = '\0';
  541. decoded = base64_decode((unsigned char *) pos, os_strlen(pos),
  542. decoded_len);
  543. *pos2 = '<';
  544. if (decoded == NULL) {
  545. wpa_printf(MSG_DEBUG, "TNC: Failed to decode Base64 data");
  546. }
  547. return decoded;
  548. }
  549. static enum tncc_process_res tncc_get_recommendation(char *start)
  550. {
  551. char *pos, *pos2, saved;
  552. int recom;
  553. pos = os_strstr(start, "<TNCCS-Recommendation ");
  554. if (pos == NULL)
  555. return TNCCS_RECOMMENDATION_ERROR;
  556. pos += 21;
  557. pos = os_strstr(pos, " type=");
  558. if (pos == NULL)
  559. return TNCCS_RECOMMENDATION_ERROR;
  560. pos += 6;
  561. if (*pos == '"')
  562. pos++;
  563. pos2 = pos;
  564. while (*pos2 != '\0' && *pos2 != '"' && *pos2 != '>')
  565. pos2++;
  566. if (*pos2 == '\0')
  567. return TNCCS_RECOMMENDATION_ERROR;
  568. saved = *pos2;
  569. *pos2 = '\0';
  570. wpa_printf(MSG_DEBUG, "TNC: TNCCS-Recommendation: '%s'", pos);
  571. recom = TNCCS_RECOMMENDATION_ERROR;
  572. if (os_strcmp(pos, "allow") == 0)
  573. recom = TNCCS_RECOMMENDATION_ALLOW;
  574. else if (os_strcmp(pos, "none") == 0)
  575. recom = TNCCS_RECOMMENDATION_NONE;
  576. else if (os_strcmp(pos, "isolate") == 0)
  577. recom = TNCCS_RECOMMENDATION_ISOLATE;
  578. *pos2 = saved;
  579. return recom;
  580. }
  581. enum tncc_process_res tncc_process_if_tnccs(struct tncc_data *tncc,
  582. const u8 *msg, size_t len)
  583. {
  584. char *buf, *start, *end, *pos, *pos2, *payload;
  585. unsigned int batch_id;
  586. unsigned char *decoded;
  587. size_t decoded_len;
  588. enum tncc_process_res res = TNCCS_PROCESS_OK_NO_RECOMMENDATION;
  589. int recommendation_msg = 0;
  590. buf = os_malloc(len + 1);
  591. if (buf == NULL)
  592. return TNCCS_PROCESS_ERROR;
  593. os_memcpy(buf, msg, len);
  594. buf[len] = '\0';
  595. start = os_strstr(buf, "<TNCCS-Batch ");
  596. end = os_strstr(buf, "</TNCCS-Batch>");
  597. if (start == NULL || end == NULL || start > end) {
  598. os_free(buf);
  599. return TNCCS_PROCESS_ERROR;
  600. }
  601. start += 13;
  602. while (*start == ' ')
  603. start++;
  604. *end = '\0';
  605. pos = os_strstr(start, "BatchId=");
  606. if (pos == NULL) {
  607. os_free(buf);
  608. return TNCCS_PROCESS_ERROR;
  609. }
  610. pos += 8;
  611. if (*pos == '"')
  612. pos++;
  613. batch_id = atoi(pos);
  614. wpa_printf(MSG_DEBUG, "TNC: Received IF-TNCCS BatchId=%u",
  615. batch_id);
  616. if (batch_id != tncc->last_batchid + 1) {
  617. wpa_printf(MSG_DEBUG, "TNC: Unexpected IF-TNCCS BatchId "
  618. "%u (expected %u)",
  619. batch_id, tncc->last_batchid + 1);
  620. os_free(buf);
  621. return TNCCS_PROCESS_ERROR;
  622. }
  623. tncc->last_batchid = batch_id;
  624. while (*pos != '\0' && *pos != '>')
  625. pos++;
  626. if (*pos == '\0') {
  627. os_free(buf);
  628. return TNCCS_PROCESS_ERROR;
  629. }
  630. pos++;
  631. payload = start;
  632. /*
  633. * <IMC-IMV-Message>
  634. * <Type>01234567</Type>
  635. * <Base64>foo==</Base64>
  636. * </IMC-IMV-Message>
  637. */
  638. while (*start) {
  639. char *endpos;
  640. unsigned int type;
  641. pos = os_strstr(start, "<IMC-IMV-Message>");
  642. if (pos == NULL)
  643. break;
  644. start = pos + 17;
  645. end = os_strstr(start, "</IMC-IMV-Message>");
  646. if (end == NULL)
  647. break;
  648. *end = '\0';
  649. endpos = end;
  650. end += 18;
  651. if (tncc_get_type(start, &type) < 0) {
  652. *endpos = '<';
  653. start = end;
  654. continue;
  655. }
  656. wpa_printf(MSG_DEBUG, "TNC: IMC-IMV-Message Type 0x%x", type);
  657. decoded = tncc_get_base64(start, &decoded_len);
  658. if (decoded == NULL) {
  659. *endpos = '<';
  660. start = end;
  661. continue;
  662. }
  663. tncc_send_to_imcs(tncc, type, decoded, decoded_len);
  664. os_free(decoded);
  665. start = end;
  666. }
  667. /*
  668. * <TNCC-TNCS-Message>
  669. * <Type>01234567</Type>
  670. * <XML><TNCCS-Foo type="foo"></TNCCS-Foo></XML>
  671. * <Base64>foo==</Base64>
  672. * </TNCC-TNCS-Message>
  673. */
  674. start = payload;
  675. while (*start) {
  676. unsigned int type;
  677. char *xml, *xmlend, *endpos;
  678. pos = os_strstr(start, "<TNCC-TNCS-Message>");
  679. if (pos == NULL)
  680. break;
  681. start = pos + 19;
  682. end = os_strstr(start, "</TNCC-TNCS-Message>");
  683. if (end == NULL)
  684. break;
  685. *end = '\0';
  686. endpos = end;
  687. end += 20;
  688. if (tncc_get_type(start, &type) < 0) {
  689. *endpos = '<';
  690. start = end;
  691. continue;
  692. }
  693. wpa_printf(MSG_DEBUG, "TNC: TNCC-TNCS-Message Type 0x%x",
  694. type);
  695. /* Base64 OR XML */
  696. decoded = NULL;
  697. xml = NULL;
  698. xmlend = NULL;
  699. pos = os_strstr(start, "<XML>");
  700. if (pos) {
  701. pos += 5;
  702. pos2 = os_strstr(pos, "</XML>");
  703. if (pos2 == NULL) {
  704. *endpos = '<';
  705. start = end;
  706. continue;
  707. }
  708. xmlend = pos2;
  709. xml = pos;
  710. } else {
  711. decoded = tncc_get_base64(start, &decoded_len);
  712. if (decoded == NULL) {
  713. *endpos = '<';
  714. start = end;
  715. continue;
  716. }
  717. }
  718. if (decoded) {
  719. wpa_hexdump_ascii(MSG_MSGDUMP,
  720. "TNC: TNCC-TNCS-Message Base64",
  721. decoded, decoded_len);
  722. os_free(decoded);
  723. }
  724. if (xml) {
  725. wpa_hexdump_ascii(MSG_MSGDUMP,
  726. "TNC: TNCC-TNCS-Message XML",
  727. (unsigned char *) xml,
  728. xmlend - xml);
  729. }
  730. if (type == TNC_TNCCS_RECOMMENDATION && xml) {
  731. /*
  732. * <TNCCS-Recommendation type="allow">
  733. * </TNCCS-Recommendation>
  734. */
  735. *xmlend = '\0';
  736. res = tncc_get_recommendation(xml);
  737. *xmlend = '<';
  738. recommendation_msg = 1;
  739. }
  740. start = end;
  741. }
  742. os_free(buf);
  743. if (recommendation_msg)
  744. tncc_notify_recommendation(tncc, res);
  745. return res;
  746. }
  747. #ifdef CONFIG_NATIVE_WINDOWS
  748. static int tncc_read_config_reg(struct tncc_data *tncc, HKEY hive)
  749. {
  750. HKEY hk, hk2;
  751. LONG ret;
  752. DWORD i;
  753. struct tnc_if_imc *imc, *last;
  754. int j;
  755. last = tncc->imc;
  756. while (last && last->next)
  757. last = last->next;
  758. ret = RegOpenKeyEx(hive, TNC_WINREG_PATH, 0, KEY_ENUMERATE_SUB_KEYS,
  759. &hk);
  760. if (ret != ERROR_SUCCESS)
  761. return 0;
  762. for (i = 0; ; i++) {
  763. TCHAR name[255], *val;
  764. DWORD namelen, buflen;
  765. namelen = 255;
  766. ret = RegEnumKeyEx(hk, i, name, &namelen, NULL, NULL, NULL,
  767. NULL);
  768. if (ret == ERROR_NO_MORE_ITEMS)
  769. break;
  770. if (ret != ERROR_SUCCESS) {
  771. wpa_printf(MSG_DEBUG, "TNC: RegEnumKeyEx failed: 0x%x",
  772. (unsigned int) ret);
  773. break;
  774. }
  775. if (namelen >= 255)
  776. namelen = 255 - 1;
  777. name[namelen] = '\0';
  778. wpa_printf(MSG_DEBUG, "TNC: IMC '" TSTR "'", name);
  779. ret = RegOpenKeyEx(hk, name, 0, KEY_QUERY_VALUE, &hk2);
  780. if (ret != ERROR_SUCCESS) {
  781. wpa_printf(MSG_DEBUG, "Could not open IMC key '" TSTR
  782. "'", name);
  783. continue;
  784. }
  785. ret = RegQueryValueEx(hk2, TEXT("Path"), NULL, NULL, NULL,
  786. &buflen);
  787. if (ret != ERROR_SUCCESS) {
  788. wpa_printf(MSG_DEBUG, "TNC: Could not read Path from "
  789. "IMC key '" TSTR "'", name);
  790. RegCloseKey(hk2);
  791. continue;
  792. }
  793. val = os_malloc(buflen);
  794. if (val == NULL) {
  795. RegCloseKey(hk2);
  796. continue;
  797. }
  798. ret = RegQueryValueEx(hk2, TEXT("Path"), NULL, NULL,
  799. (LPBYTE) val, &buflen);
  800. if (ret != ERROR_SUCCESS) {
  801. os_free(val);
  802. RegCloseKey(hk2);
  803. continue;
  804. }
  805. RegCloseKey(hk2);
  806. wpa_unicode2ascii_inplace(val);
  807. wpa_printf(MSG_DEBUG, "TNC: IMC Path '%s'", (char *) val);
  808. for (j = 0; j < TNC_MAX_IMC_ID; j++) {
  809. if (tnc_imc[j] == NULL)
  810. break;
  811. }
  812. if (j >= TNC_MAX_IMC_ID) {
  813. wpa_printf(MSG_DEBUG, "TNC: Too many IMCs");
  814. os_free(val);
  815. continue;
  816. }
  817. imc = os_zalloc(sizeof(*imc));
  818. if (imc == NULL) {
  819. os_free(val);
  820. break;
  821. }
  822. imc->imcID = j;
  823. wpa_unicode2ascii_inplace(name);
  824. imc->name = os_strdup((char *) name);
  825. imc->path = os_strdup((char *) val);
  826. os_free(val);
  827. if (last == NULL)
  828. tncc->imc = imc;
  829. else
  830. last->next = imc;
  831. last = imc;
  832. tnc_imc[imc->imcID] = imc;
  833. }
  834. RegCloseKey(hk);
  835. return 0;
  836. }
  837. static int tncc_read_config(struct tncc_data *tncc)
  838. {
  839. if (tncc_read_config_reg(tncc, HKEY_LOCAL_MACHINE) < 0 ||
  840. tncc_read_config_reg(tncc, HKEY_CURRENT_USER) < 0)
  841. return -1;
  842. return 0;
  843. }
  844. #else /* CONFIG_NATIVE_WINDOWS */
  845. static struct tnc_if_imc * tncc_parse_imc(char *start, char *end, int *error)
  846. {
  847. struct tnc_if_imc *imc;
  848. char *pos, *pos2;
  849. int i;
  850. for (i = 0; i < TNC_MAX_IMC_ID; i++) {
  851. if (tnc_imc[i] == NULL)
  852. break;
  853. }
  854. if (i >= TNC_MAX_IMC_ID) {
  855. wpa_printf(MSG_DEBUG, "TNC: Too many IMCs");
  856. return NULL;
  857. }
  858. imc = os_zalloc(sizeof(*imc));
  859. if (imc == NULL) {
  860. *error = 1;
  861. return NULL;
  862. }
  863. imc->imcID = i;
  864. pos = start;
  865. wpa_printf(MSG_DEBUG, "TNC: Configured IMC: %s", pos);
  866. if (pos + 1 >= end || *pos != '"') {
  867. wpa_printf(MSG_ERROR, "TNC: Ignoring invalid IMC line '%s' "
  868. "(no starting quotation mark)", start);
  869. os_free(imc);
  870. return NULL;
  871. }
  872. pos++;
  873. pos2 = pos;
  874. while (pos2 < end && *pos2 != '"')
  875. pos2++;
  876. if (pos2 >= end) {
  877. wpa_printf(MSG_ERROR, "TNC: Ignoring invalid IMC line '%s' "
  878. "(no ending quotation mark)", start);
  879. os_free(imc);
  880. return NULL;
  881. }
  882. *pos2 = '\0';
  883. wpa_printf(MSG_DEBUG, "TNC: Name: '%s'", pos);
  884. imc->name = os_strdup(pos);
  885. pos = pos2 + 1;
  886. if (pos >= end || *pos != ' ') {
  887. wpa_printf(MSG_ERROR, "TNC: Ignoring invalid IMC line '%s' "
  888. "(no space after name)", start);
  889. os_free(imc);
  890. return NULL;
  891. }
  892. pos++;
  893. wpa_printf(MSG_DEBUG, "TNC: IMC file: '%s'", pos);
  894. imc->path = os_strdup(pos);
  895. tnc_imc[imc->imcID] = imc;
  896. return imc;
  897. }
  898. static int tncc_read_config(struct tncc_data *tncc)
  899. {
  900. char *config, *end, *pos, *line_end;
  901. size_t config_len;
  902. struct tnc_if_imc *imc, *last;
  903. last = NULL;
  904. config = os_readfile(TNC_CONFIG_FILE, &config_len);
  905. if (config == NULL) {
  906. wpa_printf(MSG_ERROR, "TNC: Could not open TNC configuration "
  907. "file '%s'", TNC_CONFIG_FILE);
  908. return -1;
  909. }
  910. end = config + config_len;
  911. for (pos = config; pos < end; pos = line_end + 1) {
  912. line_end = pos;
  913. while (*line_end != '\n' && *line_end != '\r' &&
  914. line_end < end)
  915. line_end++;
  916. *line_end = '\0';
  917. if (os_strncmp(pos, "IMC ", 4) == 0) {
  918. int error = 0;
  919. imc = tncc_parse_imc(pos + 4, line_end, &error);
  920. if (error)
  921. return -1;
  922. if (imc) {
  923. if (last == NULL)
  924. tncc->imc = imc;
  925. else
  926. last->next = imc;
  927. last = imc;
  928. }
  929. }
  930. }
  931. os_free(config);
  932. return 0;
  933. }
  934. #endif /* CONFIG_NATIVE_WINDOWS */
  935. struct tncc_data * tncc_init(void)
  936. {
  937. struct tncc_data *tncc;
  938. struct tnc_if_imc *imc;
  939. tncc = os_zalloc(sizeof(*tncc));
  940. if (tncc == NULL)
  941. return NULL;
  942. /* TODO:
  943. * move loading and Initialize() to a location that is not
  944. * re-initialized for every EAP-TNC session (?)
  945. */
  946. if (tncc_read_config(tncc) < 0) {
  947. wpa_printf(MSG_ERROR, "TNC: Failed to read TNC configuration");
  948. goto failed;
  949. }
  950. for (imc = tncc->imc; imc; imc = imc->next) {
  951. if (tncc_load_imc(imc)) {
  952. wpa_printf(MSG_ERROR, "TNC: Failed to load IMC '%s'",
  953. imc->name);
  954. goto failed;
  955. }
  956. }
  957. return tncc;
  958. failed:
  959. tncc_deinit(tncc);
  960. return NULL;
  961. }
  962. void tncc_deinit(struct tncc_data *tncc)
  963. {
  964. struct tnc_if_imc *imc, *prev;
  965. imc = tncc->imc;
  966. while (imc) {
  967. tncc_unload_imc(imc);
  968. prev = imc;
  969. imc = imc->next;
  970. os_free(prev);
  971. }
  972. os_free(tncc);
  973. }
  974. static struct wpabuf * tncc_build_soh(void)
  975. {
  976. struct wpabuf *buf;
  977. u8 *tlv_len, *tlv_len2, *outer_len, *inner_len, *ssoh_len, *end;
  978. u8 correlation_id[24];
  979. int ver = 2;
  980. if (os_get_random(correlation_id, sizeof(correlation_id)))
  981. return NULL;
  982. wpa_hexdump(MSG_DEBUG, "TNC: SoH Correlation ID",
  983. correlation_id, sizeof(correlation_id));
  984. buf = wpabuf_alloc(200);
  985. if (buf == NULL)
  986. return NULL;
  987. /* Vendor-Specific TLV (Microsoft) - SoH */
  988. wpabuf_put_be16(buf, EAP_TLV_VENDOR_SPECIFIC_TLV); /* TLV Type */
  989. tlv_len = wpabuf_put(buf, 2); /* Length */
  990. wpabuf_put_be32(buf, EAP_VENDOR_MICROSOFT); /* Vendor_Id */
  991. wpabuf_put_be16(buf, 0x01); /* TLV Type - SoH TLV */
  992. tlv_len2 = wpabuf_put(buf, 2); /* Length */
  993. /* SoH Header */
  994. wpabuf_put_be16(buf, EAP_TLV_VENDOR_SPECIFIC_TLV); /* Outer Type */
  995. outer_len = wpabuf_put(buf, 2);
  996. wpabuf_put_be32(buf, EAP_VENDOR_MICROSOFT); /* IANA SMI Code */
  997. wpabuf_put_be16(buf, ver); /* Inner Type */
  998. inner_len = wpabuf_put(buf, 2);
  999. if (ver == 2) {
  1000. /* SoH Mode Sub-Header */
  1001. /* Outer Type */
  1002. wpabuf_put_be16(buf, EAP_TLV_VENDOR_SPECIFIC_TLV);
  1003. wpabuf_put_be16(buf, 4 + 24 + 1 + 1); /* Length */
  1004. wpabuf_put_be32(buf, EAP_VENDOR_MICROSOFT); /* IANA SMI Code */
  1005. /* Value: */
  1006. wpabuf_put_data(buf, correlation_id, sizeof(correlation_id));
  1007. wpabuf_put_u8(buf, 0x01); /* Intent Flag - Request */
  1008. wpabuf_put_u8(buf, 0x00); /* Content-Type Flag */
  1009. }
  1010. /* SSoH TLV */
  1011. /* System-Health-Id */
  1012. wpabuf_put_be16(buf, 0x0002); /* Type */
  1013. wpabuf_put_be16(buf, 4); /* Length */
  1014. wpabuf_put_be32(buf, 79616);
  1015. /* Vendor-Specific Attribute */
  1016. wpabuf_put_be16(buf, EAP_TLV_VENDOR_SPECIFIC_TLV);
  1017. ssoh_len = wpabuf_put(buf, 2);
  1018. wpabuf_put_be32(buf, EAP_VENDOR_MICROSOFT); /* IANA SMI Code */
  1019. /* TODO: MS-Machine-Inventory */
  1020. /* TODO: MS-Quarantine-State */
  1021. /* MS-Packet-Info */
  1022. wpabuf_put_u8(buf, 0x03);
  1023. wpabuf_put_u8(buf, 0x11); /* r=request, vers=1 */
  1024. /* TODO: MS-MachineName */
  1025. /* MS-CorrelationId */
  1026. wpabuf_put_u8(buf, 0x06);
  1027. wpabuf_put_data(buf, correlation_id, sizeof(correlation_id));
  1028. end = wpabuf_put(buf, 0);
  1029. WPA_PUT_BE16(ssoh_len, end - ssoh_len - 2);
  1030. /* TODO: SoHReportEntry TLV (zero or more) */
  1031. /* Update length fields */
  1032. end = wpabuf_put(buf, 0);
  1033. WPA_PUT_BE16(tlv_len, end - tlv_len - 2);
  1034. WPA_PUT_BE16(tlv_len2, end - tlv_len2 - 2);
  1035. WPA_PUT_BE16(outer_len, end - outer_len - 2);
  1036. WPA_PUT_BE16(inner_len, end - inner_len - 2);
  1037. return buf;
  1038. }
  1039. struct wpabuf * tncc_process_soh_request(const u8 *data, size_t len)
  1040. {
  1041. const u8 *pos;
  1042. wpa_hexdump(MSG_DEBUG, "TNC: SoH Request", data, len);
  1043. if (len < 12)
  1044. return NULL;
  1045. /* SoH Request */
  1046. pos = data;
  1047. /* TLV Type */
  1048. if (WPA_GET_BE16(pos) != EAP_TLV_VENDOR_SPECIFIC_TLV)
  1049. return NULL;
  1050. pos += 2;
  1051. /* Length */
  1052. if (WPA_GET_BE16(pos) < 8)
  1053. return NULL;
  1054. pos += 2;
  1055. /* Vendor_Id */
  1056. if (WPA_GET_BE32(pos) != EAP_VENDOR_MICROSOFT)
  1057. return NULL;
  1058. pos += 4;
  1059. /* TLV Type */
  1060. if (WPA_GET_BE16(pos) != 0x02 /* SoH request TLV */)
  1061. return NULL;
  1062. wpa_printf(MSG_DEBUG, "TNC: SoH Request TLV received");
  1063. return tncc_build_soh();
  1064. }