~ubuntu-branches/ubuntu/gutsy/wpasupplicant/gutsy

« back to all changes in this revision

Viewing changes to src/eap_peer/tncc.c

  • Committer: Bazaar Package Importer
  • Author(s): Reinhard Tartler, Alexander Sack
  • Date: 2007-08-26 16:06:57 UTC
  • mfrom: (1.1.9 upstream)
  • Revision ID: james.westby@ubuntu.com-20070826160657-2m8pxoweuxe8f93t
Tags: 0.6.0+0.5.8-0ubuntu1
* New upstream release
* remove patch 11_erroneous_manpage_ref, applied upstream
* remove patch 25_wpas_dbus_unregister_iface_fix, applied upstream

[ Alexander Sack ]
* bumping upstream version to replace development version 0.6.0 with
  this package from stable release branch.
* attempt to fix wierd timeout and high latency issues by going
  back to stable upstream version (0.5.9) (LP: #140763,
  LP: #141233).

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
 
 
89
 
struct tnc_if_imc {
90
 
        struct tnc_if_imc *next;
91
 
        char *name;
92
 
        char *path;
93
 
        void *dlhandle; /* from dlopen() */
94
 
        TNC_IMCID imcID;
95
 
        TNC_ConnectionID connectionID;
96
 
        TNC_MessageTypeList supported_types;
97
 
        size_t num_supported_types;
98
 
        u8 *imc_send;
99
 
        size_t imc_send_len;
100
 
 
101
 
        /* Functions implemented by IMCs (with TNC_IMC_ prefix) */
102
 
        TNC_Result (*Initialize)(
103
 
                TNC_IMCID imcID,
104
 
                TNC_Version minVersion,
105
 
                TNC_Version maxVersion,
106
 
                TNC_Version *pOutActualVersion);
107
 
        TNC_Result (*NotifyConnectionChange)(
108
 
                TNC_IMCID imcID,
109
 
                TNC_ConnectionID connectionID,
110
 
                TNC_ConnectionState newState);
111
 
        TNC_Result (*BeginHandshake)(
112
 
                TNC_IMCID imcID,
113
 
                TNC_ConnectionID connectionID);
114
 
        TNC_Result (*ReceiveMessage)(
115
 
                TNC_IMCID imcID,
116
 
                TNC_ConnectionID connectionID,
117
 
                TNC_BufferReference messageBuffer,
118
 
                TNC_UInt32 messageLength,
119
 
                TNC_MessageType messageType);
120
 
        TNC_Result (*BatchEnding)(
121
 
                TNC_IMCID imcID,
122
 
                TNC_ConnectionID connectionID);
123
 
        TNC_Result (*Terminate)(TNC_IMCID imcID);
124
 
        TNC_Result (*ProvideBindFunction)(
125
 
                TNC_IMCID imcID,
126
 
                TNC_TNCC_BindFunctionPointer bindFunction);
127
 
};
128
 
 
129
 
struct tncc_data {
130
 
        struct tnc_if_imc *imc;
131
 
        unsigned int last_batchid;
132
 
};
133
 
 
134
 
#define TNC_MAX_IMC_ID 10
135
 
static struct tnc_if_imc *tnc_imc[TNC_MAX_IMC_ID] = { NULL };
136
 
 
137
 
 
138
 
/* TNCC functions that IMCs can call */
139
 
 
140
 
TNC_Result TNC_TNCC_ReportMessageTypes(
141
 
        TNC_IMCID imcID,
142
 
        TNC_MessageTypeList supportedTypes,
143
 
        TNC_UInt32 typeCount)
144
 
{
145
 
        TNC_UInt32 i;
146
 
        struct tnc_if_imc *imc;
147
 
 
148
 
        wpa_printf(MSG_DEBUG, "TNC: TNC_TNCC_ReportMessageTypes(imcID=%lu "
149
 
                   "typeCount=%lu)",
150
 
                   (unsigned long) imcID, (unsigned long) typeCount);
151
 
 
152
 
        for (i = 0; i < typeCount; i++) {
153
 
                wpa_printf(MSG_DEBUG, "TNC: supportedTypes[%lu] = %lu",
154
 
                           i, supportedTypes[i]);
155
 
        }
156
 
 
157
 
        if (imcID >= TNC_MAX_IMC_ID || tnc_imc[imcID] == NULL)
158
 
                return TNC_RESULT_INVALID_PARAMETER;
159
 
 
160
 
        imc = tnc_imc[imcID];
161
 
        os_free(imc->supported_types);
162
 
        imc->supported_types =
163
 
                os_malloc(typeCount * sizeof(TNC_MessageTypeList));
164
 
        if (imc->supported_types == NULL)
165
 
                return TNC_RESULT_FATAL;
166
 
        os_memcpy(imc->supported_types, supportedTypes,
167
 
                  typeCount * sizeof(TNC_MessageTypeList));
168
 
        imc->num_supported_types = typeCount;
169
 
 
170
 
        return TNC_RESULT_SUCCESS;
171
 
}
172
 
 
173
 
 
174
 
TNC_Result TNC_TNCC_SendMessage(
175
 
        TNC_IMCID imcID,
176
 
        TNC_ConnectionID connectionID,
177
 
        TNC_BufferReference message,
178
 
        TNC_UInt32 messageLength,
179
 
        TNC_MessageType messageType)
180
 
{
181
 
        struct tnc_if_imc *imc;
182
 
        unsigned char *b64;
183
 
        size_t b64len;
184
 
 
185
 
        wpa_printf(MSG_DEBUG, "TNC: TNC_TNCC_SendMessage(imcID=%lu "
186
 
                   "connectionID=%lu messageType=%lu)",
187
 
                   imcID, connectionID, messageType);
188
 
        wpa_hexdump_ascii(MSG_DEBUG, "TNC: TNC_TNCC_SendMessage",
189
 
                          message, messageLength);
190
 
 
191
 
        if (imcID >= TNC_MAX_IMC_ID || tnc_imc[imcID] == NULL)
192
 
                return TNC_RESULT_INVALID_PARAMETER;
193
 
 
194
 
        b64 = base64_encode(message, messageLength, &b64len);
195
 
        if (b64 == NULL)
196
 
                return TNC_RESULT_FATAL;
197
 
 
198
 
        imc = tnc_imc[imcID];
199
 
        os_free(imc->imc_send);
200
 
        imc->imc_send_len = 0;
201
 
        imc->imc_send = os_zalloc(b64len + 100);
202
 
        if (imc->imc_send == NULL) {
203
 
                os_free(b64);
204
 
                return TNC_RESULT_OTHER;
205
 
        }
206
 
 
207
 
        imc->imc_send_len =
208
 
                os_snprintf((char *) imc->imc_send, b64len + 100,
209
 
                            "<IMC-IMV-Message><Type>%08X</Type>"
210
 
                            "<Base64>%s</Base64></IMC-IMV-Message>",
211
 
                            (unsigned int) messageType, b64);
212
 
 
213
 
        os_free(b64);
214
 
 
215
 
        return TNC_RESULT_SUCCESS;
216
 
}
217
 
 
218
 
 
219
 
TNC_Result TNC_TNCC_RequestHandshakeRetry(
220
 
        TNC_IMCID imcID,
221
 
        TNC_ConnectionID connectionID,
222
 
        TNC_RetryReason reason)
223
 
{
224
 
        wpa_printf(MSG_DEBUG, "TNC: TNC_TNCC_RequestHandshakeRetry");
225
 
 
226
 
        if (imcID >= TNC_MAX_IMC_ID || tnc_imc[imcID] == NULL)
227
 
                return TNC_RESULT_INVALID_PARAMETER;
228
 
 
229
 
        /*
230
 
         * TODO: trigger a call to eapol_sm_request_reauth(). This would
231
 
         * require that the IMC continues to be loaded in memory afer
232
 
         * authentication..
233
 
         */
234
 
 
235
 
        return TNC_RESULT_SUCCESS;
236
 
}
237
 
 
238
 
 
239
 
TNC_Result TNC_9048_LogMessage(TNC_IMCID imcID, TNC_UInt32 severity,
240
 
                               const char *message)
241
 
{
242
 
        wpa_printf(MSG_DEBUG, "TNC: TNC_9048_LogMessage(imcID=%lu "
243
 
                   "severity==%lu message='%s')",
244
 
                   imcID, severity, message);
245
 
        return TNC_RESULT_SUCCESS;
246
 
}
247
 
 
248
 
 
249
 
TNC_Result TNC_9048_UserMessage(TNC_IMCID imcID, TNC_ConnectionID connectionID,
250
 
                                const char *message)
251
 
{
252
 
        wpa_printf(MSG_DEBUG, "TNC: TNC_9048_UserMessage(imcID=%lu "
253
 
                   "connectionID==%lu message='%s')",
254
 
                   imcID, connectionID, message);
255
 
        return TNC_RESULT_SUCCESS;
256
 
}
257
 
 
258
 
 
259
 
TNC_Result TNC_TNCC_BindFunction(
260
 
        TNC_IMCID imcID,
261
 
        char *functionName,
262
 
        void **pOutfunctionPointer)
263
 
{
264
 
        wpa_printf(MSG_DEBUG, "TNC: TNC_TNCC_BindFunction(imcID=%lu, "
265
 
                   "functionName='%s')", (unsigned long) imcID, functionName);
266
 
 
267
 
        if (imcID >= TNC_MAX_IMC_ID || tnc_imc[imcID] == NULL)
268
 
                return TNC_RESULT_INVALID_PARAMETER;
269
 
 
270
 
        if (pOutfunctionPointer == NULL)
271
 
                return TNC_RESULT_INVALID_PARAMETER;
272
 
 
273
 
        if (os_strcmp(functionName, "TNC_TNCC_ReportMessageTypes") == 0)
274
 
                *pOutfunctionPointer = TNC_TNCC_ReportMessageTypes;
275
 
        else if (os_strcmp(functionName, "TNC_TNCC_SendMessage") == 0)
276
 
                *pOutfunctionPointer = TNC_TNCC_SendMessage;
277
 
        else if (os_strcmp(functionName, "TNC_TNCC_RequestHandshakeRetry") ==
278
 
                 0)
279
 
                *pOutfunctionPointer = TNC_TNCC_RequestHandshakeRetry;
280
 
        else if (os_strcmp(functionName, "TNC_9048_LogMessage") == 0)
281
 
                *pOutfunctionPointer = TNC_9048_LogMessage;
282
 
        else if (os_strcmp(functionName, "TNC_9048_UserMessage") == 0)
283
 
                *pOutfunctionPointer = TNC_9048_UserMessage;
284
 
        else
285
 
                *pOutfunctionPointer = NULL;
286
 
 
287
 
        return TNC_RESULT_SUCCESS;
288
 
}
289
 
 
290
 
 
291
 
static void * tncc_get_sym(void *handle, char *func)
292
 
{
293
 
        void *fptr;
294
 
 
295
 
#ifdef CONFIG_NATIVE_WINDOWS
296
 
#ifdef _WIN32_WCE
297
 
        fptr = GetProcAddressA(handle, func);
298
 
#else /* _WIN32_WCE */
299
 
        fptr = GetProcAddress(handle, func);
300
 
#endif /* _WIN32_WCE */
301
 
#else /* CONFIG_NATIVE_WINDOWS */
302
 
        fptr = dlsym(handle, func);
303
 
#endif /* CONFIG_NATIVE_WINDOWS */
304
 
 
305
 
        return fptr;
306
 
}
307
 
 
308
 
 
309
 
static int tncc_imc_resolve_funcs(struct tnc_if_imc *imc)
310
 
{
311
 
        void *handle = imc->dlhandle;
312
 
 
313
 
        /* Mandatory IMC functions */
314
 
        imc->Initialize = tncc_get_sym(handle, "TNC_IMC_Initialize");
315
 
        if (imc->Initialize == NULL) {
316
 
                wpa_printf(MSG_ERROR, "TNC: IMC does not export "
317
 
                           "TNC_IMC_Initialize");
318
 
                return -1;
319
 
        }
320
 
 
321
 
        imc->BeginHandshake = tncc_get_sym(handle, "TNC_IMC_BeginHandshake");
322
 
        if (imc->BeginHandshake == NULL) {
323
 
                wpa_printf(MSG_ERROR, "TNC: IMC does not export "
324
 
                           "TNC_IMC_BeginHandshake");
325
 
                return -1;
326
 
        }
327
 
 
328
 
        imc->ProvideBindFunction =
329
 
                tncc_get_sym(handle, "TNC_IMC_ProvideBindFunction");
330
 
        if (imc->ProvideBindFunction == NULL) {
331
 
                wpa_printf(MSG_ERROR, "TNC: IMC does not export "
332
 
                           "TNC_IMC_ProvideBindFunction");
333
 
                return -1;
334
 
        }
335
 
 
336
 
        /* Optional IMC functions */
337
 
        imc->NotifyConnectionChange =
338
 
                tncc_get_sym(handle, "TNC_IMC_NotifyConnectionChange");
339
 
        imc->ReceiveMessage = tncc_get_sym(handle, "TNC_IMC_ReceiveMessage");
340
 
        imc->BatchEnding = tncc_get_sym(handle, "TNC_IMC_BatchEnding");
341
 
        imc->Terminate = tncc_get_sym(handle, "TNC_IMC_Terminate");
342
 
 
343
 
        return 0;
344
 
}
345
 
 
346
 
 
347
 
static int tncc_imc_initialize(struct tnc_if_imc *imc)
348
 
{
349
 
        TNC_Result res;
350
 
        TNC_Version imc_ver;
351
 
 
352
 
        wpa_printf(MSG_DEBUG, "TNC: Calling TNC_IMC_Initialize for IMC '%s'",
353
 
                   imc->name);
354
 
        res = imc->Initialize(imc->imcID, TNC_IFIMC_VERSION_1,
355
 
                              TNC_IFIMC_VERSION_1, &imc_ver);
356
 
        wpa_printf(MSG_DEBUG, "TNC: TNC_IMC_Initialize: res=%lu imc_ver=%lu",
357
 
                   (unsigned long) res, (unsigned long) imc_ver);
358
 
 
359
 
        return res == TNC_RESULT_SUCCESS ? 0 : -1;
360
 
}
361
 
 
362
 
 
363
 
static int tncc_imc_terminate(struct tnc_if_imc *imc)
364
 
{
365
 
        TNC_Result res;
366
 
 
367
 
        if (imc->Terminate == NULL)
368
 
                return 0;
369
 
 
370
 
        wpa_printf(MSG_DEBUG, "TNC: Calling TNC_IMC_Terminate for IMC '%s'",
371
 
                   imc->name);
372
 
        res = imc->Terminate(imc->imcID);
373
 
        wpa_printf(MSG_DEBUG, "TNC: TNC_IMC_Terminate: %lu",
374
 
                   (unsigned long) res);
375
 
 
376
 
        return res == TNC_RESULT_SUCCESS ? 0 : -1;
377
 
}
378
 
 
379
 
 
380
 
static int tncc_imc_provide_bind_function(struct tnc_if_imc *imc)
381
 
{
382
 
        TNC_Result res;
383
 
 
384
 
        wpa_printf(MSG_DEBUG, "TNC: Calling TNC_IMC_ProvideBindFunction for "
385
 
                   "IMC '%s'", imc->name);
386
 
        res = imc->ProvideBindFunction(imc->imcID, TNC_TNCC_BindFunction);
387
 
        wpa_printf(MSG_DEBUG, "TNC: TNC_IMC_ProvideBindFunction: res=%lu",
388
 
                   (unsigned long) res);
389
 
 
390
 
        return res == TNC_RESULT_SUCCESS ? 0 : -1;
391
 
}
392
 
 
393
 
 
394
 
static int tncc_imc_notify_connection_change(struct tnc_if_imc *imc,
395
 
                                             TNC_ConnectionState state)
396
 
{
397
 
        TNC_Result res;
398
 
 
399
 
        if (imc->NotifyConnectionChange == NULL)
400
 
                return 0;
401
 
 
402
 
        wpa_printf(MSG_DEBUG, "TNC: Calling TNC_IMC_NotifyConnectionChange(%d)"
403
 
                   " for IMC '%s'", (int) state, imc->name);
404
 
        res = imc->NotifyConnectionChange(imc->imcID, imc->connectionID,
405
 
                                          state);
406
 
        wpa_printf(MSG_DEBUG, "TNC: TNC_IMC_NotifyConnectionChange: %lu",
407
 
                   (unsigned long) res);
408
 
 
409
 
        return res == TNC_RESULT_SUCCESS ? 0 : -1;
410
 
}
411
 
 
412
 
 
413
 
static int tncc_imc_begin_handshake(struct tnc_if_imc *imc)
414
 
{
415
 
        TNC_Result res;
416
 
 
417
 
        wpa_printf(MSG_DEBUG, "TNC: Calling TNC_IMC_BeginHandshake for IMC "
418
 
                   "'%s'", imc->name);
419
 
        res = imc->BeginHandshake(imc->imcID, imc->connectionID);
420
 
        wpa_printf(MSG_DEBUG, "TNC: TNC_IMC_BeginHandshake: %lu",
421
 
                   (unsigned long) res);
422
 
 
423
 
        return res == TNC_RESULT_SUCCESS ? 0 : -1;
424
 
}
425
 
 
426
 
 
427
 
static int tncc_load_imc(struct tnc_if_imc *imc)
428
 
{
429
 
        if (imc->path == NULL) {
430
 
                wpa_printf(MSG_DEBUG, "TNC: No IMC configured");
431
 
                return -1;
432
 
        }
433
 
 
434
 
        wpa_printf(MSG_DEBUG, "TNC: Opening IMC: %s (%s)",
435
 
                   imc->name, imc->path);
436
 
#ifdef CONFIG_NATIVE_WINDOWS
437
 
#ifdef UNICODE
438
 
        {
439
 
                TCHAR *lib = wpa_strdup_tchar(imc->path);
440
 
                if (lib == NULL)
441
 
                        return -1;
442
 
                imc->dlhandle = LoadLibrary(lib);
443
 
                os_free(lib);
444
 
        }
445
 
#else /* UNICODE */
446
 
        imc->dlhandle = LoadLibrary(imc->path);
447
 
#endif /* UNICODE */
448
 
        if (imc->dlhandle == NULL) {
449
 
                wpa_printf(MSG_ERROR, "TNC: Failed to open IMC '%s' (%s): %d",
450
 
                           imc->name, imc->path, (int) GetLastError());
451
 
                return -1;
452
 
        }
453
 
#else /* CONFIG_NATIVE_WINDOWS */
454
 
        imc->dlhandle = dlopen(imc->path, RTLD_LAZY);
455
 
        if (imc->dlhandle == NULL) {
456
 
                wpa_printf(MSG_ERROR, "TNC: Failed to open IMC '%s' (%s): %s",
457
 
                           imc->name, imc->path, dlerror());
458
 
                return -1;
459
 
        }
460
 
#endif /* CONFIG_NATIVE_WINDOWS */
461
 
 
462
 
        if (tncc_imc_resolve_funcs(imc) < 0) {
463
 
                wpa_printf(MSG_ERROR, "TNC: Failed to resolve IMC functions");
464
 
                return -1;
465
 
        }
466
 
 
467
 
        if (tncc_imc_initialize(imc) < 0 ||
468
 
            tncc_imc_provide_bind_function(imc) < 0) {
469
 
                wpa_printf(MSG_ERROR, "TNC: Failed to initialize IMC");
470
 
                return -1;
471
 
        }
472
 
 
473
 
        return 0;
474
 
}
475
 
 
476
 
 
477
 
static void tncc_unload_imc(struct tnc_if_imc *imc)
478
 
{
479
 
        tncc_imc_terminate(imc);
480
 
        tnc_imc[imc->imcID] = NULL;
481
 
 
482
 
        if (imc->dlhandle) {
483
 
#ifdef CONFIG_NATIVE_WINDOWS
484
 
                FreeLibrary(imc->dlhandle);
485
 
#else /* CONFIG_NATIVE_WINDOWS */
486
 
                dlclose(imc->dlhandle);
487
 
#endif /* CONFIG_NATIVE_WINDOWS */
488
 
        }
489
 
        os_free(imc->name);
490
 
        os_free(imc->path);
491
 
        os_free(imc->supported_types);
492
 
        os_free(imc->imc_send);
493
 
}
494
 
 
495
 
 
496
 
static int tncc_supported_type(struct tnc_if_imc *imc, unsigned int type)
497
 
{
498
 
        size_t i;
499
 
        unsigned int vendor, subtype;
500
 
 
501
 
        if (imc == NULL || imc->supported_types == NULL)
502
 
                return 0;
503
 
 
504
 
        vendor = type >> 8;
505
 
        subtype = type & 0xff;
506
 
 
507
 
        for (i = 0; i < imc->num_supported_types; i++) {
508
 
                unsigned int svendor, ssubtype;
509
 
                svendor = imc->supported_types[i] >> 8;
510
 
                ssubtype = imc->supported_types[i] & 0xff;
511
 
                if ((vendor == svendor || svendor == TNC_VENDORID_ANY) &&
512
 
                    (subtype == ssubtype || ssubtype == TNC_SUBTYPE_ANY))
513
 
                        return 1;
514
 
        }
515
 
 
516
 
        return 0;
517
 
}
518
 
 
519
 
 
520
 
static void tncc_send_to_imcs(struct tncc_data *tncc, unsigned int type,
521
 
                              const u8 *msg, size_t len)
522
 
{
523
 
        struct tnc_if_imc *imc;
524
 
        TNC_Result res;
525
 
 
526
 
        wpa_hexdump_ascii(MSG_MSGDUMP, "TNC: Message to IMC(s)", msg, len);
527
 
 
528
 
        for (imc = tncc->imc; imc; imc = imc->next) {
529
 
                if (imc->ReceiveMessage == NULL ||
530
 
                    !tncc_supported_type(imc, type))
531
 
                        continue;
532
 
 
533
 
                wpa_printf(MSG_DEBUG, "TNC: Call ReceiveMessage for IMC '%s'",
534
 
                           imc->name);
535
 
                res = imc->ReceiveMessage(imc->imcID, imc->connectionID,
536
 
                                          (TNC_BufferReference) msg, len,
537
 
                                          type);
538
 
                wpa_printf(MSG_DEBUG, "TNC: ReceiveMessage: %lu",
539
 
                           (unsigned long) res);
540
 
        }
541
 
}
542
 
 
543
 
 
544
 
void tncc_init_connection(struct tncc_data *tncc)
545
 
{
546
 
        struct tnc_if_imc *imc;
547
 
 
548
 
        for (imc = tncc->imc; imc; imc = imc->next) {
549
 
                tncc_imc_notify_connection_change(
550
 
                        imc, TNC_CONNECTION_STATE_CREATE);
551
 
                tncc_imc_notify_connection_change(
552
 
                        imc, TNC_CONNECTION_STATE_HANDSHAKE);
553
 
 
554
 
                os_free(imc->imc_send);
555
 
                imc->imc_send = NULL;
556
 
                imc->imc_send_len = 0;
557
 
 
558
 
                tncc_imc_begin_handshake(imc);
559
 
        }
560
 
}
561
 
 
562
 
 
563
 
size_t tncc_total_send_len(struct tncc_data *tncc)
564
 
{
565
 
        struct tnc_if_imc *imc;
566
 
 
567
 
        size_t len = 0;
568
 
        for (imc = tncc->imc; imc; imc = imc->next)
569
 
                len += imc->imc_send_len;
570
 
        return len;
571
 
}
572
 
 
573
 
 
574
 
u8 * tncc_copy_send_buf(struct tncc_data *tncc, u8 *pos)
575
 
{
576
 
        struct tnc_if_imc *imc;
577
 
 
578
 
        for (imc = tncc->imc; imc; imc = imc->next) {
579
 
                if (imc->imc_send == NULL)
580
 
                        continue;
581
 
 
582
 
                os_memcpy(pos, imc->imc_send, imc->imc_send_len);
583
 
                pos += imc->imc_send_len;
584
 
                os_free(imc->imc_send);
585
 
                imc->imc_send = NULL;
586
 
                imc->imc_send_len = 0;
587
 
        }
588
 
 
589
 
        return pos;
590
 
}
591
 
 
592
 
 
593
 
char * tncc_if_tnccs_start(struct tncc_data *tncc)
594
 
{
595
 
        char *buf = os_malloc(1000);
596
 
        if (buf == NULL)
597
 
                return NULL;
598
 
        tncc->last_batchid++;
599
 
        os_snprintf(buf, 1000, IF_TNCCS_START, tncc->last_batchid);
600
 
        return buf;
601
 
}
602
 
 
603
 
 
604
 
char * tncc_if_tnccs_end(void)
605
 
{
606
 
        char *buf = os_malloc(100);
607
 
        if (buf == NULL)
608
 
                return NULL;
609
 
        os_snprintf(buf, 100, IF_TNCCS_END);
610
 
        return buf;
611
 
}
612
 
 
613
 
 
614
 
int tncc_process_if_tnccs(struct tncc_data *tncc, const u8 *msg, size_t len)
615
 
{
616
 
        char *buf, *start, *end, *pos, *pos2;
617
 
        unsigned int batch_id;
618
 
        unsigned char *decoded;
619
 
        size_t decoded_len;
620
 
 
621
 
        buf = os_malloc(len + 1);
622
 
        if (buf == NULL)
623
 
                return -1;
624
 
 
625
 
        os_memcpy(buf, msg, len);
626
 
        buf[len] = '\0';
627
 
        start = os_strstr(buf, "<TNCCS-Batch ");
628
 
        end = os_strstr(buf, "</TNCCS-Batch>");
629
 
        if (start == NULL || end == NULL || start > end) {
630
 
                os_free(buf);
631
 
                return -1;
632
 
        }
633
 
 
634
 
        start += 13;
635
 
        while (*start == ' ')
636
 
                start++;
637
 
        *end = '\0';
638
 
 
639
 
        pos = os_strstr(start, "BatchId=");
640
 
        if (pos == NULL) {
641
 
                os_free(buf);
642
 
                return -1;
643
 
        }
644
 
 
645
 
        pos += 8;
646
 
        if (*pos == '"')
647
 
                pos++;
648
 
        batch_id = atoi(pos);
649
 
        wpa_printf(MSG_DEBUG, "TNC: Received IF-TNCCS BatchId=%u",
650
 
                   batch_id);
651
 
        if (batch_id != tncc->last_batchid + 1) {
652
 
                wpa_printf(MSG_DEBUG, "TNC: Unexpected IF-TNCCS BatchId "
653
 
                           "%u (expected %u)",
654
 
                           batch_id, tncc->last_batchid + 1);
655
 
                os_free(buf);
656
 
                return -1;
657
 
        }
658
 
        tncc->last_batchid = batch_id;
659
 
 
660
 
        /*
661
 
         * <IMC-IMV-Message>
662
 
         * <Type>01234567</Type>
663
 
         * <Base64>foo==</Base64>
664
 
         * </IMC-IMV-Message>
665
 
         */
666
 
 
667
 
        while (*start) {
668
 
                unsigned int type;
669
 
 
670
 
                pos = os_strstr(start, "<IMC-IMV-Message>");
671
 
                if (pos == NULL)
672
 
                        break;
673
 
                start = pos + 17;
674
 
                end = os_strstr(start, "</IMC-IMV-Message>");
675
 
                if (end == NULL)
676
 
                        break;
677
 
                *end = '\0';
678
 
                end += 18;
679
 
 
680
 
                pos = os_strstr(start, "<Type>");
681
 
                if (pos == NULL) {
682
 
                        start = end;
683
 
                        continue;
684
 
                }
685
 
 
686
 
                pos += 6;
687
 
                while (*pos == ' ')
688
 
                        pos++;
689
 
                type = atoi(pos);
690
 
                wpa_printf(MSG_DEBUG, "TNC: IMC-IMV-Message Type 0x%x", type);
691
 
 
692
 
                pos = os_strstr(start, "<Base64>");
693
 
                if (pos == NULL) {
694
 
                        start = end;
695
 
                        continue;
696
 
                }
697
 
                pos += 8;
698
 
 
699
 
                pos2 = os_strstr(pos, "</Base64>");
700
 
                if (pos2 == NULL) {
701
 
                        start = end;
702
 
                        continue;
703
 
                }
704
 
                *pos2 = '\0';
705
 
 
706
 
                decoded = base64_decode((unsigned char *) pos, os_strlen(pos),
707
 
                                        &decoded_len);
708
 
                if (decoded == NULL) {
709
 
                        wpa_printf(MSG_DEBUG, "TNC: Failed to decode "
710
 
                                   "IMC-IMV-Message Base64 data");
711
 
                        start = end;
712
 
                        continue;
713
 
                }
714
 
 
715
 
                tncc_send_to_imcs(tncc, type, decoded, decoded_len);
716
 
 
717
 
                os_free(decoded);
718
 
 
719
 
                start = end;
720
 
        }
721
 
 
722
 
        os_free(buf);
723
 
 
724
 
        return 0;
725
 
}
726
 
 
727
 
 
728
 
#ifdef CONFIG_NATIVE_WINDOWS
729
 
static int tncc_read_config_reg(struct tncc_data *tncc, HKEY hive)
730
 
{
731
 
        HKEY hk, hk2;
732
 
        LONG ret;
733
 
        DWORD i;
734
 
        struct tnc_if_imc *imc, *last;
735
 
        int j;
736
 
 
737
 
        last = tncc->imc;
738
 
        while (last && last->next)
739
 
                last = last->next;
740
 
 
741
 
        ret = RegOpenKeyEx(hive, TNC_WINREG_PATH, 0, KEY_ENUMERATE_SUB_KEYS,
742
 
                           &hk);
743
 
        if (ret != ERROR_SUCCESS)
744
 
                return 0;
745
 
 
746
 
        for (i = 0; ; i++) {
747
 
                TCHAR name[255], *val;
748
 
                DWORD namelen, buflen;
749
 
 
750
 
                namelen = 255;
751
 
                ret = RegEnumKeyEx(hk, i, name, &namelen, NULL, NULL, NULL,
752
 
                                   NULL);
753
 
 
754
 
                if (ret == ERROR_NO_MORE_ITEMS)
755
 
                        break;
756
 
 
757
 
                if (ret != ERROR_SUCCESS) {
758
 
                        wpa_printf(MSG_DEBUG, "TNC: RegEnumKeyEx failed: 0x%x",
759
 
                                   (unsigned int) ret);
760
 
                        break;
761
 
                }
762
 
 
763
 
                if (namelen >= 255)
764
 
                        namelen = 255 - 1;
765
 
                name[namelen] = '\0';
766
 
 
767
 
                wpa_printf(MSG_DEBUG, "TNC: IMC '" TSTR "'", name);
768
 
 
769
 
                ret = RegOpenKeyEx(hk, name, 0, KEY_QUERY_VALUE, &hk2);
770
 
                if (ret != ERROR_SUCCESS) {
771
 
                        wpa_printf(MSG_DEBUG, "Could not open IMC key '" TSTR
772
 
                                   "'", name);
773
 
                        continue;
774
 
                }
775
 
 
776
 
                ret = RegQueryValueEx(hk2, TEXT("Path"), NULL, NULL, NULL,
777
 
                                      &buflen);
778
 
                if (ret != ERROR_SUCCESS) {
779
 
                        wpa_printf(MSG_DEBUG, "TNC: Could not read Path from "
780
 
                                   "IMC key '" TSTR "'", name);
781
 
                        RegCloseKey(hk2);
782
 
                        continue;
783
 
                }
784
 
 
785
 
                val = os_malloc(buflen);
786
 
                if (val == NULL) {
787
 
                        RegCloseKey(hk2);
788
 
                        continue;
789
 
                }
790
 
 
791
 
                ret = RegQueryValueEx(hk2, TEXT("Path"), NULL, NULL,
792
 
                                      (LPBYTE) val, &buflen);
793
 
                if (ret != ERROR_SUCCESS) {
794
 
                        os_free(val);
795
 
                        RegCloseKey(hk2);
796
 
                        continue;
797
 
                }
798
 
 
799
 
                RegCloseKey(hk2);
800
 
 
801
 
                wpa_unicode2ascii_inplace(val);
802
 
                wpa_printf(MSG_DEBUG, "TNC: IMC Path '%s'", (char *) val);
803
 
 
804
 
                for (j = 0; j < TNC_MAX_IMC_ID; j++) {
805
 
                        if (tnc_imc[j] == NULL)
806
 
                                break;
807
 
                }
808
 
                if (j >= TNC_MAX_IMC_ID) {
809
 
                        wpa_printf(MSG_DEBUG, "TNC: Too many IMCs");
810
 
                        os_free(val);
811
 
                        continue;
812
 
                }
813
 
 
814
 
                imc = os_zalloc(sizeof(*imc));
815
 
                if (imc == NULL) {
816
 
                        os_free(val);
817
 
                        break;
818
 
                }
819
 
 
820
 
                imc->imcID = j;
821
 
 
822
 
                wpa_unicode2ascii_inplace(name);
823
 
                imc->name = os_strdup((char *) name);
824
 
                imc->path = os_strdup((char *) val);
825
 
 
826
 
                os_free(val);
827
 
 
828
 
                if (last == NULL)
829
 
                        tncc->imc = imc;
830
 
                else
831
 
                        last->next = imc;
832
 
                last = imc;
833
 
 
834
 
                tnc_imc[imc->imcID] = imc;
835
 
        }
836
 
 
837
 
        RegCloseKey(hk);
838
 
 
839
 
        return 0;
840
 
}
841
 
 
842
 
 
843
 
static int tncc_read_config(struct tncc_data *tncc)
844
 
{
845
 
        if (tncc_read_config_reg(tncc, HKEY_LOCAL_MACHINE) < 0 ||
846
 
            tncc_read_config_reg(tncc, HKEY_CURRENT_USER) < 0)
847
 
                return -1;
848
 
        return 0;
849
 
}
850
 
 
851
 
#else /* CONFIG_NATIVE_WINDOWS */
852
 
 
853
 
static struct tnc_if_imc * tncc_parse_imc(char *start, char *end, int *error)
854
 
{
855
 
        struct tnc_if_imc *imc;
856
 
        char *pos, *pos2;
857
 
        int i;
858
 
 
859
 
        for (i = 0; i < TNC_MAX_IMC_ID; i++) {
860
 
                if (tnc_imc[i] == NULL)
861
 
                        break;
862
 
        }
863
 
        if (i >= TNC_MAX_IMC_ID) {
864
 
                wpa_printf(MSG_DEBUG, "TNC: Too many IMCs");
865
 
                return NULL;
866
 
        }
867
 
 
868
 
        imc = os_zalloc(sizeof(*imc));
869
 
        if (imc == NULL) {
870
 
                *error = 1;
871
 
                return NULL;
872
 
        }
873
 
 
874
 
        imc->imcID = i;
875
 
 
876
 
        pos = start;
877
 
        wpa_printf(MSG_DEBUG, "TNC: Configured IMC: %s", pos);
878
 
        if (pos + 1 >= end || *pos != '"') {
879
 
                wpa_printf(MSG_ERROR, "TNC: Ignoring invalid IMC line '%s' "
880
 
                           "(no starting quotation mark)", start);
881
 
                os_free(imc);
882
 
                return NULL;
883
 
        }
884
 
 
885
 
        pos++;
886
 
        pos2 = pos;
887
 
        while (pos2 < end && *pos2 != '"')
888
 
                pos2++;
889
 
        if (pos2 >= end) {
890
 
                wpa_printf(MSG_ERROR, "TNC: Ignoring invalid IMC line '%s' "
891
 
                           "(no ending quotation mark)", start);
892
 
                os_free(imc);
893
 
                return NULL;
894
 
        }
895
 
        *pos2 = '\0';
896
 
        wpa_printf(MSG_DEBUG, "TNC: Name: '%s'", pos);
897
 
        imc->name = os_strdup(pos);
898
 
 
899
 
        pos = pos2 + 1;
900
 
        if (pos >= end || *pos != ' ') {
901
 
                wpa_printf(MSG_ERROR, "TNC: Ignoring invalid IMC line '%s' "
902
 
                           "(no space after name)", start);
903
 
                os_free(imc);
904
 
                return NULL;
905
 
        }
906
 
 
907
 
        pos++;
908
 
        wpa_printf(MSG_DEBUG, "TNC: IMC file: '%s'", pos);
909
 
        imc->path = os_strdup(pos);
910
 
        tnc_imc[imc->imcID] = imc;
911
 
 
912
 
        return imc;
913
 
}
914
 
 
915
 
 
916
 
static int tncc_read_config(struct tncc_data *tncc)
917
 
{
918
 
        char *config, *end, *pos, *line_end;
919
 
        size_t config_len;
920
 
        struct tnc_if_imc *imc, *last;
921
 
 
922
 
        last = NULL;
923
 
 
924
 
        config = os_readfile(TNC_CONFIG_FILE, &config_len);
925
 
        if (config == NULL) {
926
 
                wpa_printf(MSG_ERROR, "TNC: Could not open TNC configuration "
927
 
                           "file '%s'", TNC_CONFIG_FILE);
928
 
                return -1;
929
 
        }
930
 
 
931
 
        end = config + config_len;
932
 
        for (pos = config; pos < end; pos = line_end + 1) {
933
 
                line_end = pos;
934
 
                while (*line_end != '\n' && *line_end != '\r' &&
935
 
                       line_end < end)
936
 
                        line_end++;
937
 
                *line_end = '\0';
938
 
 
939
 
                if (os_strncmp(pos, "IMC ", 4) == 0) {
940
 
                        int error = 0;
941
 
 
942
 
                        imc = tncc_parse_imc(pos + 4, line_end, &error);
943
 
                        if (error)
944
 
                                return -1;
945
 
                        if (imc) {
946
 
                                if (last == NULL)
947
 
                                        tncc->imc = imc;
948
 
                                else
949
 
                                        last->next = imc;
950
 
                                last = imc;
951
 
                        }
952
 
                }
953
 
        }
954
 
 
955
 
        os_free(config);
956
 
 
957
 
        return 0;
958
 
}
959
 
 
960
 
#endif /* CONFIG_NATIVE_WINDOWS */
961
 
 
962
 
 
963
 
struct tncc_data * tncc_init(void)
964
 
{
965
 
        struct tncc_data *tncc;
966
 
        struct tnc_if_imc *imc;
967
 
 
968
 
        tncc = os_zalloc(sizeof(*tncc));
969
 
        if (tncc == NULL)
970
 
                return NULL;
971
 
 
972
 
        /* TODO:
973
 
         * move loading and Initialize() to a location that is not
974
 
         *    re-initialized for every EAP-TNC session (?)
975
 
         */
976
 
 
977
 
        if (tncc_read_config(tncc) < 0) {
978
 
                wpa_printf(MSG_ERROR, "TNC: Failed to read TNC configuration");
979
 
                goto failed;
980
 
        }
981
 
 
982
 
        for (imc = tncc->imc; imc; imc = imc->next) {
983
 
                if (tncc_load_imc(imc)) {
984
 
                        wpa_printf(MSG_ERROR, "TNC: Failed to load IMC '%s'",
985
 
                                   imc->name);
986
 
                        goto failed;
987
 
                }
988
 
        }
989
 
 
990
 
        return tncc;
991
 
 
992
 
failed:
993
 
        tncc_deinit(tncc);
994
 
        return NULL;
995
 
}
996
 
 
997
 
 
998
 
void tncc_deinit(struct tncc_data *tncc)
999
 
{
1000
 
        struct tnc_if_imc *imc, *prev;
1001
 
 
1002
 
        imc = tncc->imc;
1003
 
        while (imc) {
1004
 
                tncc_unload_imc(imc);
1005
 
 
1006
 
                prev = imc;
1007
 
                imc = imc->next;
1008
 
                os_free(prev);
1009
 
        }
1010
 
 
1011
 
        os_free(tncc);
1012
 
}