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 1443382998 Lines: 421 545 77.2 %
Date: 2015-09-27 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           3 : 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           3 :         wpa_printf(MSG_DEBUG, "TNC: TNC_TNCC_ReportMessageTypes(imcID=%lu "
     116             :                    "typeCount=%lu)",
     117             :                    (unsigned long) imcID, (unsigned long) typeCount);
     118             : 
     119           6 :         for (i = 0; i < typeCount; i++) {
     120           3 :                 wpa_printf(MSG_DEBUG, "TNC: supportedTypes[%lu] = %lu",
     121           3 :                            i, supportedTypes[i]);
     122             :         }
     123             : 
     124           3 :         if (imcID >= TNC_MAX_IMC_ID || tnc_imc[imcID] == NULL)
     125           0 :                 return TNC_RESULT_INVALID_PARAMETER;
     126             : 
     127           3 :         imc = tnc_imc[imcID];
     128           3 :         os_free(imc->supported_types);
     129           3 :         imc->supported_types =
     130           3 :                 os_malloc(typeCount * sizeof(TNC_MessageType));
     131           3 :         if (imc->supported_types == NULL)
     132           0 :                 return TNC_RESULT_FATAL;
     133           3 :         os_memcpy(imc->supported_types, supportedTypes,
     134             :                   typeCount * sizeof(TNC_MessageType));
     135           3 :         imc->num_supported_types = typeCount;
     136             : 
     137           3 :         return TNC_RESULT_SUCCESS;
     138             : }
     139             : 
     140             : 
     141           6 : 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           6 :         wpa_printf(MSG_DEBUG, "TNC: TNC_TNCC_SendMessage(imcID=%lu "
     153             :                    "connectionID=%lu messageType=%lu)",
     154             :                    imcID, connectionID, messageType);
     155           6 :         wpa_hexdump_ascii(MSG_DEBUG, "TNC: TNC_TNCC_SendMessage",
     156             :                           message, messageLength);
     157             : 
     158           6 :         if (imcID >= TNC_MAX_IMC_ID || tnc_imc[imcID] == NULL)
     159           0 :                 return TNC_RESULT_INVALID_PARAMETER;
     160             : 
     161           6 :         b64 = base64_encode(message, messageLength, &b64len);
     162           6 :         if (b64 == NULL)
     163           0 :                 return TNC_RESULT_FATAL;
     164             : 
     165           6 :         imc = tnc_imc[imcID];
     166           6 :         os_free(imc->imc_send);
     167           6 :         imc->imc_send_len = 0;
     168           6 :         imc->imc_send = os_zalloc(b64len + 100);
     169           6 :         if (imc->imc_send == NULL) {
     170           0 :                 os_free(b64);
     171           0 :                 return TNC_RESULT_OTHER;
     172             :         }
     173             : 
     174           6 :         imc->imc_send_len =
     175           6 :                 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           6 :         os_free(b64);
     181             : 
     182           6 :         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           9 : TNC_Result TNC_TNCC_BindFunction(
     227             :         TNC_IMCID imcID,
     228             :         char *functionName,
     229             :         void **pOutfunctionPointer)
     230             : {
     231           9 :         wpa_printf(MSG_DEBUG, "TNC: TNC_TNCC_BindFunction(imcID=%lu, "
     232             :                    "functionName='%s')", (unsigned long) imcID, functionName);
     233             : 
     234           9 :         if (imcID >= TNC_MAX_IMC_ID || tnc_imc[imcID] == NULL)
     235           0 :                 return TNC_RESULT_INVALID_PARAMETER;
     236             : 
     237           9 :         if (pOutfunctionPointer == NULL)
     238           0 :                 return TNC_RESULT_INVALID_PARAMETER;
     239             : 
     240           9 :         if (os_strcmp(functionName, "TNC_TNCC_ReportMessageTypes") == 0)
     241           3 :                 *pOutfunctionPointer = TNC_TNCC_ReportMessageTypes;
     242           6 :         else if (os_strcmp(functionName, "TNC_TNCC_SendMessage") == 0)
     243           3 :                 *pOutfunctionPointer = TNC_TNCC_SendMessage;
     244           3 :         else if (os_strcmp(functionName, "TNC_TNCC_RequestHandshakeRetry") ==
     245             :                  0)
     246           3 :                 *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           9 :         return TNC_RESULT_SUCCESS;
     255             : }
     256             : 
     257             : 
     258          42 : 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          42 :         fptr = dlsym(handle, func);
     270             : #endif /* CONFIG_NATIVE_WINDOWS */
     271             : 
     272          42 :         return fptr;
     273             : }
     274             : 
     275             : 
     276           6 : static int tncc_imc_resolve_funcs(struct tnc_if_imc *imc)
     277             : {
     278           6 :         void *handle = imc->dlhandle;
     279             : 
     280             :         /* Mandatory IMC functions */
     281           6 :         imc->Initialize = tncc_get_sym(handle, "TNC_IMC_Initialize");
     282           6 :         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           6 :         imc->BeginHandshake = tncc_get_sym(handle, "TNC_IMC_BeginHandshake");
     289           6 :         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           6 :         imc->ProvideBindFunction =
     296           6 :                 tncc_get_sym(handle, "TNC_IMC_ProvideBindFunction");
     297           6 :         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           6 :         imc->NotifyConnectionChange =
     305           6 :                 tncc_get_sym(handle, "TNC_IMC_NotifyConnectionChange");
     306           6 :         imc->ReceiveMessage = tncc_get_sym(handle, "TNC_IMC_ReceiveMessage");
     307           6 :         imc->BatchEnding = tncc_get_sym(handle, "TNC_IMC_BatchEnding");
     308           6 :         imc->Terminate = tncc_get_sym(handle, "TNC_IMC_Terminate");
     309             : 
     310           6 :         return 0;
     311             : }
     312             : 
     313             : 
     314           6 : static int tncc_imc_initialize(struct tnc_if_imc *imc)
     315             : {
     316             :         TNC_Result res;
     317             :         TNC_Version imc_ver;
     318             : 
     319           6 :         wpa_printf(MSG_DEBUG, "TNC: Calling TNC_IMC_Initialize for IMC '%s'",
     320             :                    imc->name);
     321           6 :         res = imc->Initialize(imc->imcID, TNC_IFIMC_VERSION_1,
     322             :                               TNC_IFIMC_VERSION_1, &imc_ver);
     323           6 :         wpa_printf(MSG_DEBUG, "TNC: TNC_IMC_Initialize: res=%lu imc_ver=%lu",
     324             :                    (unsigned long) res, (unsigned long) imc_ver);
     325             : 
     326           6 :         return res == TNC_RESULT_SUCCESS ? 0 : -1;
     327             : }
     328             : 
     329             : 
     330           6 : static int tncc_imc_terminate(struct tnc_if_imc *imc)
     331             : {
     332             :         TNC_Result res;
     333             : 
     334           6 :         if (imc->Terminate == NULL)
     335           3 :                 return 0;
     336             : 
     337           3 :         wpa_printf(MSG_DEBUG, "TNC: Calling TNC_IMC_Terminate for IMC '%s'",
     338             :                    imc->name);
     339           3 :         res = imc->Terminate(imc->imcID);
     340           3 :         wpa_printf(MSG_DEBUG, "TNC: TNC_IMC_Terminate: %lu",
     341             :                    (unsigned long) res);
     342             : 
     343           3 :         return res == TNC_RESULT_SUCCESS ? 0 : -1;
     344             : }
     345             : 
     346             : 
     347           6 : static int tncc_imc_provide_bind_function(struct tnc_if_imc *imc)
     348             : {
     349             :         TNC_Result res;
     350             : 
     351           6 :         wpa_printf(MSG_DEBUG, "TNC: Calling TNC_IMC_ProvideBindFunction for "
     352             :                    "IMC '%s'", imc->name);
     353           6 :         res = imc->ProvideBindFunction(imc->imcID, TNC_TNCC_BindFunction);
     354           6 :         wpa_printf(MSG_DEBUG, "TNC: TNC_IMC_ProvideBindFunction: res=%lu",
     355             :                    (unsigned long) res);
     356             : 
     357           6 :         return res == TNC_RESULT_SUCCESS ? 0 : -1;
     358             : }
     359             : 
     360             : 
     361          18 : static int tncc_imc_notify_connection_change(struct tnc_if_imc *imc,
     362             :                                              TNC_ConnectionState state)
     363             : {
     364             :         TNC_Result res;
     365             : 
     366          18 :         if (imc->NotifyConnectionChange == NULL)
     367           9 :                 return 0;
     368             : 
     369           9 :         wpa_printf(MSG_DEBUG, "TNC: Calling TNC_IMC_NotifyConnectionChange(%d)"
     370             :                    " for IMC '%s'", (int) state, imc->name);
     371           9 :         res = imc->NotifyConnectionChange(imc->imcID, imc->connectionID,
     372             :                                           state);
     373           9 :         wpa_printf(MSG_DEBUG, "TNC: TNC_IMC_NotifyConnectionChange: %lu",
     374             :                    (unsigned long) res);
     375             : 
     376           9 :         return res == TNC_RESULT_SUCCESS ? 0 : -1;
     377             : }
     378             : 
     379             : 
     380           6 : static int tncc_imc_begin_handshake(struct tnc_if_imc *imc)
     381             : {
     382             :         TNC_Result res;
     383             : 
     384           6 :         wpa_printf(MSG_DEBUG, "TNC: Calling TNC_IMC_BeginHandshake for IMC "
     385             :                    "'%s'", imc->name);
     386           6 :         res = imc->BeginHandshake(imc->imcID, imc->connectionID);
     387           6 :         wpa_printf(MSG_DEBUG, "TNC: TNC_IMC_BeginHandshake: %lu",
     388             :                    (unsigned long) res);
     389             : 
     390           6 :         return res == TNC_RESULT_SUCCESS ? 0 : -1;
     391             : }
     392             : 
     393             : 
     394           6 : static int tncc_load_imc(struct tnc_if_imc *imc)
     395             : {
     396           6 :         if (imc->path == NULL) {
     397           0 :                 wpa_printf(MSG_DEBUG, "TNC: No IMC configured");
     398           0 :                 return -1;
     399             :         }
     400             : 
     401           6 :         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           6 :         imc->dlhandle = dlopen(imc->path, RTLD_LAZY);
     422           6 :         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           6 :         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          12 :         if (tncc_imc_initialize(imc) < 0 ||
     435           6 :             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           6 :         return 0;
     441             : }
     442             : 
     443             : 
     444           6 : static void tncc_unload_imc(struct tnc_if_imc *imc)
     445             : {
     446           6 :         tncc_imc_terminate(imc);
     447           6 :         tnc_imc[imc->imcID] = NULL;
     448             : 
     449           6 :         if (imc->dlhandle) {
     450             : #ifdef CONFIG_NATIVE_WINDOWS
     451             :                 FreeLibrary(imc->dlhandle);
     452             : #else /* CONFIG_NATIVE_WINDOWS */
     453           6 :                 dlclose(imc->dlhandle);
     454             : #endif /* CONFIG_NATIVE_WINDOWS */
     455             :         }
     456           6 :         os_free(imc->name);
     457           6 :         os_free(imc->path);
     458           6 :         os_free(imc->supported_types);
     459           6 :         os_free(imc->imc_send);
     460           6 : }
     461             : 
     462             : 
     463           3 : 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           3 :         if (imc == NULL || imc->supported_types == NULL)
     469           0 :                 return 0;
     470             : 
     471           3 :         vendor = type >> 8;
     472           3 :         subtype = type & 0xff;
     473             : 
     474           3 :         for (i = 0; i < imc->num_supported_types; i++) {
     475             :                 unsigned int svendor, ssubtype;
     476           3 :                 svendor = imc->supported_types[i] >> 8;
     477           3 :                 ssubtype = imc->supported_types[i] & 0xff;
     478           3 :                 if ((vendor == svendor || svendor == TNC_VENDORID_ANY) &&
     479           3 :                     (subtype == ssubtype || ssubtype == TNC_SUBTYPE_ANY))
     480           3 :                         return 1;
     481             :         }
     482             : 
     483           0 :         return 0;
     484             : }
     485             : 
     486             : 
     487           3 : 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           3 :         wpa_hexdump_ascii(MSG_MSGDUMP, "TNC: Message to IMC(s)", msg, len);
     494             : 
     495           9 :         for (imc = tncc->imc; imc; imc = imc->next) {
     496           9 :                 if (imc->ReceiveMessage == NULL ||
     497           3 :                     !tncc_supported_type(imc, type))
     498           3 :                         continue;
     499             : 
     500           3 :                 wpa_printf(MSG_DEBUG, "TNC: Call ReceiveMessage for IMC '%s'",
     501             :                            imc->name);
     502           3 :                 res = imc->ReceiveMessage(imc->imcID, imc->connectionID,
     503             :                                           (TNC_BufferReference) msg, len,
     504             :                                           type);
     505           3 :                 wpa_printf(MSG_DEBUG, "TNC: ReceiveMessage: %lu",
     506             :                            (unsigned long) res);
     507             :         }
     508           3 : }
     509             : 
     510             : 
     511           3 : void tncc_init_connection(struct tncc_data *tncc)
     512             : {
     513             :         struct tnc_if_imc *imc;
     514             : 
     515           9 :         for (imc = tncc->imc; imc; imc = imc->next) {
     516           6 :                 tncc_imc_notify_connection_change(
     517             :                         imc, TNC_CONNECTION_STATE_CREATE);
     518           6 :                 tncc_imc_notify_connection_change(
     519             :                         imc, TNC_CONNECTION_STATE_HANDSHAKE);
     520             : 
     521           6 :                 os_free(imc->imc_send);
     522           6 :                 imc->imc_send = NULL;
     523           6 :                 imc->imc_send_len = 0;
     524             : 
     525           6 :                 tncc_imc_begin_handshake(imc);
     526             :         }
     527           3 : }
     528             : 
     529             : 
     530           6 : size_t tncc_total_send_len(struct tncc_data *tncc)
     531             : {
     532             :         struct tnc_if_imc *imc;
     533             : 
     534           6 :         size_t len = 0;
     535          18 :         for (imc = tncc->imc; imc; imc = imc->next)
     536          12 :                 len += imc->imc_send_len;
     537           6 :         return len;
     538             : }
     539             : 
     540             : 
     541           6 : u8 * tncc_copy_send_buf(struct tncc_data *tncc, u8 *pos)
     542             : {
     543             :         struct tnc_if_imc *imc;
     544             : 
     545          18 :         for (imc = tncc->imc; imc; imc = imc->next) {
     546          12 :                 if (imc->imc_send == NULL)
     547           6 :                         continue;
     548             : 
     549           6 :                 os_memcpy(pos, imc->imc_send, imc->imc_send_len);
     550           6 :                 pos += imc->imc_send_len;
     551           6 :                 os_free(imc->imc_send);
     552           6 :                 imc->imc_send = NULL;
     553           6 :                 imc->imc_send_len = 0;
     554             :         }
     555             : 
     556           6 :         return pos;
     557             : }
     558             : 
     559             : 
     560           6 : char * tncc_if_tnccs_start(struct tncc_data *tncc)
     561             : {
     562           6 :         char *buf = os_malloc(1000);
     563           6 :         if (buf == NULL)
     564           0 :                 return NULL;
     565           6 :         tncc->last_batchid++;
     566           6 :         os_snprintf(buf, 1000, IF_TNCCS_START, tncc->last_batchid);
     567           6 :         return buf;
     568             : }
     569             : 
     570             : 
     571           6 : char * tncc_if_tnccs_end(void)
     572             : {
     573           6 :         char *buf = os_malloc(100);
     574           6 :         if (buf == NULL)
     575           0 :                 return NULL;
     576           6 :         os_snprintf(buf, 100, IF_TNCCS_END);
     577           6 :         return buf;
     578             : }
     579             : 
     580             : 
     581           3 : 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           3 :         switch (res) {
     588             :         case TNCCS_RECOMMENDATION_ALLOW:
     589           3 :                 state = TNC_CONNECTION_STATE_ACCESS_ALLOWED;
     590           3 :                 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           9 :         for (imc = tncc->imc; imc; imc = imc->next)
     603           6 :                 tncc_imc_notify_connection_change(imc, state);
     604           3 : }
     605             : 
     606             : 
     607           6 : static int tncc_get_type(char *start, unsigned int *type)
     608             : {
     609           6 :         char *pos = os_strstr(start, "<Type>");
     610           6 :         if (pos == NULL)
     611           0 :                 return -1;
     612           6 :         pos += 6;
     613           6 :         *type = strtoul(pos, NULL, 16);
     614           6 :         return 0;
     615             : }
     616             : 
     617             : 
     618           3 : static unsigned char * tncc_get_base64(char *start, size_t *decoded_len)
     619             : {
     620             :         char *pos, *pos2;
     621             :         unsigned char *decoded;
     622             : 
     623           3 :         pos = os_strstr(start, "<Base64>");
     624           3 :         if (pos == NULL)
     625           0 :                 return NULL;
     626             : 
     627           3 :         pos += 8;
     628           3 :         pos2 = os_strstr(pos, "</Base64>");
     629           3 :         if (pos2 == NULL)
     630           0 :                 return NULL;
     631           3 :         *pos2 = '\0';
     632             : 
     633           3 :         decoded = base64_decode((unsigned char *) pos, os_strlen(pos),
     634             :                                 decoded_len);
     635           3 :         *pos2 = '<';
     636           3 :         if (decoded == NULL) {
     637           0 :                 wpa_printf(MSG_DEBUG, "TNC: Failed to decode Base64 data");
     638             :         }
     639             : 
     640           3 :         return decoded;
     641             : }
     642             : 
     643             : 
     644           3 : static enum tncc_process_res tncc_get_recommendation(char *start)
     645             : {
     646             :         char *pos, *pos2, saved;
     647             :         int recom;
     648             : 
     649           3 :         pos = os_strstr(start, "<TNCCS-Recommendation ");
     650           3 :         if (pos == NULL)
     651           0 :                 return TNCCS_RECOMMENDATION_ERROR;
     652             : 
     653           3 :         pos += 21;
     654           3 :         pos = os_strstr(pos, " type=");
     655           3 :         if (pos == NULL)
     656           0 :                 return TNCCS_RECOMMENDATION_ERROR;
     657           3 :         pos += 6;
     658             : 
     659           3 :         if (*pos == '"')
     660           3 :                 pos++;
     661             : 
     662           3 :         pos2 = pos;
     663          21 :         while (*pos2 != '\0' && *pos2 != '"' && *pos2 != '>')
     664          15 :                 pos2++;
     665             : 
     666           3 :         if (*pos2 == '\0')
     667           0 :                 return TNCCS_RECOMMENDATION_ERROR;
     668             : 
     669           3 :         saved = *pos2;
     670           3 :         *pos2 = '\0';
     671           3 :         wpa_printf(MSG_DEBUG, "TNC: TNCCS-Recommendation: '%s'", pos);
     672             : 
     673           3 :         recom = TNCCS_RECOMMENDATION_ERROR;
     674           3 :         if (os_strcmp(pos, "allow") == 0)
     675           3 :                 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           3 :         *pos2 = saved;
     682             : 
     683           3 :         return recom;
     684             : }
     685             : 
     686             : 
     687           6 : 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           6 :         enum tncc_process_res res = TNCCS_PROCESS_OK_NO_RECOMMENDATION;
     695           6 :         int recommendation_msg = 0;
     696             : 
     697           6 :         buf = dup_binstr(msg, len);
     698           6 :         if (buf == NULL)
     699           0 :                 return TNCCS_PROCESS_ERROR;
     700             : 
     701           6 :         start = os_strstr(buf, "<TNCCS-Batch ");
     702           6 :         end = os_strstr(buf, "</TNCCS-Batch>");
     703           6 :         if (start == NULL || end == NULL || start > end) {
     704           0 :                 os_free(buf);
     705           0 :                 return TNCCS_PROCESS_ERROR;
     706             :         }
     707             : 
     708           6 :         start += 13;
     709          12 :         while (*start == ' ')
     710           0 :                 start++;
     711           6 :         *end = '\0';
     712             : 
     713           6 :         pos = os_strstr(start, "BatchId=");
     714           6 :         if (pos == NULL) {
     715           0 :                 os_free(buf);
     716           0 :                 return TNCCS_PROCESS_ERROR;
     717             :         }
     718             : 
     719           6 :         pos += 8;
     720           6 :         if (*pos == '"')
     721           6 :                 pos++;
     722           6 :         batch_id = atoi(pos);
     723           6 :         wpa_printf(MSG_DEBUG, "TNC: Received IF-TNCCS BatchId=%u",
     724             :                    batch_id);
     725           6 :         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           6 :         tncc->last_batchid = batch_id;
     733             : 
     734        1710 :         while (*pos != '\0' && *pos != '>')
     735        1698 :                 pos++;
     736           6 :         if (*pos == '\0') {
     737           0 :                 os_free(buf);
     738           0 :                 return TNCCS_PROCESS_ERROR;
     739             :         }
     740           6 :         pos++;
     741           6 :         payload = start;
     742             : 
     743             :         /*
     744             :          * <IMC-IMV-Message>
     745             :          * <Type>01234567</Type>
     746             :          * <Base64>foo==</Base64>
     747             :          * </IMC-IMV-Message>
     748             :          */
     749             : 
     750          15 :         while (*start) {
     751             :                 char *endpos;
     752             :                 unsigned int type;
     753             : 
     754           9 :                 pos = os_strstr(start, "<IMC-IMV-Message>");
     755           9 :                 if (pos == NULL)
     756          12 :                         break;
     757           3 :                 start = pos + 17;
     758           3 :                 end = os_strstr(start, "</IMC-IMV-Message>");
     759           3 :                 if (end == NULL)
     760           0 :                         break;
     761           3 :                 *end = '\0';
     762           3 :                 endpos = end;
     763           3 :                 end += 18;
     764             : 
     765           3 :                 if (tncc_get_type(start, &type) < 0) {
     766           0 :                         *endpos = '<';
     767           0 :                         start = end;
     768           0 :                         continue;
     769             :                 }
     770           3 :                 wpa_printf(MSG_DEBUG, "TNC: IMC-IMV-Message Type 0x%x", type);
     771             : 
     772           3 :                 decoded = tncc_get_base64(start, &decoded_len);
     773           3 :                 if (decoded == NULL) {
     774           0 :                         *endpos = '<';
     775           0 :                         start = end;
     776           0 :                         continue;
     777             :                 }
     778             : 
     779           3 :                 tncc_send_to_imcs(tncc, type, decoded, decoded_len);
     780             : 
     781           3 :                 os_free(decoded);
     782             : 
     783           3 :                 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           6 :         start = payload;
     795          15 :         while (*start) {
     796             :                 unsigned int type;
     797             :                 char *xml, *xmlend, *endpos;
     798             : 
     799           9 :                 pos = os_strstr(start, "<TNCC-TNCS-Message>");
     800           9 :                 if (pos == NULL)
     801          12 :                         break;
     802           3 :                 start = pos + 19;
     803           3 :                 end = os_strstr(start, "</TNCC-TNCS-Message>");
     804           3 :                 if (end == NULL)
     805           0 :                         break;
     806           3 :                 *end = '\0';
     807           3 :                 endpos = end;
     808           3 :                 end += 20;
     809             : 
     810           3 :                 if (tncc_get_type(start, &type) < 0) {
     811           0 :                         *endpos = '<';
     812           0 :                         start = end;
     813           0 :                         continue;
     814             :                 }
     815           3 :                 wpa_printf(MSG_DEBUG, "TNC: TNCC-TNCS-Message Type 0x%x",
     816             :                            type);
     817             : 
     818             :                 /* Base64 OR XML */
     819           3 :                 decoded = NULL;
     820           3 :                 xml = NULL;
     821           3 :                 xmlend = NULL;
     822           3 :                 pos = os_strstr(start, "<XML>");
     823           3 :                 if (pos) {
     824           3 :                         pos += 5;
     825           3 :                         pos2 = os_strstr(pos, "</XML>");
     826           3 :                         if (pos2 == NULL) {
     827           0 :                                 *endpos = '<';
     828           0 :                                 start = end;
     829           0 :                                 continue;
     830             :                         }
     831           3 :                         xmlend = pos2;
     832           3 :                         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           3 :                 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           3 :                 if (xml) {
     850           3 :                         wpa_hexdump_ascii(MSG_MSGDUMP,
     851             :                                           "TNC: TNCC-TNCS-Message XML",
     852             :                                           (unsigned char *) xml,
     853           3 :                                           xmlend - xml);
     854             :                 }
     855             : 
     856           3 :                 if (type == TNC_TNCCS_RECOMMENDATION && xml) {
     857             :                         /*
     858             :                          * <TNCCS-Recommendation type="allow">
     859             :                          * </TNCCS-Recommendation>
     860             :                          */
     861           3 :                         *xmlend = '\0';
     862           3 :                         res = tncc_get_recommendation(xml);
     863           3 :                         *xmlend = '<';
     864           3 :                         recommendation_msg = 1;
     865             :                 }
     866             : 
     867           3 :                 start = end;
     868             :         }
     869             : 
     870           6 :         os_free(buf);
     871             : 
     872           6 :         if (recommendation_msg)
     873           3 :                 tncc_notify_recommendation(tncc, res);
     874             : 
     875           6 :         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           6 : 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           9 :         for (i = 0; i < TNC_MAX_IMC_ID; i++) {
    1011           9 :                 if (tnc_imc[i] == NULL)
    1012           6 :                         break;
    1013             :         }
    1014           6 :         if (i >= TNC_MAX_IMC_ID) {
    1015           0 :                 wpa_printf(MSG_DEBUG, "TNC: Too many IMCs");
    1016           0 :                 return NULL;
    1017             :         }
    1018             : 
    1019           6 :         imc = os_zalloc(sizeof(*imc));
    1020           6 :         if (imc == NULL) {
    1021           0 :                 *error = 1;
    1022           0 :                 return NULL;
    1023             :         }
    1024             : 
    1025           6 :         imc->imcID = i;
    1026             : 
    1027           6 :         pos = start;
    1028           6 :         wpa_printf(MSG_DEBUG, "TNC: Configured IMC: %s", pos);
    1029           6 :         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           6 :         pos++;
    1037           6 :         pos2 = pos;
    1038          75 :         while (pos2 < end && *pos2 != '"')
    1039          63 :                 pos2++;
    1040           6 :         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           6 :         *pos2 = '\0';
    1047           6 :         wpa_printf(MSG_DEBUG, "TNC: Name: '%s'", pos);
    1048           6 :         imc->name = os_strdup(pos);
    1049             : 
    1050           6 :         pos = pos2 + 1;
    1051           6 :         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           6 :         pos++;
    1060           6 :         wpa_printf(MSG_DEBUG, "TNC: IMC file: '%s'", pos);
    1061           6 :         imc->path = os_strdup(pos);
    1062           6 :         tnc_imc[imc->imcID] = imc;
    1063             : 
    1064           6 :         return imc;
    1065             : }
    1066             : 
    1067             : 
    1068           3 : 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           3 :         last = NULL;
    1075             : 
    1076           3 :         config = os_readfile(TNC_CONFIG_FILE, &config_len);
    1077           3 :         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           3 :         end = config + config_len;
    1084          15 :         for (pos = config; pos < end; pos = line_end + 1) {
    1085          12 :                 line_end = pos;
    1086         480 :                 while (*line_end != '\n' && *line_end != '\r' &&
    1087             :                        line_end < end)
    1088         456 :                         line_end++;
    1089          12 :                 *line_end = '\0';
    1090             : 
    1091          12 :                 if (os_strncmp(pos, "IMC ", 4) == 0) {
    1092           6 :                         int error = 0;
    1093             : 
    1094           6 :                         imc = tncc_parse_imc(pos + 4, line_end, &error);
    1095           6 :                         if (error) {
    1096           0 :                                 os_free(config);
    1097           0 :                                 return -1;
    1098             :                         }
    1099           6 :                         if (imc) {
    1100           6 :                                 if (last == NULL)
    1101           3 :                                         tncc->imc = imc;
    1102             :                                 else
    1103           3 :                                         last->next = imc;
    1104           6 :                                 last = imc;
    1105             :                         }
    1106             :                 }
    1107             :         }
    1108             : 
    1109           3 :         os_free(config);
    1110             : 
    1111           3 :         return 0;
    1112             : }
    1113             : 
    1114             : #endif /* CONFIG_NATIVE_WINDOWS */
    1115             : 
    1116             : 
    1117           3 : struct tncc_data * tncc_init(void)
    1118             : {
    1119             :         struct tncc_data *tncc;
    1120             :         struct tnc_if_imc *imc;
    1121             : 
    1122           3 :         tncc = os_zalloc(sizeof(*tncc));
    1123           3 :         if (tncc == NULL)
    1124           0 :                 return NULL;
    1125             : 
    1126             :         /* TODO:
    1127             :          * move loading and Initialize() to a location that is not
    1128             :          *    re-initialized for every EAP-TNC session (?)
    1129             :          */
    1130             : 
    1131           3 :         if (tncc_read_config(tncc) < 0) {
    1132           0 :                 wpa_printf(MSG_ERROR, "TNC: Failed to read TNC configuration");
    1133           0 :                 goto failed;
    1134             :         }
    1135             : 
    1136           9 :         for (imc = tncc->imc; imc; imc = imc->next) {
    1137           6 :                 if (tncc_load_imc(imc)) {
    1138           0 :                         wpa_printf(MSG_ERROR, "TNC: Failed to load IMC '%s'",
    1139             :                                    imc->name);
    1140           0 :                         goto failed;
    1141             :                 }
    1142             :         }
    1143             : 
    1144           3 :         return tncc;
    1145             : 
    1146             : failed:
    1147           0 :         tncc_deinit(tncc);
    1148           0 :         return NULL;
    1149             : }
    1150             : 
    1151             : 
    1152           3 : void tncc_deinit(struct tncc_data *tncc)
    1153             : {
    1154             :         struct tnc_if_imc *imc, *prev;
    1155             : 
    1156           3 :         imc = tncc->imc;
    1157          12 :         while (imc) {
    1158           6 :                 tncc_unload_imc(imc);
    1159             : 
    1160           6 :                 prev = imc;
    1161           6 :                 imc = imc->next;
    1162           6 :                 os_free(prev);
    1163             :         }
    1164             : 
    1165           3 :         os_free(tncc);
    1166           3 : }
    1167             : 
    1168             : 
    1169           3 : static struct wpabuf * tncc_build_soh(int ver)
    1170             : {
    1171             :         struct wpabuf *buf;
    1172             :         u8 *tlv_len, *tlv_len2, *outer_len, *inner_len, *ssoh_len, *end;
    1173             :         u8 correlation_id[24];
    1174             :         /* TODO: get correct name */
    1175           3 :         char *machinename = "wpa_supplicant@w1.fi";
    1176             : 
    1177           3 :         if (os_get_random(correlation_id, sizeof(correlation_id)))
    1178           0 :                 return NULL;
    1179           3 :         wpa_hexdump(MSG_DEBUG, "TNC: SoH Correlation ID",
    1180             :                     correlation_id, sizeof(correlation_id));
    1181             : 
    1182           3 :         buf = wpabuf_alloc(200);
    1183           3 :         if (buf == NULL)
    1184           0 :                 return NULL;
    1185             : 
    1186             :         /* Vendor-Specific TLV (Microsoft) - SoH */
    1187           3 :         wpabuf_put_be16(buf, EAP_TLV_VENDOR_SPECIFIC_TLV); /* TLV Type */
    1188           3 :         tlv_len = wpabuf_put(buf, 2); /* Length */
    1189           3 :         wpabuf_put_be32(buf, EAP_VENDOR_MICROSOFT); /* Vendor_Id */
    1190           3 :         wpabuf_put_be16(buf, 0x01); /* TLV Type - SoH TLV */
    1191           3 :         tlv_len2 = wpabuf_put(buf, 2); /* Length */
    1192             : 
    1193             :         /* SoH Header */
    1194           3 :         wpabuf_put_be16(buf, EAP_TLV_VENDOR_SPECIFIC_TLV); /* Outer Type */
    1195           3 :         outer_len = wpabuf_put(buf, 2);
    1196           3 :         wpabuf_put_be32(buf, EAP_VENDOR_MICROSOFT); /* IANA SMI Code */
    1197           3 :         wpabuf_put_be16(buf, ver); /* Inner Type */
    1198           3 :         inner_len = wpabuf_put(buf, 2);
    1199             : 
    1200           3 :         if (ver == 2) {
    1201             :                 /* SoH Mode Sub-Header */
    1202             :                 /* Outer Type */
    1203           3 :                 wpabuf_put_be16(buf, EAP_TLV_VENDOR_SPECIFIC_TLV);
    1204           3 :                 wpabuf_put_be16(buf, 4 + 24 + 1 + 1); /* Length */
    1205           3 :                 wpabuf_put_be32(buf, EAP_VENDOR_MICROSOFT); /* IANA SMI Code */
    1206             :                 /* Value: */
    1207           3 :                 wpabuf_put_data(buf, correlation_id, sizeof(correlation_id));
    1208           3 :                 wpabuf_put_u8(buf, 0x01); /* Intent Flag - Request */
    1209           3 :                 wpabuf_put_u8(buf, 0x00); /* Content-Type Flag */
    1210             :         }
    1211             : 
    1212             :         /* SSoH TLV */
    1213             :         /* System-Health-Id */
    1214           3 :         wpabuf_put_be16(buf, 0x0002); /* Type */
    1215           3 :         wpabuf_put_be16(buf, 4); /* Length */
    1216           3 :         wpabuf_put_be32(buf, 79616);
    1217             :         /* Vendor-Specific Attribute */
    1218           3 :         wpabuf_put_be16(buf, EAP_TLV_VENDOR_SPECIFIC_TLV);
    1219           3 :         ssoh_len = wpabuf_put(buf, 2);
    1220           3 :         wpabuf_put_be32(buf, EAP_VENDOR_MICROSOFT); /* IANA SMI Code */
    1221             : 
    1222             :         /* MS-Packet-Info */
    1223           3 :         wpabuf_put_u8(buf, SSOH_MS_PACKET_INFO);
    1224             :         /* Note: IF-TNCCS-SOH v1.0 r8 claims this field to be:
    1225             :          * Reserved(4 bits) r(1 bit) Vers(3 bits), but Windows XP
    1226             :          * SP3 seems to be sending 0x11 for SSoH, i.e., r(request/response) bit
    1227             :          * would not be in the specified location.
    1228             :          * [MS-SOH] 4.0.2: Reserved(3 bits) r(1 bit) Vers(4 bits)
    1229             :          */
    1230           3 :         wpabuf_put_u8(buf, 0x11); /* r=request, vers=1 */
    1231             : 
    1232             :         /* MS-Machine-Inventory */
    1233             :         /* TODO: get correct values; 0 = not applicable for OS */
    1234           3 :         wpabuf_put_u8(buf, SSOH_MS_MACHINE_INVENTORY);
    1235           3 :         wpabuf_put_be32(buf, 0); /* osVersionMajor */
    1236           3 :         wpabuf_put_be32(buf, 0); /* osVersionMinor */
    1237           3 :         wpabuf_put_be32(buf, 0); /* osVersionBuild */
    1238           3 :         wpabuf_put_be16(buf, 0); /* spVersionMajor */
    1239           3 :         wpabuf_put_be16(buf, 0); /* spVersionMinor */
    1240           3 :         wpabuf_put_be16(buf, 0); /* procArch */
    1241             : 
    1242             :         /* MS-MachineName */
    1243           3 :         wpabuf_put_u8(buf, SSOH_MS_MACHINENAME);
    1244           3 :         wpabuf_put_be16(buf, os_strlen(machinename) + 1);
    1245           3 :         wpabuf_put_data(buf, machinename, os_strlen(machinename) + 1);
    1246             : 
    1247             :         /* MS-CorrelationId */
    1248           3 :         wpabuf_put_u8(buf, SSOH_MS_CORRELATIONID);
    1249           3 :         wpabuf_put_data(buf, correlation_id, sizeof(correlation_id));
    1250             : 
    1251             :         /* MS-Quarantine-State */
    1252           3 :         wpabuf_put_u8(buf, SSOH_MS_QUARANTINE_STATE);
    1253           3 :         wpabuf_put_be16(buf, 1); /* Flags: ExtState=0, f=0, qState=1 */
    1254           3 :         wpabuf_put_be32(buf, 0xffffffff); /* ProbTime (hi) */
    1255           3 :         wpabuf_put_be32(buf, 0xffffffff); /* ProbTime (lo) */
    1256           3 :         wpabuf_put_be16(buf, 1); /* urlLenInBytes */
    1257           3 :         wpabuf_put_u8(buf, 0); /* null termination for the url */
    1258             : 
    1259             :         /* MS-Machine-Inventory-Ex */
    1260           3 :         wpabuf_put_u8(buf, SSOH_MS_MACHINE_INVENTORY_EX);
    1261           3 :         wpabuf_put_be32(buf, 0); /* Reserved
    1262             :                                   * (note: Windows XP SP3 uses 0xdecafbad) */
    1263           3 :         wpabuf_put_u8(buf, 1); /* ProductType: Client */
    1264             : 
    1265             :         /* Update SSoH Length */
    1266           3 :         end = wpabuf_put(buf, 0);
    1267           3 :         WPA_PUT_BE16(ssoh_len, end - ssoh_len - 2);
    1268             : 
    1269             :         /* TODO: SoHReportEntry TLV (zero or more) */
    1270             : 
    1271             :         /* Update length fields */
    1272           3 :         end = wpabuf_put(buf, 0);
    1273           3 :         WPA_PUT_BE16(tlv_len, end - tlv_len - 2);
    1274           3 :         WPA_PUT_BE16(tlv_len2, end - tlv_len2 - 2);
    1275           3 :         WPA_PUT_BE16(outer_len, end - outer_len - 2);
    1276           3 :         WPA_PUT_BE16(inner_len, end - inner_len - 2);
    1277             : 
    1278           3 :         return buf;
    1279             : }
    1280             : 
    1281             : 
    1282           3 : struct wpabuf * tncc_process_soh_request(int ver, const u8 *data, size_t len)
    1283             : {
    1284             :         const u8 *pos;
    1285             : 
    1286           3 :         wpa_hexdump(MSG_DEBUG, "TNC: SoH Request", data, len);
    1287             : 
    1288           3 :         if (len < 12)
    1289           0 :                 return NULL;
    1290             : 
    1291             :         /* SoH Request */
    1292           3 :         pos = data;
    1293             : 
    1294             :         /* TLV Type */
    1295           3 :         if (WPA_GET_BE16(pos) != EAP_TLV_VENDOR_SPECIFIC_TLV)
    1296           0 :                 return NULL;
    1297           3 :         pos += 2;
    1298             : 
    1299             :         /* Length */
    1300           3 :         if (WPA_GET_BE16(pos) < 8)
    1301           0 :                 return NULL;
    1302           3 :         pos += 2;
    1303             : 
    1304             :         /* Vendor_Id */
    1305           3 :         if (WPA_GET_BE32(pos) != EAP_VENDOR_MICROSOFT)
    1306           0 :                 return NULL;
    1307           3 :         pos += 4;
    1308             : 
    1309             :         /* TLV Type */
    1310           3 :         if (WPA_GET_BE16(pos) != 0x02 /* SoH request TLV */)
    1311           0 :                 return NULL;
    1312             : 
    1313           3 :         wpa_printf(MSG_DEBUG, "TNC: SoH Request TLV received");
    1314             : 
    1315           3 :         return tncc_build_soh(2);
    1316             : }

Generated by: LCOV version 1.10