$search
00001 /* 00002 * EAP-TNC - TNCC (IF-IMC and IF-TNCCS) 00003 * Copyright (c) 2007, Jouni Malinen <j@w1.fi> 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License version 2 as 00007 * published by the Free Software Foundation. 00008 * 00009 * Alternatively, this software may be distributed under the terms of BSD 00010 * license. 00011 * 00012 * See README and COPYING for more details. 00013 */ 00014 00015 #include "includes.h" 00016 #ifndef CONFIG_NATIVE_WINDOWS 00017 #include <dlfcn.h> 00018 #endif /* CONFIG_NATIVE_WINDOWS */ 00019 00020 #include "common.h" 00021 #include "base64.h" 00022 #include "tncc.h" 00023 #include "eap_common/eap_tlv_common.h" 00024 #include "eap_common/eap_defs.h" 00025 00026 00027 #ifdef UNICODE 00028 #define TSTR "%S" 00029 #else /* UNICODE */ 00030 #define TSTR "%s" 00031 #endif /* UNICODE */ 00032 00033 00034 #define TNC_CONFIG_FILE "/etc/tnc_config" 00035 #define TNC_WINREG_PATH TEXT("SOFTWARE\\Trusted Computing Group\\TNC\\IMCs") 00036 #define IF_TNCCS_START \ 00037 "<?xml version=\"1.0\"?>\n" \ 00038 "<TNCCS-Batch BatchId=\"%d\" Recipient=\"TNCS\" " \ 00039 "xmlns=\"http://www.trustedcomputinggroup.org/IWG/TNC/1_0/IF_TNCCS#\" " \ 00040 "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " \ 00041 "xsi:schemaLocation=\"http://www.trustedcomputinggroup.org/IWG/TNC/1_0/" \ 00042 "IF_TNCCS# https://www.trustedcomputinggroup.org/XML/SCHEMA/TNCCS_1.0.xsd\">\n" 00043 #define IF_TNCCS_END "\n</TNCCS-Batch>" 00044 00045 /* TNC IF-IMC */ 00046 00047 typedef unsigned long TNC_UInt32; 00048 typedef unsigned char *TNC_BufferReference; 00049 00050 typedef TNC_UInt32 TNC_IMCID; 00051 typedef TNC_UInt32 TNC_ConnectionID; 00052 typedef TNC_UInt32 TNC_ConnectionState; 00053 typedef TNC_UInt32 TNC_RetryReason; 00054 typedef TNC_UInt32 TNC_MessageType; 00055 typedef TNC_MessageType *TNC_MessageTypeList; 00056 typedef TNC_UInt32 TNC_VendorID; 00057 typedef TNC_UInt32 TNC_MessageSubtype; 00058 typedef TNC_UInt32 TNC_Version; 00059 typedef TNC_UInt32 TNC_Result; 00060 00061 typedef TNC_Result (*TNC_TNCC_BindFunctionPointer)( 00062 TNC_IMCID imcID, 00063 char *functionName, 00064 void **pOutfunctionPointer); 00065 00066 #define TNC_RESULT_SUCCESS 0 00067 #define TNC_RESULT_NOT_INITIALIZED 1 00068 #define TNC_RESULT_ALREADY_INITIALIZED 2 00069 #define TNC_RESULT_NO_COMMON_VERSION 3 00070 #define TNC_RESULT_CANT_RETRY 4 00071 #define TNC_RESULT_WONT_RETRY 5 00072 #define TNC_RESULT_INVALID_PARAMETER 6 00073 #define TNC_RESULT_CANT_RESPOND 7 00074 #define TNC_RESULT_ILLEGAL_OPERATION 8 00075 #define TNC_RESULT_OTHER 9 00076 #define TNC_RESULT_FATAL 10 00077 00078 #define TNC_CONNECTION_STATE_CREATE 0 00079 #define TNC_CONNECTION_STATE_HANDSHAKE 1 00080 #define TNC_CONNECTION_STATE_ACCESS_ALLOWED 2 00081 #define TNC_CONNECTION_STATE_ACCESS_ISOLATED 3 00082 #define TNC_CONNECTION_STATE_ACCESS_NONE 4 00083 #define TNC_CONNECTION_STATE_DELETE 5 00084 00085 #define TNC_IFIMC_VERSION_1 1 00086 00087 #define TNC_VENDORID_ANY ((TNC_VendorID) 0xffffff) 00088 #define TNC_SUBTYPE_ANY ((TNC_MessageSubtype) 0xff) 00089 00090 /* TNCC-TNCS Message Types */ 00091 #define TNC_TNCCS_RECOMMENDATION 0x00000001 00092 #define TNC_TNCCS_ERROR 0x00000002 00093 #define TNC_TNCCS_PREFERREDLANGUAGE 0x00000003 00094 #define TNC_TNCCS_REASONSTRINGS 0x00000004 00095 00096 00097 /* IF-TNCCS-SOH - SSoH and SSoHR Attributes */ 00098 enum { 00099 SSOH_MS_MACHINE_INVENTORY = 1, 00100 SSOH_MS_QUARANTINE_STATE = 2, 00101 SSOH_MS_PACKET_INFO = 3, 00102 SSOH_MS_SYSTEMGENERATED_IDS = 4, 00103 SSOH_MS_MACHINENAME = 5, 00104 SSOH_MS_CORRELATIONID = 6, 00105 SSOH_MS_INSTALLED_SHVS = 7, 00106 SSOH_MS_MACHINE_INVENTORY_EX = 8 00107 }; 00108 00109 struct tnc_if_imc { 00110 struct tnc_if_imc *next; 00111 char *name; 00112 char *path; 00113 void *dlhandle; /* from dlopen() */ 00114 TNC_IMCID imcID; 00115 TNC_ConnectionID connectionID; 00116 TNC_MessageTypeList supported_types; 00117 size_t num_supported_types; 00118 u8 *imc_send; 00119 size_t imc_send_len; 00120 00121 /* Functions implemented by IMCs (with TNC_IMC_ prefix) */ 00122 TNC_Result (*Initialize)( 00123 TNC_IMCID imcID, 00124 TNC_Version minVersion, 00125 TNC_Version maxVersion, 00126 TNC_Version *pOutActualVersion); 00127 TNC_Result (*NotifyConnectionChange)( 00128 TNC_IMCID imcID, 00129 TNC_ConnectionID connectionID, 00130 TNC_ConnectionState newState); 00131 TNC_Result (*BeginHandshake)( 00132 TNC_IMCID imcID, 00133 TNC_ConnectionID connectionID); 00134 TNC_Result (*ReceiveMessage)( 00135 TNC_IMCID imcID, 00136 TNC_ConnectionID connectionID, 00137 TNC_BufferReference messageBuffer, 00138 TNC_UInt32 messageLength, 00139 TNC_MessageType messageType); 00140 TNC_Result (*BatchEnding)( 00141 TNC_IMCID imcID, 00142 TNC_ConnectionID connectionID); 00143 TNC_Result (*Terminate)(TNC_IMCID imcID); 00144 TNC_Result (*ProvideBindFunction)( 00145 TNC_IMCID imcID, 00146 TNC_TNCC_BindFunctionPointer bindFunction); 00147 }; 00148 00149 struct tncc_data { 00150 struct tnc_if_imc *imc; 00151 unsigned int last_batchid; 00152 }; 00153 00154 #define TNC_MAX_IMC_ID 10 00155 static struct tnc_if_imc *tnc_imc[TNC_MAX_IMC_ID] = { NULL }; 00156 00157 00158 /* TNCC functions that IMCs can call */ 00159 00160 TNC_Result TNC_TNCC_ReportMessageTypes( 00161 TNC_IMCID imcID, 00162 TNC_MessageTypeList supportedTypes, 00163 TNC_UInt32 typeCount) 00164 { 00165 TNC_UInt32 i; 00166 struct tnc_if_imc *imc; 00167 00168 wpa_printf(MSG_DEBUG, "TNC: TNC_TNCC_ReportMessageTypes(imcID=%lu " 00169 "typeCount=%lu)", 00170 (unsigned long) imcID, (unsigned long) typeCount); 00171 00172 for (i = 0; i < typeCount; i++) { 00173 wpa_printf(MSG_DEBUG, "TNC: supportedTypes[%lu] = %lu", 00174 i, supportedTypes[i]); 00175 } 00176 00177 if (imcID >= TNC_MAX_IMC_ID || tnc_imc[imcID] == NULL) 00178 return TNC_RESULT_INVALID_PARAMETER; 00179 00180 imc = tnc_imc[imcID]; 00181 os_free(imc->supported_types); 00182 imc->supported_types = 00183 os_malloc(typeCount * sizeof(TNC_MessageTypeList)); 00184 if (imc->supported_types == NULL) 00185 return TNC_RESULT_FATAL; 00186 os_memcpy(imc->supported_types, supportedTypes, 00187 typeCount * sizeof(TNC_MessageTypeList)); 00188 imc->num_supported_types = typeCount; 00189 00190 return TNC_RESULT_SUCCESS; 00191 } 00192 00193 00194 TNC_Result TNC_TNCC_SendMessage( 00195 TNC_IMCID imcID, 00196 TNC_ConnectionID connectionID, 00197 TNC_BufferReference message, 00198 TNC_UInt32 messageLength, 00199 TNC_MessageType messageType) 00200 { 00201 struct tnc_if_imc *imc; 00202 unsigned char *b64; 00203 size_t b64len; 00204 00205 wpa_printf(MSG_DEBUG, "TNC: TNC_TNCC_SendMessage(imcID=%lu " 00206 "connectionID=%lu messageType=%lu)", 00207 imcID, connectionID, messageType); 00208 wpa_hexdump_ascii(MSG_DEBUG, "TNC: TNC_TNCC_SendMessage", 00209 message, messageLength); 00210 00211 if (imcID >= TNC_MAX_IMC_ID || tnc_imc[imcID] == NULL) 00212 return TNC_RESULT_INVALID_PARAMETER; 00213 00214 b64 = base64_encode(message, messageLength, &b64len); 00215 if (b64 == NULL) 00216 return TNC_RESULT_FATAL; 00217 00218 imc = tnc_imc[imcID]; 00219 os_free(imc->imc_send); 00220 imc->imc_send_len = 0; 00221 imc->imc_send = os_zalloc(b64len + 100); 00222 if (imc->imc_send == NULL) { 00223 os_free(b64); 00224 return TNC_RESULT_OTHER; 00225 } 00226 00227 imc->imc_send_len = 00228 os_snprintf((char *) imc->imc_send, b64len + 100, 00229 "<IMC-IMV-Message><Type>%08X</Type>" 00230 "<Base64>%s</Base64></IMC-IMV-Message>", 00231 (unsigned int) messageType, b64); 00232 00233 os_free(b64); 00234 00235 return TNC_RESULT_SUCCESS; 00236 } 00237 00238 00239 TNC_Result TNC_TNCC_RequestHandshakeRetry( 00240 TNC_IMCID imcID, 00241 TNC_ConnectionID connectionID, 00242 TNC_RetryReason reason) 00243 { 00244 wpa_printf(MSG_DEBUG, "TNC: TNC_TNCC_RequestHandshakeRetry"); 00245 00246 if (imcID >= TNC_MAX_IMC_ID || tnc_imc[imcID] == NULL) 00247 return TNC_RESULT_INVALID_PARAMETER; 00248 00249 /* 00250 * TODO: trigger a call to eapol_sm_request_reauth(). This would 00251 * require that the IMC continues to be loaded in memory afer 00252 * authentication.. 00253 */ 00254 00255 return TNC_RESULT_SUCCESS; 00256 } 00257 00258 00259 TNC_Result TNC_9048_LogMessage(TNC_IMCID imcID, TNC_UInt32 severity, 00260 const char *message) 00261 { 00262 wpa_printf(MSG_DEBUG, "TNC: TNC_9048_LogMessage(imcID=%lu " 00263 "severity==%lu message='%s')", 00264 imcID, severity, message); 00265 return TNC_RESULT_SUCCESS; 00266 } 00267 00268 00269 TNC_Result TNC_9048_UserMessage(TNC_IMCID imcID, TNC_ConnectionID connectionID, 00270 const char *message) 00271 { 00272 wpa_printf(MSG_DEBUG, "TNC: TNC_9048_UserMessage(imcID=%lu " 00273 "connectionID==%lu message='%s')", 00274 imcID, connectionID, message); 00275 return TNC_RESULT_SUCCESS; 00276 } 00277 00278 00279 TNC_Result TNC_TNCC_BindFunction( 00280 TNC_IMCID imcID, 00281 char *functionName, 00282 void **pOutfunctionPointer) 00283 { 00284 wpa_printf(MSG_DEBUG, "TNC: TNC_TNCC_BindFunction(imcID=%lu, " 00285 "functionName='%s')", (unsigned long) imcID, functionName); 00286 00287 if (imcID >= TNC_MAX_IMC_ID || tnc_imc[imcID] == NULL) 00288 return TNC_RESULT_INVALID_PARAMETER; 00289 00290 if (pOutfunctionPointer == NULL) 00291 return TNC_RESULT_INVALID_PARAMETER; 00292 00293 if (os_strcmp(functionName, "TNC_TNCC_ReportMessageTypes") == 0) 00294 *pOutfunctionPointer = TNC_TNCC_ReportMessageTypes; 00295 else if (os_strcmp(functionName, "TNC_TNCC_SendMessage") == 0) 00296 *pOutfunctionPointer = TNC_TNCC_SendMessage; 00297 else if (os_strcmp(functionName, "TNC_TNCC_RequestHandshakeRetry") == 00298 0) 00299 *pOutfunctionPointer = TNC_TNCC_RequestHandshakeRetry; 00300 else if (os_strcmp(functionName, "TNC_9048_LogMessage") == 0) 00301 *pOutfunctionPointer = TNC_9048_LogMessage; 00302 else if (os_strcmp(functionName, "TNC_9048_UserMessage") == 0) 00303 *pOutfunctionPointer = TNC_9048_UserMessage; 00304 else 00305 *pOutfunctionPointer = NULL; 00306 00307 return TNC_RESULT_SUCCESS; 00308 } 00309 00310 00311 static void * tncc_get_sym(void *handle, char *func) 00312 { 00313 void *fptr; 00314 00315 #ifdef CONFIG_NATIVE_WINDOWS 00316 #ifdef _WIN32_WCE 00317 fptr = GetProcAddressA(handle, func); 00318 #else /* _WIN32_WCE */ 00319 fptr = GetProcAddress(handle, func); 00320 #endif /* _WIN32_WCE */ 00321 #else /* CONFIG_NATIVE_WINDOWS */ 00322 fptr = dlsym(handle, func); 00323 #endif /* CONFIG_NATIVE_WINDOWS */ 00324 00325 return fptr; 00326 } 00327 00328 00329 static int tncc_imc_resolve_funcs(struct tnc_if_imc *imc) 00330 { 00331 void *handle = imc->dlhandle; 00332 00333 /* Mandatory IMC functions */ 00334 imc->Initialize = tncc_get_sym(handle, "TNC_IMC_Initialize"); 00335 if (imc->Initialize == NULL) { 00336 wpa_printf(MSG_ERROR, "TNC: IMC does not export " 00337 "TNC_IMC_Initialize"); 00338 return -1; 00339 } 00340 00341 imc->BeginHandshake = tncc_get_sym(handle, "TNC_IMC_BeginHandshake"); 00342 if (imc->BeginHandshake == NULL) { 00343 wpa_printf(MSG_ERROR, "TNC: IMC does not export " 00344 "TNC_IMC_BeginHandshake"); 00345 return -1; 00346 } 00347 00348 imc->ProvideBindFunction = 00349 tncc_get_sym(handle, "TNC_IMC_ProvideBindFunction"); 00350 if (imc->ProvideBindFunction == NULL) { 00351 wpa_printf(MSG_ERROR, "TNC: IMC does not export " 00352 "TNC_IMC_ProvideBindFunction"); 00353 return -1; 00354 } 00355 00356 /* Optional IMC functions */ 00357 imc->NotifyConnectionChange = 00358 tncc_get_sym(handle, "TNC_IMC_NotifyConnectionChange"); 00359 imc->ReceiveMessage = tncc_get_sym(handle, "TNC_IMC_ReceiveMessage"); 00360 imc->BatchEnding = tncc_get_sym(handle, "TNC_IMC_BatchEnding"); 00361 imc->Terminate = tncc_get_sym(handle, "TNC_IMC_Terminate"); 00362 00363 return 0; 00364 } 00365 00366 00367 static int tncc_imc_initialize(struct tnc_if_imc *imc) 00368 { 00369 TNC_Result res; 00370 TNC_Version imc_ver; 00371 00372 wpa_printf(MSG_DEBUG, "TNC: Calling TNC_IMC_Initialize for IMC '%s'", 00373 imc->name); 00374 res = imc->Initialize(imc->imcID, TNC_IFIMC_VERSION_1, 00375 TNC_IFIMC_VERSION_1, &imc_ver); 00376 wpa_printf(MSG_DEBUG, "TNC: TNC_IMC_Initialize: res=%lu imc_ver=%lu", 00377 (unsigned long) res, (unsigned long) imc_ver); 00378 00379 return res == TNC_RESULT_SUCCESS ? 0 : -1; 00380 } 00381 00382 00383 static int tncc_imc_terminate(struct tnc_if_imc *imc) 00384 { 00385 TNC_Result res; 00386 00387 if (imc->Terminate == NULL) 00388 return 0; 00389 00390 wpa_printf(MSG_DEBUG, "TNC: Calling TNC_IMC_Terminate for IMC '%s'", 00391 imc->name); 00392 res = imc->Terminate(imc->imcID); 00393 wpa_printf(MSG_DEBUG, "TNC: TNC_IMC_Terminate: %lu", 00394 (unsigned long) res); 00395 00396 return res == TNC_RESULT_SUCCESS ? 0 : -1; 00397 } 00398 00399 00400 static int tncc_imc_provide_bind_function(struct tnc_if_imc *imc) 00401 { 00402 TNC_Result res; 00403 00404 wpa_printf(MSG_DEBUG, "TNC: Calling TNC_IMC_ProvideBindFunction for " 00405 "IMC '%s'", imc->name); 00406 res = imc->ProvideBindFunction(imc->imcID, TNC_TNCC_BindFunction); 00407 wpa_printf(MSG_DEBUG, "TNC: TNC_IMC_ProvideBindFunction: res=%lu", 00408 (unsigned long) res); 00409 00410 return res == TNC_RESULT_SUCCESS ? 0 : -1; 00411 } 00412 00413 00414 static int tncc_imc_notify_connection_change(struct tnc_if_imc *imc, 00415 TNC_ConnectionState state) 00416 { 00417 TNC_Result res; 00418 00419 if (imc->NotifyConnectionChange == NULL) 00420 return 0; 00421 00422 wpa_printf(MSG_DEBUG, "TNC: Calling TNC_IMC_NotifyConnectionChange(%d)" 00423 " for IMC '%s'", (int) state, imc->name); 00424 res = imc->NotifyConnectionChange(imc->imcID, imc->connectionID, 00425 state); 00426 wpa_printf(MSG_DEBUG, "TNC: TNC_IMC_NotifyConnectionChange: %lu", 00427 (unsigned long) res); 00428 00429 return res == TNC_RESULT_SUCCESS ? 0 : -1; 00430 } 00431 00432 00433 static int tncc_imc_begin_handshake(struct tnc_if_imc *imc) 00434 { 00435 TNC_Result res; 00436 00437 wpa_printf(MSG_DEBUG, "TNC: Calling TNC_IMC_BeginHandshake for IMC " 00438 "'%s'", imc->name); 00439 res = imc->BeginHandshake(imc->imcID, imc->connectionID); 00440 wpa_printf(MSG_DEBUG, "TNC: TNC_IMC_BeginHandshake: %lu", 00441 (unsigned long) res); 00442 00443 return res == TNC_RESULT_SUCCESS ? 0 : -1; 00444 } 00445 00446 00447 static int tncc_load_imc(struct tnc_if_imc *imc) 00448 { 00449 if (imc->path == NULL) { 00450 wpa_printf(MSG_DEBUG, "TNC: No IMC configured"); 00451 return -1; 00452 } 00453 00454 wpa_printf(MSG_DEBUG, "TNC: Opening IMC: %s (%s)", 00455 imc->name, imc->path); 00456 #ifdef CONFIG_NATIVE_WINDOWS 00457 #ifdef UNICODE 00458 { 00459 TCHAR *lib = wpa_strdup_tchar(imc->path); 00460 if (lib == NULL) 00461 return -1; 00462 imc->dlhandle = LoadLibrary(lib); 00463 os_free(lib); 00464 } 00465 #else /* UNICODE */ 00466 imc->dlhandle = LoadLibrary(imc->path); 00467 #endif /* UNICODE */ 00468 if (imc->dlhandle == NULL) { 00469 wpa_printf(MSG_ERROR, "TNC: Failed to open IMC '%s' (%s): %d", 00470 imc->name, imc->path, (int) GetLastError()); 00471 return -1; 00472 } 00473 #else /* CONFIG_NATIVE_WINDOWS */ 00474 imc->dlhandle = dlopen(imc->path, RTLD_LAZY); 00475 if (imc->dlhandle == NULL) { 00476 wpa_printf(MSG_ERROR, "TNC: Failed to open IMC '%s' (%s): %s", 00477 imc->name, imc->path, dlerror()); 00478 return -1; 00479 } 00480 #endif /* CONFIG_NATIVE_WINDOWS */ 00481 00482 if (tncc_imc_resolve_funcs(imc) < 0) { 00483 wpa_printf(MSG_ERROR, "TNC: Failed to resolve IMC functions"); 00484 return -1; 00485 } 00486 00487 if (tncc_imc_initialize(imc) < 0 || 00488 tncc_imc_provide_bind_function(imc) < 0) { 00489 wpa_printf(MSG_ERROR, "TNC: Failed to initialize IMC"); 00490 return -1; 00491 } 00492 00493 return 0; 00494 } 00495 00496 00497 static void tncc_unload_imc(struct tnc_if_imc *imc) 00498 { 00499 tncc_imc_terminate(imc); 00500 tnc_imc[imc->imcID] = NULL; 00501 00502 if (imc->dlhandle) { 00503 #ifdef CONFIG_NATIVE_WINDOWS 00504 FreeLibrary(imc->dlhandle); 00505 #else /* CONFIG_NATIVE_WINDOWS */ 00506 dlclose(imc->dlhandle); 00507 #endif /* CONFIG_NATIVE_WINDOWS */ 00508 } 00509 os_free(imc->name); 00510 os_free(imc->path); 00511 os_free(imc->supported_types); 00512 os_free(imc->imc_send); 00513 } 00514 00515 00516 static int tncc_supported_type(struct tnc_if_imc *imc, unsigned int type) 00517 { 00518 size_t i; 00519 unsigned int vendor, subtype; 00520 00521 if (imc == NULL || imc->supported_types == NULL) 00522 return 0; 00523 00524 vendor = type >> 8; 00525 subtype = type & 0xff; 00526 00527 for (i = 0; i < imc->num_supported_types; i++) { 00528 unsigned int svendor, ssubtype; 00529 svendor = imc->supported_types[i] >> 8; 00530 ssubtype = imc->supported_types[i] & 0xff; 00531 if ((vendor == svendor || svendor == TNC_VENDORID_ANY) && 00532 (subtype == ssubtype || ssubtype == TNC_SUBTYPE_ANY)) 00533 return 1; 00534 } 00535 00536 return 0; 00537 } 00538 00539 00540 static void tncc_send_to_imcs(struct tncc_data *tncc, unsigned int type, 00541 const u8 *msg, size_t len) 00542 { 00543 struct tnc_if_imc *imc; 00544 TNC_Result res; 00545 00546 wpa_hexdump_ascii(MSG_MSGDUMP, "TNC: Message to IMC(s)", msg, len); 00547 00548 for (imc = tncc->imc; imc; imc = imc->next) { 00549 if (imc->ReceiveMessage == NULL || 00550 !tncc_supported_type(imc, type)) 00551 continue; 00552 00553 wpa_printf(MSG_DEBUG, "TNC: Call ReceiveMessage for IMC '%s'", 00554 imc->name); 00555 res = imc->ReceiveMessage(imc->imcID, imc->connectionID, 00556 (TNC_BufferReference) msg, len, 00557 type); 00558 wpa_printf(MSG_DEBUG, "TNC: ReceiveMessage: %lu", 00559 (unsigned long) res); 00560 } 00561 } 00562 00563 00564 void tncc_init_connection(struct tncc_data *tncc) 00565 { 00566 struct tnc_if_imc *imc; 00567 00568 for (imc = tncc->imc; imc; imc = imc->next) { 00569 tncc_imc_notify_connection_change( 00570 imc, TNC_CONNECTION_STATE_CREATE); 00571 tncc_imc_notify_connection_change( 00572 imc, TNC_CONNECTION_STATE_HANDSHAKE); 00573 00574 os_free(imc->imc_send); 00575 imc->imc_send = NULL; 00576 imc->imc_send_len = 0; 00577 00578 tncc_imc_begin_handshake(imc); 00579 } 00580 } 00581 00582 00583 size_t tncc_total_send_len(struct tncc_data *tncc) 00584 { 00585 struct tnc_if_imc *imc; 00586 00587 size_t len = 0; 00588 for (imc = tncc->imc; imc; imc = imc->next) 00589 len += imc->imc_send_len; 00590 return len; 00591 } 00592 00593 00594 u8 * tncc_copy_send_buf(struct tncc_data *tncc, u8 *pos) 00595 { 00596 struct tnc_if_imc *imc; 00597 00598 for (imc = tncc->imc; imc; imc = imc->next) { 00599 if (imc->imc_send == NULL) 00600 continue; 00601 00602 os_memcpy(pos, imc->imc_send, imc->imc_send_len); 00603 pos += imc->imc_send_len; 00604 os_free(imc->imc_send); 00605 imc->imc_send = NULL; 00606 imc->imc_send_len = 0; 00607 } 00608 00609 return pos; 00610 } 00611 00612 00613 char * tncc_if_tnccs_start(struct tncc_data *tncc) 00614 { 00615 char *buf = os_malloc(1000); 00616 if (buf == NULL) 00617 return NULL; 00618 tncc->last_batchid++; 00619 os_snprintf(buf, 1000, IF_TNCCS_START, tncc->last_batchid); 00620 return buf; 00621 } 00622 00623 00624 char * tncc_if_tnccs_end(void) 00625 { 00626 char *buf = os_malloc(100); 00627 if (buf == NULL) 00628 return NULL; 00629 os_snprintf(buf, 100, IF_TNCCS_END); 00630 return buf; 00631 } 00632 00633 00634 static void tncc_notify_recommendation(struct tncc_data *tncc, 00635 enum tncc_process_res res) 00636 { 00637 TNC_ConnectionState state; 00638 struct tnc_if_imc *imc; 00639 00640 switch (res) { 00641 case TNCCS_RECOMMENDATION_ALLOW: 00642 state = TNC_CONNECTION_STATE_ACCESS_ALLOWED; 00643 break; 00644 case TNCCS_RECOMMENDATION_NONE: 00645 state = TNC_CONNECTION_STATE_ACCESS_NONE; 00646 break; 00647 case TNCCS_RECOMMENDATION_ISOLATE: 00648 state = TNC_CONNECTION_STATE_ACCESS_ISOLATED; 00649 break; 00650 default: 00651 state = TNC_CONNECTION_STATE_ACCESS_NONE; 00652 break; 00653 } 00654 00655 for (imc = tncc->imc; imc; imc = imc->next) 00656 tncc_imc_notify_connection_change(imc, state); 00657 } 00658 00659 00660 static int tncc_get_type(char *start, unsigned int *type) 00661 { 00662 char *pos = os_strstr(start, "<Type>"); 00663 if (pos == NULL) 00664 return -1; 00665 pos += 6; 00666 *type = strtoul(pos, NULL, 16); 00667 return 0; 00668 } 00669 00670 00671 static unsigned char * tncc_get_base64(char *start, size_t *decoded_len) 00672 { 00673 char *pos, *pos2; 00674 unsigned char *decoded; 00675 00676 pos = os_strstr(start, "<Base64>"); 00677 if (pos == NULL) 00678 return NULL; 00679 00680 pos += 8; 00681 pos2 = os_strstr(pos, "</Base64>"); 00682 if (pos2 == NULL) 00683 return NULL; 00684 *pos2 = '\0'; 00685 00686 decoded = base64_decode((unsigned char *) pos, os_strlen(pos), 00687 decoded_len); 00688 *pos2 = '<'; 00689 if (decoded == NULL) { 00690 wpa_printf(MSG_DEBUG, "TNC: Failed to decode Base64 data"); 00691 } 00692 00693 return decoded; 00694 } 00695 00696 00697 static enum tncc_process_res tncc_get_recommendation(char *start) 00698 { 00699 char *pos, *pos2, saved; 00700 int recom; 00701 00702 pos = os_strstr(start, "<TNCCS-Recommendation "); 00703 if (pos == NULL) 00704 return TNCCS_RECOMMENDATION_ERROR; 00705 00706 pos += 21; 00707 pos = os_strstr(pos, " type="); 00708 if (pos == NULL) 00709 return TNCCS_RECOMMENDATION_ERROR; 00710 pos += 6; 00711 00712 if (*pos == '"') 00713 pos++; 00714 00715 pos2 = pos; 00716 while (*pos2 != '\0' && *pos2 != '"' && *pos2 != '>') 00717 pos2++; 00718 00719 if (*pos2 == '\0') 00720 return TNCCS_RECOMMENDATION_ERROR; 00721 00722 saved = *pos2; 00723 *pos2 = '\0'; 00724 wpa_printf(MSG_DEBUG, "TNC: TNCCS-Recommendation: '%s'", pos); 00725 00726 recom = TNCCS_RECOMMENDATION_ERROR; 00727 if (os_strcmp(pos, "allow") == 0) 00728 recom = TNCCS_RECOMMENDATION_ALLOW; 00729 else if (os_strcmp(pos, "none") == 0) 00730 recom = TNCCS_RECOMMENDATION_NONE; 00731 else if (os_strcmp(pos, "isolate") == 0) 00732 recom = TNCCS_RECOMMENDATION_ISOLATE; 00733 00734 *pos2 = saved; 00735 00736 return recom; 00737 } 00738 00739 00740 enum tncc_process_res tncc_process_if_tnccs(struct tncc_data *tncc, 00741 const u8 *msg, size_t len) 00742 { 00743 char *buf, *start, *end, *pos, *pos2, *payload; 00744 unsigned int batch_id; 00745 unsigned char *decoded; 00746 size_t decoded_len; 00747 enum tncc_process_res res = TNCCS_PROCESS_OK_NO_RECOMMENDATION; 00748 int recommendation_msg = 0; 00749 00750 buf = os_malloc(len + 1); 00751 if (buf == NULL) 00752 return TNCCS_PROCESS_ERROR; 00753 00754 os_memcpy(buf, msg, len); 00755 buf[len] = '\0'; 00756 start = os_strstr(buf, "<TNCCS-Batch "); 00757 end = os_strstr(buf, "</TNCCS-Batch>"); 00758 if (start == NULL || end == NULL || start > end) { 00759 os_free(buf); 00760 return TNCCS_PROCESS_ERROR; 00761 } 00762 00763 start += 13; 00764 while (*start == ' ') 00765 start++; 00766 *end = '\0'; 00767 00768 pos = os_strstr(start, "BatchId="); 00769 if (pos == NULL) { 00770 os_free(buf); 00771 return TNCCS_PROCESS_ERROR; 00772 } 00773 00774 pos += 8; 00775 if (*pos == '"') 00776 pos++; 00777 batch_id = atoi(pos); 00778 wpa_printf(MSG_DEBUG, "TNC: Received IF-TNCCS BatchId=%u", 00779 batch_id); 00780 if (batch_id != tncc->last_batchid + 1) { 00781 wpa_printf(MSG_DEBUG, "TNC: Unexpected IF-TNCCS BatchId " 00782 "%u (expected %u)", 00783 batch_id, tncc->last_batchid + 1); 00784 os_free(buf); 00785 return TNCCS_PROCESS_ERROR; 00786 } 00787 tncc->last_batchid = batch_id; 00788 00789 while (*pos != '\0' && *pos != '>') 00790 pos++; 00791 if (*pos == '\0') { 00792 os_free(buf); 00793 return TNCCS_PROCESS_ERROR; 00794 } 00795 pos++; 00796 payload = start; 00797 00798 /* 00799 * <IMC-IMV-Message> 00800 * <Type>01234567</Type> 00801 * <Base64>foo==</Base64> 00802 * </IMC-IMV-Message> 00803 */ 00804 00805 while (*start) { 00806 char *endpos; 00807 unsigned int type; 00808 00809 pos = os_strstr(start, "<IMC-IMV-Message>"); 00810 if (pos == NULL) 00811 break; 00812 start = pos + 17; 00813 end = os_strstr(start, "</IMC-IMV-Message>"); 00814 if (end == NULL) 00815 break; 00816 *end = '\0'; 00817 endpos = end; 00818 end += 18; 00819 00820 if (tncc_get_type(start, &type) < 0) { 00821 *endpos = '<'; 00822 start = end; 00823 continue; 00824 } 00825 wpa_printf(MSG_DEBUG, "TNC: IMC-IMV-Message Type 0x%x", type); 00826 00827 decoded = tncc_get_base64(start, &decoded_len); 00828 if (decoded == NULL) { 00829 *endpos = '<'; 00830 start = end; 00831 continue; 00832 } 00833 00834 tncc_send_to_imcs(tncc, type, decoded, decoded_len); 00835 00836 os_free(decoded); 00837 00838 start = end; 00839 } 00840 00841 /* 00842 * <TNCC-TNCS-Message> 00843 * <Type>01234567</Type> 00844 * <XML><TNCCS-Foo type="foo"></TNCCS-Foo></XML> 00845 * <Base64>foo==</Base64> 00846 * </TNCC-TNCS-Message> 00847 */ 00848 00849 start = payload; 00850 while (*start) { 00851 unsigned int type; 00852 char *xml, *xmlend, *endpos; 00853 00854 pos = os_strstr(start, "<TNCC-TNCS-Message>"); 00855 if (pos == NULL) 00856 break; 00857 start = pos + 19; 00858 end = os_strstr(start, "</TNCC-TNCS-Message>"); 00859 if (end == NULL) 00860 break; 00861 *end = '\0'; 00862 endpos = end; 00863 end += 20; 00864 00865 if (tncc_get_type(start, &type) < 0) { 00866 *endpos = '<'; 00867 start = end; 00868 continue; 00869 } 00870 wpa_printf(MSG_DEBUG, "TNC: TNCC-TNCS-Message Type 0x%x", 00871 type); 00872 00873 /* Base64 OR XML */ 00874 decoded = NULL; 00875 xml = NULL; 00876 xmlend = NULL; 00877 pos = os_strstr(start, "<XML>"); 00878 if (pos) { 00879 pos += 5; 00880 pos2 = os_strstr(pos, "</XML>"); 00881 if (pos2 == NULL) { 00882 *endpos = '<'; 00883 start = end; 00884 continue; 00885 } 00886 xmlend = pos2; 00887 xml = pos; 00888 } else { 00889 decoded = tncc_get_base64(start, &decoded_len); 00890 if (decoded == NULL) { 00891 *endpos = '<'; 00892 start = end; 00893 continue; 00894 } 00895 } 00896 00897 if (decoded) { 00898 wpa_hexdump_ascii(MSG_MSGDUMP, 00899 "TNC: TNCC-TNCS-Message Base64", 00900 decoded, decoded_len); 00901 os_free(decoded); 00902 } 00903 00904 if (xml) { 00905 wpa_hexdump_ascii(MSG_MSGDUMP, 00906 "TNC: TNCC-TNCS-Message XML", 00907 (unsigned char *) xml, 00908 xmlend - xml); 00909 } 00910 00911 if (type == TNC_TNCCS_RECOMMENDATION && xml) { 00912 /* 00913 * <TNCCS-Recommendation type="allow"> 00914 * </TNCCS-Recommendation> 00915 */ 00916 *xmlend = '\0'; 00917 res = tncc_get_recommendation(xml); 00918 *xmlend = '<'; 00919 recommendation_msg = 1; 00920 } 00921 00922 start = end; 00923 } 00924 00925 os_free(buf); 00926 00927 if (recommendation_msg) 00928 tncc_notify_recommendation(tncc, res); 00929 00930 return res; 00931 } 00932 00933 00934 #ifdef CONFIG_NATIVE_WINDOWS 00935 static int tncc_read_config_reg(struct tncc_data *tncc, HKEY hive) 00936 { 00937 HKEY hk, hk2; 00938 LONG ret; 00939 DWORD i; 00940 struct tnc_if_imc *imc, *last; 00941 int j; 00942 00943 last = tncc->imc; 00944 while (last && last->next) 00945 last = last->next; 00946 00947 ret = RegOpenKeyEx(hive, TNC_WINREG_PATH, 0, KEY_ENUMERATE_SUB_KEYS, 00948 &hk); 00949 if (ret != ERROR_SUCCESS) 00950 return 0; 00951 00952 for (i = 0; ; i++) { 00953 TCHAR name[255], *val; 00954 DWORD namelen, buflen; 00955 00956 namelen = 255; 00957 ret = RegEnumKeyEx(hk, i, name, &namelen, NULL, NULL, NULL, 00958 NULL); 00959 00960 if (ret == ERROR_NO_MORE_ITEMS) 00961 break; 00962 00963 if (ret != ERROR_SUCCESS) { 00964 wpa_printf(MSG_DEBUG, "TNC: RegEnumKeyEx failed: 0x%x", 00965 (unsigned int) ret); 00966 break; 00967 } 00968 00969 if (namelen >= 255) 00970 namelen = 255 - 1; 00971 name[namelen] = '\0'; 00972 00973 wpa_printf(MSG_DEBUG, "TNC: IMC '" TSTR "'", name); 00974 00975 ret = RegOpenKeyEx(hk, name, 0, KEY_QUERY_VALUE, &hk2); 00976 if (ret != ERROR_SUCCESS) { 00977 wpa_printf(MSG_DEBUG, "Could not open IMC key '" TSTR 00978 "'", name); 00979 continue; 00980 } 00981 00982 ret = RegQueryValueEx(hk2, TEXT("Path"), NULL, NULL, NULL, 00983 &buflen); 00984 if (ret != ERROR_SUCCESS) { 00985 wpa_printf(MSG_DEBUG, "TNC: Could not read Path from " 00986 "IMC key '" TSTR "'", name); 00987 RegCloseKey(hk2); 00988 continue; 00989 } 00990 00991 val = os_malloc(buflen); 00992 if (val == NULL) { 00993 RegCloseKey(hk2); 00994 continue; 00995 } 00996 00997 ret = RegQueryValueEx(hk2, TEXT("Path"), NULL, NULL, 00998 (LPBYTE) val, &buflen); 00999 if (ret != ERROR_SUCCESS) { 01000 os_free(val); 01001 RegCloseKey(hk2); 01002 continue; 01003 } 01004 01005 RegCloseKey(hk2); 01006 01007 wpa_unicode2ascii_inplace(val); 01008 wpa_printf(MSG_DEBUG, "TNC: IMC Path '%s'", (char *) val); 01009 01010 for (j = 0; j < TNC_MAX_IMC_ID; j++) { 01011 if (tnc_imc[j] == NULL) 01012 break; 01013 } 01014 if (j >= TNC_MAX_IMC_ID) { 01015 wpa_printf(MSG_DEBUG, "TNC: Too many IMCs"); 01016 os_free(val); 01017 continue; 01018 } 01019 01020 imc = os_zalloc(sizeof(*imc)); 01021 if (imc == NULL) { 01022 os_free(val); 01023 break; 01024 } 01025 01026 imc->imcID = j; 01027 01028 wpa_unicode2ascii_inplace(name); 01029 imc->name = os_strdup((char *) name); 01030 imc->path = os_strdup((char *) val); 01031 01032 os_free(val); 01033 01034 if (last == NULL) 01035 tncc->imc = imc; 01036 else 01037 last->next = imc; 01038 last = imc; 01039 01040 tnc_imc[imc->imcID] = imc; 01041 } 01042 01043 RegCloseKey(hk); 01044 01045 return 0; 01046 } 01047 01048 01049 static int tncc_read_config(struct tncc_data *tncc) 01050 { 01051 if (tncc_read_config_reg(tncc, HKEY_LOCAL_MACHINE) < 0 || 01052 tncc_read_config_reg(tncc, HKEY_CURRENT_USER) < 0) 01053 return -1; 01054 return 0; 01055 } 01056 01057 #else /* CONFIG_NATIVE_WINDOWS */ 01058 01059 static struct tnc_if_imc * tncc_parse_imc(char *start, char *end, int *error) 01060 { 01061 struct tnc_if_imc *imc; 01062 char *pos, *pos2; 01063 int i; 01064 01065 for (i = 0; i < TNC_MAX_IMC_ID; i++) { 01066 if (tnc_imc[i] == NULL) 01067 break; 01068 } 01069 if (i >= TNC_MAX_IMC_ID) { 01070 wpa_printf(MSG_DEBUG, "TNC: Too many IMCs"); 01071 return NULL; 01072 } 01073 01074 imc = os_zalloc(sizeof(*imc)); 01075 if (imc == NULL) { 01076 *error = 1; 01077 return NULL; 01078 } 01079 01080 imc->imcID = i; 01081 01082 pos = start; 01083 wpa_printf(MSG_DEBUG, "TNC: Configured IMC: %s", pos); 01084 if (pos + 1 >= end || *pos != '"') { 01085 wpa_printf(MSG_ERROR, "TNC: Ignoring invalid IMC line '%s' " 01086 "(no starting quotation mark)", start); 01087 os_free(imc); 01088 return NULL; 01089 } 01090 01091 pos++; 01092 pos2 = pos; 01093 while (pos2 < end && *pos2 != '"') 01094 pos2++; 01095 if (pos2 >= end) { 01096 wpa_printf(MSG_ERROR, "TNC: Ignoring invalid IMC line '%s' " 01097 "(no ending quotation mark)", start); 01098 os_free(imc); 01099 return NULL; 01100 } 01101 *pos2 = '\0'; 01102 wpa_printf(MSG_DEBUG, "TNC: Name: '%s'", pos); 01103 imc->name = os_strdup(pos); 01104 01105 pos = pos2 + 1; 01106 if (pos >= end || *pos != ' ') { 01107 wpa_printf(MSG_ERROR, "TNC: Ignoring invalid IMC line '%s' " 01108 "(no space after name)", start); 01109 os_free(imc->name); 01110 os_free(imc); 01111 return NULL; 01112 } 01113 01114 pos++; 01115 wpa_printf(MSG_DEBUG, "TNC: IMC file: '%s'", pos); 01116 imc->path = os_strdup(pos); 01117 tnc_imc[imc->imcID] = imc; 01118 01119 return imc; 01120 } 01121 01122 01123 static int tncc_read_config(struct tncc_data *tncc) 01124 { 01125 char *config, *end, *pos, *line_end; 01126 size_t config_len; 01127 struct tnc_if_imc *imc, *last; 01128 01129 last = NULL; 01130 01131 config = os_readfile(TNC_CONFIG_FILE, &config_len); 01132 if (config == NULL) { 01133 wpa_printf(MSG_ERROR, "TNC: Could not open TNC configuration " 01134 "file '%s'", TNC_CONFIG_FILE); 01135 return -1; 01136 } 01137 01138 end = config + config_len; 01139 for (pos = config; pos < end; pos = line_end + 1) { 01140 line_end = pos; 01141 while (*line_end != '\n' && *line_end != '\r' && 01142 line_end < end) 01143 line_end++; 01144 *line_end = '\0'; 01145 01146 if (os_strncmp(pos, "IMC ", 4) == 0) { 01147 int error = 0; 01148 01149 imc = tncc_parse_imc(pos + 4, line_end, &error); 01150 if (error) 01151 return -1; 01152 if (imc) { 01153 if (last == NULL) 01154 tncc->imc = imc; 01155 else 01156 last->next = imc; 01157 last = imc; 01158 } 01159 } 01160 } 01161 01162 os_free(config); 01163 01164 return 0; 01165 } 01166 01167 #endif /* CONFIG_NATIVE_WINDOWS */ 01168 01169 01170 struct tncc_data * tncc_init(void) 01171 { 01172 struct tncc_data *tncc; 01173 struct tnc_if_imc *imc; 01174 01175 tncc = os_zalloc(sizeof(*tncc)); 01176 if (tncc == NULL) 01177 return NULL; 01178 01179 /* TODO: 01180 * move loading and Initialize() to a location that is not 01181 * re-initialized for every EAP-TNC session (?) 01182 */ 01183 01184 if (tncc_read_config(tncc) < 0) { 01185 wpa_printf(MSG_ERROR, "TNC: Failed to read TNC configuration"); 01186 goto failed; 01187 } 01188 01189 for (imc = tncc->imc; imc; imc = imc->next) { 01190 if (tncc_load_imc(imc)) { 01191 wpa_printf(MSG_ERROR, "TNC: Failed to load IMC '%s'", 01192 imc->name); 01193 goto failed; 01194 } 01195 } 01196 01197 return tncc; 01198 01199 failed: 01200 tncc_deinit(tncc); 01201 return NULL; 01202 } 01203 01204 01205 void tncc_deinit(struct tncc_data *tncc) 01206 { 01207 struct tnc_if_imc *imc, *prev; 01208 01209 imc = tncc->imc; 01210 while (imc) { 01211 tncc_unload_imc(imc); 01212 01213 prev = imc; 01214 imc = imc->next; 01215 os_free(prev); 01216 } 01217 01218 os_free(tncc); 01219 } 01220 01221 01222 static struct wpabuf * tncc_build_soh(int ver) 01223 { 01224 struct wpabuf *buf; 01225 u8 *tlv_len, *tlv_len2, *outer_len, *inner_len, *ssoh_len, *end; 01226 u8 correlation_id[24]; 01227 /* TODO: get correct name */ 01228 char *machinename = "wpa_supplicant@w1.fi"; 01229 01230 if (os_get_random(correlation_id, sizeof(correlation_id))) 01231 return NULL; 01232 wpa_hexdump(MSG_DEBUG, "TNC: SoH Correlation ID", 01233 correlation_id, sizeof(correlation_id)); 01234 01235 buf = wpabuf_alloc(200); 01236 if (buf == NULL) 01237 return NULL; 01238 01239 /* Vendor-Specific TLV (Microsoft) - SoH */ 01240 wpabuf_put_be16(buf, EAP_TLV_VENDOR_SPECIFIC_TLV); /* TLV Type */ 01241 tlv_len = wpabuf_put(buf, 2); /* Length */ 01242 wpabuf_put_be32(buf, EAP_VENDOR_MICROSOFT); /* Vendor_Id */ 01243 wpabuf_put_be16(buf, 0x01); /* TLV Type - SoH TLV */ 01244 tlv_len2 = wpabuf_put(buf, 2); /* Length */ 01245 01246 /* SoH Header */ 01247 wpabuf_put_be16(buf, EAP_TLV_VENDOR_SPECIFIC_TLV); /* Outer Type */ 01248 outer_len = wpabuf_put(buf, 2); 01249 wpabuf_put_be32(buf, EAP_VENDOR_MICROSOFT); /* IANA SMI Code */ 01250 wpabuf_put_be16(buf, ver); /* Inner Type */ 01251 inner_len = wpabuf_put(buf, 2); 01252 01253 if (ver == 2) { 01254 /* SoH Mode Sub-Header */ 01255 /* Outer Type */ 01256 wpabuf_put_be16(buf, EAP_TLV_VENDOR_SPECIFIC_TLV); 01257 wpabuf_put_be16(buf, 4 + 24 + 1 + 1); /* Length */ 01258 wpabuf_put_be32(buf, EAP_VENDOR_MICROSOFT); /* IANA SMI Code */ 01259 /* Value: */ 01260 wpabuf_put_data(buf, correlation_id, sizeof(correlation_id)); 01261 wpabuf_put_u8(buf, 0x01); /* Intent Flag - Request */ 01262 wpabuf_put_u8(buf, 0x00); /* Content-Type Flag */ 01263 } 01264 01265 /* SSoH TLV */ 01266 /* System-Health-Id */ 01267 wpabuf_put_be16(buf, 0x0002); /* Type */ 01268 wpabuf_put_be16(buf, 4); /* Length */ 01269 wpabuf_put_be32(buf, 79616); 01270 /* Vendor-Specific Attribute */ 01271 wpabuf_put_be16(buf, EAP_TLV_VENDOR_SPECIFIC_TLV); 01272 ssoh_len = wpabuf_put(buf, 2); 01273 wpabuf_put_be32(buf, EAP_VENDOR_MICROSOFT); /* IANA SMI Code */ 01274 01275 /* MS-Packet-Info */ 01276 wpabuf_put_u8(buf, SSOH_MS_PACKET_INFO); 01277 /* Note: IF-TNCCS-SOH v1.0 r8 claims this field to be: 01278 * Reserved(4 bits) r(1 bit) Vers(3 bits), but Windows XP 01279 * SP3 seems to be sending 0x11 for SSoH, i.e., r(request/response) bit 01280 * would not be in the specified location. 01281 * [MS-SOH] 4.0.2: Reserved(3 bits) r(1 bit) Vers(4 bits) 01282 */ 01283 wpabuf_put_u8(buf, 0x11); /* r=request, vers=1 */ 01284 01285 /* MS-Machine-Inventory */ 01286 /* TODO: get correct values; 0 = not applicable for OS */ 01287 wpabuf_put_u8(buf, SSOH_MS_MACHINE_INVENTORY); 01288 wpabuf_put_be32(buf, 0); /* osVersionMajor */ 01289 wpabuf_put_be32(buf, 0); /* osVersionMinor */ 01290 wpabuf_put_be32(buf, 0); /* osVersionBuild */ 01291 wpabuf_put_be16(buf, 0); /* spVersionMajor */ 01292 wpabuf_put_be16(buf, 0); /* spVersionMinor */ 01293 wpabuf_put_be16(buf, 0); /* procArch */ 01294 01295 /* MS-MachineName */ 01296 wpabuf_put_u8(buf, SSOH_MS_MACHINENAME); 01297 wpabuf_put_be16(buf, os_strlen(machinename) + 1); 01298 wpabuf_put_data(buf, machinename, os_strlen(machinename) + 1); 01299 01300 /* MS-CorrelationId */ 01301 wpabuf_put_u8(buf, SSOH_MS_CORRELATIONID); 01302 wpabuf_put_data(buf, correlation_id, sizeof(correlation_id)); 01303 01304 /* MS-Quarantine-State */ 01305 wpabuf_put_u8(buf, SSOH_MS_QUARANTINE_STATE); 01306 wpabuf_put_be16(buf, 1); /* Flags: ExtState=0, f=0, qState=1 */ 01307 wpabuf_put_be32(buf, 0xffffffff); /* ProbTime (hi) */ 01308 wpabuf_put_be32(buf, 0xffffffff); /* ProbTime (lo) */ 01309 wpabuf_put_be16(buf, 1); /* urlLenInBytes */ 01310 wpabuf_put_u8(buf, 0); /* null termination for the url */ 01311 01312 /* MS-Machine-Inventory-Ex */ 01313 wpabuf_put_u8(buf, SSOH_MS_MACHINE_INVENTORY_EX); 01314 wpabuf_put_be32(buf, 0); /* Reserved 01315 * (note: Windows XP SP3 uses 0xdecafbad) */ 01316 wpabuf_put_u8(buf, 1); /* ProductType: Client */ 01317 01318 /* Update SSoH Length */ 01319 end = wpabuf_put(buf, 0); 01320 WPA_PUT_BE16(ssoh_len, end - ssoh_len - 2); 01321 01322 /* TODO: SoHReportEntry TLV (zero or more) */ 01323 01324 /* Update length fields */ 01325 end = wpabuf_put(buf, 0); 01326 WPA_PUT_BE16(tlv_len, end - tlv_len - 2); 01327 WPA_PUT_BE16(tlv_len2, end - tlv_len2 - 2); 01328 WPA_PUT_BE16(outer_len, end - outer_len - 2); 01329 WPA_PUT_BE16(inner_len, end - inner_len - 2); 01330 01331 return buf; 01332 } 01333 01334 01335 struct wpabuf * tncc_process_soh_request(int ver, const u8 *data, size_t len) 01336 { 01337 const u8 *pos; 01338 01339 wpa_hexdump(MSG_DEBUG, "TNC: SoH Request", data, len); 01340 01341 if (len < 12) 01342 return NULL; 01343 01344 /* SoH Request */ 01345 pos = data; 01346 01347 /* TLV Type */ 01348 if (WPA_GET_BE16(pos) != EAP_TLV_VENDOR_SPECIFIC_TLV) 01349 return NULL; 01350 pos += 2; 01351 01352 /* Length */ 01353 if (WPA_GET_BE16(pos) < 8) 01354 return NULL; 01355 pos += 2; 01356 01357 /* Vendor_Id */ 01358 if (WPA_GET_BE32(pos) != EAP_VENDOR_MICROSOFT) 01359 return NULL; 01360 pos += 4; 01361 01362 /* TLV Type */ 01363 if (WPA_GET_BE16(pos) != 0x02 /* SoH request TLV */) 01364 return NULL; 01365 01366 wpa_printf(MSG_DEBUG, "TNC: SoH Request TLV received"); 01367 01368 return tncc_build_soh(2); 01369 }