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