1e5b75505Sopenharmony_ci/* 2e5b75505Sopenharmony_ci * EAP-TNC - TNCS (IF-IMV, IF-TNCCS, and IF-TNCCS-SOH) 3e5b75505Sopenharmony_ci * Copyright (c) 2007-2008, 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#include <dlfcn.h> 11e5b75505Sopenharmony_ci 12e5b75505Sopenharmony_ci#include "common.h" 13e5b75505Sopenharmony_ci#include "base64.h" 14e5b75505Sopenharmony_ci#include "common/tnc.h" 15e5b75505Sopenharmony_ci#include "tncs.h" 16e5b75505Sopenharmony_ci#include "eap_common/eap_tlv_common.h" 17e5b75505Sopenharmony_ci#include "eap_common/eap_defs.h" 18e5b75505Sopenharmony_ci 19e5b75505Sopenharmony_ci 20e5b75505Sopenharmony_ci/* TODO: TNCS must be thread-safe; review the code and add locking etc. if 21e5b75505Sopenharmony_ci * needed.. */ 22e5b75505Sopenharmony_ci 23e5b75505Sopenharmony_ci#ifndef TNC_CONFIG_FILE 24e5b75505Sopenharmony_ci#define TNC_CONFIG_FILE "/etc/tnc_config" 25e5b75505Sopenharmony_ci#endif /* TNC_CONFIG_FILE */ 26e5b75505Sopenharmony_ci#define IF_TNCCS_START \ 27e5b75505Sopenharmony_ci"<?xml version=\"1.0\"?>\n" \ 28e5b75505Sopenharmony_ci"<TNCCS-Batch BatchId=\"%d\" Recipient=\"TNCS\" " \ 29e5b75505Sopenharmony_ci"xmlns=\"http://www.trustedcomputinggroup.org/IWG/TNC/1_0/IF_TNCCS#\" " \ 30e5b75505Sopenharmony_ci"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " \ 31e5b75505Sopenharmony_ci"xsi:schemaLocation=\"http://www.trustedcomputinggroup.org/IWG/TNC/1_0/" \ 32e5b75505Sopenharmony_ci"IF_TNCCS# https://www.trustedcomputinggroup.org/XML/SCHEMA/TNCCS_1.0.xsd\">\n" 33e5b75505Sopenharmony_ci#define IF_TNCCS_END "\n</TNCCS-Batch>" 34e5b75505Sopenharmony_ci 35e5b75505Sopenharmony_ci/* TNC IF-IMV */ 36e5b75505Sopenharmony_ci 37e5b75505Sopenharmony_cistruct tnc_if_imv { 38e5b75505Sopenharmony_ci struct tnc_if_imv *next; 39e5b75505Sopenharmony_ci char *name; 40e5b75505Sopenharmony_ci char *path; 41e5b75505Sopenharmony_ci void *dlhandle; /* from dlopen() */ 42e5b75505Sopenharmony_ci TNC_IMVID imvID; 43e5b75505Sopenharmony_ci TNC_MessageTypeList supported_types; 44e5b75505Sopenharmony_ci size_t num_supported_types; 45e5b75505Sopenharmony_ci 46e5b75505Sopenharmony_ci /* Functions implemented by IMVs (with TNC_IMV_ prefix) */ 47e5b75505Sopenharmony_ci TNC_Result (*Initialize)( 48e5b75505Sopenharmony_ci TNC_IMVID imvID, 49e5b75505Sopenharmony_ci TNC_Version minVersion, 50e5b75505Sopenharmony_ci TNC_Version maxVersion, 51e5b75505Sopenharmony_ci TNC_Version *pOutActualVersion); 52e5b75505Sopenharmony_ci TNC_Result (*NotifyConnectionChange)( 53e5b75505Sopenharmony_ci TNC_IMVID imvID, 54e5b75505Sopenharmony_ci TNC_ConnectionID connectionID, 55e5b75505Sopenharmony_ci TNC_ConnectionState newState); 56e5b75505Sopenharmony_ci TNC_Result (*ReceiveMessage)( 57e5b75505Sopenharmony_ci TNC_IMVID imvID, 58e5b75505Sopenharmony_ci TNC_ConnectionID connectionID, 59e5b75505Sopenharmony_ci TNC_BufferReference message, 60e5b75505Sopenharmony_ci TNC_UInt32 messageLength, 61e5b75505Sopenharmony_ci TNC_MessageType messageType); 62e5b75505Sopenharmony_ci TNC_Result (*SolicitRecommendation)( 63e5b75505Sopenharmony_ci TNC_IMVID imvID, 64e5b75505Sopenharmony_ci TNC_ConnectionID connectionID); 65e5b75505Sopenharmony_ci TNC_Result (*BatchEnding)( 66e5b75505Sopenharmony_ci TNC_IMVID imvID, 67e5b75505Sopenharmony_ci TNC_ConnectionID connectionID); 68e5b75505Sopenharmony_ci TNC_Result (*Terminate)(TNC_IMVID imvID); 69e5b75505Sopenharmony_ci TNC_Result (*ProvideBindFunction)( 70e5b75505Sopenharmony_ci TNC_IMVID imvID, 71e5b75505Sopenharmony_ci TNC_TNCS_BindFunctionPointer bindFunction); 72e5b75505Sopenharmony_ci}; 73e5b75505Sopenharmony_ci 74e5b75505Sopenharmony_ci 75e5b75505Sopenharmony_ci#define TNC_MAX_IMV_ID 10 76e5b75505Sopenharmony_ci 77e5b75505Sopenharmony_cistruct tncs_data { 78e5b75505Sopenharmony_ci struct tncs_data *next; 79e5b75505Sopenharmony_ci struct tnc_if_imv *imv; /* local copy of tncs_global_data->imv */ 80e5b75505Sopenharmony_ci TNC_ConnectionID connectionID; 81e5b75505Sopenharmony_ci unsigned int last_batchid; 82e5b75505Sopenharmony_ci enum IMV_Action_Recommendation recommendation; 83e5b75505Sopenharmony_ci int done; 84e5b75505Sopenharmony_ci 85e5b75505Sopenharmony_ci struct conn_imv { 86e5b75505Sopenharmony_ci u8 *imv_send; 87e5b75505Sopenharmony_ci size_t imv_send_len; 88e5b75505Sopenharmony_ci enum IMV_Action_Recommendation recommendation; 89e5b75505Sopenharmony_ci int recommendation_set; 90e5b75505Sopenharmony_ci } imv_data[TNC_MAX_IMV_ID]; 91e5b75505Sopenharmony_ci 92e5b75505Sopenharmony_ci char *tncs_message; 93e5b75505Sopenharmony_ci}; 94e5b75505Sopenharmony_ci 95e5b75505Sopenharmony_ci 96e5b75505Sopenharmony_cistruct tncs_global { 97e5b75505Sopenharmony_ci struct tnc_if_imv *imv; 98e5b75505Sopenharmony_ci TNC_ConnectionID next_conn_id; 99e5b75505Sopenharmony_ci struct tncs_data *connections; 100e5b75505Sopenharmony_ci}; 101e5b75505Sopenharmony_ci 102e5b75505Sopenharmony_cistatic struct tncs_global *tncs_global_data = NULL; 103e5b75505Sopenharmony_ci 104e5b75505Sopenharmony_ci 105e5b75505Sopenharmony_cistatic struct tnc_if_imv * tncs_get_imv(TNC_IMVID imvID) 106e5b75505Sopenharmony_ci{ 107e5b75505Sopenharmony_ci struct tnc_if_imv *imv; 108e5b75505Sopenharmony_ci 109e5b75505Sopenharmony_ci if (imvID >= TNC_MAX_IMV_ID || tncs_global_data == NULL) 110e5b75505Sopenharmony_ci return NULL; 111e5b75505Sopenharmony_ci imv = tncs_global_data->imv; 112e5b75505Sopenharmony_ci while (imv) { 113e5b75505Sopenharmony_ci if (imv->imvID == imvID) 114e5b75505Sopenharmony_ci return imv; 115e5b75505Sopenharmony_ci imv = imv->next; 116e5b75505Sopenharmony_ci } 117e5b75505Sopenharmony_ci return NULL; 118e5b75505Sopenharmony_ci} 119e5b75505Sopenharmony_ci 120e5b75505Sopenharmony_ci 121e5b75505Sopenharmony_cistatic struct tncs_data * tncs_get_conn(TNC_ConnectionID connectionID) 122e5b75505Sopenharmony_ci{ 123e5b75505Sopenharmony_ci struct tncs_data *tncs; 124e5b75505Sopenharmony_ci 125e5b75505Sopenharmony_ci if (tncs_global_data == NULL) 126e5b75505Sopenharmony_ci return NULL; 127e5b75505Sopenharmony_ci 128e5b75505Sopenharmony_ci tncs = tncs_global_data->connections; 129e5b75505Sopenharmony_ci while (tncs) { 130e5b75505Sopenharmony_ci if (tncs->connectionID == connectionID) 131e5b75505Sopenharmony_ci return tncs; 132e5b75505Sopenharmony_ci tncs = tncs->next; 133e5b75505Sopenharmony_ci } 134e5b75505Sopenharmony_ci 135e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "TNC: Connection ID %lu not found", 136e5b75505Sopenharmony_ci (unsigned long) connectionID); 137e5b75505Sopenharmony_ci 138e5b75505Sopenharmony_ci return NULL; 139e5b75505Sopenharmony_ci} 140e5b75505Sopenharmony_ci 141e5b75505Sopenharmony_ci 142e5b75505Sopenharmony_ci/* TNCS functions that IMVs can call */ 143e5b75505Sopenharmony_cistatic TNC_Result TNC_TNCS_ReportMessageTypes( 144e5b75505Sopenharmony_ci TNC_IMVID imvID, 145e5b75505Sopenharmony_ci TNC_MessageTypeList supportedTypes, 146e5b75505Sopenharmony_ci TNC_UInt32 typeCount) 147e5b75505Sopenharmony_ci{ 148e5b75505Sopenharmony_ci TNC_UInt32 i; 149e5b75505Sopenharmony_ci struct tnc_if_imv *imv; 150e5b75505Sopenharmony_ci 151e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "TNC: TNC_TNCS_ReportMessageTypes(imvID=%lu " 152e5b75505Sopenharmony_ci "typeCount=%lu)", 153e5b75505Sopenharmony_ci (unsigned long) imvID, (unsigned long) typeCount); 154e5b75505Sopenharmony_ci 155e5b75505Sopenharmony_ci for (i = 0; i < typeCount; i++) { 156e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "TNC: supportedTypes[%lu] = %lu", 157e5b75505Sopenharmony_ci i, supportedTypes[i]); 158e5b75505Sopenharmony_ci } 159e5b75505Sopenharmony_ci 160e5b75505Sopenharmony_ci imv = tncs_get_imv(imvID); 161e5b75505Sopenharmony_ci if (imv == NULL) 162e5b75505Sopenharmony_ci return TNC_RESULT_INVALID_PARAMETER; 163e5b75505Sopenharmony_ci os_free(imv->supported_types); 164e5b75505Sopenharmony_ci imv->supported_types = os_memdup(supportedTypes, 165e5b75505Sopenharmony_ci typeCount * sizeof(TNC_MessageType)); 166e5b75505Sopenharmony_ci if (imv->supported_types == NULL) 167e5b75505Sopenharmony_ci return TNC_RESULT_FATAL; 168e5b75505Sopenharmony_ci imv->num_supported_types = typeCount; 169e5b75505Sopenharmony_ci 170e5b75505Sopenharmony_ci return TNC_RESULT_SUCCESS; 171e5b75505Sopenharmony_ci} 172e5b75505Sopenharmony_ci 173e5b75505Sopenharmony_ci 174e5b75505Sopenharmony_cistatic TNC_Result TNC_TNCS_SendMessage( 175e5b75505Sopenharmony_ci TNC_IMVID imvID, 176e5b75505Sopenharmony_ci TNC_ConnectionID connectionID, 177e5b75505Sopenharmony_ci TNC_BufferReference message, 178e5b75505Sopenharmony_ci TNC_UInt32 messageLength, 179e5b75505Sopenharmony_ci TNC_MessageType messageType) 180e5b75505Sopenharmony_ci{ 181e5b75505Sopenharmony_ci struct tncs_data *tncs; 182e5b75505Sopenharmony_ci unsigned char *b64; 183e5b75505Sopenharmony_ci size_t b64len; 184e5b75505Sopenharmony_ci 185e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "TNC: TNC_TNCS_SendMessage(imvID=%lu " 186e5b75505Sopenharmony_ci "connectionID=%lu messageType=%lu)", 187e5b75505Sopenharmony_ci imvID, connectionID, messageType); 188e5b75505Sopenharmony_ci wpa_hexdump_ascii(MSG_DEBUG, "TNC: TNC_TNCS_SendMessage", 189e5b75505Sopenharmony_ci message, messageLength); 190e5b75505Sopenharmony_ci 191e5b75505Sopenharmony_ci if (tncs_get_imv(imvID) == NULL) 192e5b75505Sopenharmony_ci return TNC_RESULT_INVALID_PARAMETER; 193e5b75505Sopenharmony_ci 194e5b75505Sopenharmony_ci tncs = tncs_get_conn(connectionID); 195e5b75505Sopenharmony_ci if (tncs == NULL) 196e5b75505Sopenharmony_ci return TNC_RESULT_INVALID_PARAMETER; 197e5b75505Sopenharmony_ci 198e5b75505Sopenharmony_ci b64 = base64_encode(message, messageLength, &b64len); 199e5b75505Sopenharmony_ci if (b64 == NULL) 200e5b75505Sopenharmony_ci return TNC_RESULT_FATAL; 201e5b75505Sopenharmony_ci 202e5b75505Sopenharmony_ci os_free(tncs->imv_data[imvID].imv_send); 203e5b75505Sopenharmony_ci tncs->imv_data[imvID].imv_send_len = 0; 204e5b75505Sopenharmony_ci tncs->imv_data[imvID].imv_send = os_zalloc(b64len + 100); 205e5b75505Sopenharmony_ci if (tncs->imv_data[imvID].imv_send == NULL) { 206e5b75505Sopenharmony_ci os_free(b64); 207e5b75505Sopenharmony_ci return TNC_RESULT_OTHER; 208e5b75505Sopenharmony_ci } 209e5b75505Sopenharmony_ci 210e5b75505Sopenharmony_ci tncs->imv_data[imvID].imv_send_len = 211e5b75505Sopenharmony_ci os_snprintf((char *) tncs->imv_data[imvID].imv_send, 212e5b75505Sopenharmony_ci b64len + 100, 213e5b75505Sopenharmony_ci "<IMC-IMV-Message><Type>%08X</Type>" 214e5b75505Sopenharmony_ci "<Base64>%s</Base64></IMC-IMV-Message>", 215e5b75505Sopenharmony_ci (unsigned int) messageType, b64); 216e5b75505Sopenharmony_ci 217e5b75505Sopenharmony_ci os_free(b64); 218e5b75505Sopenharmony_ci 219e5b75505Sopenharmony_ci return TNC_RESULT_SUCCESS; 220e5b75505Sopenharmony_ci} 221e5b75505Sopenharmony_ci 222e5b75505Sopenharmony_ci 223e5b75505Sopenharmony_cistatic TNC_Result TNC_TNCS_RequestHandshakeRetry( 224e5b75505Sopenharmony_ci TNC_IMVID imvID, 225e5b75505Sopenharmony_ci TNC_ConnectionID connectionID, 226e5b75505Sopenharmony_ci TNC_RetryReason reason) 227e5b75505Sopenharmony_ci{ 228e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "TNC: TNC_TNCS_RequestHandshakeRetry"); 229e5b75505Sopenharmony_ci /* TODO */ 230e5b75505Sopenharmony_ci return TNC_RESULT_SUCCESS; 231e5b75505Sopenharmony_ci} 232e5b75505Sopenharmony_ci 233e5b75505Sopenharmony_ci 234e5b75505Sopenharmony_cistatic TNC_Result TNC_TNCS_ProvideRecommendation( 235e5b75505Sopenharmony_ci TNC_IMVID imvID, 236e5b75505Sopenharmony_ci TNC_ConnectionID connectionID, 237e5b75505Sopenharmony_ci TNC_IMV_Action_Recommendation recommendation, 238e5b75505Sopenharmony_ci TNC_IMV_Evaluation_Result evaluation) 239e5b75505Sopenharmony_ci{ 240e5b75505Sopenharmony_ci struct tncs_data *tncs; 241e5b75505Sopenharmony_ci 242e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "TNC: TNC_TNCS_ProvideRecommendation(imvID=%lu " 243e5b75505Sopenharmony_ci "connectionID=%lu recommendation=%lu evaluation=%lu)", 244e5b75505Sopenharmony_ci (unsigned long) imvID, (unsigned long) connectionID, 245e5b75505Sopenharmony_ci (unsigned long) recommendation, (unsigned long) evaluation); 246e5b75505Sopenharmony_ci 247e5b75505Sopenharmony_ci if (tncs_get_imv(imvID) == NULL) 248e5b75505Sopenharmony_ci return TNC_RESULT_INVALID_PARAMETER; 249e5b75505Sopenharmony_ci 250e5b75505Sopenharmony_ci tncs = tncs_get_conn(connectionID); 251e5b75505Sopenharmony_ci if (tncs == NULL) 252e5b75505Sopenharmony_ci return TNC_RESULT_INVALID_PARAMETER; 253e5b75505Sopenharmony_ci 254e5b75505Sopenharmony_ci tncs->imv_data[imvID].recommendation = recommendation; 255e5b75505Sopenharmony_ci tncs->imv_data[imvID].recommendation_set = 1; 256e5b75505Sopenharmony_ci 257e5b75505Sopenharmony_ci return TNC_RESULT_SUCCESS; 258e5b75505Sopenharmony_ci} 259e5b75505Sopenharmony_ci 260e5b75505Sopenharmony_ci 261e5b75505Sopenharmony_cistatic TNC_Result TNC_TNCS_GetAttribute( 262e5b75505Sopenharmony_ci TNC_IMVID imvID, 263e5b75505Sopenharmony_ci TNC_ConnectionID connectionID, 264e5b75505Sopenharmony_ci TNC_AttributeID attribureID, 265e5b75505Sopenharmony_ci TNC_UInt32 bufferLength, 266e5b75505Sopenharmony_ci TNC_BufferReference buffer, 267e5b75505Sopenharmony_ci TNC_UInt32 *pOutValueLength) 268e5b75505Sopenharmony_ci{ 269e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "TNC: TNC_TNCS_GetAttribute"); 270e5b75505Sopenharmony_ci /* TODO */ 271e5b75505Sopenharmony_ci return TNC_RESULT_SUCCESS; 272e5b75505Sopenharmony_ci} 273e5b75505Sopenharmony_ci 274e5b75505Sopenharmony_ci 275e5b75505Sopenharmony_cistatic TNC_Result TNC_TNCS_SetAttribute( 276e5b75505Sopenharmony_ci TNC_IMVID imvID, 277e5b75505Sopenharmony_ci TNC_ConnectionID connectionID, 278e5b75505Sopenharmony_ci TNC_AttributeID attribureID, 279e5b75505Sopenharmony_ci TNC_UInt32 bufferLength, 280e5b75505Sopenharmony_ci TNC_BufferReference buffer) 281e5b75505Sopenharmony_ci{ 282e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "TNC: TNC_TNCS_SetAttribute"); 283e5b75505Sopenharmony_ci /* TODO */ 284e5b75505Sopenharmony_ci return TNC_RESULT_SUCCESS; 285e5b75505Sopenharmony_ci} 286e5b75505Sopenharmony_ci 287e5b75505Sopenharmony_ci 288e5b75505Sopenharmony_cistatic TNC_Result TNC_TNCS_BindFunction( 289e5b75505Sopenharmony_ci TNC_IMVID imvID, 290e5b75505Sopenharmony_ci char *functionName, 291e5b75505Sopenharmony_ci void **pOutFunctionPointer) 292e5b75505Sopenharmony_ci{ 293e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "TNC: TNC_TNCS_BindFunction(imcID=%lu, " 294e5b75505Sopenharmony_ci "functionName='%s')", (unsigned long) imvID, functionName); 295e5b75505Sopenharmony_ci 296e5b75505Sopenharmony_ci if (tncs_get_imv(imvID) == NULL) 297e5b75505Sopenharmony_ci return TNC_RESULT_INVALID_PARAMETER; 298e5b75505Sopenharmony_ci 299e5b75505Sopenharmony_ci if (pOutFunctionPointer == NULL) 300e5b75505Sopenharmony_ci return TNC_RESULT_INVALID_PARAMETER; 301e5b75505Sopenharmony_ci 302e5b75505Sopenharmony_ci if (os_strcmp(functionName, "TNC_TNCS_ReportMessageTypes") == 0) 303e5b75505Sopenharmony_ci *pOutFunctionPointer = TNC_TNCS_ReportMessageTypes; 304e5b75505Sopenharmony_ci else if (os_strcmp(functionName, "TNC_TNCS_SendMessage") == 0) 305e5b75505Sopenharmony_ci *pOutFunctionPointer = TNC_TNCS_SendMessage; 306e5b75505Sopenharmony_ci else if (os_strcmp(functionName, "TNC_TNCS_RequestHandshakeRetry") == 307e5b75505Sopenharmony_ci 0) 308e5b75505Sopenharmony_ci *pOutFunctionPointer = TNC_TNCS_RequestHandshakeRetry; 309e5b75505Sopenharmony_ci else if (os_strcmp(functionName, "TNC_TNCS_ProvideRecommendation") == 310e5b75505Sopenharmony_ci 0) 311e5b75505Sopenharmony_ci *pOutFunctionPointer = TNC_TNCS_ProvideRecommendation; 312e5b75505Sopenharmony_ci else if (os_strcmp(functionName, "TNC_TNCS_GetAttribute") == 0) 313e5b75505Sopenharmony_ci *pOutFunctionPointer = TNC_TNCS_GetAttribute; 314e5b75505Sopenharmony_ci else if (os_strcmp(functionName, "TNC_TNCS_SetAttribute") == 0) 315e5b75505Sopenharmony_ci *pOutFunctionPointer = TNC_TNCS_SetAttribute; 316e5b75505Sopenharmony_ci else 317e5b75505Sopenharmony_ci *pOutFunctionPointer = NULL; 318e5b75505Sopenharmony_ci 319e5b75505Sopenharmony_ci return TNC_RESULT_SUCCESS; 320e5b75505Sopenharmony_ci} 321e5b75505Sopenharmony_ci 322e5b75505Sopenharmony_ci 323e5b75505Sopenharmony_cistatic void * tncs_get_sym(void *handle, char *func) 324e5b75505Sopenharmony_ci{ 325e5b75505Sopenharmony_ci void *fptr; 326e5b75505Sopenharmony_ci 327e5b75505Sopenharmony_ci fptr = dlsym(handle, func); 328e5b75505Sopenharmony_ci 329e5b75505Sopenharmony_ci return fptr; 330e5b75505Sopenharmony_ci} 331e5b75505Sopenharmony_ci 332e5b75505Sopenharmony_ci 333e5b75505Sopenharmony_cistatic int tncs_imv_resolve_funcs(struct tnc_if_imv *imv) 334e5b75505Sopenharmony_ci{ 335e5b75505Sopenharmony_ci void *handle = imv->dlhandle; 336e5b75505Sopenharmony_ci 337e5b75505Sopenharmony_ci /* Mandatory IMV functions */ 338e5b75505Sopenharmony_ci imv->Initialize = tncs_get_sym(handle, "TNC_IMV_Initialize"); 339e5b75505Sopenharmony_ci if (imv->Initialize == NULL) { 340e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "TNC: IMV does not export " 341e5b75505Sopenharmony_ci "TNC_IMV_Initialize"); 342e5b75505Sopenharmony_ci return -1; 343e5b75505Sopenharmony_ci } 344e5b75505Sopenharmony_ci 345e5b75505Sopenharmony_ci imv->SolicitRecommendation = tncs_get_sym( 346e5b75505Sopenharmony_ci handle, "TNC_IMV_SolicitRecommendation"); 347e5b75505Sopenharmony_ci if (imv->SolicitRecommendation == NULL) { 348e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "TNC: IMV does not export " 349e5b75505Sopenharmony_ci "TNC_IMV_SolicitRecommendation"); 350e5b75505Sopenharmony_ci return -1; 351e5b75505Sopenharmony_ci } 352e5b75505Sopenharmony_ci 353e5b75505Sopenharmony_ci imv->ProvideBindFunction = 354e5b75505Sopenharmony_ci tncs_get_sym(handle, "TNC_IMV_ProvideBindFunction"); 355e5b75505Sopenharmony_ci if (imv->ProvideBindFunction == NULL) { 356e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "TNC: IMV does not export " 357e5b75505Sopenharmony_ci "TNC_IMV_ProvideBindFunction"); 358e5b75505Sopenharmony_ci return -1; 359e5b75505Sopenharmony_ci } 360e5b75505Sopenharmony_ci 361e5b75505Sopenharmony_ci /* Optional IMV functions */ 362e5b75505Sopenharmony_ci imv->NotifyConnectionChange = 363e5b75505Sopenharmony_ci tncs_get_sym(handle, "TNC_IMV_NotifyConnectionChange"); 364e5b75505Sopenharmony_ci imv->ReceiveMessage = tncs_get_sym(handle, "TNC_IMV_ReceiveMessage"); 365e5b75505Sopenharmony_ci imv->BatchEnding = tncs_get_sym(handle, "TNC_IMV_BatchEnding"); 366e5b75505Sopenharmony_ci imv->Terminate = tncs_get_sym(handle, "TNC_IMV_Terminate"); 367e5b75505Sopenharmony_ci 368e5b75505Sopenharmony_ci return 0; 369e5b75505Sopenharmony_ci} 370e5b75505Sopenharmony_ci 371e5b75505Sopenharmony_ci 372e5b75505Sopenharmony_cistatic int tncs_imv_initialize(struct tnc_if_imv *imv) 373e5b75505Sopenharmony_ci{ 374e5b75505Sopenharmony_ci TNC_Result res; 375e5b75505Sopenharmony_ci TNC_Version imv_ver; 376e5b75505Sopenharmony_ci 377e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "TNC: Calling TNC_IMV_Initialize for IMV '%s'", 378e5b75505Sopenharmony_ci imv->name); 379e5b75505Sopenharmony_ci res = imv->Initialize(imv->imvID, TNC_IFIMV_VERSION_1, 380e5b75505Sopenharmony_ci TNC_IFIMV_VERSION_1, &imv_ver); 381e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "TNC: TNC_IMV_Initialize: res=%lu imv_ver=%lu", 382e5b75505Sopenharmony_ci (unsigned long) res, (unsigned long) imv_ver); 383e5b75505Sopenharmony_ci 384e5b75505Sopenharmony_ci return res == TNC_RESULT_SUCCESS ? 0 : -1; 385e5b75505Sopenharmony_ci} 386e5b75505Sopenharmony_ci 387e5b75505Sopenharmony_ci 388e5b75505Sopenharmony_cistatic int tncs_imv_terminate(struct tnc_if_imv *imv) 389e5b75505Sopenharmony_ci{ 390e5b75505Sopenharmony_ci TNC_Result res; 391e5b75505Sopenharmony_ci 392e5b75505Sopenharmony_ci if (imv->Terminate == NULL) 393e5b75505Sopenharmony_ci return 0; 394e5b75505Sopenharmony_ci 395e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "TNC: Calling TNC_IMV_Terminate for IMV '%s'", 396e5b75505Sopenharmony_ci imv->name); 397e5b75505Sopenharmony_ci res = imv->Terminate(imv->imvID); 398e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "TNC: TNC_IMV_Terminate: %lu", 399e5b75505Sopenharmony_ci (unsigned long) res); 400e5b75505Sopenharmony_ci 401e5b75505Sopenharmony_ci return res == TNC_RESULT_SUCCESS ? 0 : -1; 402e5b75505Sopenharmony_ci} 403e5b75505Sopenharmony_ci 404e5b75505Sopenharmony_ci 405e5b75505Sopenharmony_cistatic int tncs_imv_provide_bind_function(struct tnc_if_imv *imv) 406e5b75505Sopenharmony_ci{ 407e5b75505Sopenharmony_ci TNC_Result res; 408e5b75505Sopenharmony_ci 409e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "TNC: Calling TNC_IMV_ProvideBindFunction for " 410e5b75505Sopenharmony_ci "IMV '%s'", imv->name); 411e5b75505Sopenharmony_ci res = imv->ProvideBindFunction(imv->imvID, TNC_TNCS_BindFunction); 412e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "TNC: TNC_IMV_ProvideBindFunction: res=%lu", 413e5b75505Sopenharmony_ci (unsigned long) res); 414e5b75505Sopenharmony_ci 415e5b75505Sopenharmony_ci return res == TNC_RESULT_SUCCESS ? 0 : -1; 416e5b75505Sopenharmony_ci} 417e5b75505Sopenharmony_ci 418e5b75505Sopenharmony_ci 419e5b75505Sopenharmony_cistatic int tncs_imv_notify_connection_change(struct tnc_if_imv *imv, 420e5b75505Sopenharmony_ci TNC_ConnectionID conn, 421e5b75505Sopenharmony_ci TNC_ConnectionState state) 422e5b75505Sopenharmony_ci{ 423e5b75505Sopenharmony_ci TNC_Result res; 424e5b75505Sopenharmony_ci 425e5b75505Sopenharmony_ci if (imv->NotifyConnectionChange == NULL) 426e5b75505Sopenharmony_ci return 0; 427e5b75505Sopenharmony_ci 428e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "TNC: Calling TNC_IMV_NotifyConnectionChange(%d)" 429e5b75505Sopenharmony_ci " for IMV '%s'", (int) state, imv->name); 430e5b75505Sopenharmony_ci res = imv->NotifyConnectionChange(imv->imvID, conn, state); 431e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "TNC: TNC_IMC_NotifyConnectionChange: %lu", 432e5b75505Sopenharmony_ci (unsigned long) res); 433e5b75505Sopenharmony_ci 434e5b75505Sopenharmony_ci return res == TNC_RESULT_SUCCESS ? 0 : -1; 435e5b75505Sopenharmony_ci} 436e5b75505Sopenharmony_ci 437e5b75505Sopenharmony_ci 438e5b75505Sopenharmony_cistatic int tncs_load_imv(struct tnc_if_imv *imv) 439e5b75505Sopenharmony_ci{ 440e5b75505Sopenharmony_ci if (imv->path == NULL) { 441e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "TNC: No IMV configured"); 442e5b75505Sopenharmony_ci return -1; 443e5b75505Sopenharmony_ci } 444e5b75505Sopenharmony_ci 445e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "TNC: Opening IMV: %s (%s)", 446e5b75505Sopenharmony_ci imv->name, imv->path); 447e5b75505Sopenharmony_ci imv->dlhandle = dlopen(imv->path, RTLD_LAZY); 448e5b75505Sopenharmony_ci if (imv->dlhandle == NULL) { 449e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "TNC: Failed to open IMV '%s' (%s): %s", 450e5b75505Sopenharmony_ci imv->name, imv->path, dlerror()); 451e5b75505Sopenharmony_ci return -1; 452e5b75505Sopenharmony_ci } 453e5b75505Sopenharmony_ci 454e5b75505Sopenharmony_ci if (tncs_imv_resolve_funcs(imv) < 0) { 455e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "TNC: Failed to resolve IMV functions"); 456e5b75505Sopenharmony_ci return -1; 457e5b75505Sopenharmony_ci } 458e5b75505Sopenharmony_ci 459e5b75505Sopenharmony_ci if (tncs_imv_initialize(imv) < 0 || 460e5b75505Sopenharmony_ci tncs_imv_provide_bind_function(imv) < 0) { 461e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "TNC: Failed to initialize IMV"); 462e5b75505Sopenharmony_ci return -1; 463e5b75505Sopenharmony_ci } 464e5b75505Sopenharmony_ci 465e5b75505Sopenharmony_ci return 0; 466e5b75505Sopenharmony_ci} 467e5b75505Sopenharmony_ci 468e5b75505Sopenharmony_ci 469e5b75505Sopenharmony_cistatic void tncs_free_imv(struct tnc_if_imv *imv) 470e5b75505Sopenharmony_ci{ 471e5b75505Sopenharmony_ci os_free(imv->name); 472e5b75505Sopenharmony_ci os_free(imv->path); 473e5b75505Sopenharmony_ci os_free(imv->supported_types); 474e5b75505Sopenharmony_ci} 475e5b75505Sopenharmony_ci 476e5b75505Sopenharmony_cistatic void tncs_unload_imv(struct tnc_if_imv *imv) 477e5b75505Sopenharmony_ci{ 478e5b75505Sopenharmony_ci tncs_imv_terminate(imv); 479e5b75505Sopenharmony_ci 480e5b75505Sopenharmony_ci if (imv->dlhandle) 481e5b75505Sopenharmony_ci dlclose(imv->dlhandle); 482e5b75505Sopenharmony_ci 483e5b75505Sopenharmony_ci tncs_free_imv(imv); 484e5b75505Sopenharmony_ci} 485e5b75505Sopenharmony_ci 486e5b75505Sopenharmony_ci 487e5b75505Sopenharmony_cistatic int tncs_supported_type(struct tnc_if_imv *imv, unsigned int type) 488e5b75505Sopenharmony_ci{ 489e5b75505Sopenharmony_ci size_t i; 490e5b75505Sopenharmony_ci unsigned int vendor, subtype; 491e5b75505Sopenharmony_ci 492e5b75505Sopenharmony_ci if (imv == NULL || imv->supported_types == NULL) 493e5b75505Sopenharmony_ci return 0; 494e5b75505Sopenharmony_ci 495e5b75505Sopenharmony_ci vendor = type >> 8; 496e5b75505Sopenharmony_ci subtype = type & 0xff; 497e5b75505Sopenharmony_ci 498e5b75505Sopenharmony_ci for (i = 0; i < imv->num_supported_types; i++) { 499e5b75505Sopenharmony_ci unsigned int svendor, ssubtype; 500e5b75505Sopenharmony_ci svendor = imv->supported_types[i] >> 8; 501e5b75505Sopenharmony_ci ssubtype = imv->supported_types[i] & 0xff; 502e5b75505Sopenharmony_ci if ((vendor == svendor || svendor == TNC_VENDORID_ANY) && 503e5b75505Sopenharmony_ci (subtype == ssubtype || ssubtype == TNC_SUBTYPE_ANY)) 504e5b75505Sopenharmony_ci return 1; 505e5b75505Sopenharmony_ci } 506e5b75505Sopenharmony_ci 507e5b75505Sopenharmony_ci return 0; 508e5b75505Sopenharmony_ci} 509e5b75505Sopenharmony_ci 510e5b75505Sopenharmony_ci 511e5b75505Sopenharmony_cistatic void tncs_send_to_imvs(struct tncs_data *tncs, unsigned int type, 512e5b75505Sopenharmony_ci const u8 *msg, size_t len) 513e5b75505Sopenharmony_ci{ 514e5b75505Sopenharmony_ci struct tnc_if_imv *imv; 515e5b75505Sopenharmony_ci TNC_Result res; 516e5b75505Sopenharmony_ci 517e5b75505Sopenharmony_ci wpa_hexdump_ascii(MSG_MSGDUMP, "TNC: Message to IMV(s)", msg, len); 518e5b75505Sopenharmony_ci 519e5b75505Sopenharmony_ci for (imv = tncs->imv; imv; imv = imv->next) { 520e5b75505Sopenharmony_ci if (imv->ReceiveMessage == NULL || 521e5b75505Sopenharmony_ci !tncs_supported_type(imv, type)) 522e5b75505Sopenharmony_ci continue; 523e5b75505Sopenharmony_ci 524e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "TNC: Call ReceiveMessage for IMV '%s'", 525e5b75505Sopenharmony_ci imv->name); 526e5b75505Sopenharmony_ci res = imv->ReceiveMessage(imv->imvID, tncs->connectionID, 527e5b75505Sopenharmony_ci (TNC_BufferReference) msg, len, 528e5b75505Sopenharmony_ci type); 529e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "TNC: ReceiveMessage: %lu", 530e5b75505Sopenharmony_ci (unsigned long) res); 531e5b75505Sopenharmony_ci } 532e5b75505Sopenharmony_ci} 533e5b75505Sopenharmony_ci 534e5b75505Sopenharmony_ci 535e5b75505Sopenharmony_cistatic void tncs_batch_ending(struct tncs_data *tncs) 536e5b75505Sopenharmony_ci{ 537e5b75505Sopenharmony_ci struct tnc_if_imv *imv; 538e5b75505Sopenharmony_ci TNC_Result res; 539e5b75505Sopenharmony_ci 540e5b75505Sopenharmony_ci for (imv = tncs->imv; imv; imv = imv->next) { 541e5b75505Sopenharmony_ci if (imv->BatchEnding == NULL) 542e5b75505Sopenharmony_ci continue; 543e5b75505Sopenharmony_ci 544e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "TNC: Call BatchEnding for IMV '%s'", 545e5b75505Sopenharmony_ci imv->name); 546e5b75505Sopenharmony_ci res = imv->BatchEnding(imv->imvID, tncs->connectionID); 547e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "TNC: BatchEnding: %lu", 548e5b75505Sopenharmony_ci (unsigned long) res); 549e5b75505Sopenharmony_ci } 550e5b75505Sopenharmony_ci} 551e5b75505Sopenharmony_ci 552e5b75505Sopenharmony_ci 553e5b75505Sopenharmony_cistatic void tncs_solicit_recommendation(struct tncs_data *tncs) 554e5b75505Sopenharmony_ci{ 555e5b75505Sopenharmony_ci struct tnc_if_imv *imv; 556e5b75505Sopenharmony_ci TNC_Result res; 557e5b75505Sopenharmony_ci 558e5b75505Sopenharmony_ci for (imv = tncs->imv; imv; imv = imv->next) { 559e5b75505Sopenharmony_ci if (tncs->imv_data[imv->imvID].recommendation_set) 560e5b75505Sopenharmony_ci continue; 561e5b75505Sopenharmony_ci 562e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "TNC: Call SolicitRecommendation for " 563e5b75505Sopenharmony_ci "IMV '%s'", imv->name); 564e5b75505Sopenharmony_ci res = imv->SolicitRecommendation(imv->imvID, 565e5b75505Sopenharmony_ci tncs->connectionID); 566e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "TNC: SolicitRecommendation: %lu", 567e5b75505Sopenharmony_ci (unsigned long) res); 568e5b75505Sopenharmony_ci } 569e5b75505Sopenharmony_ci} 570e5b75505Sopenharmony_ci 571e5b75505Sopenharmony_ci 572e5b75505Sopenharmony_civoid tncs_init_connection(struct tncs_data *tncs) 573e5b75505Sopenharmony_ci{ 574e5b75505Sopenharmony_ci struct tnc_if_imv *imv; 575e5b75505Sopenharmony_ci int i; 576e5b75505Sopenharmony_ci 577e5b75505Sopenharmony_ci for (imv = tncs->imv; imv; imv = imv->next) { 578e5b75505Sopenharmony_ci tncs_imv_notify_connection_change( 579e5b75505Sopenharmony_ci imv, tncs->connectionID, TNC_CONNECTION_STATE_CREATE); 580e5b75505Sopenharmony_ci tncs_imv_notify_connection_change( 581e5b75505Sopenharmony_ci imv, tncs->connectionID, 582e5b75505Sopenharmony_ci TNC_CONNECTION_STATE_HANDSHAKE); 583e5b75505Sopenharmony_ci } 584e5b75505Sopenharmony_ci 585e5b75505Sopenharmony_ci for (i = 0; i < TNC_MAX_IMV_ID; i++) { 586e5b75505Sopenharmony_ci os_free(tncs->imv_data[i].imv_send); 587e5b75505Sopenharmony_ci tncs->imv_data[i].imv_send = NULL; 588e5b75505Sopenharmony_ci tncs->imv_data[i].imv_send_len = 0; 589e5b75505Sopenharmony_ci } 590e5b75505Sopenharmony_ci} 591e5b75505Sopenharmony_ci 592e5b75505Sopenharmony_ci 593e5b75505Sopenharmony_cisize_t tncs_total_send_len(struct tncs_data *tncs) 594e5b75505Sopenharmony_ci{ 595e5b75505Sopenharmony_ci int i; 596e5b75505Sopenharmony_ci size_t len = 0; 597e5b75505Sopenharmony_ci 598e5b75505Sopenharmony_ci for (i = 0; i < TNC_MAX_IMV_ID; i++) 599e5b75505Sopenharmony_ci len += tncs->imv_data[i].imv_send_len; 600e5b75505Sopenharmony_ci if (tncs->tncs_message) 601e5b75505Sopenharmony_ci len += os_strlen(tncs->tncs_message); 602e5b75505Sopenharmony_ci return len; 603e5b75505Sopenharmony_ci} 604e5b75505Sopenharmony_ci 605e5b75505Sopenharmony_ci 606e5b75505Sopenharmony_ciu8 * tncs_copy_send_buf(struct tncs_data *tncs, u8 *pos) 607e5b75505Sopenharmony_ci{ 608e5b75505Sopenharmony_ci int i; 609e5b75505Sopenharmony_ci 610e5b75505Sopenharmony_ci for (i = 0; i < TNC_MAX_IMV_ID; i++) { 611e5b75505Sopenharmony_ci if (tncs->imv_data[i].imv_send == NULL) 612e5b75505Sopenharmony_ci continue; 613e5b75505Sopenharmony_ci 614e5b75505Sopenharmony_ci os_memcpy(pos, tncs->imv_data[i].imv_send, 615e5b75505Sopenharmony_ci tncs->imv_data[i].imv_send_len); 616e5b75505Sopenharmony_ci pos += tncs->imv_data[i].imv_send_len; 617e5b75505Sopenharmony_ci os_free(tncs->imv_data[i].imv_send); 618e5b75505Sopenharmony_ci tncs->imv_data[i].imv_send = NULL; 619e5b75505Sopenharmony_ci tncs->imv_data[i].imv_send_len = 0; 620e5b75505Sopenharmony_ci } 621e5b75505Sopenharmony_ci 622e5b75505Sopenharmony_ci if (tncs->tncs_message) { 623e5b75505Sopenharmony_ci size_t len = os_strlen(tncs->tncs_message); 624e5b75505Sopenharmony_ci os_memcpy(pos, tncs->tncs_message, len); 625e5b75505Sopenharmony_ci pos += len; 626e5b75505Sopenharmony_ci os_free(tncs->tncs_message); 627e5b75505Sopenharmony_ci tncs->tncs_message = NULL; 628e5b75505Sopenharmony_ci } 629e5b75505Sopenharmony_ci 630e5b75505Sopenharmony_ci return pos; 631e5b75505Sopenharmony_ci} 632e5b75505Sopenharmony_ci 633e5b75505Sopenharmony_ci 634e5b75505Sopenharmony_cichar * tncs_if_tnccs_start(struct tncs_data *tncs) 635e5b75505Sopenharmony_ci{ 636e5b75505Sopenharmony_ci char *buf = os_malloc(1000); 637e5b75505Sopenharmony_ci if (buf == NULL) 638e5b75505Sopenharmony_ci return NULL; 639e5b75505Sopenharmony_ci tncs->last_batchid++; 640e5b75505Sopenharmony_ci os_snprintf(buf, 1000, IF_TNCCS_START, tncs->last_batchid); 641e5b75505Sopenharmony_ci return buf; 642e5b75505Sopenharmony_ci} 643e5b75505Sopenharmony_ci 644e5b75505Sopenharmony_ci 645e5b75505Sopenharmony_cichar * tncs_if_tnccs_end(void) 646e5b75505Sopenharmony_ci{ 647e5b75505Sopenharmony_ci char *buf = os_malloc(100); 648e5b75505Sopenharmony_ci if (buf == NULL) 649e5b75505Sopenharmony_ci return NULL; 650e5b75505Sopenharmony_ci os_snprintf(buf, 100, IF_TNCCS_END); 651e5b75505Sopenharmony_ci return buf; 652e5b75505Sopenharmony_ci} 653e5b75505Sopenharmony_ci 654e5b75505Sopenharmony_ci 655e5b75505Sopenharmony_cistatic int tncs_get_type(char *start, unsigned int *type) 656e5b75505Sopenharmony_ci{ 657e5b75505Sopenharmony_ci char *pos = os_strstr(start, "<Type>"); 658e5b75505Sopenharmony_ci if (pos == NULL) 659e5b75505Sopenharmony_ci return -1; 660e5b75505Sopenharmony_ci pos += 6; 661e5b75505Sopenharmony_ci *type = strtoul(pos, NULL, 16); 662e5b75505Sopenharmony_ci return 0; 663e5b75505Sopenharmony_ci} 664e5b75505Sopenharmony_ci 665e5b75505Sopenharmony_ci 666e5b75505Sopenharmony_cistatic unsigned char * tncs_get_base64(char *start, size_t *decoded_len) 667e5b75505Sopenharmony_ci{ 668e5b75505Sopenharmony_ci char *pos, *pos2; 669e5b75505Sopenharmony_ci unsigned char *decoded; 670e5b75505Sopenharmony_ci 671e5b75505Sopenharmony_ci pos = os_strstr(start, "<Base64>"); 672e5b75505Sopenharmony_ci if (pos == NULL) 673e5b75505Sopenharmony_ci return NULL; 674e5b75505Sopenharmony_ci 675e5b75505Sopenharmony_ci pos += 8; 676e5b75505Sopenharmony_ci pos2 = os_strstr(pos, "</Base64>"); 677e5b75505Sopenharmony_ci if (pos2 == NULL) 678e5b75505Sopenharmony_ci return NULL; 679e5b75505Sopenharmony_ci *pos2 = '\0'; 680e5b75505Sopenharmony_ci 681e5b75505Sopenharmony_ci decoded = base64_decode((unsigned char *) pos, os_strlen(pos), 682e5b75505Sopenharmony_ci decoded_len); 683e5b75505Sopenharmony_ci *pos2 = '<'; 684e5b75505Sopenharmony_ci if (decoded == NULL) { 685e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "TNC: Failed to decode Base64 data"); 686e5b75505Sopenharmony_ci } 687e5b75505Sopenharmony_ci 688e5b75505Sopenharmony_ci return decoded; 689e5b75505Sopenharmony_ci} 690e5b75505Sopenharmony_ci 691e5b75505Sopenharmony_ci 692e5b75505Sopenharmony_cistatic enum tncs_process_res tncs_derive_recommendation(struct tncs_data *tncs) 693e5b75505Sopenharmony_ci{ 694e5b75505Sopenharmony_ci enum IMV_Action_Recommendation rec; 695e5b75505Sopenharmony_ci struct tnc_if_imv *imv; 696e5b75505Sopenharmony_ci TNC_ConnectionState state; 697e5b75505Sopenharmony_ci char *txt; 698e5b75505Sopenharmony_ci 699e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "TNC: No more messages from IMVs"); 700e5b75505Sopenharmony_ci 701e5b75505Sopenharmony_ci if (tncs->done) 702e5b75505Sopenharmony_ci return TNCCS_PROCESS_OK_NO_RECOMMENDATION; 703e5b75505Sopenharmony_ci 704e5b75505Sopenharmony_ci tncs_solicit_recommendation(tncs); 705e5b75505Sopenharmony_ci 706e5b75505Sopenharmony_ci /* Select the most restrictive recommendation */ 707e5b75505Sopenharmony_ci rec = TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION; 708e5b75505Sopenharmony_ci for (imv = tncs->imv; imv; imv = imv->next) { 709e5b75505Sopenharmony_ci TNC_IMV_Action_Recommendation irec; 710e5b75505Sopenharmony_ci irec = tncs->imv_data[imv->imvID].recommendation; 711e5b75505Sopenharmony_ci if (irec == TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS) 712e5b75505Sopenharmony_ci rec = TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS; 713e5b75505Sopenharmony_ci if (irec == TNC_IMV_ACTION_RECOMMENDATION_ISOLATE && 714e5b75505Sopenharmony_ci rec != TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS) 715e5b75505Sopenharmony_ci rec = TNC_IMV_ACTION_RECOMMENDATION_ISOLATE; 716e5b75505Sopenharmony_ci if (irec == TNC_IMV_ACTION_RECOMMENDATION_ALLOW && 717e5b75505Sopenharmony_ci rec == TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION) 718e5b75505Sopenharmony_ci rec = TNC_IMV_ACTION_RECOMMENDATION_ALLOW; 719e5b75505Sopenharmony_ci } 720e5b75505Sopenharmony_ci 721e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "TNC: Recommendation: %d", rec); 722e5b75505Sopenharmony_ci tncs->recommendation = rec; 723e5b75505Sopenharmony_ci tncs->done = 1; 724e5b75505Sopenharmony_ci 725e5b75505Sopenharmony_ci txt = NULL; 726e5b75505Sopenharmony_ci switch (rec) { 727e5b75505Sopenharmony_ci case TNC_IMV_ACTION_RECOMMENDATION_ALLOW: 728e5b75505Sopenharmony_ci case TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION: 729e5b75505Sopenharmony_ci txt = "allow"; 730e5b75505Sopenharmony_ci state = TNC_CONNECTION_STATE_ACCESS_ALLOWED; 731e5b75505Sopenharmony_ci break; 732e5b75505Sopenharmony_ci case TNC_IMV_ACTION_RECOMMENDATION_ISOLATE: 733e5b75505Sopenharmony_ci txt = "isolate"; 734e5b75505Sopenharmony_ci state = TNC_CONNECTION_STATE_ACCESS_ISOLATED; 735e5b75505Sopenharmony_ci break; 736e5b75505Sopenharmony_ci case TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS: 737e5b75505Sopenharmony_ci txt = "none"; 738e5b75505Sopenharmony_ci state = TNC_CONNECTION_STATE_ACCESS_NONE; 739e5b75505Sopenharmony_ci break; 740e5b75505Sopenharmony_ci default: 741e5b75505Sopenharmony_ci state = TNC_CONNECTION_STATE_ACCESS_ALLOWED; 742e5b75505Sopenharmony_ci break; 743e5b75505Sopenharmony_ci } 744e5b75505Sopenharmony_ci 745e5b75505Sopenharmony_ci if (txt) { 746e5b75505Sopenharmony_ci os_free(tncs->tncs_message); 747e5b75505Sopenharmony_ci tncs->tncs_message = os_zalloc(200); 748e5b75505Sopenharmony_ci if (tncs->tncs_message) { 749e5b75505Sopenharmony_ci os_snprintf(tncs->tncs_message, 199, 750e5b75505Sopenharmony_ci "<TNCC-TNCS-Message><Type>%08X</Type>" 751e5b75505Sopenharmony_ci "<XML><TNCCS-Recommendation type=\"%s\">" 752e5b75505Sopenharmony_ci "</TNCCS-Recommendation></XML>" 753e5b75505Sopenharmony_ci "</TNCC-TNCS-Message>", 754e5b75505Sopenharmony_ci TNC_TNCCS_RECOMMENDATION, txt); 755e5b75505Sopenharmony_ci } 756e5b75505Sopenharmony_ci } 757e5b75505Sopenharmony_ci 758e5b75505Sopenharmony_ci for (imv = tncs->imv; imv; imv = imv->next) { 759e5b75505Sopenharmony_ci tncs_imv_notify_connection_change(imv, tncs->connectionID, 760e5b75505Sopenharmony_ci state); 761e5b75505Sopenharmony_ci } 762e5b75505Sopenharmony_ci 763e5b75505Sopenharmony_ci switch (rec) { 764e5b75505Sopenharmony_ci case TNC_IMV_ACTION_RECOMMENDATION_ALLOW: 765e5b75505Sopenharmony_ci return TNCCS_RECOMMENDATION_ALLOW; 766e5b75505Sopenharmony_ci case TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS: 767e5b75505Sopenharmony_ci return TNCCS_RECOMMENDATION_NO_ACCESS; 768e5b75505Sopenharmony_ci case TNC_IMV_ACTION_RECOMMENDATION_ISOLATE: 769e5b75505Sopenharmony_ci return TNCCS_RECOMMENDATION_ISOLATE; 770e5b75505Sopenharmony_ci case TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION: 771e5b75505Sopenharmony_ci return TNCCS_RECOMMENDATION_NO_RECOMMENDATION; 772e5b75505Sopenharmony_ci default: 773e5b75505Sopenharmony_ci return TNCCS_PROCESS_ERROR; 774e5b75505Sopenharmony_ci } 775e5b75505Sopenharmony_ci} 776e5b75505Sopenharmony_ci 777e5b75505Sopenharmony_ci 778e5b75505Sopenharmony_cienum tncs_process_res tncs_process_if_tnccs(struct tncs_data *tncs, 779e5b75505Sopenharmony_ci const u8 *msg, size_t len) 780e5b75505Sopenharmony_ci{ 781e5b75505Sopenharmony_ci char *buf, *start, *end, *pos, *pos2, *payload; 782e5b75505Sopenharmony_ci unsigned int batch_id; 783e5b75505Sopenharmony_ci unsigned char *decoded; 784e5b75505Sopenharmony_ci size_t decoded_len; 785e5b75505Sopenharmony_ci 786e5b75505Sopenharmony_ci buf = dup_binstr(msg, len); 787e5b75505Sopenharmony_ci if (buf == NULL) 788e5b75505Sopenharmony_ci return TNCCS_PROCESS_ERROR; 789e5b75505Sopenharmony_ci 790e5b75505Sopenharmony_ci start = os_strstr(buf, "<TNCCS-Batch "); 791e5b75505Sopenharmony_ci end = os_strstr(buf, "</TNCCS-Batch>"); 792e5b75505Sopenharmony_ci if (start == NULL || end == NULL || start > end) { 793e5b75505Sopenharmony_ci os_free(buf); 794e5b75505Sopenharmony_ci return TNCCS_PROCESS_ERROR; 795e5b75505Sopenharmony_ci } 796e5b75505Sopenharmony_ci 797e5b75505Sopenharmony_ci start += 13; 798e5b75505Sopenharmony_ci while (*start == ' ') 799e5b75505Sopenharmony_ci start++; 800e5b75505Sopenharmony_ci *end = '\0'; 801e5b75505Sopenharmony_ci 802e5b75505Sopenharmony_ci pos = os_strstr(start, "BatchId="); 803e5b75505Sopenharmony_ci if (pos == NULL) { 804e5b75505Sopenharmony_ci os_free(buf); 805e5b75505Sopenharmony_ci return TNCCS_PROCESS_ERROR; 806e5b75505Sopenharmony_ci } 807e5b75505Sopenharmony_ci 808e5b75505Sopenharmony_ci pos += 8; 809e5b75505Sopenharmony_ci if (*pos == '"') 810e5b75505Sopenharmony_ci pos++; 811e5b75505Sopenharmony_ci batch_id = atoi(pos); 812e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "TNC: Received IF-TNCCS BatchId=%u", 813e5b75505Sopenharmony_ci batch_id); 814e5b75505Sopenharmony_ci if (batch_id != tncs->last_batchid + 1) { 815e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "TNC: Unexpected IF-TNCCS BatchId " 816e5b75505Sopenharmony_ci "%u (expected %u)", 817e5b75505Sopenharmony_ci batch_id, tncs->last_batchid + 1); 818e5b75505Sopenharmony_ci os_free(buf); 819e5b75505Sopenharmony_ci return TNCCS_PROCESS_ERROR; 820e5b75505Sopenharmony_ci } 821e5b75505Sopenharmony_ci tncs->last_batchid = batch_id; 822e5b75505Sopenharmony_ci 823e5b75505Sopenharmony_ci while (*pos != '\0' && *pos != '>') 824e5b75505Sopenharmony_ci pos++; 825e5b75505Sopenharmony_ci if (*pos == '\0') { 826e5b75505Sopenharmony_ci os_free(buf); 827e5b75505Sopenharmony_ci return TNCCS_PROCESS_ERROR; 828e5b75505Sopenharmony_ci } 829e5b75505Sopenharmony_ci pos++; 830e5b75505Sopenharmony_ci payload = start; 831e5b75505Sopenharmony_ci 832e5b75505Sopenharmony_ci /* 833e5b75505Sopenharmony_ci * <IMC-IMV-Message> 834e5b75505Sopenharmony_ci * <Type>01234567</Type> 835e5b75505Sopenharmony_ci * <Base64>foo==</Base64> 836e5b75505Sopenharmony_ci * </IMC-IMV-Message> 837e5b75505Sopenharmony_ci */ 838e5b75505Sopenharmony_ci 839e5b75505Sopenharmony_ci while (*start) { 840e5b75505Sopenharmony_ci char *endpos; 841e5b75505Sopenharmony_ci unsigned int type; 842e5b75505Sopenharmony_ci 843e5b75505Sopenharmony_ci pos = os_strstr(start, "<IMC-IMV-Message>"); 844e5b75505Sopenharmony_ci if (pos == NULL) 845e5b75505Sopenharmony_ci break; 846e5b75505Sopenharmony_ci start = pos + 17; 847e5b75505Sopenharmony_ci end = os_strstr(start, "</IMC-IMV-Message>"); 848e5b75505Sopenharmony_ci if (end == NULL) 849e5b75505Sopenharmony_ci break; 850e5b75505Sopenharmony_ci *end = '\0'; 851e5b75505Sopenharmony_ci endpos = end; 852e5b75505Sopenharmony_ci end += 18; 853e5b75505Sopenharmony_ci 854e5b75505Sopenharmony_ci if (tncs_get_type(start, &type) < 0) { 855e5b75505Sopenharmony_ci *endpos = '<'; 856e5b75505Sopenharmony_ci start = end; 857e5b75505Sopenharmony_ci continue; 858e5b75505Sopenharmony_ci } 859e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "TNC: IMC-IMV-Message Type 0x%x", type); 860e5b75505Sopenharmony_ci 861e5b75505Sopenharmony_ci decoded = tncs_get_base64(start, &decoded_len); 862e5b75505Sopenharmony_ci if (decoded == NULL) { 863e5b75505Sopenharmony_ci *endpos = '<'; 864e5b75505Sopenharmony_ci start = end; 865e5b75505Sopenharmony_ci continue; 866e5b75505Sopenharmony_ci } 867e5b75505Sopenharmony_ci 868e5b75505Sopenharmony_ci tncs_send_to_imvs(tncs, type, decoded, decoded_len); 869e5b75505Sopenharmony_ci 870e5b75505Sopenharmony_ci os_free(decoded); 871e5b75505Sopenharmony_ci 872e5b75505Sopenharmony_ci start = end; 873e5b75505Sopenharmony_ci } 874e5b75505Sopenharmony_ci 875e5b75505Sopenharmony_ci /* 876e5b75505Sopenharmony_ci * <TNCC-TNCS-Message> 877e5b75505Sopenharmony_ci * <Type>01234567</Type> 878e5b75505Sopenharmony_ci * <XML><TNCCS-Foo type="foo"></TNCCS-Foo></XML> 879e5b75505Sopenharmony_ci * <Base64>foo==</Base64> 880e5b75505Sopenharmony_ci * </TNCC-TNCS-Message> 881e5b75505Sopenharmony_ci */ 882e5b75505Sopenharmony_ci 883e5b75505Sopenharmony_ci start = payload; 884e5b75505Sopenharmony_ci while (*start) { 885e5b75505Sopenharmony_ci unsigned int type; 886e5b75505Sopenharmony_ci char *xml, *xmlend, *endpos; 887e5b75505Sopenharmony_ci 888e5b75505Sopenharmony_ci pos = os_strstr(start, "<TNCC-TNCS-Message>"); 889e5b75505Sopenharmony_ci if (pos == NULL) 890e5b75505Sopenharmony_ci break; 891e5b75505Sopenharmony_ci start = pos + 19; 892e5b75505Sopenharmony_ci end = os_strstr(start, "</TNCC-TNCS-Message>"); 893e5b75505Sopenharmony_ci if (end == NULL) 894e5b75505Sopenharmony_ci break; 895e5b75505Sopenharmony_ci *end = '\0'; 896e5b75505Sopenharmony_ci endpos = end; 897e5b75505Sopenharmony_ci end += 20; 898e5b75505Sopenharmony_ci 899e5b75505Sopenharmony_ci if (tncs_get_type(start, &type) < 0) { 900e5b75505Sopenharmony_ci *endpos = '<'; 901e5b75505Sopenharmony_ci start = end; 902e5b75505Sopenharmony_ci continue; 903e5b75505Sopenharmony_ci } 904e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "TNC: TNCC-TNCS-Message Type 0x%x", 905e5b75505Sopenharmony_ci type); 906e5b75505Sopenharmony_ci 907e5b75505Sopenharmony_ci /* Base64 OR XML */ 908e5b75505Sopenharmony_ci decoded = NULL; 909e5b75505Sopenharmony_ci xml = NULL; 910e5b75505Sopenharmony_ci xmlend = NULL; 911e5b75505Sopenharmony_ci pos = os_strstr(start, "<XML>"); 912e5b75505Sopenharmony_ci if (pos) { 913e5b75505Sopenharmony_ci pos += 5; 914e5b75505Sopenharmony_ci pos2 = os_strstr(pos, "</XML>"); 915e5b75505Sopenharmony_ci if (pos2 == NULL) { 916e5b75505Sopenharmony_ci *endpos = '<'; 917e5b75505Sopenharmony_ci start = end; 918e5b75505Sopenharmony_ci continue; 919e5b75505Sopenharmony_ci } 920e5b75505Sopenharmony_ci xmlend = pos2; 921e5b75505Sopenharmony_ci xml = pos; 922e5b75505Sopenharmony_ci } else { 923e5b75505Sopenharmony_ci decoded = tncs_get_base64(start, &decoded_len); 924e5b75505Sopenharmony_ci if (decoded == NULL) { 925e5b75505Sopenharmony_ci *endpos = '<'; 926e5b75505Sopenharmony_ci start = end; 927e5b75505Sopenharmony_ci continue; 928e5b75505Sopenharmony_ci } 929e5b75505Sopenharmony_ci } 930e5b75505Sopenharmony_ci 931e5b75505Sopenharmony_ci if (decoded) { 932e5b75505Sopenharmony_ci wpa_hexdump_ascii(MSG_MSGDUMP, 933e5b75505Sopenharmony_ci "TNC: TNCC-TNCS-Message Base64", 934e5b75505Sopenharmony_ci decoded, decoded_len); 935e5b75505Sopenharmony_ci os_free(decoded); 936e5b75505Sopenharmony_ci } 937e5b75505Sopenharmony_ci 938e5b75505Sopenharmony_ci if (xml) { 939e5b75505Sopenharmony_ci wpa_hexdump_ascii(MSG_MSGDUMP, 940e5b75505Sopenharmony_ci "TNC: TNCC-TNCS-Message XML", 941e5b75505Sopenharmony_ci (unsigned char *) xml, 942e5b75505Sopenharmony_ci xmlend - xml); 943e5b75505Sopenharmony_ci } 944e5b75505Sopenharmony_ci 945e5b75505Sopenharmony_ci start = end; 946e5b75505Sopenharmony_ci } 947e5b75505Sopenharmony_ci 948e5b75505Sopenharmony_ci os_free(buf); 949e5b75505Sopenharmony_ci 950e5b75505Sopenharmony_ci tncs_batch_ending(tncs); 951e5b75505Sopenharmony_ci 952e5b75505Sopenharmony_ci if (tncs_total_send_len(tncs) == 0) 953e5b75505Sopenharmony_ci return tncs_derive_recommendation(tncs); 954e5b75505Sopenharmony_ci 955e5b75505Sopenharmony_ci return TNCCS_PROCESS_OK_NO_RECOMMENDATION; 956e5b75505Sopenharmony_ci} 957e5b75505Sopenharmony_ci 958e5b75505Sopenharmony_ci 959e5b75505Sopenharmony_cistatic struct tnc_if_imv * tncs_parse_imv(int id, char *start, char *end, 960e5b75505Sopenharmony_ci int *error) 961e5b75505Sopenharmony_ci{ 962e5b75505Sopenharmony_ci struct tnc_if_imv *imv; 963e5b75505Sopenharmony_ci char *pos, *pos2; 964e5b75505Sopenharmony_ci 965e5b75505Sopenharmony_ci if (id >= TNC_MAX_IMV_ID) { 966e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "TNC: Too many IMVs"); 967e5b75505Sopenharmony_ci return NULL; 968e5b75505Sopenharmony_ci } 969e5b75505Sopenharmony_ci 970e5b75505Sopenharmony_ci imv = os_zalloc(sizeof(*imv)); 971e5b75505Sopenharmony_ci if (imv == NULL) { 972e5b75505Sopenharmony_ci *error = 1; 973e5b75505Sopenharmony_ci return NULL; 974e5b75505Sopenharmony_ci } 975e5b75505Sopenharmony_ci 976e5b75505Sopenharmony_ci imv->imvID = id; 977e5b75505Sopenharmony_ci 978e5b75505Sopenharmony_ci pos = start; 979e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "TNC: Configured IMV: %s", pos); 980e5b75505Sopenharmony_ci if (pos + 1 >= end || *pos != '"') { 981e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "TNC: Ignoring invalid IMV line '%s' " 982e5b75505Sopenharmony_ci "(no starting quotation mark)", start); 983e5b75505Sopenharmony_ci os_free(imv); 984e5b75505Sopenharmony_ci return NULL; 985e5b75505Sopenharmony_ci } 986e5b75505Sopenharmony_ci 987e5b75505Sopenharmony_ci pos++; 988e5b75505Sopenharmony_ci pos2 = pos; 989e5b75505Sopenharmony_ci while (pos2 < end && *pos2 != '"') 990e5b75505Sopenharmony_ci pos2++; 991e5b75505Sopenharmony_ci if (pos2 >= end) { 992e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "TNC: Ignoring invalid IMV line '%s' " 993e5b75505Sopenharmony_ci "(no ending quotation mark)", start); 994e5b75505Sopenharmony_ci os_free(imv); 995e5b75505Sopenharmony_ci return NULL; 996e5b75505Sopenharmony_ci } 997e5b75505Sopenharmony_ci *pos2 = '\0'; 998e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "TNC: Name: '%s'", pos); 999e5b75505Sopenharmony_ci imv->name = os_strdup(pos); 1000e5b75505Sopenharmony_ci 1001e5b75505Sopenharmony_ci pos = pos2 + 1; 1002e5b75505Sopenharmony_ci if (pos >= end || *pos != ' ') { 1003e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "TNC: Ignoring invalid IMV line '%s' " 1004e5b75505Sopenharmony_ci "(no space after name)", start); 1005e5b75505Sopenharmony_ci os_free(imv); 1006e5b75505Sopenharmony_ci return NULL; 1007e5b75505Sopenharmony_ci } 1008e5b75505Sopenharmony_ci 1009e5b75505Sopenharmony_ci pos++; 1010e5b75505Sopenharmony_ci wpa_printf(MSG_DEBUG, "TNC: IMV file: '%s'", pos); 1011e5b75505Sopenharmony_ci imv->path = os_strdup(pos); 1012e5b75505Sopenharmony_ci 1013e5b75505Sopenharmony_ci return imv; 1014e5b75505Sopenharmony_ci} 1015e5b75505Sopenharmony_ci 1016e5b75505Sopenharmony_ci 1017e5b75505Sopenharmony_cistatic int tncs_read_config(struct tncs_global *global) 1018e5b75505Sopenharmony_ci{ 1019e5b75505Sopenharmony_ci char *config, *end, *pos, *line_end; 1020e5b75505Sopenharmony_ci size_t config_len; 1021e5b75505Sopenharmony_ci struct tnc_if_imv *imv, *last; 1022e5b75505Sopenharmony_ci int id = 0; 1023e5b75505Sopenharmony_ci 1024e5b75505Sopenharmony_ci last = NULL; 1025e5b75505Sopenharmony_ci 1026e5b75505Sopenharmony_ci config = os_readfile(TNC_CONFIG_FILE, &config_len); 1027e5b75505Sopenharmony_ci if (config == NULL) { 1028e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "TNC: Could not open TNC configuration " 1029e5b75505Sopenharmony_ci "file '%s'", TNC_CONFIG_FILE); 1030e5b75505Sopenharmony_ci return -1; 1031e5b75505Sopenharmony_ci } 1032e5b75505Sopenharmony_ci 1033e5b75505Sopenharmony_ci end = config + config_len; 1034e5b75505Sopenharmony_ci for (pos = config; pos < end; pos = line_end + 1) { 1035e5b75505Sopenharmony_ci line_end = pos; 1036e5b75505Sopenharmony_ci while (*line_end != '\n' && *line_end != '\r' && 1037e5b75505Sopenharmony_ci line_end < end) 1038e5b75505Sopenharmony_ci line_end++; 1039e5b75505Sopenharmony_ci *line_end = '\0'; 1040e5b75505Sopenharmony_ci 1041e5b75505Sopenharmony_ci if (os_strncmp(pos, "IMV ", 4) == 0) { 1042e5b75505Sopenharmony_ci int error = 0; 1043e5b75505Sopenharmony_ci 1044e5b75505Sopenharmony_ci imv = tncs_parse_imv(id++, pos + 4, line_end, &error); 1045e5b75505Sopenharmony_ci if (error) 1046e5b75505Sopenharmony_ci return -1; 1047e5b75505Sopenharmony_ci if (imv) { 1048e5b75505Sopenharmony_ci if (last == NULL) 1049e5b75505Sopenharmony_ci global->imv = imv; 1050e5b75505Sopenharmony_ci else 1051e5b75505Sopenharmony_ci last->next = imv; 1052e5b75505Sopenharmony_ci last = imv; 1053e5b75505Sopenharmony_ci } 1054e5b75505Sopenharmony_ci } 1055e5b75505Sopenharmony_ci } 1056e5b75505Sopenharmony_ci 1057e5b75505Sopenharmony_ci os_free(config); 1058e5b75505Sopenharmony_ci 1059e5b75505Sopenharmony_ci return 0; 1060e5b75505Sopenharmony_ci} 1061e5b75505Sopenharmony_ci 1062e5b75505Sopenharmony_ci 1063e5b75505Sopenharmony_cistruct tncs_data * tncs_init(void) 1064e5b75505Sopenharmony_ci{ 1065e5b75505Sopenharmony_ci struct tncs_data *tncs; 1066e5b75505Sopenharmony_ci 1067e5b75505Sopenharmony_ci if (tncs_global_data == NULL) 1068e5b75505Sopenharmony_ci return NULL; 1069e5b75505Sopenharmony_ci 1070e5b75505Sopenharmony_ci tncs = os_zalloc(sizeof(*tncs)); 1071e5b75505Sopenharmony_ci if (tncs == NULL) 1072e5b75505Sopenharmony_ci return NULL; 1073e5b75505Sopenharmony_ci tncs->imv = tncs_global_data->imv; 1074e5b75505Sopenharmony_ci tncs->connectionID = tncs_global_data->next_conn_id++; 1075e5b75505Sopenharmony_ci tncs->next = tncs_global_data->connections; 1076e5b75505Sopenharmony_ci tncs_global_data->connections = tncs; 1077e5b75505Sopenharmony_ci 1078e5b75505Sopenharmony_ci return tncs; 1079e5b75505Sopenharmony_ci} 1080e5b75505Sopenharmony_ci 1081e5b75505Sopenharmony_ci 1082e5b75505Sopenharmony_civoid tncs_deinit(struct tncs_data *tncs) 1083e5b75505Sopenharmony_ci{ 1084e5b75505Sopenharmony_ci int i; 1085e5b75505Sopenharmony_ci struct tncs_data *prev, *conn; 1086e5b75505Sopenharmony_ci 1087e5b75505Sopenharmony_ci if (tncs == NULL) 1088e5b75505Sopenharmony_ci return; 1089e5b75505Sopenharmony_ci 1090e5b75505Sopenharmony_ci for (i = 0; i < TNC_MAX_IMV_ID; i++) 1091e5b75505Sopenharmony_ci os_free(tncs->imv_data[i].imv_send); 1092e5b75505Sopenharmony_ci 1093e5b75505Sopenharmony_ci prev = NULL; 1094e5b75505Sopenharmony_ci conn = tncs_global_data->connections; 1095e5b75505Sopenharmony_ci while (conn) { 1096e5b75505Sopenharmony_ci if (conn == tncs) { 1097e5b75505Sopenharmony_ci if (prev) 1098e5b75505Sopenharmony_ci prev->next = tncs->next; 1099e5b75505Sopenharmony_ci else 1100e5b75505Sopenharmony_ci tncs_global_data->connections = tncs->next; 1101e5b75505Sopenharmony_ci break; 1102e5b75505Sopenharmony_ci } 1103e5b75505Sopenharmony_ci prev = conn; 1104e5b75505Sopenharmony_ci conn = conn->next; 1105e5b75505Sopenharmony_ci } 1106e5b75505Sopenharmony_ci 1107e5b75505Sopenharmony_ci os_free(tncs->tncs_message); 1108e5b75505Sopenharmony_ci os_free(tncs); 1109e5b75505Sopenharmony_ci} 1110e5b75505Sopenharmony_ci 1111e5b75505Sopenharmony_ci 1112e5b75505Sopenharmony_ciint tncs_global_init(void) 1113e5b75505Sopenharmony_ci{ 1114e5b75505Sopenharmony_ci struct tnc_if_imv *imv; 1115e5b75505Sopenharmony_ci 1116e5b75505Sopenharmony_ci if (tncs_global_data) 1117e5b75505Sopenharmony_ci return 0; 1118e5b75505Sopenharmony_ci 1119e5b75505Sopenharmony_ci tncs_global_data = os_zalloc(sizeof(*tncs_global_data)); 1120e5b75505Sopenharmony_ci if (tncs_global_data == NULL) 1121e5b75505Sopenharmony_ci return -1; 1122e5b75505Sopenharmony_ci 1123e5b75505Sopenharmony_ci if (tncs_read_config(tncs_global_data) < 0) { 1124e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "TNC: Failed to read TNC configuration"); 1125e5b75505Sopenharmony_ci goto failed; 1126e5b75505Sopenharmony_ci } 1127e5b75505Sopenharmony_ci 1128e5b75505Sopenharmony_ci for (imv = tncs_global_data->imv; imv; imv = imv->next) { 1129e5b75505Sopenharmony_ci if (tncs_load_imv(imv)) { 1130e5b75505Sopenharmony_ci wpa_printf(MSG_ERROR, "TNC: Failed to load IMV '%s'", 1131e5b75505Sopenharmony_ci imv->name); 1132e5b75505Sopenharmony_ci goto failed; 1133e5b75505Sopenharmony_ci } 1134e5b75505Sopenharmony_ci } 1135e5b75505Sopenharmony_ci 1136e5b75505Sopenharmony_ci return 0; 1137e5b75505Sopenharmony_ci 1138e5b75505Sopenharmony_cifailed: 1139e5b75505Sopenharmony_ci tncs_global_deinit(); 1140e5b75505Sopenharmony_ci return -1; 1141e5b75505Sopenharmony_ci} 1142e5b75505Sopenharmony_ci 1143e5b75505Sopenharmony_ci 1144e5b75505Sopenharmony_civoid tncs_global_deinit(void) 1145e5b75505Sopenharmony_ci{ 1146e5b75505Sopenharmony_ci struct tnc_if_imv *imv, *prev; 1147e5b75505Sopenharmony_ci 1148e5b75505Sopenharmony_ci if (tncs_global_data == NULL) 1149e5b75505Sopenharmony_ci return; 1150e5b75505Sopenharmony_ci 1151e5b75505Sopenharmony_ci imv = tncs_global_data->imv; 1152e5b75505Sopenharmony_ci while (imv) { 1153e5b75505Sopenharmony_ci tncs_unload_imv(imv); 1154e5b75505Sopenharmony_ci 1155e5b75505Sopenharmony_ci prev = imv; 1156e5b75505Sopenharmony_ci imv = imv->next; 1157e5b75505Sopenharmony_ci os_free(prev); 1158e5b75505Sopenharmony_ci } 1159e5b75505Sopenharmony_ci 1160e5b75505Sopenharmony_ci os_free(tncs_global_data); 1161e5b75505Sopenharmony_ci tncs_global_data = NULL; 1162e5b75505Sopenharmony_ci} 1163e5b75505Sopenharmony_ci 1164e5b75505Sopenharmony_ci 1165e5b75505Sopenharmony_cistruct wpabuf * tncs_build_soh_request(void) 1166e5b75505Sopenharmony_ci{ 1167e5b75505Sopenharmony_ci struct wpabuf *buf; 1168e5b75505Sopenharmony_ci 1169e5b75505Sopenharmony_ci /* 1170e5b75505Sopenharmony_ci * Build a SoH Request TLV (to be used inside SoH EAP Extensions 1171e5b75505Sopenharmony_ci * Method) 1172e5b75505Sopenharmony_ci */ 1173e5b75505Sopenharmony_ci 1174e5b75505Sopenharmony_ci buf = wpabuf_alloc(8 + 4); 1175e5b75505Sopenharmony_ci if (buf == NULL) 1176e5b75505Sopenharmony_ci return NULL; 1177e5b75505Sopenharmony_ci 1178e5b75505Sopenharmony_ci /* Vendor-Specific TLV (Microsoft) - SoH Request */ 1179e5b75505Sopenharmony_ci wpabuf_put_be16(buf, EAP_TLV_VENDOR_SPECIFIC_TLV); /* TLV Type */ 1180e5b75505Sopenharmony_ci wpabuf_put_be16(buf, 8); /* Length */ 1181e5b75505Sopenharmony_ci 1182e5b75505Sopenharmony_ci wpabuf_put_be32(buf, EAP_VENDOR_MICROSOFT); /* Vendor_Id */ 1183e5b75505Sopenharmony_ci 1184e5b75505Sopenharmony_ci wpabuf_put_be16(buf, 0x02); /* TLV Type - SoH Request TLV */ 1185e5b75505Sopenharmony_ci wpabuf_put_be16(buf, 0); /* Length */ 1186e5b75505Sopenharmony_ci 1187e5b75505Sopenharmony_ci return buf; 1188e5b75505Sopenharmony_ci} 1189e5b75505Sopenharmony_ci 1190e5b75505Sopenharmony_ci 1191e5b75505Sopenharmony_cistruct wpabuf * tncs_process_soh(const u8 *soh_tlv, size_t soh_tlv_len, 1192e5b75505Sopenharmony_ci int *failure) 1193e5b75505Sopenharmony_ci{ 1194e5b75505Sopenharmony_ci wpa_hexdump(MSG_DEBUG, "TNC: SoH TLV", soh_tlv, soh_tlv_len); 1195e5b75505Sopenharmony_ci *failure = 0; 1196e5b75505Sopenharmony_ci 1197e5b75505Sopenharmony_ci /* TODO: return MS-SoH Response TLV */ 1198e5b75505Sopenharmony_ci 1199e5b75505Sopenharmony_ci return NULL; 1200e5b75505Sopenharmony_ci} 1201