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