📄 tncc.c
字号:
/* * EAP-TNC - TNCC (IF-IMC and IF-TNCCS) * Copyright (c) 2007, Jouni Malinen <j@w1.fi> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Alternatively, this software may be distributed under the terms of BSD * license. * * See README and COPYING for more details. */#include "includes.h"#ifndef CONFIG_NATIVE_WINDOWS#include <dlfcn.h>#endif /* CONFIG_NATIVE_WINDOWS */#include "common.h"#include "base64.h"#include "tncc.h"#include "eap_common/eap_tlv_common.h"#include "eap_common/eap_defs.h"#ifdef UNICODE#define TSTR "%S"#else /* UNICODE */#define TSTR "%s"#endif /* UNICODE */#define TNC_CONFIG_FILE "/etc/tnc_config"#define TNC_WINREG_PATH TEXT("SOFTWARE\\Trusted Computing Group\\TNC\\IMCs")#define IF_TNCCS_START \"<?xml version=\"1.0\"?>\n" \"<TNCCS-Batch BatchId=\"%d\" Recipient=\"TNCS\" " \"xmlns=\"http://www.trustedcomputinggroup.org/IWG/TNC/1_0/IF_TNCCS#\" " \"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " \"xsi:schemaLocation=\"http://www.trustedcomputinggroup.org/IWG/TNC/1_0/" \"IF_TNCCS# https://www.trustedcomputinggroup.org/XML/SCHEMA/TNCCS_1.0.xsd\">\n"#define IF_TNCCS_END "\n</TNCCS-Batch>"/* TNC IF-IMC */typedef unsigned long TNC_UInt32;typedef unsigned char *TNC_BufferReference;typedef TNC_UInt32 TNC_IMCID;typedef TNC_UInt32 TNC_ConnectionID;typedef TNC_UInt32 TNC_ConnectionState;typedef TNC_UInt32 TNC_RetryReason;typedef TNC_UInt32 TNC_MessageType;typedef TNC_MessageType *TNC_MessageTypeList;typedef TNC_UInt32 TNC_VendorID;typedef TNC_UInt32 TNC_MessageSubtype;typedef TNC_UInt32 TNC_Version;typedef TNC_UInt32 TNC_Result;typedef TNC_Result (*TNC_TNCC_BindFunctionPointer)( TNC_IMCID imcID, char *functionName, void **pOutfunctionPointer);#define TNC_RESULT_SUCCESS 0#define TNC_RESULT_NOT_INITIALIZED 1#define TNC_RESULT_ALREADY_INITIALIZED 2#define TNC_RESULT_NO_COMMON_VERSION 3#define TNC_RESULT_CANT_RETRY 4#define TNC_RESULT_WONT_RETRY 5#define TNC_RESULT_INVALID_PARAMETER 6#define TNC_RESULT_CANT_RESPOND 7#define TNC_RESULT_ILLEGAL_OPERATION 8#define TNC_RESULT_OTHER 9#define TNC_RESULT_FATAL 10#define TNC_CONNECTION_STATE_CREATE 0#define TNC_CONNECTION_STATE_HANDSHAKE 1#define TNC_CONNECTION_STATE_ACCESS_ALLOWED 2#define TNC_CONNECTION_STATE_ACCESS_ISOLATED 3#define TNC_CONNECTION_STATE_ACCESS_NONE 4#define TNC_CONNECTION_STATE_DELETE 5#define TNC_IFIMC_VERSION_1 1#define TNC_VENDORID_ANY ((TNC_VendorID) 0xffffff)#define TNC_SUBTYPE_ANY ((TNC_MessageSubtype) 0xff)/* TNCC-TNCS Message Types */#define TNC_TNCCS_RECOMMENDATION 0x00000001#define TNC_TNCCS_ERROR 0x00000002#define TNC_TNCCS_PREFERREDLANGUAGE 0x00000003#define TNC_TNCCS_REASONSTRINGS 0x00000004/* IF-TNCCS-SOH - SSoH and SSoHR Attributes */enum { SSOH_MS_MACHINE_INVENTORY = 1, SSOH_MS_QUARANTINE_STATE = 2, SSOH_MS_PACKET_INFO = 3, SSOH_MS_SYSTEMGENERATED_IDS = 4, SSOH_MS_MACHINENAME = 5, SSOH_MS_CORRELATIONID = 6, SSOH_MS_INSTALLED_SHVS = 7, SSOH_MS_MACHINE_INVENTORY_EX = 8};struct tnc_if_imc { struct tnc_if_imc *next; char *name; char *path; void *dlhandle; /* from dlopen() */ TNC_IMCID imcID; TNC_ConnectionID connectionID; TNC_MessageTypeList supported_types; size_t num_supported_types; u8 *imc_send; size_t imc_send_len; /* Functions implemented by IMCs (with TNC_IMC_ prefix) */ TNC_Result (*Initialize)( TNC_IMCID imcID, TNC_Version minVersion, TNC_Version maxVersion, TNC_Version *pOutActualVersion); TNC_Result (*NotifyConnectionChange)( TNC_IMCID imcID, TNC_ConnectionID connectionID, TNC_ConnectionState newState); TNC_Result (*BeginHandshake)( TNC_IMCID imcID, TNC_ConnectionID connectionID); TNC_Result (*ReceiveMessage)( TNC_IMCID imcID, TNC_ConnectionID connectionID, TNC_BufferReference messageBuffer, TNC_UInt32 messageLength, TNC_MessageType messageType); TNC_Result (*BatchEnding)( TNC_IMCID imcID, TNC_ConnectionID connectionID); TNC_Result (*Terminate)(TNC_IMCID imcID); TNC_Result (*ProvideBindFunction)( TNC_IMCID imcID, TNC_TNCC_BindFunctionPointer bindFunction);};struct tncc_data { struct tnc_if_imc *imc; unsigned int last_batchid;};#define TNC_MAX_IMC_ID 10static struct tnc_if_imc *tnc_imc[TNC_MAX_IMC_ID] = { NULL };/* TNCC functions that IMCs can call */TNC_Result TNC_TNCC_ReportMessageTypes( TNC_IMCID imcID, TNC_MessageTypeList supportedTypes, TNC_UInt32 typeCount){ TNC_UInt32 i; struct tnc_if_imc *imc; wpa_printf(MSG_DEBUG, "TNC: TNC_TNCC_ReportMessageTypes(imcID=%lu " "typeCount=%lu)", (unsigned long) imcID, (unsigned long) typeCount); for (i = 0; i < typeCount; i++) { wpa_printf(MSG_DEBUG, "TNC: supportedTypes[%lu] = %lu", i, supportedTypes[i]); } if (imcID >= TNC_MAX_IMC_ID || tnc_imc[imcID] == NULL) return TNC_RESULT_INVALID_PARAMETER; imc = tnc_imc[imcID]; os_free(imc->supported_types); imc->supported_types = os_malloc(typeCount * sizeof(TNC_MessageTypeList)); if (imc->supported_types == NULL) return TNC_RESULT_FATAL; os_memcpy(imc->supported_types, supportedTypes, typeCount * sizeof(TNC_MessageTypeList)); imc->num_supported_types = typeCount; return TNC_RESULT_SUCCESS;}TNC_Result TNC_TNCC_SendMessage( TNC_IMCID imcID, TNC_ConnectionID connectionID, TNC_BufferReference message, TNC_UInt32 messageLength, TNC_MessageType messageType){ struct tnc_if_imc *imc; unsigned char *b64; size_t b64len; wpa_printf(MSG_DEBUG, "TNC: TNC_TNCC_SendMessage(imcID=%lu " "connectionID=%lu messageType=%lu)", imcID, connectionID, messageType); wpa_hexdump_ascii(MSG_DEBUG, "TNC: TNC_TNCC_SendMessage", message, messageLength); if (imcID >= TNC_MAX_IMC_ID || tnc_imc[imcID] == NULL) return TNC_RESULT_INVALID_PARAMETER; b64 = base64_encode(message, messageLength, &b64len); if (b64 == NULL) return TNC_RESULT_FATAL; imc = tnc_imc[imcID]; os_free(imc->imc_send); imc->imc_send_len = 0; imc->imc_send = os_zalloc(b64len + 100); if (imc->imc_send == NULL) { os_free(b64); return TNC_RESULT_OTHER; } imc->imc_send_len = os_snprintf((char *) imc->imc_send, b64len + 100, "<IMC-IMV-Message><Type>%08X</Type>" "<Base64>%s</Base64></IMC-IMV-Message>", (unsigned int) messageType, b64); os_free(b64); return TNC_RESULT_SUCCESS;}TNC_Result TNC_TNCC_RequestHandshakeRetry( TNC_IMCID imcID, TNC_ConnectionID connectionID, TNC_RetryReason reason){ wpa_printf(MSG_DEBUG, "TNC: TNC_TNCC_RequestHandshakeRetry"); if (imcID >= TNC_MAX_IMC_ID || tnc_imc[imcID] == NULL) return TNC_RESULT_INVALID_PARAMETER; /* * TODO: trigger a call to eapol_sm_request_reauth(). This would * require that the IMC continues to be loaded in memory afer * authentication.. */ return TNC_RESULT_SUCCESS;}TNC_Result TNC_9048_LogMessage(TNC_IMCID imcID, TNC_UInt32 severity, const char *message){ wpa_printf(MSG_DEBUG, "TNC: TNC_9048_LogMessage(imcID=%lu " "severity==%lu message='%s')", imcID, severity, message); return TNC_RESULT_SUCCESS;}TNC_Result TNC_9048_UserMessage(TNC_IMCID imcID, TNC_ConnectionID connectionID, const char *message){ wpa_printf(MSG_DEBUG, "TNC: TNC_9048_UserMessage(imcID=%lu " "connectionID==%lu message='%s')", imcID, connectionID, message); return TNC_RESULT_SUCCESS;}TNC_Result TNC_TNCC_BindFunction( TNC_IMCID imcID, char *functionName, void **pOutfunctionPointer){ wpa_printf(MSG_DEBUG, "TNC: TNC_TNCC_BindFunction(imcID=%lu, " "functionName='%s')", (unsigned long) imcID, functionName); if (imcID >= TNC_MAX_IMC_ID || tnc_imc[imcID] == NULL) return TNC_RESULT_INVALID_PARAMETER; if (pOutfunctionPointer == NULL) return TNC_RESULT_INVALID_PARAMETER; if (os_strcmp(functionName, "TNC_TNCC_ReportMessageTypes") == 0) *pOutfunctionPointer = TNC_TNCC_ReportMessageTypes; else if (os_strcmp(functionName, "TNC_TNCC_SendMessage") == 0) *pOutfunctionPointer = TNC_TNCC_SendMessage; else if (os_strcmp(functionName, "TNC_TNCC_RequestHandshakeRetry") == 0) *pOutfunctionPointer = TNC_TNCC_RequestHandshakeRetry; else if (os_strcmp(functionName, "TNC_9048_LogMessage") == 0) *pOutfunctionPointer = TNC_9048_LogMessage; else if (os_strcmp(functionName, "TNC_9048_UserMessage") == 0) *pOutfunctionPointer = TNC_9048_UserMessage; else *pOutfunctionPointer = NULL; return TNC_RESULT_SUCCESS;}static void * tncc_get_sym(void *handle, char *func){ void *fptr;#ifdef CONFIG_NATIVE_WINDOWS#ifdef _WIN32_WCE fptr = GetProcAddressA(handle, func);#else /* _WIN32_WCE */ fptr = GetProcAddress(handle, func);#endif /* _WIN32_WCE */#else /* CONFIG_NATIVE_WINDOWS */ fptr = dlsym(handle, func);#endif /* CONFIG_NATIVE_WINDOWS */ return fptr;}static int tncc_imc_resolve_funcs(struct tnc_if_imc *imc){ void *handle = imc->dlhandle; /* Mandatory IMC functions */ imc->Initialize = tncc_get_sym(handle, "TNC_IMC_Initialize"); if (imc->Initialize == NULL) { wpa_printf(MSG_ERROR, "TNC: IMC does not export " "TNC_IMC_Initialize"); return -1; } imc->BeginHandshake = tncc_get_sym(handle, "TNC_IMC_BeginHandshake"); if (imc->BeginHandshake == NULL) { wpa_printf(MSG_ERROR, "TNC: IMC does not export " "TNC_IMC_BeginHandshake"); return -1; } imc->ProvideBindFunction = tncc_get_sym(handle, "TNC_IMC_ProvideBindFunction"); if (imc->ProvideBindFunction == NULL) { wpa_printf(MSG_ERROR, "TNC: IMC does not export " "TNC_IMC_ProvideBindFunction"); return -1; } /* Optional IMC functions */ imc->NotifyConnectionChange = tncc_get_sym(handle, "TNC_IMC_NotifyConnectionChange"); imc->ReceiveMessage = tncc_get_sym(handle, "TNC_IMC_ReceiveMessage"); imc->BatchEnding = tncc_get_sym(handle, "TNC_IMC_BatchEnding"); imc->Terminate = tncc_get_sym(handle, "TNC_IMC_Terminate"); return 0;}static int tncc_imc_initialize(struct tnc_if_imc *imc){ TNC_Result res; TNC_Version imc_ver; wpa_printf(MSG_DEBUG, "TNC: Calling TNC_IMC_Initialize for IMC '%s'", imc->name); res = imc->Initialize(imc->imcID, TNC_IFIMC_VERSION_1, TNC_IFIMC_VERSION_1, &imc_ver); wpa_printf(MSG_DEBUG, "TNC: TNC_IMC_Initialize: res=%lu imc_ver=%lu", (unsigned long) res, (unsigned long) imc_ver); return res == TNC_RESULT_SUCCESS ? 0 : -1;}static int tncc_imc_terminate(struct tnc_if_imc *imc){ TNC_Result res; if (imc->Terminate == NULL) return 0; wpa_printf(MSG_DEBUG, "TNC: Calling TNC_IMC_Terminate for IMC '%s'", imc->name); res = imc->Terminate(imc->imcID); wpa_printf(MSG_DEBUG, "TNC: TNC_IMC_Terminate: %lu", (unsigned long) res); return res == TNC_RESULT_SUCCESS ? 0 : -1;}static int tncc_imc_provide_bind_function(struct tnc_if_imc *imc){ TNC_Result res; wpa_printf(MSG_DEBUG, "TNC: Calling TNC_IMC_ProvideBindFunction for " "IMC '%s'", imc->name); res = imc->ProvideBindFunction(imc->imcID, TNC_TNCC_BindFunction); wpa_printf(MSG_DEBUG, "TNC: TNC_IMC_ProvideBindFunction: res=%lu", (unsigned long) res); return res == TNC_RESULT_SUCCESS ? 0 : -1;}static int tncc_imc_notify_connection_change(struct tnc_if_imc *imc, TNC_ConnectionState state){ TNC_Result res; if (imc->NotifyConnectionChange == NULL) return 0; wpa_printf(MSG_DEBUG, "TNC: Calling TNC_IMC_NotifyConnectionChange(%d)" " for IMC '%s'", (int) state, imc->name); res = imc->NotifyConnectionChange(imc->imcID, imc->connectionID, state); wpa_printf(MSG_DEBUG, "TNC: TNC_IMC_NotifyConnectionChange: %lu", (unsigned long) res); return res == TNC_RESULT_SUCCESS ? 0 : -1;}static int tncc_imc_begin_handshake(struct tnc_if_imc *imc){ TNC_Result res; wpa_printf(MSG_DEBUG, "TNC: Calling TNC_IMC_BeginHandshake for IMC " "'%s'", imc->name); res = imc->BeginHandshake(imc->imcID, imc->connectionID); wpa_printf(MSG_DEBUG, "TNC: TNC_IMC_BeginHandshake: %lu", (unsigned long) res); return res == TNC_RESULT_SUCCESS ? 0 : -1;}static int tncc_load_imc(struct tnc_if_imc *imc){ if (imc->path == NULL) { wpa_printf(MSG_DEBUG, "TNC: No IMC configured"); return -1; } wpa_printf(MSG_DEBUG, "TNC: Opening IMC: %s (%s)", imc->name, imc->path);#ifdef CONFIG_NATIVE_WINDOWS#ifdef UNICODE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -