Branch data Line data Source code
1 : : /*
2 : : * EAP-TNC - TNCC (IF-IMC and IF-TNCCS)
3 : : * Copyright (c) 2007, Jouni Malinen <j@w1.fi>
4 : : *
5 : : * This software may be distributed under the terms of the BSD license.
6 : : * See README for more details.
7 : : */
8 : :
9 : : #include "includes.h"
10 : : #ifndef CONFIG_NATIVE_WINDOWS
11 : : #include <dlfcn.h>
12 : : #endif /* CONFIG_NATIVE_WINDOWS */
13 : :
14 : : #include "common.h"
15 : : #include "base64.h"
16 : : #include "tncc.h"
17 : : #include "eap_common/eap_tlv_common.h"
18 : : #include "eap_common/eap_defs.h"
19 : :
20 : :
21 : : #ifdef UNICODE
22 : : #define TSTR "%S"
23 : : #else /* UNICODE */
24 : : #define TSTR "%s"
25 : : #endif /* UNICODE */
26 : :
27 : :
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 : :
39 : : /* TNC IF-IMC */
40 : :
41 : : typedef unsigned long TNC_UInt32;
42 : : typedef unsigned char *TNC_BufferReference;
43 : :
44 : : typedef TNC_UInt32 TNC_IMCID;
45 : : typedef TNC_UInt32 TNC_ConnectionID;
46 : : typedef TNC_UInt32 TNC_ConnectionState;
47 : : typedef TNC_UInt32 TNC_RetryReason;
48 : : typedef TNC_UInt32 TNC_MessageType;
49 : : typedef TNC_MessageType *TNC_MessageTypeList;
50 : : typedef TNC_UInt32 TNC_VendorID;
51 : : typedef TNC_UInt32 TNC_MessageSubtype;
52 : : typedef TNC_UInt32 TNC_Version;
53 : : typedef TNC_UInt32 TNC_Result;
54 : :
55 : : typedef TNC_Result (*TNC_TNCC_BindFunctionPointer)(
56 : : TNC_IMCID imcID,
57 : : char *functionName,
58 : : void **pOutfunctionPointer);
59 : :
60 : : #define TNC_RESULT_SUCCESS 0
61 : : #define TNC_RESULT_NOT_INITIALIZED 1
62 : : #define TNC_RESULT_ALREADY_INITIALIZED 2
63 : : #define TNC_RESULT_NO_COMMON_VERSION 3
64 : : #define TNC_RESULT_CANT_RETRY 4
65 : : #define TNC_RESULT_WONT_RETRY 5
66 : : #define TNC_RESULT_INVALID_PARAMETER 6
67 : : #define TNC_RESULT_CANT_RESPOND 7
68 : : #define TNC_RESULT_ILLEGAL_OPERATION 8
69 : : #define TNC_RESULT_OTHER 9
70 : : #define TNC_RESULT_FATAL 10
71 : :
72 : : #define TNC_CONNECTION_STATE_CREATE 0
73 : : #define TNC_CONNECTION_STATE_HANDSHAKE 1
74 : : #define TNC_CONNECTION_STATE_ACCESS_ALLOWED 2
75 : : #define TNC_CONNECTION_STATE_ACCESS_ISOLATED 3
76 : : #define TNC_CONNECTION_STATE_ACCESS_NONE 4
77 : : #define TNC_CONNECTION_STATE_DELETE 5
78 : :
79 : : #define TNC_IFIMC_VERSION_1 1
80 : :
81 : : #define TNC_VENDORID_ANY ((TNC_VendorID) 0xffffff)
82 : : #define TNC_SUBTYPE_ANY ((TNC_MessageSubtype) 0xff)
83 : :
84 : : /* TNCC-TNCS Message Types */
85 : : #define TNC_TNCCS_RECOMMENDATION 0x00000001
86 : : #define TNC_TNCCS_ERROR 0x00000002
87 : : #define TNC_TNCCS_PREFERREDLANGUAGE 0x00000003
88 : : #define TNC_TNCCS_REASONSTRINGS 0x00000004
89 : :
90 : :
91 : : /* IF-TNCCS-SOH - SSoH and SSoHR Attributes */
92 : : enum {
93 : : SSOH_MS_MACHINE_INVENTORY = 1,
94 : : SSOH_MS_QUARANTINE_STATE = 2,
95 : : SSOH_MS_PACKET_INFO = 3,
96 : : SSOH_MS_SYSTEMGENERATED_IDS = 4,
97 : : SSOH_MS_MACHINENAME = 5,
98 : : SSOH_MS_CORRELATIONID = 6,
99 : : SSOH_MS_INSTALLED_SHVS = 7,
100 : : SSOH_MS_MACHINE_INVENTORY_EX = 8
101 : : };
102 : :
103 : : struct tnc_if_imc {
104 : : struct tnc_if_imc *next;
105 : : char *name;
106 : : char *path;
107 : : void *dlhandle; /* from dlopen() */
108 : : TNC_IMCID imcID;
109 : : TNC_ConnectionID connectionID;
110 : : TNC_MessageTypeList supported_types;
111 : : size_t num_supported_types;
112 : : u8 *imc_send;
113 : : size_t imc_send_len;
114 : :
115 : : /* Functions implemented by IMCs (with TNC_IMC_ prefix) */
116 : : TNC_Result (*Initialize)(
117 : : TNC_IMCID imcID,
118 : : TNC_Version minVersion,
119 : : TNC_Version maxVersion,
120 : : TNC_Version *pOutActualVersion);
121 : : TNC_Result (*NotifyConnectionChange)(
122 : : TNC_IMCID imcID,
123 : : TNC_ConnectionID connectionID,
124 : : TNC_ConnectionState newState);
125 : : TNC_Result (*BeginHandshake)(
126 : : TNC_IMCID imcID,
127 : : TNC_ConnectionID connectionID);
128 : : TNC_Result (*ReceiveMessage)(
129 : : TNC_IMCID imcID,
130 : : TNC_ConnectionID connectionID,
131 : : TNC_BufferReference messageBuffer,
132 : : TNC_UInt32 messageLength,
133 : : TNC_MessageType messageType);
134 : : TNC_Result (*BatchEnding)(
135 : : TNC_IMCID imcID,
136 : : TNC_ConnectionID connectionID);
137 : : TNC_Result (*Terminate)(TNC_IMCID imcID);
138 : : TNC_Result (*ProvideBindFunction)(
139 : : TNC_IMCID imcID,
140 : : TNC_TNCC_BindFunctionPointer bindFunction);
141 : : };
142 : :
143 : : struct tncc_data {
144 : : struct tnc_if_imc *imc;
145 : : unsigned int last_batchid;
146 : : };
147 : :
148 : : #define TNC_MAX_IMC_ID 10
149 : : static struct tnc_if_imc *tnc_imc[TNC_MAX_IMC_ID] = { NULL };
150 : :
151 : :
152 : : /* TNCC functions that IMCs can call */
153 : :
154 : 0 : TNC_Result TNC_TNCC_ReportMessageTypes(
155 : : TNC_IMCID imcID,
156 : : TNC_MessageTypeList supportedTypes,
157 : : TNC_UInt32 typeCount)
158 : : {
159 : : TNC_UInt32 i;
160 : : struct tnc_if_imc *imc;
161 : :
162 : 0 : wpa_printf(MSG_DEBUG, "TNC: TNC_TNCC_ReportMessageTypes(imcID=%lu "
163 : : "typeCount=%lu)",
164 : : (unsigned long) imcID, (unsigned long) typeCount);
165 : :
166 [ # # ]: 0 : for (i = 0; i < typeCount; i++) {
167 : 0 : wpa_printf(MSG_DEBUG, "TNC: supportedTypes[%lu] = %lu",
168 : 0 : i, supportedTypes[i]);
169 : : }
170 : :
171 [ # # ][ # # ]: 0 : if (imcID >= TNC_MAX_IMC_ID || tnc_imc[imcID] == NULL)
172 : 0 : return TNC_RESULT_INVALID_PARAMETER;
173 : :
174 : 0 : imc = tnc_imc[imcID];
175 : 0 : os_free(imc->supported_types);
176 : 0 : imc->supported_types =
177 : 0 : os_malloc(typeCount * sizeof(TNC_MessageType));
178 [ # # ]: 0 : if (imc->supported_types == NULL)
179 : 0 : return TNC_RESULT_FATAL;
180 : 0 : os_memcpy(imc->supported_types, supportedTypes,
181 : : typeCount * sizeof(TNC_MessageType));
182 : 0 : imc->num_supported_types = typeCount;
183 : :
184 : 0 : return TNC_RESULT_SUCCESS;
185 : : }
186 : :
187 : :
188 : 0 : TNC_Result TNC_TNCC_SendMessage(
189 : : TNC_IMCID imcID,
190 : : TNC_ConnectionID connectionID,
191 : : TNC_BufferReference message,
192 : : TNC_UInt32 messageLength,
193 : : TNC_MessageType messageType)
194 : : {
195 : : struct tnc_if_imc *imc;
196 : : unsigned char *b64;
197 : : size_t b64len;
198 : :
199 : 0 : wpa_printf(MSG_DEBUG, "TNC: TNC_TNCC_SendMessage(imcID=%lu "
200 : : "connectionID=%lu messageType=%lu)",
201 : : imcID, connectionID, messageType);
202 : 0 : wpa_hexdump_ascii(MSG_DEBUG, "TNC: TNC_TNCC_SendMessage",
203 : : message, messageLength);
204 : :
205 [ # # ][ # # ]: 0 : if (imcID >= TNC_MAX_IMC_ID || tnc_imc[imcID] == NULL)
206 : 0 : return TNC_RESULT_INVALID_PARAMETER;
207 : :
208 : 0 : b64 = base64_encode(message, messageLength, &b64len);
209 [ # # ]: 0 : if (b64 == NULL)
210 : 0 : return TNC_RESULT_FATAL;
211 : :
212 : 0 : imc = tnc_imc[imcID];
213 : 0 : os_free(imc->imc_send);
214 : 0 : imc->imc_send_len = 0;
215 : 0 : imc->imc_send = os_zalloc(b64len + 100);
216 [ # # ]: 0 : if (imc->imc_send == NULL) {
217 : 0 : os_free(b64);
218 : 0 : return TNC_RESULT_OTHER;
219 : : }
220 : :
221 : 0 : imc->imc_send_len =
222 : 0 : os_snprintf((char *) imc->imc_send, b64len + 100,
223 : : "<IMC-IMV-Message><Type>%08X</Type>"
224 : : "<Base64>%s</Base64></IMC-IMV-Message>",
225 : : (unsigned int) messageType, b64);
226 : :
227 : 0 : os_free(b64);
228 : :
229 : 0 : return TNC_RESULT_SUCCESS;
230 : : }
231 : :
232 : :
233 : 0 : TNC_Result TNC_TNCC_RequestHandshakeRetry(
234 : : TNC_IMCID imcID,
235 : : TNC_ConnectionID connectionID,
236 : : TNC_RetryReason reason)
237 : : {
238 : 0 : wpa_printf(MSG_DEBUG, "TNC: TNC_TNCC_RequestHandshakeRetry");
239 : :
240 [ # # ][ # # ]: 0 : if (imcID >= TNC_MAX_IMC_ID || tnc_imc[imcID] == NULL)
241 : 0 : return TNC_RESULT_INVALID_PARAMETER;
242 : :
243 : : /*
244 : : * TODO: trigger a call to eapol_sm_request_reauth(). This would
245 : : * require that the IMC continues to be loaded in memory afer
246 : : * authentication..
247 : : */
248 : :
249 : 0 : return TNC_RESULT_SUCCESS;
250 : : }
251 : :
252 : :
253 : 0 : TNC_Result TNC_9048_LogMessage(TNC_IMCID imcID, TNC_UInt32 severity,
254 : : const char *message)
255 : : {
256 : 0 : wpa_printf(MSG_DEBUG, "TNC: TNC_9048_LogMessage(imcID=%lu "
257 : : "severity==%lu message='%s')",
258 : : imcID, severity, message);
259 : 0 : return TNC_RESULT_SUCCESS;
260 : : }
261 : :
262 : :
263 : 0 : TNC_Result TNC_9048_UserMessage(TNC_IMCID imcID, TNC_ConnectionID connectionID,
264 : : const char *message)
265 : : {
266 : 0 : wpa_printf(MSG_DEBUG, "TNC: TNC_9048_UserMessage(imcID=%lu "
267 : : "connectionID==%lu message='%s')",
268 : : imcID, connectionID, message);
269 : 0 : return TNC_RESULT_SUCCESS;
270 : : }
271 : :
272 : :
273 : 0 : TNC_Result TNC_TNCC_BindFunction(
274 : : TNC_IMCID imcID,
275 : : char *functionName,
276 : : void **pOutfunctionPointer)
277 : : {
278 : 0 : wpa_printf(MSG_DEBUG, "TNC: TNC_TNCC_BindFunction(imcID=%lu, "
279 : : "functionName='%s')", (unsigned long) imcID, functionName);
280 : :
281 [ # # ][ # # ]: 0 : if (imcID >= TNC_MAX_IMC_ID || tnc_imc[imcID] == NULL)
282 : 0 : return TNC_RESULT_INVALID_PARAMETER;
283 : :
284 [ # # ]: 0 : if (pOutfunctionPointer == NULL)
285 : 0 : return TNC_RESULT_INVALID_PARAMETER;
286 : :
287 [ # # ]: 0 : if (os_strcmp(functionName, "TNC_TNCC_ReportMessageTypes") == 0)
288 : 0 : *pOutfunctionPointer = TNC_TNCC_ReportMessageTypes;
289 [ # # ]: 0 : else if (os_strcmp(functionName, "TNC_TNCC_SendMessage") == 0)
290 : 0 : *pOutfunctionPointer = TNC_TNCC_SendMessage;
291 [ # # ]: 0 : else if (os_strcmp(functionName, "TNC_TNCC_RequestHandshakeRetry") ==
292 : : 0)
293 : 0 : *pOutfunctionPointer = TNC_TNCC_RequestHandshakeRetry;
294 [ # # ]: 0 : else if (os_strcmp(functionName, "TNC_9048_LogMessage") == 0)
295 : 0 : *pOutfunctionPointer = TNC_9048_LogMessage;
296 [ # # ]: 0 : else if (os_strcmp(functionName, "TNC_9048_UserMessage") == 0)
297 : 0 : *pOutfunctionPointer = TNC_9048_UserMessage;
298 : : else
299 : 0 : *pOutfunctionPointer = NULL;
300 : :
301 : 0 : return TNC_RESULT_SUCCESS;
302 : : }
303 : :
304 : :
305 : 0 : static void * tncc_get_sym(void *handle, char *func)
306 : : {
307 : : void *fptr;
308 : :
309 : : #ifdef CONFIG_NATIVE_WINDOWS
310 : : #ifdef _WIN32_WCE
311 : : fptr = GetProcAddressA(handle, func);
312 : : #else /* _WIN32_WCE */
313 : : fptr = GetProcAddress(handle, func);
314 : : #endif /* _WIN32_WCE */
315 : : #else /* CONFIG_NATIVE_WINDOWS */
316 : 0 : fptr = dlsym(handle, func);
317 : : #endif /* CONFIG_NATIVE_WINDOWS */
318 : :
319 : 0 : return fptr;
320 : : }
321 : :
322 : :
323 : 0 : static int tncc_imc_resolve_funcs(struct tnc_if_imc *imc)
324 : : {
325 : 0 : void *handle = imc->dlhandle;
326 : :
327 : : /* Mandatory IMC functions */
328 : 0 : imc->Initialize = tncc_get_sym(handle, "TNC_IMC_Initialize");
329 [ # # ]: 0 : if (imc->Initialize == NULL) {
330 : 0 : wpa_printf(MSG_ERROR, "TNC: IMC does not export "
331 : : "TNC_IMC_Initialize");
332 : 0 : return -1;
333 : : }
334 : :
335 : 0 : imc->BeginHandshake = tncc_get_sym(handle, "TNC_IMC_BeginHandshake");
336 [ # # ]: 0 : if (imc->BeginHandshake == NULL) {
337 : 0 : wpa_printf(MSG_ERROR, "TNC: IMC does not export "
338 : : "TNC_IMC_BeginHandshake");
339 : 0 : return -1;
340 : : }
341 : :
342 : 0 : imc->ProvideBindFunction =
343 : 0 : tncc_get_sym(handle, "TNC_IMC_ProvideBindFunction");
344 [ # # ]: 0 : if (imc->ProvideBindFunction == NULL) {
345 : 0 : wpa_printf(MSG_ERROR, "TNC: IMC does not export "
346 : : "TNC_IMC_ProvideBindFunction");
347 : 0 : return -1;
348 : : }
349 : :
350 : : /* Optional IMC functions */
351 : 0 : imc->NotifyConnectionChange =
352 : 0 : tncc_get_sym(handle, "TNC_IMC_NotifyConnectionChange");
353 : 0 : imc->ReceiveMessage = tncc_get_sym(handle, "TNC_IMC_ReceiveMessage");
354 : 0 : imc->BatchEnding = tncc_get_sym(handle, "TNC_IMC_BatchEnding");
355 : 0 : imc->Terminate = tncc_get_sym(handle, "TNC_IMC_Terminate");
356 : :
357 : 0 : return 0;
358 : : }
359 : :
360 : :
361 : 0 : static int tncc_imc_initialize(struct tnc_if_imc *imc)
362 : : {
363 : : TNC_Result res;
364 : : TNC_Version imc_ver;
365 : :
366 : 0 : wpa_printf(MSG_DEBUG, "TNC: Calling TNC_IMC_Initialize for IMC '%s'",
367 : : imc->name);
368 : 0 : res = imc->Initialize(imc->imcID, TNC_IFIMC_VERSION_1,
369 : : TNC_IFIMC_VERSION_1, &imc_ver);
370 : 0 : wpa_printf(MSG_DEBUG, "TNC: TNC_IMC_Initialize: res=%lu imc_ver=%lu",
371 : : (unsigned long) res, (unsigned long) imc_ver);
372 : :
373 [ # # ]: 0 : return res == TNC_RESULT_SUCCESS ? 0 : -1;
374 : : }
375 : :
376 : :
377 : 0 : static int tncc_imc_terminate(struct tnc_if_imc *imc)
378 : : {
379 : : TNC_Result res;
380 : :
381 [ # # ]: 0 : if (imc->Terminate == NULL)
382 : 0 : return 0;
383 : :
384 : 0 : wpa_printf(MSG_DEBUG, "TNC: Calling TNC_IMC_Terminate for IMC '%s'",
385 : : imc->name);
386 : 0 : res = imc->Terminate(imc->imcID);
387 : 0 : wpa_printf(MSG_DEBUG, "TNC: TNC_IMC_Terminate: %lu",
388 : : (unsigned long) res);
389 : :
390 [ # # ]: 0 : return res == TNC_RESULT_SUCCESS ? 0 : -1;
391 : : }
392 : :
393 : :
394 : 0 : static int tncc_imc_provide_bind_function(struct tnc_if_imc *imc)
395 : : {
396 : : TNC_Result res;
397 : :
398 : 0 : wpa_printf(MSG_DEBUG, "TNC: Calling TNC_IMC_ProvideBindFunction for "
399 : : "IMC '%s'", imc->name);
400 : 0 : res = imc->ProvideBindFunction(imc->imcID, TNC_TNCC_BindFunction);
401 : 0 : wpa_printf(MSG_DEBUG, "TNC: TNC_IMC_ProvideBindFunction: res=%lu",
402 : : (unsigned long) res);
403 : :
404 [ # # ]: 0 : return res == TNC_RESULT_SUCCESS ? 0 : -1;
405 : : }
406 : :
407 : :
408 : 0 : static int tncc_imc_notify_connection_change(struct tnc_if_imc *imc,
409 : : TNC_ConnectionState state)
410 : : {
411 : : TNC_Result res;
412 : :
413 [ # # ]: 0 : if (imc->NotifyConnectionChange == NULL)
414 : 0 : return 0;
415 : :
416 : 0 : wpa_printf(MSG_DEBUG, "TNC: Calling TNC_IMC_NotifyConnectionChange(%d)"
417 : : " for IMC '%s'", (int) state, imc->name);
418 : 0 : res = imc->NotifyConnectionChange(imc->imcID, imc->connectionID,
419 : : state);
420 : 0 : wpa_printf(MSG_DEBUG, "TNC: TNC_IMC_NotifyConnectionChange: %lu",
421 : : (unsigned long) res);
422 : :
423 [ # # ]: 0 : return res == TNC_RESULT_SUCCESS ? 0 : -1;
424 : : }
425 : :
426 : :
427 : 0 : static int tncc_imc_begin_handshake(struct tnc_if_imc *imc)
428 : : {
429 : : TNC_Result res;
430 : :
431 : 0 : wpa_printf(MSG_DEBUG, "TNC: Calling TNC_IMC_BeginHandshake for IMC "
432 : : "'%s'", imc->name);
433 : 0 : res = imc->BeginHandshake(imc->imcID, imc->connectionID);
434 : 0 : wpa_printf(MSG_DEBUG, "TNC: TNC_IMC_BeginHandshake: %lu",
435 : : (unsigned long) res);
436 : :
437 [ # # ]: 0 : return res == TNC_RESULT_SUCCESS ? 0 : -1;
438 : : }
439 : :
440 : :
441 : 0 : static int tncc_load_imc(struct tnc_if_imc *imc)
442 : : {
443 [ # # ]: 0 : if (imc->path == NULL) {
444 : 0 : wpa_printf(MSG_DEBUG, "TNC: No IMC configured");
445 : 0 : return -1;
446 : : }
447 : :
448 : 0 : wpa_printf(MSG_DEBUG, "TNC: Opening IMC: %s (%s)",
449 : : imc->name, imc->path);
450 : : #ifdef CONFIG_NATIVE_WINDOWS
451 : : #ifdef UNICODE
452 : : {
453 : : TCHAR *lib = wpa_strdup_tchar(imc->path);
454 : : if (lib == NULL)
455 : : return -1;
456 : : imc->dlhandle = LoadLibrary(lib);
457 : : os_free(lib);
458 : : }
459 : : #else /* UNICODE */
460 : : imc->dlhandle = LoadLibrary(imc->path);
461 : : #endif /* UNICODE */
462 : : if (imc->dlhandle == NULL) {
463 : : wpa_printf(MSG_ERROR, "TNC: Failed to open IMC '%s' (%s): %d",
464 : : imc->name, imc->path, (int) GetLastError());
465 : : return -1;
466 : : }
467 : : #else /* CONFIG_NATIVE_WINDOWS */
468 : 0 : imc->dlhandle = dlopen(imc->path, RTLD_LAZY);
469 [ # # ]: 0 : if (imc->dlhandle == NULL) {
470 : 0 : wpa_printf(MSG_ERROR, "TNC: Failed to open IMC '%s' (%s): %s",
471 : : imc->name, imc->path, dlerror());
472 : 0 : return -1;
473 : : }
474 : : #endif /* CONFIG_NATIVE_WINDOWS */
475 : :
476 [ # # ]: 0 : if (tncc_imc_resolve_funcs(imc) < 0) {
477 : 0 : wpa_printf(MSG_ERROR, "TNC: Failed to resolve IMC functions");
478 : 0 : return -1;
479 : : }
480 : :
481 [ # # # # ]: 0 : if (tncc_imc_initialize(imc) < 0 ||
482 : 0 : tncc_imc_provide_bind_function(imc) < 0) {
483 : 0 : wpa_printf(MSG_ERROR, "TNC: Failed to initialize IMC");
484 : 0 : return -1;
485 : : }
486 : :
487 : 0 : return 0;
488 : : }
489 : :
490 : :
491 : 0 : static void tncc_unload_imc(struct tnc_if_imc *imc)
492 : : {
493 : 0 : tncc_imc_terminate(imc);
494 : 0 : tnc_imc[imc->imcID] = NULL;
495 : :
496 [ # # ]: 0 : if (imc->dlhandle) {
497 : : #ifdef CONFIG_NATIVE_WINDOWS
498 : : FreeLibrary(imc->dlhandle);
499 : : #else /* CONFIG_NATIVE_WINDOWS */
500 : 0 : dlclose(imc->dlhandle);
501 : : #endif /* CONFIG_NATIVE_WINDOWS */
502 : : }
503 : 0 : os_free(imc->name);
504 : 0 : os_free(imc->path);
505 : 0 : os_free(imc->supported_types);
506 : 0 : os_free(imc->imc_send);
507 : 0 : }
508 : :
509 : :
510 : 0 : static int tncc_supported_type(struct tnc_if_imc *imc, unsigned int type)
511 : : {
512 : : size_t i;
513 : : unsigned int vendor, subtype;
514 : :
515 [ # # ][ # # ]: 0 : if (imc == NULL || imc->supported_types == NULL)
516 : 0 : return 0;
517 : :
518 : 0 : vendor = type >> 8;
519 : 0 : subtype = type & 0xff;
520 : :
521 [ # # ]: 0 : for (i = 0; i < imc->num_supported_types; i++) {
522 : : unsigned int svendor, ssubtype;
523 : 0 : svendor = imc->supported_types[i] >> 8;
524 : 0 : ssubtype = imc->supported_types[i] & 0xff;
525 [ # # ][ # # ]: 0 : if ((vendor == svendor || svendor == TNC_VENDORID_ANY) &&
[ # # ]
526 [ # # ]: 0 : (subtype == ssubtype || ssubtype == TNC_SUBTYPE_ANY))
527 : 0 : return 1;
528 : : }
529 : :
530 : 0 : return 0;
531 : : }
532 : :
533 : :
534 : 0 : static void tncc_send_to_imcs(struct tncc_data *tncc, unsigned int type,
535 : : const u8 *msg, size_t len)
536 : : {
537 : : struct tnc_if_imc *imc;
538 : : TNC_Result res;
539 : :
540 : 0 : wpa_hexdump_ascii(MSG_MSGDUMP, "TNC: Message to IMC(s)", msg, len);
541 : :
542 [ # # ]: 0 : for (imc = tncc->imc; imc; imc = imc->next) {
543 [ # # # # ]: 0 : if (imc->ReceiveMessage == NULL ||
544 : 0 : !tncc_supported_type(imc, type))
545 : 0 : continue;
546 : :
547 : 0 : wpa_printf(MSG_DEBUG, "TNC: Call ReceiveMessage for IMC '%s'",
548 : : imc->name);
549 : 0 : res = imc->ReceiveMessage(imc->imcID, imc->connectionID,
550 : : (TNC_BufferReference) msg, len,
551 : : type);
552 : 0 : wpa_printf(MSG_DEBUG, "TNC: ReceiveMessage: %lu",
553 : : (unsigned long) res);
554 : : }
555 : 0 : }
556 : :
557 : :
558 : 0 : void tncc_init_connection(struct tncc_data *tncc)
559 : : {
560 : : struct tnc_if_imc *imc;
561 : :
562 [ # # ]: 0 : for (imc = tncc->imc; imc; imc = imc->next) {
563 : 0 : tncc_imc_notify_connection_change(
564 : : imc, TNC_CONNECTION_STATE_CREATE);
565 : 0 : tncc_imc_notify_connection_change(
566 : : imc, TNC_CONNECTION_STATE_HANDSHAKE);
567 : :
568 : 0 : os_free(imc->imc_send);
569 : 0 : imc->imc_send = NULL;
570 : 0 : imc->imc_send_len = 0;
571 : :
572 : 0 : tncc_imc_begin_handshake(imc);
573 : : }
574 : 0 : }
575 : :
576 : :
577 : 0 : size_t tncc_total_send_len(struct tncc_data *tncc)
578 : : {
579 : : struct tnc_if_imc *imc;
580 : :
581 : 0 : size_t len = 0;
582 [ # # ]: 0 : for (imc = tncc->imc; imc; imc = imc->next)
583 : 0 : len += imc->imc_send_len;
584 : 0 : return len;
585 : : }
586 : :
587 : :
588 : 0 : u8 * tncc_copy_send_buf(struct tncc_data *tncc, u8 *pos)
589 : : {
590 : : struct tnc_if_imc *imc;
591 : :
592 [ # # ]: 0 : for (imc = tncc->imc; imc; imc = imc->next) {
593 [ # # ]: 0 : if (imc->imc_send == NULL)
594 : 0 : continue;
595 : :
596 : 0 : os_memcpy(pos, imc->imc_send, imc->imc_send_len);
597 : 0 : pos += imc->imc_send_len;
598 : 0 : os_free(imc->imc_send);
599 : 0 : imc->imc_send = NULL;
600 : 0 : imc->imc_send_len = 0;
601 : : }
602 : :
603 : 0 : return pos;
604 : : }
605 : :
606 : :
607 : 0 : char * tncc_if_tnccs_start(struct tncc_data *tncc)
608 : : {
609 : 0 : char *buf = os_malloc(1000);
610 [ # # ]: 0 : if (buf == NULL)
611 : 0 : return NULL;
612 : 0 : tncc->last_batchid++;
613 : 0 : os_snprintf(buf, 1000, IF_TNCCS_START, tncc->last_batchid);
614 : 0 : return buf;
615 : : }
616 : :
617 : :
618 : 0 : char * tncc_if_tnccs_end(void)
619 : : {
620 : 0 : char *buf = os_malloc(100);
621 [ # # ]: 0 : if (buf == NULL)
622 : 0 : return NULL;
623 : 0 : os_snprintf(buf, 100, IF_TNCCS_END);
624 : 0 : return buf;
625 : : }
626 : :
627 : :
628 : 0 : static void tncc_notify_recommendation(struct tncc_data *tncc,
629 : : enum tncc_process_res res)
630 : : {
631 : : TNC_ConnectionState state;
632 : : struct tnc_if_imc *imc;
633 : :
634 [ # # # # ]: 0 : switch (res) {
635 : : case TNCCS_RECOMMENDATION_ALLOW:
636 : 0 : state = TNC_CONNECTION_STATE_ACCESS_ALLOWED;
637 : 0 : break;
638 : : case TNCCS_RECOMMENDATION_NONE:
639 : 0 : state = TNC_CONNECTION_STATE_ACCESS_NONE;
640 : 0 : break;
641 : : case TNCCS_RECOMMENDATION_ISOLATE:
642 : 0 : state = TNC_CONNECTION_STATE_ACCESS_ISOLATED;
643 : 0 : break;
644 : : default:
645 : 0 : state = TNC_CONNECTION_STATE_ACCESS_NONE;
646 : 0 : break;
647 : : }
648 : :
649 [ # # ]: 0 : for (imc = tncc->imc; imc; imc = imc->next)
650 : 0 : tncc_imc_notify_connection_change(imc, state);
651 : 0 : }
652 : :
653 : :
654 : 0 : static int tncc_get_type(char *start, unsigned int *type)
655 : : {
656 : 0 : char *pos = os_strstr(start, "<Type>");
657 [ # # ]: 0 : if (pos == NULL)
658 : 0 : return -1;
659 : 0 : pos += 6;
660 : 0 : *type = strtoul(pos, NULL, 16);
661 : 0 : return 0;
662 : : }
663 : :
664 : :
665 : 0 : static unsigned char * tncc_get_base64(char *start, size_t *decoded_len)
666 : : {
667 : : char *pos, *pos2;
668 : : unsigned char *decoded;
669 : :
670 : 0 : pos = os_strstr(start, "<Base64>");
671 [ # # ]: 0 : if (pos == NULL)
672 : 0 : return NULL;
673 : :
674 : 0 : pos += 8;
675 : 0 : pos2 = os_strstr(pos, "</Base64>");
676 [ # # ]: 0 : if (pos2 == NULL)
677 : 0 : return NULL;
678 : 0 : *pos2 = '\0';
679 : :
680 : 0 : decoded = base64_decode((unsigned char *) pos, os_strlen(pos),
681 : : decoded_len);
682 : 0 : *pos2 = '<';
683 [ # # ]: 0 : if (decoded == NULL) {
684 : 0 : wpa_printf(MSG_DEBUG, "TNC: Failed to decode Base64 data");
685 : : }
686 : :
687 : 0 : return decoded;
688 : : }
689 : :
690 : :
691 : 0 : static enum tncc_process_res tncc_get_recommendation(char *start)
692 : : {
693 : : char *pos, *pos2, saved;
694 : : int recom;
695 : :
696 : 0 : pos = os_strstr(start, "<TNCCS-Recommendation ");
697 [ # # ]: 0 : if (pos == NULL)
698 : 0 : return TNCCS_RECOMMENDATION_ERROR;
699 : :
700 : 0 : pos += 21;
701 : 0 : pos = os_strstr(pos, " type=");
702 [ # # ]: 0 : if (pos == NULL)
703 : 0 : return TNCCS_RECOMMENDATION_ERROR;
704 : 0 : pos += 6;
705 : :
706 [ # # ]: 0 : if (*pos == '"')
707 : 0 : pos++;
708 : :
709 : 0 : pos2 = pos;
710 [ # # ][ # # ]: 0 : while (*pos2 != '\0' && *pos2 != '"' && *pos2 != '>')
[ # # ]
711 : 0 : pos2++;
712 : :
713 [ # # ]: 0 : if (*pos2 == '\0')
714 : 0 : return TNCCS_RECOMMENDATION_ERROR;
715 : :
716 : 0 : saved = *pos2;
717 : 0 : *pos2 = '\0';
718 : 0 : wpa_printf(MSG_DEBUG, "TNC: TNCCS-Recommendation: '%s'", pos);
719 : :
720 : 0 : recom = TNCCS_RECOMMENDATION_ERROR;
721 [ # # ]: 0 : if (os_strcmp(pos, "allow") == 0)
722 : 0 : recom = TNCCS_RECOMMENDATION_ALLOW;
723 [ # # ]: 0 : else if (os_strcmp(pos, "none") == 0)
724 : 0 : recom = TNCCS_RECOMMENDATION_NONE;
725 [ # # ]: 0 : else if (os_strcmp(pos, "isolate") == 0)
726 : 0 : recom = TNCCS_RECOMMENDATION_ISOLATE;
727 : :
728 : 0 : *pos2 = saved;
729 : :
730 : 0 : return recom;
731 : : }
732 : :
733 : :
734 : 0 : enum tncc_process_res tncc_process_if_tnccs(struct tncc_data *tncc,
735 : : const u8 *msg, size_t len)
736 : : {
737 : : char *buf, *start, *end, *pos, *pos2, *payload;
738 : : unsigned int batch_id;
739 : : unsigned char *decoded;
740 : : size_t decoded_len;
741 : 0 : enum tncc_process_res res = TNCCS_PROCESS_OK_NO_RECOMMENDATION;
742 : 0 : int recommendation_msg = 0;
743 : :
744 : 0 : buf = dup_binstr(msg, len);
745 [ # # ]: 0 : if (buf == NULL)
746 : 0 : return TNCCS_PROCESS_ERROR;
747 : :
748 : 0 : start = os_strstr(buf, "<TNCCS-Batch ");
749 : 0 : end = os_strstr(buf, "</TNCCS-Batch>");
750 [ # # ][ # # ]: 0 : if (start == NULL || end == NULL || start > end) {
[ # # ]
751 : 0 : os_free(buf);
752 : 0 : return TNCCS_PROCESS_ERROR;
753 : : }
754 : :
755 : 0 : start += 13;
756 [ # # ]: 0 : while (*start == ' ')
757 : 0 : start++;
758 : 0 : *end = '\0';
759 : :
760 : 0 : pos = os_strstr(start, "BatchId=");
761 [ # # ]: 0 : if (pos == NULL) {
762 : 0 : os_free(buf);
763 : 0 : return TNCCS_PROCESS_ERROR;
764 : : }
765 : :
766 : 0 : pos += 8;
767 [ # # ]: 0 : if (*pos == '"')
768 : 0 : pos++;
769 : 0 : batch_id = atoi(pos);
770 : 0 : wpa_printf(MSG_DEBUG, "TNC: Received IF-TNCCS BatchId=%u",
771 : : batch_id);
772 [ # # ]: 0 : if (batch_id != tncc->last_batchid + 1) {
773 : 0 : wpa_printf(MSG_DEBUG, "TNC: Unexpected IF-TNCCS BatchId "
774 : : "%u (expected %u)",
775 : 0 : batch_id, tncc->last_batchid + 1);
776 : 0 : os_free(buf);
777 : 0 : return TNCCS_PROCESS_ERROR;
778 : : }
779 : 0 : tncc->last_batchid = batch_id;
780 : :
781 [ # # ][ # # ]: 0 : while (*pos != '\0' && *pos != '>')
782 : 0 : pos++;
783 [ # # ]: 0 : if (*pos == '\0') {
784 : 0 : os_free(buf);
785 : 0 : return TNCCS_PROCESS_ERROR;
786 : : }
787 : 0 : pos++;
788 : 0 : payload = start;
789 : :
790 : : /*
791 : : * <IMC-IMV-Message>
792 : : * <Type>01234567</Type>
793 : : * <Base64>foo==</Base64>
794 : : * </IMC-IMV-Message>
795 : : */
796 : :
797 [ # # ]: 0 : while (*start) {
798 : : char *endpos;
799 : : unsigned int type;
800 : :
801 : 0 : pos = os_strstr(start, "<IMC-IMV-Message>");
802 [ # # ]: 0 : if (pos == NULL)
803 : 0 : break;
804 : 0 : start = pos + 17;
805 : 0 : end = os_strstr(start, "</IMC-IMV-Message>");
806 [ # # ]: 0 : if (end == NULL)
807 : 0 : break;
808 : 0 : *end = '\0';
809 : 0 : endpos = end;
810 : 0 : end += 18;
811 : :
812 [ # # ]: 0 : if (tncc_get_type(start, &type) < 0) {
813 : 0 : *endpos = '<';
814 : 0 : start = end;
815 : 0 : continue;
816 : : }
817 : 0 : wpa_printf(MSG_DEBUG, "TNC: IMC-IMV-Message Type 0x%x", type);
818 : :
819 : 0 : decoded = tncc_get_base64(start, &decoded_len);
820 [ # # ]: 0 : if (decoded == NULL) {
821 : 0 : *endpos = '<';
822 : 0 : start = end;
823 : 0 : continue;
824 : : }
825 : :
826 : 0 : tncc_send_to_imcs(tncc, type, decoded, decoded_len);
827 : :
828 : 0 : os_free(decoded);
829 : :
830 : 0 : start = end;
831 : : }
832 : :
833 : : /*
834 : : * <TNCC-TNCS-Message>
835 : : * <Type>01234567</Type>
836 : : * <XML><TNCCS-Foo type="foo"></TNCCS-Foo></XML>
837 : : * <Base64>foo==</Base64>
838 : : * </TNCC-TNCS-Message>
839 : : */
840 : :
841 : 0 : start = payload;
842 [ # # ]: 0 : while (*start) {
843 : : unsigned int type;
844 : : char *xml, *xmlend, *endpos;
845 : :
846 : 0 : pos = os_strstr(start, "<TNCC-TNCS-Message>");
847 [ # # ]: 0 : if (pos == NULL)
848 : 0 : break;
849 : 0 : start = pos + 19;
850 : 0 : end = os_strstr(start, "</TNCC-TNCS-Message>");
851 [ # # ]: 0 : if (end == NULL)
852 : 0 : break;
853 : 0 : *end = '\0';
854 : 0 : endpos = end;
855 : 0 : end += 20;
856 : :
857 [ # # ]: 0 : if (tncc_get_type(start, &type) < 0) {
858 : 0 : *endpos = '<';
859 : 0 : start = end;
860 : 0 : continue;
861 : : }
862 : 0 : wpa_printf(MSG_DEBUG, "TNC: TNCC-TNCS-Message Type 0x%x",
863 : : type);
864 : :
865 : : /* Base64 OR XML */
866 : 0 : decoded = NULL;
867 : 0 : xml = NULL;
868 : 0 : xmlend = NULL;
869 : 0 : pos = os_strstr(start, "<XML>");
870 [ # # ]: 0 : if (pos) {
871 : 0 : pos += 5;
872 : 0 : pos2 = os_strstr(pos, "</XML>");
873 [ # # ]: 0 : if (pos2 == NULL) {
874 : 0 : *endpos = '<';
875 : 0 : start = end;
876 : 0 : continue;
877 : : }
878 : 0 : xmlend = pos2;
879 : 0 : xml = pos;
880 : : } else {
881 : 0 : decoded = tncc_get_base64(start, &decoded_len);
882 [ # # ]: 0 : if (decoded == NULL) {
883 : 0 : *endpos = '<';
884 : 0 : start = end;
885 : 0 : continue;
886 : : }
887 : : }
888 : :
889 [ # # ]: 0 : if (decoded) {
890 : 0 : wpa_hexdump_ascii(MSG_MSGDUMP,
891 : : "TNC: TNCC-TNCS-Message Base64",
892 : : decoded, decoded_len);
893 : 0 : os_free(decoded);
894 : : }
895 : :
896 [ # # ]: 0 : if (xml) {
897 : 0 : wpa_hexdump_ascii(MSG_MSGDUMP,
898 : : "TNC: TNCC-TNCS-Message XML",
899 : : (unsigned char *) xml,
900 : 0 : xmlend - xml);
901 : : }
902 : :
903 [ # # ][ # # ]: 0 : if (type == TNC_TNCCS_RECOMMENDATION && xml) {
904 : : /*
905 : : * <TNCCS-Recommendation type="allow">
906 : : * </TNCCS-Recommendation>
907 : : */
908 : 0 : *xmlend = '\0';
909 : 0 : res = tncc_get_recommendation(xml);
910 : 0 : *xmlend = '<';
911 : 0 : recommendation_msg = 1;
912 : : }
913 : :
914 : 0 : start = end;
915 : : }
916 : :
917 : 0 : os_free(buf);
918 : :
919 [ # # ]: 0 : if (recommendation_msg)
920 : 0 : tncc_notify_recommendation(tncc, res);
921 : :
922 : 0 : return res;
923 : : }
924 : :
925 : :
926 : : #ifdef CONFIG_NATIVE_WINDOWS
927 : : static int tncc_read_config_reg(struct tncc_data *tncc, HKEY hive)
928 : : {
929 : : HKEY hk, hk2;
930 : : LONG ret;
931 : : DWORD i;
932 : : struct tnc_if_imc *imc, *last;
933 : : int j;
934 : :
935 : : last = tncc->imc;
936 : : while (last && last->next)
937 : : last = last->next;
938 : :
939 : : ret = RegOpenKeyEx(hive, TNC_WINREG_PATH, 0, KEY_ENUMERATE_SUB_KEYS,
940 : : &hk);
941 : : if (ret != ERROR_SUCCESS)
942 : : return 0;
943 : :
944 : : for (i = 0; ; i++) {
945 : : TCHAR name[255], *val;
946 : : DWORD namelen, buflen;
947 : :
948 : : namelen = 255;
949 : : ret = RegEnumKeyEx(hk, i, name, &namelen, NULL, NULL, NULL,
950 : : NULL);
951 : :
952 : : if (ret == ERROR_NO_MORE_ITEMS)
953 : : break;
954 : :
955 : : if (ret != ERROR_SUCCESS) {
956 : : wpa_printf(MSG_DEBUG, "TNC: RegEnumKeyEx failed: 0x%x",
957 : : (unsigned int) ret);
958 : : break;
959 : : }
960 : :
961 : : if (namelen >= 255)
962 : : namelen = 255 - 1;
963 : : name[namelen] = '\0';
964 : :
965 : : wpa_printf(MSG_DEBUG, "TNC: IMC '" TSTR "'", name);
966 : :
967 : : ret = RegOpenKeyEx(hk, name, 0, KEY_QUERY_VALUE, &hk2);
968 : : if (ret != ERROR_SUCCESS) {
969 : : wpa_printf(MSG_DEBUG, "Could not open IMC key '" TSTR
970 : : "'", name);
971 : : continue;
972 : : }
973 : :
974 : : ret = RegQueryValueEx(hk2, TEXT("Path"), NULL, NULL, NULL,
975 : : &buflen);
976 : : if (ret != ERROR_SUCCESS) {
977 : : wpa_printf(MSG_DEBUG, "TNC: Could not read Path from "
978 : : "IMC key '" TSTR "'", name);
979 : : RegCloseKey(hk2);
980 : : continue;
981 : : }
982 : :
983 : : val = os_malloc(buflen);
984 : : if (val == NULL) {
985 : : RegCloseKey(hk2);
986 : : continue;
987 : : }
988 : :
989 : : ret = RegQueryValueEx(hk2, TEXT("Path"), NULL, NULL,
990 : : (LPBYTE) val, &buflen);
991 : : if (ret != ERROR_SUCCESS) {
992 : : os_free(val);
993 : : RegCloseKey(hk2);
994 : : continue;
995 : : }
996 : :
997 : : RegCloseKey(hk2);
998 : :
999 : : wpa_unicode2ascii_inplace(val);
1000 : : wpa_printf(MSG_DEBUG, "TNC: IMC Path '%s'", (char *) val);
1001 : :
1002 : : for (j = 0; j < TNC_MAX_IMC_ID; j++) {
1003 : : if (tnc_imc[j] == NULL)
1004 : : break;
1005 : : }
1006 : : if (j >= TNC_MAX_IMC_ID) {
1007 : : wpa_printf(MSG_DEBUG, "TNC: Too many IMCs");
1008 : : os_free(val);
1009 : : continue;
1010 : : }
1011 : :
1012 : : imc = os_zalloc(sizeof(*imc));
1013 : : if (imc == NULL) {
1014 : : os_free(val);
1015 : : break;
1016 : : }
1017 : :
1018 : : imc->imcID = j;
1019 : :
1020 : : wpa_unicode2ascii_inplace(name);
1021 : : imc->name = os_strdup((char *) name);
1022 : : imc->path = os_strdup((char *) val);
1023 : :
1024 : : os_free(val);
1025 : :
1026 : : if (last == NULL)
1027 : : tncc->imc = imc;
1028 : : else
1029 : : last->next = imc;
1030 : : last = imc;
1031 : :
1032 : : tnc_imc[imc->imcID] = imc;
1033 : : }
1034 : :
1035 : : RegCloseKey(hk);
1036 : :
1037 : : return 0;
1038 : : }
1039 : :
1040 : :
1041 : : static int tncc_read_config(struct tncc_data *tncc)
1042 : : {
1043 : : if (tncc_read_config_reg(tncc, HKEY_LOCAL_MACHINE) < 0 ||
1044 : : tncc_read_config_reg(tncc, HKEY_CURRENT_USER) < 0)
1045 : : return -1;
1046 : : return 0;
1047 : : }
1048 : :
1049 : : #else /* CONFIG_NATIVE_WINDOWS */
1050 : :
1051 : 0 : static struct tnc_if_imc * tncc_parse_imc(char *start, char *end, int *error)
1052 : : {
1053 : : struct tnc_if_imc *imc;
1054 : : char *pos, *pos2;
1055 : : int i;
1056 : :
1057 [ # # ]: 0 : for (i = 0; i < TNC_MAX_IMC_ID; i++) {
1058 [ # # ]: 0 : if (tnc_imc[i] == NULL)
1059 : 0 : break;
1060 : : }
1061 [ # # ]: 0 : if (i >= TNC_MAX_IMC_ID) {
1062 : 0 : wpa_printf(MSG_DEBUG, "TNC: Too many IMCs");
1063 : 0 : return NULL;
1064 : : }
1065 : :
1066 : 0 : imc = os_zalloc(sizeof(*imc));
1067 [ # # ]: 0 : if (imc == NULL) {
1068 : 0 : *error = 1;
1069 : 0 : return NULL;
1070 : : }
1071 : :
1072 : 0 : imc->imcID = i;
1073 : :
1074 : 0 : pos = start;
1075 : 0 : wpa_printf(MSG_DEBUG, "TNC: Configured IMC: %s", pos);
1076 [ # # ][ # # ]: 0 : if (pos + 1 >= end || *pos != '"') {
1077 : 0 : wpa_printf(MSG_ERROR, "TNC: Ignoring invalid IMC line '%s' "
1078 : : "(no starting quotation mark)", start);
1079 : 0 : os_free(imc);
1080 : 0 : return NULL;
1081 : : }
1082 : :
1083 : 0 : pos++;
1084 : 0 : pos2 = pos;
1085 [ # # ][ # # ]: 0 : while (pos2 < end && *pos2 != '"')
1086 : 0 : pos2++;
1087 [ # # ]: 0 : if (pos2 >= end) {
1088 : 0 : wpa_printf(MSG_ERROR, "TNC: Ignoring invalid IMC line '%s' "
1089 : : "(no ending quotation mark)", start);
1090 : 0 : os_free(imc);
1091 : 0 : return NULL;
1092 : : }
1093 : 0 : *pos2 = '\0';
1094 : 0 : wpa_printf(MSG_DEBUG, "TNC: Name: '%s'", pos);
1095 : 0 : imc->name = os_strdup(pos);
1096 : :
1097 : 0 : pos = pos2 + 1;
1098 [ # # ][ # # ]: 0 : if (pos >= end || *pos != ' ') {
1099 : 0 : wpa_printf(MSG_ERROR, "TNC: Ignoring invalid IMC line '%s' "
1100 : : "(no space after name)", start);
1101 : 0 : os_free(imc->name);
1102 : 0 : os_free(imc);
1103 : 0 : return NULL;
1104 : : }
1105 : :
1106 : 0 : pos++;
1107 : 0 : wpa_printf(MSG_DEBUG, "TNC: IMC file: '%s'", pos);
1108 : 0 : imc->path = os_strdup(pos);
1109 : 0 : tnc_imc[imc->imcID] = imc;
1110 : :
1111 : 0 : return imc;
1112 : : }
1113 : :
1114 : :
1115 : 0 : static int tncc_read_config(struct tncc_data *tncc)
1116 : : {
1117 : : char *config, *end, *pos, *line_end;
1118 : : size_t config_len;
1119 : : struct tnc_if_imc *imc, *last;
1120 : :
1121 : 0 : last = NULL;
1122 : :
1123 : 0 : config = os_readfile(TNC_CONFIG_FILE, &config_len);
1124 [ # # ]: 0 : if (config == NULL) {
1125 : 0 : wpa_printf(MSG_ERROR, "TNC: Could not open TNC configuration "
1126 : : "file '%s'", TNC_CONFIG_FILE);
1127 : 0 : return -1;
1128 : : }
1129 : :
1130 : 0 : end = config + config_len;
1131 [ # # ]: 0 : for (pos = config; pos < end; pos = line_end + 1) {
1132 : 0 : line_end = pos;
1133 [ # # ][ # # ]: 0 : while (*line_end != '\n' && *line_end != '\r' &&
[ # # ]
1134 : : line_end < end)
1135 : 0 : line_end++;
1136 : 0 : *line_end = '\0';
1137 : :
1138 [ # # ]: 0 : if (os_strncmp(pos, "IMC ", 4) == 0) {
1139 : 0 : int error = 0;
1140 : :
1141 : 0 : imc = tncc_parse_imc(pos + 4, line_end, &error);
1142 [ # # ]: 0 : if (error)
1143 : 0 : return -1;
1144 [ # # ]: 0 : if (imc) {
1145 [ # # ]: 0 : if (last == NULL)
1146 : 0 : tncc->imc = imc;
1147 : : else
1148 : 0 : last->next = imc;
1149 : 0 : last = imc;
1150 : : }
1151 : : }
1152 : : }
1153 : :
1154 : 0 : os_free(config);
1155 : :
1156 : 0 : return 0;
1157 : : }
1158 : :
1159 : : #endif /* CONFIG_NATIVE_WINDOWS */
1160 : :
1161 : :
1162 : 0 : struct tncc_data * tncc_init(void)
1163 : : {
1164 : : struct tncc_data *tncc;
1165 : : struct tnc_if_imc *imc;
1166 : :
1167 : 0 : tncc = os_zalloc(sizeof(*tncc));
1168 [ # # ]: 0 : if (tncc == NULL)
1169 : 0 : return NULL;
1170 : :
1171 : : /* TODO:
1172 : : * move loading and Initialize() to a location that is not
1173 : : * re-initialized for every EAP-TNC session (?)
1174 : : */
1175 : :
1176 [ # # ]: 0 : if (tncc_read_config(tncc) < 0) {
1177 : 0 : wpa_printf(MSG_ERROR, "TNC: Failed to read TNC configuration");
1178 : 0 : goto failed;
1179 : : }
1180 : :
1181 [ # # ]: 0 : for (imc = tncc->imc; imc; imc = imc->next) {
1182 [ # # ]: 0 : if (tncc_load_imc(imc)) {
1183 : 0 : wpa_printf(MSG_ERROR, "TNC: Failed to load IMC '%s'",
1184 : : imc->name);
1185 : 0 : goto failed;
1186 : : }
1187 : : }
1188 : :
1189 : 0 : return tncc;
1190 : :
1191 : : failed:
1192 : 0 : tncc_deinit(tncc);
1193 : 0 : return NULL;
1194 : : }
1195 : :
1196 : :
1197 : 0 : void tncc_deinit(struct tncc_data *tncc)
1198 : : {
1199 : : struct tnc_if_imc *imc, *prev;
1200 : :
1201 : 0 : imc = tncc->imc;
1202 [ # # ]: 0 : while (imc) {
1203 : 0 : tncc_unload_imc(imc);
1204 : :
1205 : 0 : prev = imc;
1206 : 0 : imc = imc->next;
1207 : 0 : os_free(prev);
1208 : : }
1209 : :
1210 : 0 : os_free(tncc);
1211 : 0 : }
1212 : :
1213 : :
1214 : 0 : static struct wpabuf * tncc_build_soh(int ver)
1215 : : {
1216 : : struct wpabuf *buf;
1217 : : u8 *tlv_len, *tlv_len2, *outer_len, *inner_len, *ssoh_len, *end;
1218 : : u8 correlation_id[24];
1219 : : /* TODO: get correct name */
1220 : 0 : char *machinename = "wpa_supplicant@w1.fi";
1221 : :
1222 [ # # ]: 0 : if (os_get_random(correlation_id, sizeof(correlation_id)))
1223 : 0 : return NULL;
1224 : 0 : wpa_hexdump(MSG_DEBUG, "TNC: SoH Correlation ID",
1225 : : correlation_id, sizeof(correlation_id));
1226 : :
1227 : 0 : buf = wpabuf_alloc(200);
1228 [ # # ]: 0 : if (buf == NULL)
1229 : 0 : return NULL;
1230 : :
1231 : : /* Vendor-Specific TLV (Microsoft) - SoH */
1232 : 0 : wpabuf_put_be16(buf, EAP_TLV_VENDOR_SPECIFIC_TLV); /* TLV Type */
1233 : 0 : tlv_len = wpabuf_put(buf, 2); /* Length */
1234 : 0 : wpabuf_put_be32(buf, EAP_VENDOR_MICROSOFT); /* Vendor_Id */
1235 : 0 : wpabuf_put_be16(buf, 0x01); /* TLV Type - SoH TLV */
1236 : 0 : tlv_len2 = wpabuf_put(buf, 2); /* Length */
1237 : :
1238 : : /* SoH Header */
1239 : 0 : wpabuf_put_be16(buf, EAP_TLV_VENDOR_SPECIFIC_TLV); /* Outer Type */
1240 : 0 : outer_len = wpabuf_put(buf, 2);
1241 : 0 : wpabuf_put_be32(buf, EAP_VENDOR_MICROSOFT); /* IANA SMI Code */
1242 : 0 : wpabuf_put_be16(buf, ver); /* Inner Type */
1243 : 0 : inner_len = wpabuf_put(buf, 2);
1244 : :
1245 [ # # ]: 0 : if (ver == 2) {
1246 : : /* SoH Mode Sub-Header */
1247 : : /* Outer Type */
1248 : 0 : wpabuf_put_be16(buf, EAP_TLV_VENDOR_SPECIFIC_TLV);
1249 : 0 : wpabuf_put_be16(buf, 4 + 24 + 1 + 1); /* Length */
1250 : 0 : wpabuf_put_be32(buf, EAP_VENDOR_MICROSOFT); /* IANA SMI Code */
1251 : : /* Value: */
1252 : 0 : wpabuf_put_data(buf, correlation_id, sizeof(correlation_id));
1253 : 0 : wpabuf_put_u8(buf, 0x01); /* Intent Flag - Request */
1254 : 0 : wpabuf_put_u8(buf, 0x00); /* Content-Type Flag */
1255 : : }
1256 : :
1257 : : /* SSoH TLV */
1258 : : /* System-Health-Id */
1259 : 0 : wpabuf_put_be16(buf, 0x0002); /* Type */
1260 : 0 : wpabuf_put_be16(buf, 4); /* Length */
1261 : 0 : wpabuf_put_be32(buf, 79616);
1262 : : /* Vendor-Specific Attribute */
1263 : 0 : wpabuf_put_be16(buf, EAP_TLV_VENDOR_SPECIFIC_TLV);
1264 : 0 : ssoh_len = wpabuf_put(buf, 2);
1265 : 0 : wpabuf_put_be32(buf, EAP_VENDOR_MICROSOFT); /* IANA SMI Code */
1266 : :
1267 : : /* MS-Packet-Info */
1268 : 0 : wpabuf_put_u8(buf, SSOH_MS_PACKET_INFO);
1269 : : /* Note: IF-TNCCS-SOH v1.0 r8 claims this field to be:
1270 : : * Reserved(4 bits) r(1 bit) Vers(3 bits), but Windows XP
1271 : : * SP3 seems to be sending 0x11 for SSoH, i.e., r(request/response) bit
1272 : : * would not be in the specified location.
1273 : : * [MS-SOH] 4.0.2: Reserved(3 bits) r(1 bit) Vers(4 bits)
1274 : : */
1275 : 0 : wpabuf_put_u8(buf, 0x11); /* r=request, vers=1 */
1276 : :
1277 : : /* MS-Machine-Inventory */
1278 : : /* TODO: get correct values; 0 = not applicable for OS */
1279 : 0 : wpabuf_put_u8(buf, SSOH_MS_MACHINE_INVENTORY);
1280 : 0 : wpabuf_put_be32(buf, 0); /* osVersionMajor */
1281 : 0 : wpabuf_put_be32(buf, 0); /* osVersionMinor */
1282 : 0 : wpabuf_put_be32(buf, 0); /* osVersionBuild */
1283 : 0 : wpabuf_put_be16(buf, 0); /* spVersionMajor */
1284 : 0 : wpabuf_put_be16(buf, 0); /* spVersionMinor */
1285 : 0 : wpabuf_put_be16(buf, 0); /* procArch */
1286 : :
1287 : : /* MS-MachineName */
1288 : 0 : wpabuf_put_u8(buf, SSOH_MS_MACHINENAME);
1289 : 0 : wpabuf_put_be16(buf, os_strlen(machinename) + 1);
1290 : 0 : wpabuf_put_data(buf, machinename, os_strlen(machinename) + 1);
1291 : :
1292 : : /* MS-CorrelationId */
1293 : 0 : wpabuf_put_u8(buf, SSOH_MS_CORRELATIONID);
1294 : 0 : wpabuf_put_data(buf, correlation_id, sizeof(correlation_id));
1295 : :
1296 : : /* MS-Quarantine-State */
1297 : 0 : wpabuf_put_u8(buf, SSOH_MS_QUARANTINE_STATE);
1298 : 0 : wpabuf_put_be16(buf, 1); /* Flags: ExtState=0, f=0, qState=1 */
1299 : 0 : wpabuf_put_be32(buf, 0xffffffff); /* ProbTime (hi) */
1300 : 0 : wpabuf_put_be32(buf, 0xffffffff); /* ProbTime (lo) */
1301 : 0 : wpabuf_put_be16(buf, 1); /* urlLenInBytes */
1302 : 0 : wpabuf_put_u8(buf, 0); /* null termination for the url */
1303 : :
1304 : : /* MS-Machine-Inventory-Ex */
1305 : 0 : wpabuf_put_u8(buf, SSOH_MS_MACHINE_INVENTORY_EX);
1306 : 0 : wpabuf_put_be32(buf, 0); /* Reserved
1307 : : * (note: Windows XP SP3 uses 0xdecafbad) */
1308 : 0 : wpabuf_put_u8(buf, 1); /* ProductType: Client */
1309 : :
1310 : : /* Update SSoH Length */
1311 : 0 : end = wpabuf_put(buf, 0);
1312 : 0 : WPA_PUT_BE16(ssoh_len, end - ssoh_len - 2);
1313 : :
1314 : : /* TODO: SoHReportEntry TLV (zero or more) */
1315 : :
1316 : : /* Update length fields */
1317 : 0 : end = wpabuf_put(buf, 0);
1318 : 0 : WPA_PUT_BE16(tlv_len, end - tlv_len - 2);
1319 : 0 : WPA_PUT_BE16(tlv_len2, end - tlv_len2 - 2);
1320 : 0 : WPA_PUT_BE16(outer_len, end - outer_len - 2);
1321 : 0 : WPA_PUT_BE16(inner_len, end - inner_len - 2);
1322 : :
1323 : 0 : return buf;
1324 : : }
1325 : :
1326 : :
1327 : 0 : struct wpabuf * tncc_process_soh_request(int ver, const u8 *data, size_t len)
1328 : : {
1329 : : const u8 *pos;
1330 : :
1331 : 0 : wpa_hexdump(MSG_DEBUG, "TNC: SoH Request", data, len);
1332 : :
1333 [ # # ]: 0 : if (len < 12)
1334 : 0 : return NULL;
1335 : :
1336 : : /* SoH Request */
1337 : 0 : pos = data;
1338 : :
1339 : : /* TLV Type */
1340 [ # # ]: 0 : if (WPA_GET_BE16(pos) != EAP_TLV_VENDOR_SPECIFIC_TLV)
1341 : 0 : return NULL;
1342 : 0 : pos += 2;
1343 : :
1344 : : /* Length */
1345 [ # # ]: 0 : if (WPA_GET_BE16(pos) < 8)
1346 : 0 : return NULL;
1347 : 0 : pos += 2;
1348 : :
1349 : : /* Vendor_Id */
1350 [ # # ]: 0 : if (WPA_GET_BE32(pos) != EAP_VENDOR_MICROSOFT)
1351 : 0 : return NULL;
1352 : 0 : pos += 4;
1353 : :
1354 : : /* TLV Type */
1355 [ # # ]: 0 : if (WPA_GET_BE16(pos) != 0x02 /* SoH request TLV */)
1356 : 0 : return NULL;
1357 : :
1358 : 0 : wpa_printf(MSG_DEBUG, "TNC: SoH Request TLV received");
1359 : :
1360 : 0 : return tncc_build_soh(2);
1361 : : }
|