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 1388338050 Lines: 0 544 0.0 %
Date: 2013-12-29 Functions: 0 33 0.0 %
Branches: 0 256 0.0 %

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

Generated by: LCOV version 1.9