LCOV - code coverage report
Current view: top level - src/eap_peer - tncc.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1401264779 Lines: 421 544 77.4 %
Date: 2014-05-28 Functions: 30 33 90.9 %

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

Generated by: LCOV version 1.10