139beb93cSSam Leffler /*
239beb93cSSam Leffler * EAP-TNC - TNCC (IF-IMC and IF-TNCCS)
339beb93cSSam Leffler * Copyright (c) 2007, Jouni Malinen <j@w1.fi>
439beb93cSSam Leffler *
5f05cddf9SRui Paulo * This software may be distributed under the terms of the BSD license.
6f05cddf9SRui Paulo * See README for more details.
739beb93cSSam Leffler */
839beb93cSSam Leffler
939beb93cSSam Leffler #include "includes.h"
1039beb93cSSam Leffler #ifndef CONFIG_NATIVE_WINDOWS
1139beb93cSSam Leffler #include <dlfcn.h>
1239beb93cSSam Leffler #endif /* CONFIG_NATIVE_WINDOWS */
1339beb93cSSam Leffler
1439beb93cSSam Leffler #include "common.h"
1539beb93cSSam Leffler #include "base64.h"
165b9c547cSRui Paulo #include "common/tnc.h"
1739beb93cSSam Leffler #include "tncc.h"
1839beb93cSSam Leffler #include "eap_common/eap_tlv_common.h"
1939beb93cSSam Leffler #include "eap_common/eap_defs.h"
2039beb93cSSam Leffler
2139beb93cSSam Leffler
2239beb93cSSam Leffler #ifdef UNICODE
2339beb93cSSam Leffler #define TSTR "%S"
2439beb93cSSam Leffler #else /* UNICODE */
2539beb93cSSam Leffler #define TSTR "%s"
2639beb93cSSam Leffler #endif /* UNICODE */
2739beb93cSSam Leffler
2839beb93cSSam Leffler
295b9c547cSRui Paulo #ifndef TNC_CONFIG_FILE
3039beb93cSSam Leffler #define TNC_CONFIG_FILE "/etc/tnc_config"
315b9c547cSRui Paulo #endif /* TNC_CONFIG_FILE */
3239beb93cSSam Leffler #define TNC_WINREG_PATH TEXT("SOFTWARE\\Trusted Computing Group\\TNC\\IMCs")
3339beb93cSSam Leffler #define IF_TNCCS_START \
3439beb93cSSam Leffler "<?xml version=\"1.0\"?>\n" \
3539beb93cSSam Leffler "<TNCCS-Batch BatchId=\"%d\" Recipient=\"TNCS\" " \
3639beb93cSSam Leffler "xmlns=\"http://www.trustedcomputinggroup.org/IWG/TNC/1_0/IF_TNCCS#\" " \
3739beb93cSSam Leffler "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " \
3839beb93cSSam Leffler "xsi:schemaLocation=\"http://www.trustedcomputinggroup.org/IWG/TNC/1_0/" \
3939beb93cSSam Leffler "IF_TNCCS# https://www.trustedcomputinggroup.org/XML/SCHEMA/TNCCS_1.0.xsd\">\n"
4039beb93cSSam Leffler #define IF_TNCCS_END "\n</TNCCS-Batch>"
4139beb93cSSam Leffler
4239beb93cSSam Leffler /* TNC IF-IMC */
4339beb93cSSam Leffler
4439beb93cSSam Leffler /* IF-TNCCS-SOH - SSoH and SSoHR Attributes */
4539beb93cSSam Leffler enum {
4639beb93cSSam Leffler SSOH_MS_MACHINE_INVENTORY = 1,
4739beb93cSSam Leffler SSOH_MS_QUARANTINE_STATE = 2,
4839beb93cSSam Leffler SSOH_MS_PACKET_INFO = 3,
4939beb93cSSam Leffler SSOH_MS_SYSTEMGENERATED_IDS = 4,
5039beb93cSSam Leffler SSOH_MS_MACHINENAME = 5,
5139beb93cSSam Leffler SSOH_MS_CORRELATIONID = 6,
5239beb93cSSam Leffler SSOH_MS_INSTALLED_SHVS = 7,
5339beb93cSSam Leffler SSOH_MS_MACHINE_INVENTORY_EX = 8
5439beb93cSSam Leffler };
5539beb93cSSam Leffler
5639beb93cSSam Leffler struct tnc_if_imc {
5739beb93cSSam Leffler struct tnc_if_imc *next;
5839beb93cSSam Leffler char *name;
5939beb93cSSam Leffler char *path;
6039beb93cSSam Leffler void *dlhandle; /* from dlopen() */
6139beb93cSSam Leffler TNC_IMCID imcID;
6239beb93cSSam Leffler TNC_ConnectionID connectionID;
6339beb93cSSam Leffler TNC_MessageTypeList supported_types;
6439beb93cSSam Leffler size_t num_supported_types;
6539beb93cSSam Leffler u8 *imc_send;
6639beb93cSSam Leffler size_t imc_send_len;
6739beb93cSSam Leffler
6839beb93cSSam Leffler /* Functions implemented by IMCs (with TNC_IMC_ prefix) */
6939beb93cSSam Leffler TNC_Result (*Initialize)(
7039beb93cSSam Leffler TNC_IMCID imcID,
7139beb93cSSam Leffler TNC_Version minVersion,
7239beb93cSSam Leffler TNC_Version maxVersion,
7339beb93cSSam Leffler TNC_Version *pOutActualVersion);
7439beb93cSSam Leffler TNC_Result (*NotifyConnectionChange)(
7539beb93cSSam Leffler TNC_IMCID imcID,
7639beb93cSSam Leffler TNC_ConnectionID connectionID,
7739beb93cSSam Leffler TNC_ConnectionState newState);
7839beb93cSSam Leffler TNC_Result (*BeginHandshake)(
7939beb93cSSam Leffler TNC_IMCID imcID,
8039beb93cSSam Leffler TNC_ConnectionID connectionID);
8139beb93cSSam Leffler TNC_Result (*ReceiveMessage)(
8239beb93cSSam Leffler TNC_IMCID imcID,
8339beb93cSSam Leffler TNC_ConnectionID connectionID,
8439beb93cSSam Leffler TNC_BufferReference messageBuffer,
8539beb93cSSam Leffler TNC_UInt32 messageLength,
8639beb93cSSam Leffler TNC_MessageType messageType);
8739beb93cSSam Leffler TNC_Result (*BatchEnding)(
8839beb93cSSam Leffler TNC_IMCID imcID,
8939beb93cSSam Leffler TNC_ConnectionID connectionID);
9039beb93cSSam Leffler TNC_Result (*Terminate)(TNC_IMCID imcID);
9139beb93cSSam Leffler TNC_Result (*ProvideBindFunction)(
9239beb93cSSam Leffler TNC_IMCID imcID,
9339beb93cSSam Leffler TNC_TNCC_BindFunctionPointer bindFunction);
9439beb93cSSam Leffler };
9539beb93cSSam Leffler
9639beb93cSSam Leffler struct tncc_data {
9739beb93cSSam Leffler struct tnc_if_imc *imc;
9839beb93cSSam Leffler unsigned int last_batchid;
9939beb93cSSam Leffler };
10039beb93cSSam Leffler
10139beb93cSSam Leffler #define TNC_MAX_IMC_ID 10
10239beb93cSSam Leffler static struct tnc_if_imc *tnc_imc[TNC_MAX_IMC_ID] = { NULL };
10339beb93cSSam Leffler
10439beb93cSSam Leffler
10539beb93cSSam Leffler /* TNCC functions that IMCs can call */
10639beb93cSSam Leffler
TNC_TNCC_ReportMessageTypes(TNC_IMCID imcID,TNC_MessageTypeList supportedTypes,TNC_UInt32 typeCount)107780fb4a2SCy Schubert static TNC_Result TNC_TNCC_ReportMessageTypes(
10839beb93cSSam Leffler TNC_IMCID imcID,
10939beb93cSSam Leffler TNC_MessageTypeList supportedTypes,
11039beb93cSSam Leffler TNC_UInt32 typeCount)
11139beb93cSSam Leffler {
11239beb93cSSam Leffler TNC_UInt32 i;
11339beb93cSSam Leffler struct tnc_if_imc *imc;
11439beb93cSSam Leffler
11539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TNC: TNC_TNCC_ReportMessageTypes(imcID=%lu "
11639beb93cSSam Leffler "typeCount=%lu)",
11739beb93cSSam Leffler (unsigned long) imcID, (unsigned long) typeCount);
11839beb93cSSam Leffler
11939beb93cSSam Leffler for (i = 0; i < typeCount; i++) {
12039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TNC: supportedTypes[%lu] = %lu",
12139beb93cSSam Leffler i, supportedTypes[i]);
12239beb93cSSam Leffler }
12339beb93cSSam Leffler
12439beb93cSSam Leffler if (imcID >= TNC_MAX_IMC_ID || tnc_imc[imcID] == NULL)
12539beb93cSSam Leffler return TNC_RESULT_INVALID_PARAMETER;
12639beb93cSSam Leffler
12739beb93cSSam Leffler imc = tnc_imc[imcID];
12839beb93cSSam Leffler os_free(imc->supported_types);
12985732ac8SCy Schubert imc->supported_types = os_memdup(supportedTypes,
13085732ac8SCy Schubert typeCount * sizeof(TNC_MessageType));
13139beb93cSSam Leffler if (imc->supported_types == NULL)
13239beb93cSSam Leffler return TNC_RESULT_FATAL;
13339beb93cSSam Leffler imc->num_supported_types = typeCount;
13439beb93cSSam Leffler
13539beb93cSSam Leffler return TNC_RESULT_SUCCESS;
13639beb93cSSam Leffler }
13739beb93cSSam Leffler
13839beb93cSSam Leffler
TNC_TNCC_SendMessage(TNC_IMCID imcID,TNC_ConnectionID connectionID,TNC_BufferReference message,TNC_UInt32 messageLength,TNC_MessageType messageType)139780fb4a2SCy Schubert static TNC_Result TNC_TNCC_SendMessage(
14039beb93cSSam Leffler TNC_IMCID imcID,
14139beb93cSSam Leffler TNC_ConnectionID connectionID,
14239beb93cSSam Leffler TNC_BufferReference message,
14339beb93cSSam Leffler TNC_UInt32 messageLength,
14439beb93cSSam Leffler TNC_MessageType messageType)
14539beb93cSSam Leffler {
14639beb93cSSam Leffler struct tnc_if_imc *imc;
147*c1d255d3SCy Schubert char *b64;
14839beb93cSSam Leffler size_t b64len;
14939beb93cSSam Leffler
15039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TNC: TNC_TNCC_SendMessage(imcID=%lu "
15139beb93cSSam Leffler "connectionID=%lu messageType=%lu)",
15239beb93cSSam Leffler imcID, connectionID, messageType);
15339beb93cSSam Leffler wpa_hexdump_ascii(MSG_DEBUG, "TNC: TNC_TNCC_SendMessage",
15439beb93cSSam Leffler message, messageLength);
15539beb93cSSam Leffler
15639beb93cSSam Leffler if (imcID >= TNC_MAX_IMC_ID || tnc_imc[imcID] == NULL)
15739beb93cSSam Leffler return TNC_RESULT_INVALID_PARAMETER;
15839beb93cSSam Leffler
15939beb93cSSam Leffler b64 = base64_encode(message, messageLength, &b64len);
16039beb93cSSam Leffler if (b64 == NULL)
16139beb93cSSam Leffler return TNC_RESULT_FATAL;
16239beb93cSSam Leffler
16339beb93cSSam Leffler imc = tnc_imc[imcID];
16439beb93cSSam Leffler os_free(imc->imc_send);
16539beb93cSSam Leffler imc->imc_send_len = 0;
16639beb93cSSam Leffler imc->imc_send = os_zalloc(b64len + 100);
16739beb93cSSam Leffler if (imc->imc_send == NULL) {
16839beb93cSSam Leffler os_free(b64);
16939beb93cSSam Leffler return TNC_RESULT_OTHER;
17039beb93cSSam Leffler }
17139beb93cSSam Leffler
17239beb93cSSam Leffler imc->imc_send_len =
17339beb93cSSam Leffler os_snprintf((char *) imc->imc_send, b64len + 100,
17439beb93cSSam Leffler "<IMC-IMV-Message><Type>%08X</Type>"
17539beb93cSSam Leffler "<Base64>%s</Base64></IMC-IMV-Message>",
17639beb93cSSam Leffler (unsigned int) messageType, b64);
17739beb93cSSam Leffler
17839beb93cSSam Leffler os_free(b64);
17939beb93cSSam Leffler
18039beb93cSSam Leffler return TNC_RESULT_SUCCESS;
18139beb93cSSam Leffler }
18239beb93cSSam Leffler
18339beb93cSSam Leffler
TNC_TNCC_RequestHandshakeRetry(TNC_IMCID imcID,TNC_ConnectionID connectionID,TNC_RetryReason reason)184780fb4a2SCy Schubert static TNC_Result TNC_TNCC_RequestHandshakeRetry(
18539beb93cSSam Leffler TNC_IMCID imcID,
18639beb93cSSam Leffler TNC_ConnectionID connectionID,
18739beb93cSSam Leffler TNC_RetryReason reason)
18839beb93cSSam Leffler {
18939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TNC: TNC_TNCC_RequestHandshakeRetry");
19039beb93cSSam Leffler
19139beb93cSSam Leffler if (imcID >= TNC_MAX_IMC_ID || tnc_imc[imcID] == NULL)
19239beb93cSSam Leffler return TNC_RESULT_INVALID_PARAMETER;
19339beb93cSSam Leffler
19439beb93cSSam Leffler /*
19539beb93cSSam Leffler * TODO: trigger a call to eapol_sm_request_reauth(). This would
19639beb93cSSam Leffler * require that the IMC continues to be loaded in memory afer
19739beb93cSSam Leffler * authentication..
19839beb93cSSam Leffler */
19939beb93cSSam Leffler
20039beb93cSSam Leffler return TNC_RESULT_SUCCESS;
20139beb93cSSam Leffler }
20239beb93cSSam Leffler
20339beb93cSSam Leffler
TNC_9048_LogMessage(TNC_IMCID imcID,TNC_UInt32 severity,const char * message)204780fb4a2SCy Schubert static TNC_Result TNC_9048_LogMessage(TNC_IMCID imcID, TNC_UInt32 severity,
20539beb93cSSam Leffler const char *message)
20639beb93cSSam Leffler {
20739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TNC: TNC_9048_LogMessage(imcID=%lu "
20839beb93cSSam Leffler "severity==%lu message='%s')",
20939beb93cSSam Leffler imcID, severity, message);
21039beb93cSSam Leffler return TNC_RESULT_SUCCESS;
21139beb93cSSam Leffler }
21239beb93cSSam Leffler
21339beb93cSSam Leffler
TNC_9048_UserMessage(TNC_IMCID imcID,TNC_ConnectionID connectionID,const char * message)214780fb4a2SCy Schubert static TNC_Result TNC_9048_UserMessage(TNC_IMCID imcID,
215780fb4a2SCy Schubert TNC_ConnectionID connectionID,
21639beb93cSSam Leffler const char *message)
21739beb93cSSam Leffler {
21839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TNC: TNC_9048_UserMessage(imcID=%lu "
21939beb93cSSam Leffler "connectionID==%lu message='%s')",
22039beb93cSSam Leffler imcID, connectionID, message);
22139beb93cSSam Leffler return TNC_RESULT_SUCCESS;
22239beb93cSSam Leffler }
22339beb93cSSam Leffler
22439beb93cSSam Leffler
TNC_TNCC_BindFunction(TNC_IMCID imcID,char * functionName,void ** pOutfunctionPointer)225780fb4a2SCy Schubert static TNC_Result TNC_TNCC_BindFunction(
22639beb93cSSam Leffler TNC_IMCID imcID,
22739beb93cSSam Leffler char *functionName,
22839beb93cSSam Leffler void **pOutfunctionPointer)
22939beb93cSSam Leffler {
23039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TNC: TNC_TNCC_BindFunction(imcID=%lu, "
23139beb93cSSam Leffler "functionName='%s')", (unsigned long) imcID, functionName);
23239beb93cSSam Leffler
23339beb93cSSam Leffler if (imcID >= TNC_MAX_IMC_ID || tnc_imc[imcID] == NULL)
23439beb93cSSam Leffler return TNC_RESULT_INVALID_PARAMETER;
23539beb93cSSam Leffler
23639beb93cSSam Leffler if (pOutfunctionPointer == NULL)
23739beb93cSSam Leffler return TNC_RESULT_INVALID_PARAMETER;
23839beb93cSSam Leffler
23939beb93cSSam Leffler if (os_strcmp(functionName, "TNC_TNCC_ReportMessageTypes") == 0)
24039beb93cSSam Leffler *pOutfunctionPointer = TNC_TNCC_ReportMessageTypes;
24139beb93cSSam Leffler else if (os_strcmp(functionName, "TNC_TNCC_SendMessage") == 0)
24239beb93cSSam Leffler *pOutfunctionPointer = TNC_TNCC_SendMessage;
24339beb93cSSam Leffler else if (os_strcmp(functionName, "TNC_TNCC_RequestHandshakeRetry") ==
24439beb93cSSam Leffler 0)
24539beb93cSSam Leffler *pOutfunctionPointer = TNC_TNCC_RequestHandshakeRetry;
24639beb93cSSam Leffler else if (os_strcmp(functionName, "TNC_9048_LogMessage") == 0)
24739beb93cSSam Leffler *pOutfunctionPointer = TNC_9048_LogMessage;
24839beb93cSSam Leffler else if (os_strcmp(functionName, "TNC_9048_UserMessage") == 0)
24939beb93cSSam Leffler *pOutfunctionPointer = TNC_9048_UserMessage;
25039beb93cSSam Leffler else
25139beb93cSSam Leffler *pOutfunctionPointer = NULL;
25239beb93cSSam Leffler
25339beb93cSSam Leffler return TNC_RESULT_SUCCESS;
25439beb93cSSam Leffler }
25539beb93cSSam Leffler
25639beb93cSSam Leffler
tncc_get_sym(void * handle,char * func)25739beb93cSSam Leffler static void * tncc_get_sym(void *handle, char *func)
25839beb93cSSam Leffler {
25939beb93cSSam Leffler void *fptr;
26039beb93cSSam Leffler
26139beb93cSSam Leffler #ifdef CONFIG_NATIVE_WINDOWS
26239beb93cSSam Leffler #ifdef _WIN32_WCE
26339beb93cSSam Leffler fptr = GetProcAddressA(handle, func);
26439beb93cSSam Leffler #else /* _WIN32_WCE */
26539beb93cSSam Leffler fptr = GetProcAddress(handle, func);
26639beb93cSSam Leffler #endif /* _WIN32_WCE */
26739beb93cSSam Leffler #else /* CONFIG_NATIVE_WINDOWS */
26839beb93cSSam Leffler fptr = dlsym(handle, func);
26939beb93cSSam Leffler #endif /* CONFIG_NATIVE_WINDOWS */
27039beb93cSSam Leffler
27139beb93cSSam Leffler return fptr;
27239beb93cSSam Leffler }
27339beb93cSSam Leffler
27439beb93cSSam Leffler
tncc_imc_resolve_funcs(struct tnc_if_imc * imc)27539beb93cSSam Leffler static int tncc_imc_resolve_funcs(struct tnc_if_imc *imc)
27639beb93cSSam Leffler {
27739beb93cSSam Leffler void *handle = imc->dlhandle;
27839beb93cSSam Leffler
27939beb93cSSam Leffler /* Mandatory IMC functions */
28039beb93cSSam Leffler imc->Initialize = tncc_get_sym(handle, "TNC_IMC_Initialize");
28139beb93cSSam Leffler if (imc->Initialize == NULL) {
28239beb93cSSam Leffler wpa_printf(MSG_ERROR, "TNC: IMC does not export "
28339beb93cSSam Leffler "TNC_IMC_Initialize");
28439beb93cSSam Leffler return -1;
28539beb93cSSam Leffler }
28639beb93cSSam Leffler
28739beb93cSSam Leffler imc->BeginHandshake = tncc_get_sym(handle, "TNC_IMC_BeginHandshake");
28839beb93cSSam Leffler if (imc->BeginHandshake == NULL) {
28939beb93cSSam Leffler wpa_printf(MSG_ERROR, "TNC: IMC does not export "
29039beb93cSSam Leffler "TNC_IMC_BeginHandshake");
29139beb93cSSam Leffler return -1;
29239beb93cSSam Leffler }
29339beb93cSSam Leffler
29439beb93cSSam Leffler imc->ProvideBindFunction =
29539beb93cSSam Leffler tncc_get_sym(handle, "TNC_IMC_ProvideBindFunction");
29639beb93cSSam Leffler if (imc->ProvideBindFunction == NULL) {
29739beb93cSSam Leffler wpa_printf(MSG_ERROR, "TNC: IMC does not export "
29839beb93cSSam Leffler "TNC_IMC_ProvideBindFunction");
29939beb93cSSam Leffler return -1;
30039beb93cSSam Leffler }
30139beb93cSSam Leffler
30239beb93cSSam Leffler /* Optional IMC functions */
30339beb93cSSam Leffler imc->NotifyConnectionChange =
30439beb93cSSam Leffler tncc_get_sym(handle, "TNC_IMC_NotifyConnectionChange");
30539beb93cSSam Leffler imc->ReceiveMessage = tncc_get_sym(handle, "TNC_IMC_ReceiveMessage");
30639beb93cSSam Leffler imc->BatchEnding = tncc_get_sym(handle, "TNC_IMC_BatchEnding");
30739beb93cSSam Leffler imc->Terminate = tncc_get_sym(handle, "TNC_IMC_Terminate");
30839beb93cSSam Leffler
30939beb93cSSam Leffler return 0;
31039beb93cSSam Leffler }
31139beb93cSSam Leffler
31239beb93cSSam Leffler
tncc_imc_initialize(struct tnc_if_imc * imc)31339beb93cSSam Leffler static int tncc_imc_initialize(struct tnc_if_imc *imc)
31439beb93cSSam Leffler {
31539beb93cSSam Leffler TNC_Result res;
31639beb93cSSam Leffler TNC_Version imc_ver;
31739beb93cSSam Leffler
31839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TNC: Calling TNC_IMC_Initialize for IMC '%s'",
31939beb93cSSam Leffler imc->name);
32039beb93cSSam Leffler res = imc->Initialize(imc->imcID, TNC_IFIMC_VERSION_1,
32139beb93cSSam Leffler TNC_IFIMC_VERSION_1, &imc_ver);
32239beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TNC: TNC_IMC_Initialize: res=%lu imc_ver=%lu",
32339beb93cSSam Leffler (unsigned long) res, (unsigned long) imc_ver);
32439beb93cSSam Leffler
32539beb93cSSam Leffler return res == TNC_RESULT_SUCCESS ? 0 : -1;
32639beb93cSSam Leffler }
32739beb93cSSam Leffler
32839beb93cSSam Leffler
tncc_imc_terminate(struct tnc_if_imc * imc)32939beb93cSSam Leffler static int tncc_imc_terminate(struct tnc_if_imc *imc)
33039beb93cSSam Leffler {
33139beb93cSSam Leffler TNC_Result res;
33239beb93cSSam Leffler
33339beb93cSSam Leffler if (imc->Terminate == NULL)
33439beb93cSSam Leffler return 0;
33539beb93cSSam Leffler
33639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TNC: Calling TNC_IMC_Terminate for IMC '%s'",
33739beb93cSSam Leffler imc->name);
33839beb93cSSam Leffler res = imc->Terminate(imc->imcID);
33939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TNC: TNC_IMC_Terminate: %lu",
34039beb93cSSam Leffler (unsigned long) res);
34139beb93cSSam Leffler
34239beb93cSSam Leffler return res == TNC_RESULT_SUCCESS ? 0 : -1;
34339beb93cSSam Leffler }
34439beb93cSSam Leffler
34539beb93cSSam Leffler
tncc_imc_provide_bind_function(struct tnc_if_imc * imc)34639beb93cSSam Leffler static int tncc_imc_provide_bind_function(struct tnc_if_imc *imc)
34739beb93cSSam Leffler {
34839beb93cSSam Leffler TNC_Result res;
34939beb93cSSam Leffler
35039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TNC: Calling TNC_IMC_ProvideBindFunction for "
35139beb93cSSam Leffler "IMC '%s'", imc->name);
35239beb93cSSam Leffler res = imc->ProvideBindFunction(imc->imcID, TNC_TNCC_BindFunction);
35339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TNC: TNC_IMC_ProvideBindFunction: res=%lu",
35439beb93cSSam Leffler (unsigned long) res);
35539beb93cSSam Leffler
35639beb93cSSam Leffler return res == TNC_RESULT_SUCCESS ? 0 : -1;
35739beb93cSSam Leffler }
35839beb93cSSam Leffler
35939beb93cSSam Leffler
tncc_imc_notify_connection_change(struct tnc_if_imc * imc,TNC_ConnectionState state)36039beb93cSSam Leffler static int tncc_imc_notify_connection_change(struct tnc_if_imc *imc,
36139beb93cSSam Leffler TNC_ConnectionState state)
36239beb93cSSam Leffler {
36339beb93cSSam Leffler TNC_Result res;
36439beb93cSSam Leffler
36539beb93cSSam Leffler if (imc->NotifyConnectionChange == NULL)
36639beb93cSSam Leffler return 0;
36739beb93cSSam Leffler
36839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TNC: Calling TNC_IMC_NotifyConnectionChange(%d)"
36939beb93cSSam Leffler " for IMC '%s'", (int) state, imc->name);
37039beb93cSSam Leffler res = imc->NotifyConnectionChange(imc->imcID, imc->connectionID,
37139beb93cSSam Leffler state);
37239beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TNC: TNC_IMC_NotifyConnectionChange: %lu",
37339beb93cSSam Leffler (unsigned long) res);
37439beb93cSSam Leffler
37539beb93cSSam Leffler return res == TNC_RESULT_SUCCESS ? 0 : -1;
37639beb93cSSam Leffler }
37739beb93cSSam Leffler
37839beb93cSSam Leffler
tncc_imc_begin_handshake(struct tnc_if_imc * imc)37939beb93cSSam Leffler static int tncc_imc_begin_handshake(struct tnc_if_imc *imc)
38039beb93cSSam Leffler {
38139beb93cSSam Leffler TNC_Result res;
38239beb93cSSam Leffler
38339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TNC: Calling TNC_IMC_BeginHandshake for IMC "
38439beb93cSSam Leffler "'%s'", imc->name);
38539beb93cSSam Leffler res = imc->BeginHandshake(imc->imcID, imc->connectionID);
38639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TNC: TNC_IMC_BeginHandshake: %lu",
38739beb93cSSam Leffler (unsigned long) res);
38839beb93cSSam Leffler
38939beb93cSSam Leffler return res == TNC_RESULT_SUCCESS ? 0 : -1;
39039beb93cSSam Leffler }
39139beb93cSSam Leffler
39239beb93cSSam Leffler
tncc_load_imc(struct tnc_if_imc * imc)39339beb93cSSam Leffler static int tncc_load_imc(struct tnc_if_imc *imc)
39439beb93cSSam Leffler {
39539beb93cSSam Leffler if (imc->path == NULL) {
39639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TNC: No IMC configured");
39739beb93cSSam Leffler return -1;
39839beb93cSSam Leffler }
39939beb93cSSam Leffler
40039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TNC: Opening IMC: %s (%s)",
40139beb93cSSam Leffler imc->name, imc->path);
40239beb93cSSam Leffler #ifdef CONFIG_NATIVE_WINDOWS
40339beb93cSSam Leffler #ifdef UNICODE
40439beb93cSSam Leffler {
40539beb93cSSam Leffler TCHAR *lib = wpa_strdup_tchar(imc->path);
40639beb93cSSam Leffler if (lib == NULL)
40739beb93cSSam Leffler return -1;
40839beb93cSSam Leffler imc->dlhandle = LoadLibrary(lib);
40939beb93cSSam Leffler os_free(lib);
41039beb93cSSam Leffler }
41139beb93cSSam Leffler #else /* UNICODE */
41239beb93cSSam Leffler imc->dlhandle = LoadLibrary(imc->path);
41339beb93cSSam Leffler #endif /* UNICODE */
41439beb93cSSam Leffler if (imc->dlhandle == NULL) {
41539beb93cSSam Leffler wpa_printf(MSG_ERROR, "TNC: Failed to open IMC '%s' (%s): %d",
41639beb93cSSam Leffler imc->name, imc->path, (int) GetLastError());
41739beb93cSSam Leffler return -1;
41839beb93cSSam Leffler }
41939beb93cSSam Leffler #else /* CONFIG_NATIVE_WINDOWS */
42039beb93cSSam Leffler imc->dlhandle = dlopen(imc->path, RTLD_LAZY);
42139beb93cSSam Leffler if (imc->dlhandle == NULL) {
42239beb93cSSam Leffler wpa_printf(MSG_ERROR, "TNC: Failed to open IMC '%s' (%s): %s",
42339beb93cSSam Leffler imc->name, imc->path, dlerror());
42439beb93cSSam Leffler return -1;
42539beb93cSSam Leffler }
42639beb93cSSam Leffler #endif /* CONFIG_NATIVE_WINDOWS */
42739beb93cSSam Leffler
42839beb93cSSam Leffler if (tncc_imc_resolve_funcs(imc) < 0) {
42939beb93cSSam Leffler wpa_printf(MSG_ERROR, "TNC: Failed to resolve IMC functions");
43039beb93cSSam Leffler return -1;
43139beb93cSSam Leffler }
43239beb93cSSam Leffler
43339beb93cSSam Leffler if (tncc_imc_initialize(imc) < 0 ||
43439beb93cSSam Leffler tncc_imc_provide_bind_function(imc) < 0) {
43539beb93cSSam Leffler wpa_printf(MSG_ERROR, "TNC: Failed to initialize IMC");
43639beb93cSSam Leffler return -1;
43739beb93cSSam Leffler }
43839beb93cSSam Leffler
43939beb93cSSam Leffler return 0;
44039beb93cSSam Leffler }
44139beb93cSSam Leffler
44239beb93cSSam Leffler
tncc_unload_imc(struct tnc_if_imc * imc)44339beb93cSSam Leffler static void tncc_unload_imc(struct tnc_if_imc *imc)
44439beb93cSSam Leffler {
44539beb93cSSam Leffler tncc_imc_terminate(imc);
44639beb93cSSam Leffler tnc_imc[imc->imcID] = NULL;
44739beb93cSSam Leffler
44839beb93cSSam Leffler if (imc->dlhandle) {
44939beb93cSSam Leffler #ifdef CONFIG_NATIVE_WINDOWS
45039beb93cSSam Leffler FreeLibrary(imc->dlhandle);
45139beb93cSSam Leffler #else /* CONFIG_NATIVE_WINDOWS */
45239beb93cSSam Leffler dlclose(imc->dlhandle);
45339beb93cSSam Leffler #endif /* CONFIG_NATIVE_WINDOWS */
45439beb93cSSam Leffler }
45539beb93cSSam Leffler os_free(imc->name);
45639beb93cSSam Leffler os_free(imc->path);
45739beb93cSSam Leffler os_free(imc->supported_types);
45839beb93cSSam Leffler os_free(imc->imc_send);
45939beb93cSSam Leffler }
46039beb93cSSam Leffler
46139beb93cSSam Leffler
tncc_supported_type(struct tnc_if_imc * imc,unsigned int type)46239beb93cSSam Leffler static int tncc_supported_type(struct tnc_if_imc *imc, unsigned int type)
46339beb93cSSam Leffler {
46439beb93cSSam Leffler size_t i;
46539beb93cSSam Leffler unsigned int vendor, subtype;
46639beb93cSSam Leffler
46739beb93cSSam Leffler if (imc == NULL || imc->supported_types == NULL)
46839beb93cSSam Leffler return 0;
46939beb93cSSam Leffler
47039beb93cSSam Leffler vendor = type >> 8;
47139beb93cSSam Leffler subtype = type & 0xff;
47239beb93cSSam Leffler
47339beb93cSSam Leffler for (i = 0; i < imc->num_supported_types; i++) {
47439beb93cSSam Leffler unsigned int svendor, ssubtype;
47539beb93cSSam Leffler svendor = imc->supported_types[i] >> 8;
47639beb93cSSam Leffler ssubtype = imc->supported_types[i] & 0xff;
47739beb93cSSam Leffler if ((vendor == svendor || svendor == TNC_VENDORID_ANY) &&
47839beb93cSSam Leffler (subtype == ssubtype || ssubtype == TNC_SUBTYPE_ANY))
47939beb93cSSam Leffler return 1;
48039beb93cSSam Leffler }
48139beb93cSSam Leffler
48239beb93cSSam Leffler return 0;
48339beb93cSSam Leffler }
48439beb93cSSam Leffler
48539beb93cSSam Leffler
tncc_send_to_imcs(struct tncc_data * tncc,unsigned int type,const u8 * msg,size_t len)48639beb93cSSam Leffler static void tncc_send_to_imcs(struct tncc_data *tncc, unsigned int type,
48739beb93cSSam Leffler const u8 *msg, size_t len)
48839beb93cSSam Leffler {
48939beb93cSSam Leffler struct tnc_if_imc *imc;
49039beb93cSSam Leffler TNC_Result res;
49139beb93cSSam Leffler
49239beb93cSSam Leffler wpa_hexdump_ascii(MSG_MSGDUMP, "TNC: Message to IMC(s)", msg, len);
49339beb93cSSam Leffler
49439beb93cSSam Leffler for (imc = tncc->imc; imc; imc = imc->next) {
49539beb93cSSam Leffler if (imc->ReceiveMessage == NULL ||
49639beb93cSSam Leffler !tncc_supported_type(imc, type))
49739beb93cSSam Leffler continue;
49839beb93cSSam Leffler
49939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TNC: Call ReceiveMessage for IMC '%s'",
50039beb93cSSam Leffler imc->name);
50139beb93cSSam Leffler res = imc->ReceiveMessage(imc->imcID, imc->connectionID,
50239beb93cSSam Leffler (TNC_BufferReference) msg, len,
50339beb93cSSam Leffler type);
50439beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TNC: ReceiveMessage: %lu",
50539beb93cSSam Leffler (unsigned long) res);
50639beb93cSSam Leffler }
50739beb93cSSam Leffler }
50839beb93cSSam Leffler
50939beb93cSSam Leffler
tncc_init_connection(struct tncc_data * tncc)51039beb93cSSam Leffler void tncc_init_connection(struct tncc_data *tncc)
51139beb93cSSam Leffler {
51239beb93cSSam Leffler struct tnc_if_imc *imc;
51339beb93cSSam Leffler
51439beb93cSSam Leffler for (imc = tncc->imc; imc; imc = imc->next) {
51539beb93cSSam Leffler tncc_imc_notify_connection_change(
51639beb93cSSam Leffler imc, TNC_CONNECTION_STATE_CREATE);
51739beb93cSSam Leffler tncc_imc_notify_connection_change(
51839beb93cSSam Leffler imc, TNC_CONNECTION_STATE_HANDSHAKE);
51939beb93cSSam Leffler
52039beb93cSSam Leffler os_free(imc->imc_send);
52139beb93cSSam Leffler imc->imc_send = NULL;
52239beb93cSSam Leffler imc->imc_send_len = 0;
52339beb93cSSam Leffler
52439beb93cSSam Leffler tncc_imc_begin_handshake(imc);
52539beb93cSSam Leffler }
52639beb93cSSam Leffler }
52739beb93cSSam Leffler
52839beb93cSSam Leffler
tncc_total_send_len(struct tncc_data * tncc)52939beb93cSSam Leffler size_t tncc_total_send_len(struct tncc_data *tncc)
53039beb93cSSam Leffler {
53139beb93cSSam Leffler struct tnc_if_imc *imc;
53239beb93cSSam Leffler
53339beb93cSSam Leffler size_t len = 0;
53439beb93cSSam Leffler for (imc = tncc->imc; imc; imc = imc->next)
53539beb93cSSam Leffler len += imc->imc_send_len;
53639beb93cSSam Leffler return len;
53739beb93cSSam Leffler }
53839beb93cSSam Leffler
53939beb93cSSam Leffler
tncc_copy_send_buf(struct tncc_data * tncc,u8 * pos)54039beb93cSSam Leffler u8 * tncc_copy_send_buf(struct tncc_data *tncc, u8 *pos)
54139beb93cSSam Leffler {
54239beb93cSSam Leffler struct tnc_if_imc *imc;
54339beb93cSSam Leffler
54439beb93cSSam Leffler for (imc = tncc->imc; imc; imc = imc->next) {
54539beb93cSSam Leffler if (imc->imc_send == NULL)
54639beb93cSSam Leffler continue;
54739beb93cSSam Leffler
54839beb93cSSam Leffler os_memcpy(pos, imc->imc_send, imc->imc_send_len);
54939beb93cSSam Leffler pos += imc->imc_send_len;
55039beb93cSSam Leffler os_free(imc->imc_send);
55139beb93cSSam Leffler imc->imc_send = NULL;
55239beb93cSSam Leffler imc->imc_send_len = 0;
55339beb93cSSam Leffler }
55439beb93cSSam Leffler
55539beb93cSSam Leffler return pos;
55639beb93cSSam Leffler }
55739beb93cSSam Leffler
55839beb93cSSam Leffler
tncc_if_tnccs_start(struct tncc_data * tncc)55939beb93cSSam Leffler char * tncc_if_tnccs_start(struct tncc_data *tncc)
56039beb93cSSam Leffler {
56139beb93cSSam Leffler char *buf = os_malloc(1000);
56239beb93cSSam Leffler if (buf == NULL)
56339beb93cSSam Leffler return NULL;
56439beb93cSSam Leffler tncc->last_batchid++;
56539beb93cSSam Leffler os_snprintf(buf, 1000, IF_TNCCS_START, tncc->last_batchid);
56639beb93cSSam Leffler return buf;
56739beb93cSSam Leffler }
56839beb93cSSam Leffler
56939beb93cSSam Leffler
tncc_if_tnccs_end(void)57039beb93cSSam Leffler char * tncc_if_tnccs_end(void)
57139beb93cSSam Leffler {
57239beb93cSSam Leffler char *buf = os_malloc(100);
57339beb93cSSam Leffler if (buf == NULL)
57439beb93cSSam Leffler return NULL;
57539beb93cSSam Leffler os_snprintf(buf, 100, IF_TNCCS_END);
57639beb93cSSam Leffler return buf;
57739beb93cSSam Leffler }
57839beb93cSSam Leffler
57939beb93cSSam Leffler
tncc_notify_recommendation(struct tncc_data * tncc,enum tncc_process_res res)58039beb93cSSam Leffler static void tncc_notify_recommendation(struct tncc_data *tncc,
58139beb93cSSam Leffler enum tncc_process_res res)
58239beb93cSSam Leffler {
58339beb93cSSam Leffler TNC_ConnectionState state;
58439beb93cSSam Leffler struct tnc_if_imc *imc;
58539beb93cSSam Leffler
58639beb93cSSam Leffler switch (res) {
58739beb93cSSam Leffler case TNCCS_RECOMMENDATION_ALLOW:
58839beb93cSSam Leffler state = TNC_CONNECTION_STATE_ACCESS_ALLOWED;
58939beb93cSSam Leffler break;
59039beb93cSSam Leffler case TNCCS_RECOMMENDATION_NONE:
59139beb93cSSam Leffler state = TNC_CONNECTION_STATE_ACCESS_NONE;
59239beb93cSSam Leffler break;
59339beb93cSSam Leffler case TNCCS_RECOMMENDATION_ISOLATE:
59439beb93cSSam Leffler state = TNC_CONNECTION_STATE_ACCESS_ISOLATED;
59539beb93cSSam Leffler break;
59639beb93cSSam Leffler default:
59739beb93cSSam Leffler state = TNC_CONNECTION_STATE_ACCESS_NONE;
59839beb93cSSam Leffler break;
59939beb93cSSam Leffler }
60039beb93cSSam Leffler
60139beb93cSSam Leffler for (imc = tncc->imc; imc; imc = imc->next)
60239beb93cSSam Leffler tncc_imc_notify_connection_change(imc, state);
60339beb93cSSam Leffler }
60439beb93cSSam Leffler
60539beb93cSSam Leffler
tncc_get_type(char * start,unsigned int * type)60639beb93cSSam Leffler static int tncc_get_type(char *start, unsigned int *type)
60739beb93cSSam Leffler {
60839beb93cSSam Leffler char *pos = os_strstr(start, "<Type>");
60939beb93cSSam Leffler if (pos == NULL)
61039beb93cSSam Leffler return -1;
61139beb93cSSam Leffler pos += 6;
61239beb93cSSam Leffler *type = strtoul(pos, NULL, 16);
61339beb93cSSam Leffler return 0;
61439beb93cSSam Leffler }
61539beb93cSSam Leffler
61639beb93cSSam Leffler
tncc_get_base64(char * start,size_t * decoded_len)61739beb93cSSam Leffler static unsigned char * tncc_get_base64(char *start, size_t *decoded_len)
61839beb93cSSam Leffler {
61939beb93cSSam Leffler char *pos, *pos2;
62039beb93cSSam Leffler unsigned char *decoded;
62139beb93cSSam Leffler
62239beb93cSSam Leffler pos = os_strstr(start, "<Base64>");
62339beb93cSSam Leffler if (pos == NULL)
62439beb93cSSam Leffler return NULL;
62539beb93cSSam Leffler
62639beb93cSSam Leffler pos += 8;
62739beb93cSSam Leffler pos2 = os_strstr(pos, "</Base64>");
62839beb93cSSam Leffler if (pos2 == NULL)
62939beb93cSSam Leffler return NULL;
63039beb93cSSam Leffler *pos2 = '\0';
63139beb93cSSam Leffler
632*c1d255d3SCy Schubert decoded = base64_decode(pos, os_strlen(pos), decoded_len);
63339beb93cSSam Leffler *pos2 = '<';
63439beb93cSSam Leffler if (decoded == NULL) {
63539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TNC: Failed to decode Base64 data");
63639beb93cSSam Leffler }
63739beb93cSSam Leffler
63839beb93cSSam Leffler return decoded;
63939beb93cSSam Leffler }
64039beb93cSSam Leffler
64139beb93cSSam Leffler
tncc_get_recommendation(char * start)64239beb93cSSam Leffler static enum tncc_process_res tncc_get_recommendation(char *start)
64339beb93cSSam Leffler {
64439beb93cSSam Leffler char *pos, *pos2, saved;
64539beb93cSSam Leffler int recom;
64639beb93cSSam Leffler
64739beb93cSSam Leffler pos = os_strstr(start, "<TNCCS-Recommendation ");
64839beb93cSSam Leffler if (pos == NULL)
64939beb93cSSam Leffler return TNCCS_RECOMMENDATION_ERROR;
65039beb93cSSam Leffler
65139beb93cSSam Leffler pos += 21;
65239beb93cSSam Leffler pos = os_strstr(pos, " type=");
65339beb93cSSam Leffler if (pos == NULL)
65439beb93cSSam Leffler return TNCCS_RECOMMENDATION_ERROR;
65539beb93cSSam Leffler pos += 6;
65639beb93cSSam Leffler
65739beb93cSSam Leffler if (*pos == '"')
65839beb93cSSam Leffler pos++;
65939beb93cSSam Leffler
66039beb93cSSam Leffler pos2 = pos;
66139beb93cSSam Leffler while (*pos2 != '\0' && *pos2 != '"' && *pos2 != '>')
66239beb93cSSam Leffler pos2++;
66339beb93cSSam Leffler
66439beb93cSSam Leffler if (*pos2 == '\0')
66539beb93cSSam Leffler return TNCCS_RECOMMENDATION_ERROR;
66639beb93cSSam Leffler
66739beb93cSSam Leffler saved = *pos2;
66839beb93cSSam Leffler *pos2 = '\0';
66939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TNC: TNCCS-Recommendation: '%s'", pos);
67039beb93cSSam Leffler
67139beb93cSSam Leffler recom = TNCCS_RECOMMENDATION_ERROR;
67239beb93cSSam Leffler if (os_strcmp(pos, "allow") == 0)
67339beb93cSSam Leffler recom = TNCCS_RECOMMENDATION_ALLOW;
67439beb93cSSam Leffler else if (os_strcmp(pos, "none") == 0)
67539beb93cSSam Leffler recom = TNCCS_RECOMMENDATION_NONE;
67639beb93cSSam Leffler else if (os_strcmp(pos, "isolate") == 0)
67739beb93cSSam Leffler recom = TNCCS_RECOMMENDATION_ISOLATE;
67839beb93cSSam Leffler
67939beb93cSSam Leffler *pos2 = saved;
68039beb93cSSam Leffler
68139beb93cSSam Leffler return recom;
68239beb93cSSam Leffler }
68339beb93cSSam Leffler
68439beb93cSSam Leffler
tncc_process_if_tnccs(struct tncc_data * tncc,const u8 * msg,size_t len)68539beb93cSSam Leffler enum tncc_process_res tncc_process_if_tnccs(struct tncc_data *tncc,
68639beb93cSSam Leffler const u8 *msg, size_t len)
68739beb93cSSam Leffler {
68839beb93cSSam Leffler char *buf, *start, *end, *pos, *pos2, *payload;
68939beb93cSSam Leffler unsigned int batch_id;
69039beb93cSSam Leffler unsigned char *decoded;
69139beb93cSSam Leffler size_t decoded_len;
69239beb93cSSam Leffler enum tncc_process_res res = TNCCS_PROCESS_OK_NO_RECOMMENDATION;
69339beb93cSSam Leffler int recommendation_msg = 0;
69439beb93cSSam Leffler
695780fb4a2SCy Schubert wpa_hexdump_ascii(MSG_MSGDUMP, "TNC: Received IF-TNCCS message",
696780fb4a2SCy Schubert msg, len);
6975b9c547cSRui Paulo buf = dup_binstr(msg, len);
69839beb93cSSam Leffler if (buf == NULL)
69939beb93cSSam Leffler return TNCCS_PROCESS_ERROR;
70039beb93cSSam Leffler
70139beb93cSSam Leffler start = os_strstr(buf, "<TNCCS-Batch ");
70239beb93cSSam Leffler end = os_strstr(buf, "</TNCCS-Batch>");
70339beb93cSSam Leffler if (start == NULL || end == NULL || start > end) {
70439beb93cSSam Leffler os_free(buf);
70539beb93cSSam Leffler return TNCCS_PROCESS_ERROR;
70639beb93cSSam Leffler }
70739beb93cSSam Leffler
70839beb93cSSam Leffler start += 13;
70939beb93cSSam Leffler while (*start == ' ')
71039beb93cSSam Leffler start++;
71139beb93cSSam Leffler *end = '\0';
71239beb93cSSam Leffler
71339beb93cSSam Leffler pos = os_strstr(start, "BatchId=");
71439beb93cSSam Leffler if (pos == NULL) {
71539beb93cSSam Leffler os_free(buf);
71639beb93cSSam Leffler return TNCCS_PROCESS_ERROR;
71739beb93cSSam Leffler }
71839beb93cSSam Leffler
71939beb93cSSam Leffler pos += 8;
72039beb93cSSam Leffler if (*pos == '"')
72139beb93cSSam Leffler pos++;
72239beb93cSSam Leffler batch_id = atoi(pos);
72339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TNC: Received IF-TNCCS BatchId=%u",
72439beb93cSSam Leffler batch_id);
72539beb93cSSam Leffler if (batch_id != tncc->last_batchid + 1) {
72639beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TNC: Unexpected IF-TNCCS BatchId "
72739beb93cSSam Leffler "%u (expected %u)",
72839beb93cSSam Leffler batch_id, tncc->last_batchid + 1);
72939beb93cSSam Leffler os_free(buf);
73039beb93cSSam Leffler return TNCCS_PROCESS_ERROR;
73139beb93cSSam Leffler }
73239beb93cSSam Leffler tncc->last_batchid = batch_id;
73339beb93cSSam Leffler
73439beb93cSSam Leffler while (*pos != '\0' && *pos != '>')
73539beb93cSSam Leffler pos++;
73639beb93cSSam Leffler if (*pos == '\0') {
73739beb93cSSam Leffler os_free(buf);
73839beb93cSSam Leffler return TNCCS_PROCESS_ERROR;
73939beb93cSSam Leffler }
74039beb93cSSam Leffler pos++;
74139beb93cSSam Leffler payload = start;
74239beb93cSSam Leffler
74339beb93cSSam Leffler /*
74439beb93cSSam Leffler * <IMC-IMV-Message>
74539beb93cSSam Leffler * <Type>01234567</Type>
74639beb93cSSam Leffler * <Base64>foo==</Base64>
74739beb93cSSam Leffler * </IMC-IMV-Message>
74839beb93cSSam Leffler */
74939beb93cSSam Leffler
75039beb93cSSam Leffler while (*start) {
75139beb93cSSam Leffler char *endpos;
75239beb93cSSam Leffler unsigned int type;
75339beb93cSSam Leffler
75439beb93cSSam Leffler pos = os_strstr(start, "<IMC-IMV-Message>");
75539beb93cSSam Leffler if (pos == NULL)
75639beb93cSSam Leffler break;
75739beb93cSSam Leffler start = pos + 17;
75839beb93cSSam Leffler end = os_strstr(start, "</IMC-IMV-Message>");
75939beb93cSSam Leffler if (end == NULL)
76039beb93cSSam Leffler break;
76139beb93cSSam Leffler *end = '\0';
76239beb93cSSam Leffler endpos = end;
76339beb93cSSam Leffler end += 18;
76439beb93cSSam Leffler
76539beb93cSSam Leffler if (tncc_get_type(start, &type) < 0) {
76639beb93cSSam Leffler *endpos = '<';
76739beb93cSSam Leffler start = end;
76839beb93cSSam Leffler continue;
76939beb93cSSam Leffler }
77039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TNC: IMC-IMV-Message Type 0x%x", type);
77139beb93cSSam Leffler
77239beb93cSSam Leffler decoded = tncc_get_base64(start, &decoded_len);
77339beb93cSSam Leffler if (decoded == NULL) {
77439beb93cSSam Leffler *endpos = '<';
77539beb93cSSam Leffler start = end;
77639beb93cSSam Leffler continue;
77739beb93cSSam Leffler }
77839beb93cSSam Leffler
77939beb93cSSam Leffler tncc_send_to_imcs(tncc, type, decoded, decoded_len);
78039beb93cSSam Leffler
78139beb93cSSam Leffler os_free(decoded);
78239beb93cSSam Leffler
78339beb93cSSam Leffler start = end;
78439beb93cSSam Leffler }
78539beb93cSSam Leffler
78639beb93cSSam Leffler /*
78739beb93cSSam Leffler * <TNCC-TNCS-Message>
78839beb93cSSam Leffler * <Type>01234567</Type>
78939beb93cSSam Leffler * <XML><TNCCS-Foo type="foo"></TNCCS-Foo></XML>
79039beb93cSSam Leffler * <Base64>foo==</Base64>
79139beb93cSSam Leffler * </TNCC-TNCS-Message>
79239beb93cSSam Leffler */
79339beb93cSSam Leffler
79439beb93cSSam Leffler start = payload;
79539beb93cSSam Leffler while (*start) {
79639beb93cSSam Leffler unsigned int type;
79739beb93cSSam Leffler char *xml, *xmlend, *endpos;
79839beb93cSSam Leffler
79939beb93cSSam Leffler pos = os_strstr(start, "<TNCC-TNCS-Message>");
80039beb93cSSam Leffler if (pos == NULL)
80139beb93cSSam Leffler break;
80239beb93cSSam Leffler start = pos + 19;
80339beb93cSSam Leffler end = os_strstr(start, "</TNCC-TNCS-Message>");
80439beb93cSSam Leffler if (end == NULL)
80539beb93cSSam Leffler break;
80639beb93cSSam Leffler *end = '\0';
80739beb93cSSam Leffler endpos = end;
80839beb93cSSam Leffler end += 20;
80939beb93cSSam Leffler
81039beb93cSSam Leffler if (tncc_get_type(start, &type) < 0) {
81139beb93cSSam Leffler *endpos = '<';
81239beb93cSSam Leffler start = end;
81339beb93cSSam Leffler continue;
81439beb93cSSam Leffler }
81539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TNC: TNCC-TNCS-Message Type 0x%x",
81639beb93cSSam Leffler type);
81739beb93cSSam Leffler
81839beb93cSSam Leffler /* Base64 OR XML */
81939beb93cSSam Leffler decoded = NULL;
82039beb93cSSam Leffler xml = NULL;
82139beb93cSSam Leffler xmlend = NULL;
82239beb93cSSam Leffler pos = os_strstr(start, "<XML>");
82339beb93cSSam Leffler if (pos) {
82439beb93cSSam Leffler pos += 5;
82539beb93cSSam Leffler pos2 = os_strstr(pos, "</XML>");
82639beb93cSSam Leffler if (pos2 == NULL) {
82739beb93cSSam Leffler *endpos = '<';
82839beb93cSSam Leffler start = end;
82939beb93cSSam Leffler continue;
83039beb93cSSam Leffler }
83139beb93cSSam Leffler xmlend = pos2;
83239beb93cSSam Leffler xml = pos;
83339beb93cSSam Leffler } else {
83439beb93cSSam Leffler decoded = tncc_get_base64(start, &decoded_len);
83539beb93cSSam Leffler if (decoded == NULL) {
83639beb93cSSam Leffler *endpos = '<';
83739beb93cSSam Leffler start = end;
83839beb93cSSam Leffler continue;
83939beb93cSSam Leffler }
84039beb93cSSam Leffler }
84139beb93cSSam Leffler
84239beb93cSSam Leffler if (decoded) {
84339beb93cSSam Leffler wpa_hexdump_ascii(MSG_MSGDUMP,
84439beb93cSSam Leffler "TNC: TNCC-TNCS-Message Base64",
84539beb93cSSam Leffler decoded, decoded_len);
84639beb93cSSam Leffler os_free(decoded);
84739beb93cSSam Leffler }
84839beb93cSSam Leffler
84939beb93cSSam Leffler if (xml) {
85039beb93cSSam Leffler wpa_hexdump_ascii(MSG_MSGDUMP,
85139beb93cSSam Leffler "TNC: TNCC-TNCS-Message XML",
85239beb93cSSam Leffler (unsigned char *) xml,
85339beb93cSSam Leffler xmlend - xml);
85439beb93cSSam Leffler }
85539beb93cSSam Leffler
85639beb93cSSam Leffler if (type == TNC_TNCCS_RECOMMENDATION && xml) {
85739beb93cSSam Leffler /*
85839beb93cSSam Leffler * <TNCCS-Recommendation type="allow">
85939beb93cSSam Leffler * </TNCCS-Recommendation>
86039beb93cSSam Leffler */
86139beb93cSSam Leffler *xmlend = '\0';
86239beb93cSSam Leffler res = tncc_get_recommendation(xml);
86339beb93cSSam Leffler *xmlend = '<';
86439beb93cSSam Leffler recommendation_msg = 1;
86539beb93cSSam Leffler }
86639beb93cSSam Leffler
86739beb93cSSam Leffler start = end;
86839beb93cSSam Leffler }
86939beb93cSSam Leffler
87039beb93cSSam Leffler os_free(buf);
87139beb93cSSam Leffler
87239beb93cSSam Leffler if (recommendation_msg)
87339beb93cSSam Leffler tncc_notify_recommendation(tncc, res);
87439beb93cSSam Leffler
87539beb93cSSam Leffler return res;
87639beb93cSSam Leffler }
87739beb93cSSam Leffler
87839beb93cSSam Leffler
87939beb93cSSam Leffler #ifdef CONFIG_NATIVE_WINDOWS
tncc_read_config_reg(struct tncc_data * tncc,HKEY hive)88039beb93cSSam Leffler static int tncc_read_config_reg(struct tncc_data *tncc, HKEY hive)
88139beb93cSSam Leffler {
88239beb93cSSam Leffler HKEY hk, hk2;
88339beb93cSSam Leffler LONG ret;
88439beb93cSSam Leffler DWORD i;
88539beb93cSSam Leffler struct tnc_if_imc *imc, *last;
88639beb93cSSam Leffler int j;
88739beb93cSSam Leffler
88839beb93cSSam Leffler last = tncc->imc;
88939beb93cSSam Leffler while (last && last->next)
89039beb93cSSam Leffler last = last->next;
89139beb93cSSam Leffler
89239beb93cSSam Leffler ret = RegOpenKeyEx(hive, TNC_WINREG_PATH, 0, KEY_ENUMERATE_SUB_KEYS,
89339beb93cSSam Leffler &hk);
89439beb93cSSam Leffler if (ret != ERROR_SUCCESS)
89539beb93cSSam Leffler return 0;
89639beb93cSSam Leffler
89739beb93cSSam Leffler for (i = 0; ; i++) {
89839beb93cSSam Leffler TCHAR name[255], *val;
89939beb93cSSam Leffler DWORD namelen, buflen;
90039beb93cSSam Leffler
90139beb93cSSam Leffler namelen = 255;
90239beb93cSSam Leffler ret = RegEnumKeyEx(hk, i, name, &namelen, NULL, NULL, NULL,
90339beb93cSSam Leffler NULL);
90439beb93cSSam Leffler
90539beb93cSSam Leffler if (ret == ERROR_NO_MORE_ITEMS)
90639beb93cSSam Leffler break;
90739beb93cSSam Leffler
90839beb93cSSam Leffler if (ret != ERROR_SUCCESS) {
90939beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TNC: RegEnumKeyEx failed: 0x%x",
91039beb93cSSam Leffler (unsigned int) ret);
91139beb93cSSam Leffler break;
91239beb93cSSam Leffler }
91339beb93cSSam Leffler
91439beb93cSSam Leffler if (namelen >= 255)
91539beb93cSSam Leffler namelen = 255 - 1;
91639beb93cSSam Leffler name[namelen] = '\0';
91739beb93cSSam Leffler
91839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TNC: IMC '" TSTR "'", name);
91939beb93cSSam Leffler
92039beb93cSSam Leffler ret = RegOpenKeyEx(hk, name, 0, KEY_QUERY_VALUE, &hk2);
92139beb93cSSam Leffler if (ret != ERROR_SUCCESS) {
92239beb93cSSam Leffler wpa_printf(MSG_DEBUG, "Could not open IMC key '" TSTR
92339beb93cSSam Leffler "'", name);
92439beb93cSSam Leffler continue;
92539beb93cSSam Leffler }
92639beb93cSSam Leffler
92739beb93cSSam Leffler ret = RegQueryValueEx(hk2, TEXT("Path"), NULL, NULL, NULL,
92839beb93cSSam Leffler &buflen);
92939beb93cSSam Leffler if (ret != ERROR_SUCCESS) {
93039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TNC: Could not read Path from "
93139beb93cSSam Leffler "IMC key '" TSTR "'", name);
93239beb93cSSam Leffler RegCloseKey(hk2);
93339beb93cSSam Leffler continue;
93439beb93cSSam Leffler }
93539beb93cSSam Leffler
93639beb93cSSam Leffler val = os_malloc(buflen);
93739beb93cSSam Leffler if (val == NULL) {
93839beb93cSSam Leffler RegCloseKey(hk2);
93939beb93cSSam Leffler continue;
94039beb93cSSam Leffler }
94139beb93cSSam Leffler
94239beb93cSSam Leffler ret = RegQueryValueEx(hk2, TEXT("Path"), NULL, NULL,
94339beb93cSSam Leffler (LPBYTE) val, &buflen);
94439beb93cSSam Leffler if (ret != ERROR_SUCCESS) {
94539beb93cSSam Leffler os_free(val);
94639beb93cSSam Leffler RegCloseKey(hk2);
94739beb93cSSam Leffler continue;
94839beb93cSSam Leffler }
94939beb93cSSam Leffler
95039beb93cSSam Leffler RegCloseKey(hk2);
95139beb93cSSam Leffler
95239beb93cSSam Leffler wpa_unicode2ascii_inplace(val);
95339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TNC: IMC Path '%s'", (char *) val);
95439beb93cSSam Leffler
95539beb93cSSam Leffler for (j = 0; j < TNC_MAX_IMC_ID; j++) {
95639beb93cSSam Leffler if (tnc_imc[j] == NULL)
95739beb93cSSam Leffler break;
95839beb93cSSam Leffler }
95939beb93cSSam Leffler if (j >= TNC_MAX_IMC_ID) {
96039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TNC: Too many IMCs");
96139beb93cSSam Leffler os_free(val);
96239beb93cSSam Leffler continue;
96339beb93cSSam Leffler }
96439beb93cSSam Leffler
96539beb93cSSam Leffler imc = os_zalloc(sizeof(*imc));
96639beb93cSSam Leffler if (imc == NULL) {
96739beb93cSSam Leffler os_free(val);
96839beb93cSSam Leffler break;
96939beb93cSSam Leffler }
97039beb93cSSam Leffler
97139beb93cSSam Leffler imc->imcID = j;
97239beb93cSSam Leffler
97339beb93cSSam Leffler wpa_unicode2ascii_inplace(name);
97439beb93cSSam Leffler imc->name = os_strdup((char *) name);
97539beb93cSSam Leffler imc->path = os_strdup((char *) val);
97639beb93cSSam Leffler
97739beb93cSSam Leffler os_free(val);
97839beb93cSSam Leffler
97939beb93cSSam Leffler if (last == NULL)
98039beb93cSSam Leffler tncc->imc = imc;
98139beb93cSSam Leffler else
98239beb93cSSam Leffler last->next = imc;
98339beb93cSSam Leffler last = imc;
98439beb93cSSam Leffler
98539beb93cSSam Leffler tnc_imc[imc->imcID] = imc;
98639beb93cSSam Leffler }
98739beb93cSSam Leffler
98839beb93cSSam Leffler RegCloseKey(hk);
98939beb93cSSam Leffler
99039beb93cSSam Leffler return 0;
99139beb93cSSam Leffler }
99239beb93cSSam Leffler
99339beb93cSSam Leffler
tncc_read_config(struct tncc_data * tncc)99439beb93cSSam Leffler static int tncc_read_config(struct tncc_data *tncc)
99539beb93cSSam Leffler {
99639beb93cSSam Leffler if (tncc_read_config_reg(tncc, HKEY_LOCAL_MACHINE) < 0 ||
99739beb93cSSam Leffler tncc_read_config_reg(tncc, HKEY_CURRENT_USER) < 0)
99839beb93cSSam Leffler return -1;
99939beb93cSSam Leffler return 0;
100039beb93cSSam Leffler }
100139beb93cSSam Leffler
100239beb93cSSam Leffler #else /* CONFIG_NATIVE_WINDOWS */
100339beb93cSSam Leffler
tncc_parse_imc(char * start,char * end,int * error)100439beb93cSSam Leffler static struct tnc_if_imc * tncc_parse_imc(char *start, char *end, int *error)
100539beb93cSSam Leffler {
100639beb93cSSam Leffler struct tnc_if_imc *imc;
100739beb93cSSam Leffler char *pos, *pos2;
100839beb93cSSam Leffler int i;
100939beb93cSSam Leffler
101039beb93cSSam Leffler for (i = 0; i < TNC_MAX_IMC_ID; i++) {
101139beb93cSSam Leffler if (tnc_imc[i] == NULL)
101239beb93cSSam Leffler break;
101339beb93cSSam Leffler }
101439beb93cSSam Leffler if (i >= TNC_MAX_IMC_ID) {
101539beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TNC: Too many IMCs");
101639beb93cSSam Leffler return NULL;
101739beb93cSSam Leffler }
101839beb93cSSam Leffler
101939beb93cSSam Leffler imc = os_zalloc(sizeof(*imc));
102039beb93cSSam Leffler if (imc == NULL) {
102139beb93cSSam Leffler *error = 1;
102239beb93cSSam Leffler return NULL;
102339beb93cSSam Leffler }
102439beb93cSSam Leffler
102539beb93cSSam Leffler imc->imcID = i;
102639beb93cSSam Leffler
102739beb93cSSam Leffler pos = start;
102839beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TNC: Configured IMC: %s", pos);
102939beb93cSSam Leffler if (pos + 1 >= end || *pos != '"') {
103039beb93cSSam Leffler wpa_printf(MSG_ERROR, "TNC: Ignoring invalid IMC line '%s' "
103139beb93cSSam Leffler "(no starting quotation mark)", start);
103239beb93cSSam Leffler os_free(imc);
103339beb93cSSam Leffler return NULL;
103439beb93cSSam Leffler }
103539beb93cSSam Leffler
103639beb93cSSam Leffler pos++;
103739beb93cSSam Leffler pos2 = pos;
103839beb93cSSam Leffler while (pos2 < end && *pos2 != '"')
103939beb93cSSam Leffler pos2++;
104039beb93cSSam Leffler if (pos2 >= end) {
104139beb93cSSam Leffler wpa_printf(MSG_ERROR, "TNC: Ignoring invalid IMC line '%s' "
104239beb93cSSam Leffler "(no ending quotation mark)", start);
104339beb93cSSam Leffler os_free(imc);
104439beb93cSSam Leffler return NULL;
104539beb93cSSam Leffler }
104639beb93cSSam Leffler *pos2 = '\0';
104739beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TNC: Name: '%s'", pos);
104839beb93cSSam Leffler imc->name = os_strdup(pos);
104939beb93cSSam Leffler
105039beb93cSSam Leffler pos = pos2 + 1;
105139beb93cSSam Leffler if (pos >= end || *pos != ' ') {
105239beb93cSSam Leffler wpa_printf(MSG_ERROR, "TNC: Ignoring invalid IMC line '%s' "
105339beb93cSSam Leffler "(no space after name)", start);
10543157ba21SRui Paulo os_free(imc->name);
105539beb93cSSam Leffler os_free(imc);
105639beb93cSSam Leffler return NULL;
105739beb93cSSam Leffler }
105839beb93cSSam Leffler
105939beb93cSSam Leffler pos++;
106039beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TNC: IMC file: '%s'", pos);
106139beb93cSSam Leffler imc->path = os_strdup(pos);
106239beb93cSSam Leffler tnc_imc[imc->imcID] = imc;
106339beb93cSSam Leffler
106439beb93cSSam Leffler return imc;
106539beb93cSSam Leffler }
106639beb93cSSam Leffler
106739beb93cSSam Leffler
tncc_read_config(struct tncc_data * tncc)106839beb93cSSam Leffler static int tncc_read_config(struct tncc_data *tncc)
106939beb93cSSam Leffler {
107039beb93cSSam Leffler char *config, *end, *pos, *line_end;
107139beb93cSSam Leffler size_t config_len;
107239beb93cSSam Leffler struct tnc_if_imc *imc, *last;
107339beb93cSSam Leffler
107439beb93cSSam Leffler last = NULL;
107539beb93cSSam Leffler
107639beb93cSSam Leffler config = os_readfile(TNC_CONFIG_FILE, &config_len);
107739beb93cSSam Leffler if (config == NULL) {
107839beb93cSSam Leffler wpa_printf(MSG_ERROR, "TNC: Could not open TNC configuration "
107939beb93cSSam Leffler "file '%s'", TNC_CONFIG_FILE);
108039beb93cSSam Leffler return -1;
108139beb93cSSam Leffler }
108239beb93cSSam Leffler
108339beb93cSSam Leffler end = config + config_len;
108439beb93cSSam Leffler for (pos = config; pos < end; pos = line_end + 1) {
108539beb93cSSam Leffler line_end = pos;
108639beb93cSSam Leffler while (*line_end != '\n' && *line_end != '\r' &&
108739beb93cSSam Leffler line_end < end)
108839beb93cSSam Leffler line_end++;
108939beb93cSSam Leffler *line_end = '\0';
109039beb93cSSam Leffler
109139beb93cSSam Leffler if (os_strncmp(pos, "IMC ", 4) == 0) {
109239beb93cSSam Leffler int error = 0;
109339beb93cSSam Leffler
109439beb93cSSam Leffler imc = tncc_parse_imc(pos + 4, line_end, &error);
10955b9c547cSRui Paulo if (error) {
10965b9c547cSRui Paulo os_free(config);
109739beb93cSSam Leffler return -1;
10985b9c547cSRui Paulo }
109939beb93cSSam Leffler if (imc) {
110039beb93cSSam Leffler if (last == NULL)
110139beb93cSSam Leffler tncc->imc = imc;
110239beb93cSSam Leffler else
110339beb93cSSam Leffler last->next = imc;
110439beb93cSSam Leffler last = imc;
110539beb93cSSam Leffler }
110639beb93cSSam Leffler }
110739beb93cSSam Leffler }
110839beb93cSSam Leffler
110939beb93cSSam Leffler os_free(config);
111039beb93cSSam Leffler
111139beb93cSSam Leffler return 0;
111239beb93cSSam Leffler }
111339beb93cSSam Leffler
111439beb93cSSam Leffler #endif /* CONFIG_NATIVE_WINDOWS */
111539beb93cSSam Leffler
111639beb93cSSam Leffler
tncc_init(void)111739beb93cSSam Leffler struct tncc_data * tncc_init(void)
111839beb93cSSam Leffler {
111939beb93cSSam Leffler struct tncc_data *tncc;
112039beb93cSSam Leffler struct tnc_if_imc *imc;
112139beb93cSSam Leffler
112239beb93cSSam Leffler tncc = os_zalloc(sizeof(*tncc));
112339beb93cSSam Leffler if (tncc == NULL)
112439beb93cSSam Leffler return NULL;
112539beb93cSSam Leffler
112639beb93cSSam Leffler /* TODO:
112739beb93cSSam Leffler * move loading and Initialize() to a location that is not
112839beb93cSSam Leffler * re-initialized for every EAP-TNC session (?)
112939beb93cSSam Leffler */
113039beb93cSSam Leffler
113139beb93cSSam Leffler if (tncc_read_config(tncc) < 0) {
113239beb93cSSam Leffler wpa_printf(MSG_ERROR, "TNC: Failed to read TNC configuration");
113339beb93cSSam Leffler goto failed;
113439beb93cSSam Leffler }
113539beb93cSSam Leffler
113639beb93cSSam Leffler for (imc = tncc->imc; imc; imc = imc->next) {
113739beb93cSSam Leffler if (tncc_load_imc(imc)) {
113839beb93cSSam Leffler wpa_printf(MSG_ERROR, "TNC: Failed to load IMC '%s'",
113939beb93cSSam Leffler imc->name);
114039beb93cSSam Leffler goto failed;
114139beb93cSSam Leffler }
114239beb93cSSam Leffler }
114339beb93cSSam Leffler
114439beb93cSSam Leffler return tncc;
114539beb93cSSam Leffler
114639beb93cSSam Leffler failed:
114739beb93cSSam Leffler tncc_deinit(tncc);
114839beb93cSSam Leffler return NULL;
114939beb93cSSam Leffler }
115039beb93cSSam Leffler
115139beb93cSSam Leffler
tncc_deinit(struct tncc_data * tncc)115239beb93cSSam Leffler void tncc_deinit(struct tncc_data *tncc)
115339beb93cSSam Leffler {
115439beb93cSSam Leffler struct tnc_if_imc *imc, *prev;
115539beb93cSSam Leffler
115639beb93cSSam Leffler imc = tncc->imc;
115739beb93cSSam Leffler while (imc) {
115839beb93cSSam Leffler tncc_unload_imc(imc);
115939beb93cSSam Leffler
116039beb93cSSam Leffler prev = imc;
116139beb93cSSam Leffler imc = imc->next;
116239beb93cSSam Leffler os_free(prev);
116339beb93cSSam Leffler }
116439beb93cSSam Leffler
116539beb93cSSam Leffler os_free(tncc);
116639beb93cSSam Leffler }
116739beb93cSSam Leffler
116839beb93cSSam Leffler
tncc_build_soh(int ver)116939beb93cSSam Leffler static struct wpabuf * tncc_build_soh(int ver)
117039beb93cSSam Leffler {
117139beb93cSSam Leffler struct wpabuf *buf;
117239beb93cSSam Leffler u8 *tlv_len, *tlv_len2, *outer_len, *inner_len, *ssoh_len, *end;
117339beb93cSSam Leffler u8 correlation_id[24];
117439beb93cSSam Leffler /* TODO: get correct name */
117539beb93cSSam Leffler char *machinename = "wpa_supplicant@w1.fi";
117639beb93cSSam Leffler
117739beb93cSSam Leffler if (os_get_random(correlation_id, sizeof(correlation_id)))
117839beb93cSSam Leffler return NULL;
117939beb93cSSam Leffler wpa_hexdump(MSG_DEBUG, "TNC: SoH Correlation ID",
118039beb93cSSam Leffler correlation_id, sizeof(correlation_id));
118139beb93cSSam Leffler
118239beb93cSSam Leffler buf = wpabuf_alloc(200);
118339beb93cSSam Leffler if (buf == NULL)
118439beb93cSSam Leffler return NULL;
118539beb93cSSam Leffler
118639beb93cSSam Leffler /* Vendor-Specific TLV (Microsoft) - SoH */
118739beb93cSSam Leffler wpabuf_put_be16(buf, EAP_TLV_VENDOR_SPECIFIC_TLV); /* TLV Type */
118839beb93cSSam Leffler tlv_len = wpabuf_put(buf, 2); /* Length */
118939beb93cSSam Leffler wpabuf_put_be32(buf, EAP_VENDOR_MICROSOFT); /* Vendor_Id */
119039beb93cSSam Leffler wpabuf_put_be16(buf, 0x01); /* TLV Type - SoH TLV */
119139beb93cSSam Leffler tlv_len2 = wpabuf_put(buf, 2); /* Length */
119239beb93cSSam Leffler
119339beb93cSSam Leffler /* SoH Header */
119439beb93cSSam Leffler wpabuf_put_be16(buf, EAP_TLV_VENDOR_SPECIFIC_TLV); /* Outer Type */
119539beb93cSSam Leffler outer_len = wpabuf_put(buf, 2);
119639beb93cSSam Leffler wpabuf_put_be32(buf, EAP_VENDOR_MICROSOFT); /* IANA SMI Code */
119739beb93cSSam Leffler wpabuf_put_be16(buf, ver); /* Inner Type */
119839beb93cSSam Leffler inner_len = wpabuf_put(buf, 2);
119939beb93cSSam Leffler
120039beb93cSSam Leffler if (ver == 2) {
120139beb93cSSam Leffler /* SoH Mode Sub-Header */
120239beb93cSSam Leffler /* Outer Type */
120339beb93cSSam Leffler wpabuf_put_be16(buf, EAP_TLV_VENDOR_SPECIFIC_TLV);
120439beb93cSSam Leffler wpabuf_put_be16(buf, 4 + 24 + 1 + 1); /* Length */
120539beb93cSSam Leffler wpabuf_put_be32(buf, EAP_VENDOR_MICROSOFT); /* IANA SMI Code */
120639beb93cSSam Leffler /* Value: */
120739beb93cSSam Leffler wpabuf_put_data(buf, correlation_id, sizeof(correlation_id));
120839beb93cSSam Leffler wpabuf_put_u8(buf, 0x01); /* Intent Flag - Request */
120939beb93cSSam Leffler wpabuf_put_u8(buf, 0x00); /* Content-Type Flag */
121039beb93cSSam Leffler }
121139beb93cSSam Leffler
121239beb93cSSam Leffler /* SSoH TLV */
121339beb93cSSam Leffler /* System-Health-Id */
121439beb93cSSam Leffler wpabuf_put_be16(buf, 0x0002); /* Type */
121539beb93cSSam Leffler wpabuf_put_be16(buf, 4); /* Length */
121639beb93cSSam Leffler wpabuf_put_be32(buf, 79616);
121739beb93cSSam Leffler /* Vendor-Specific Attribute */
121839beb93cSSam Leffler wpabuf_put_be16(buf, EAP_TLV_VENDOR_SPECIFIC_TLV);
121939beb93cSSam Leffler ssoh_len = wpabuf_put(buf, 2);
122039beb93cSSam Leffler wpabuf_put_be32(buf, EAP_VENDOR_MICROSOFT); /* IANA SMI Code */
122139beb93cSSam Leffler
122239beb93cSSam Leffler /* MS-Packet-Info */
122339beb93cSSam Leffler wpabuf_put_u8(buf, SSOH_MS_PACKET_INFO);
122439beb93cSSam Leffler /* Note: IF-TNCCS-SOH v1.0 r8 claims this field to be:
122539beb93cSSam Leffler * Reserved(4 bits) r(1 bit) Vers(3 bits), but Windows XP
122639beb93cSSam Leffler * SP3 seems to be sending 0x11 for SSoH, i.e., r(request/response) bit
122739beb93cSSam Leffler * would not be in the specified location.
122839beb93cSSam Leffler * [MS-SOH] 4.0.2: Reserved(3 bits) r(1 bit) Vers(4 bits)
122939beb93cSSam Leffler */
123039beb93cSSam Leffler wpabuf_put_u8(buf, 0x11); /* r=request, vers=1 */
123139beb93cSSam Leffler
123239beb93cSSam Leffler /* MS-Machine-Inventory */
123339beb93cSSam Leffler /* TODO: get correct values; 0 = not applicable for OS */
123439beb93cSSam Leffler wpabuf_put_u8(buf, SSOH_MS_MACHINE_INVENTORY);
123539beb93cSSam Leffler wpabuf_put_be32(buf, 0); /* osVersionMajor */
123639beb93cSSam Leffler wpabuf_put_be32(buf, 0); /* osVersionMinor */
123739beb93cSSam Leffler wpabuf_put_be32(buf, 0); /* osVersionBuild */
123839beb93cSSam Leffler wpabuf_put_be16(buf, 0); /* spVersionMajor */
123939beb93cSSam Leffler wpabuf_put_be16(buf, 0); /* spVersionMinor */
124039beb93cSSam Leffler wpabuf_put_be16(buf, 0); /* procArch */
124139beb93cSSam Leffler
124239beb93cSSam Leffler /* MS-MachineName */
124339beb93cSSam Leffler wpabuf_put_u8(buf, SSOH_MS_MACHINENAME);
124439beb93cSSam Leffler wpabuf_put_be16(buf, os_strlen(machinename) + 1);
124539beb93cSSam Leffler wpabuf_put_data(buf, machinename, os_strlen(machinename) + 1);
124639beb93cSSam Leffler
124739beb93cSSam Leffler /* MS-CorrelationId */
124839beb93cSSam Leffler wpabuf_put_u8(buf, SSOH_MS_CORRELATIONID);
124939beb93cSSam Leffler wpabuf_put_data(buf, correlation_id, sizeof(correlation_id));
125039beb93cSSam Leffler
125139beb93cSSam Leffler /* MS-Quarantine-State */
125239beb93cSSam Leffler wpabuf_put_u8(buf, SSOH_MS_QUARANTINE_STATE);
125339beb93cSSam Leffler wpabuf_put_be16(buf, 1); /* Flags: ExtState=0, f=0, qState=1 */
125439beb93cSSam Leffler wpabuf_put_be32(buf, 0xffffffff); /* ProbTime (hi) */
125539beb93cSSam Leffler wpabuf_put_be32(buf, 0xffffffff); /* ProbTime (lo) */
125639beb93cSSam Leffler wpabuf_put_be16(buf, 1); /* urlLenInBytes */
125739beb93cSSam Leffler wpabuf_put_u8(buf, 0); /* null termination for the url */
125839beb93cSSam Leffler
125939beb93cSSam Leffler /* MS-Machine-Inventory-Ex */
126039beb93cSSam Leffler wpabuf_put_u8(buf, SSOH_MS_MACHINE_INVENTORY_EX);
126139beb93cSSam Leffler wpabuf_put_be32(buf, 0); /* Reserved
126239beb93cSSam Leffler * (note: Windows XP SP3 uses 0xdecafbad) */
126339beb93cSSam Leffler wpabuf_put_u8(buf, 1); /* ProductType: Client */
126439beb93cSSam Leffler
126539beb93cSSam Leffler /* Update SSoH Length */
126639beb93cSSam Leffler end = wpabuf_put(buf, 0);
126739beb93cSSam Leffler WPA_PUT_BE16(ssoh_len, end - ssoh_len - 2);
126839beb93cSSam Leffler
126939beb93cSSam Leffler /* TODO: SoHReportEntry TLV (zero or more) */
127039beb93cSSam Leffler
127139beb93cSSam Leffler /* Update length fields */
127239beb93cSSam Leffler end = wpabuf_put(buf, 0);
127339beb93cSSam Leffler WPA_PUT_BE16(tlv_len, end - tlv_len - 2);
127439beb93cSSam Leffler WPA_PUT_BE16(tlv_len2, end - tlv_len2 - 2);
127539beb93cSSam Leffler WPA_PUT_BE16(outer_len, end - outer_len - 2);
127639beb93cSSam Leffler WPA_PUT_BE16(inner_len, end - inner_len - 2);
127739beb93cSSam Leffler
127839beb93cSSam Leffler return buf;
127939beb93cSSam Leffler }
128039beb93cSSam Leffler
128139beb93cSSam Leffler
tncc_process_soh_request(int ver,const u8 * data,size_t len)128239beb93cSSam Leffler struct wpabuf * tncc_process_soh_request(int ver, const u8 *data, size_t len)
128339beb93cSSam Leffler {
128439beb93cSSam Leffler const u8 *pos;
128539beb93cSSam Leffler
128639beb93cSSam Leffler wpa_hexdump(MSG_DEBUG, "TNC: SoH Request", data, len);
128739beb93cSSam Leffler
128839beb93cSSam Leffler if (len < 12)
128939beb93cSSam Leffler return NULL;
129039beb93cSSam Leffler
129139beb93cSSam Leffler /* SoH Request */
129239beb93cSSam Leffler pos = data;
129339beb93cSSam Leffler
129439beb93cSSam Leffler /* TLV Type */
129539beb93cSSam Leffler if (WPA_GET_BE16(pos) != EAP_TLV_VENDOR_SPECIFIC_TLV)
129639beb93cSSam Leffler return NULL;
129739beb93cSSam Leffler pos += 2;
129839beb93cSSam Leffler
129939beb93cSSam Leffler /* Length */
130039beb93cSSam Leffler if (WPA_GET_BE16(pos) < 8)
130139beb93cSSam Leffler return NULL;
130239beb93cSSam Leffler pos += 2;
130339beb93cSSam Leffler
130439beb93cSSam Leffler /* Vendor_Id */
130539beb93cSSam Leffler if (WPA_GET_BE32(pos) != EAP_VENDOR_MICROSOFT)
130639beb93cSSam Leffler return NULL;
130739beb93cSSam Leffler pos += 4;
130839beb93cSSam Leffler
130939beb93cSSam Leffler /* TLV Type */
131039beb93cSSam Leffler if (WPA_GET_BE16(pos) != 0x02 /* SoH request TLV */)
131139beb93cSSam Leffler return NULL;
131239beb93cSSam Leffler
131339beb93cSSam Leffler wpa_printf(MSG_DEBUG, "TNC: SoH Request TLV received");
131439beb93cSSam Leffler
131539beb93cSSam Leffler return tncc_build_soh(2);
131639beb93cSSam Leffler }
1317