~ubuntu-branches/ubuntu/vivid/wpasupplicant/vivid

« back to all changes in this revision

Viewing changes to src/eap_peer/tncc.c

  • Committer: Bazaar Package Importer
  • Author(s): Kel Modderman
  • Date: 2008-03-12 20:03:04 UTC
  • mfrom: (1.1.10 upstream)
  • mto: This revision was merged to the branch mainline in revision 4.
  • Revision ID: james.westby@ubuntu.com-20080312200304-4331y9wj46pdd34z
Tags: 0.6.3-1
* New upstream release.
* Drop patches applied upstream:
  - debian/patches/30_wpa_gui_qt4_eventhistoryui_rework.patch
  - debian/patches/31_wpa_gui_qt4_eventhistory_always_scrollbar.patch
  - debian/patches/32_wpa_gui_qt4_eventhistory_scroll_with_events.patch
  - debian/patches/40_dbus_ssid_data.patch
* Tidy up the clean target of debian/rules. Now that the madwifi headers are
  handled differently we no longer need to do any cleanup.
* Fix formatting error in debian/ifupdown/wpa_action.8 to make lintian
  quieter.
* Add patch to fix formatting errors in manpages build from sgml source. Use
  <emphasis> tags to hightlight keywords instead of surrounding them in
  strong quotes.
  - debian/patches/41_manpage_format_fixes.patch
* wpasupplicant binary package no longer suggests pcscd, guessnet, iproute
  or wireless-tools, nor does it recommend dhcp3-client. These are not
  needed.
* Add debian/patches/10_silence_siocsiwauth_icotl_failure.patch to disable
  ioctl failure messages that occur under normal conditions.
* Cherry pick two upstream git commits concerning the dbus interface:
  - debian/patches/11_avoid_dbus_version_namespace.patch
  - debian/patches/12_fix_potential_use_after_free.patch
* Add debian/patches/42_manpage_explain_available_drivers.patch to explain
  that not all of the driver backends are available in the provided
  wpa_supplicant binary, and that the canonical list of supported driver
  backends can be retrieved from the wpa_supplicant -h (help) output.
  (Closes: #466910)
* Add debian/patches/20_wpa_gui_qt4_disable_link_prl.patch to remove
  link_prl CONFIG compile flag added by qmake-qt4 >= 4.3.4-2 to avoid excess
  linking.

Show diffs side-by-side

added added

removed removed

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