eaptnc.c
来自「linux 下通过802.1认证的安装包」· C语言 代码 · 共 698 行 · 第 1/2 页
C
698 行
/**
* Support for Trusted Network Connect EAP method
*
* \file eaptnc.c
*
* Licensed under a dual GPL/BSD license. (See LICENSE file for more info.)
*
* \author chris@open1x.org
*
* \todo Add error events to this file!
*
* $Id: eaptnc.c,v 1.2.2.30 2008/01/21 22:51:49 chessing Exp $
* $Date: 2008/01/21 22:51:49 $
**/
#ifdef HAVE_TNC
#include <string.h>
#ifndef WINDOWS
#include <strings.h>
#else
#include <windows.h>
#include <stdio.h>
#include <string.h>
#include "../../stdintwin.h"
#endif
#include <stdlib.h>
#include <errno.h>
#include <libtnctncc.h>
#include "../../../lib/libxsupconfig/xsupconfig_structs.h"
#include "../../context.h"
#include "../../xsup_debug.h"
#include "../../xsup_err.h"
#include "../../frame_structs.h"
#include "../../../lib/libxsupconfig/xsupconfig.h"
#include "../../eap_sm.h"
#include "../../xsup_common.h"
#include "eaptnc.h"
#include "../eap_type_common.h"
#ifdef USE_EFENCE
#include <efence.h>
#endif
#ifndef WINDOWS
#warning Use config data, and get rid of the #define below.
#endif
// XXX Make this configurable.
#define TNC_MAX_FRAG 900
uint32_t totalretsize = 0;
struct tnc_data *tncdatahook = NULL; // Used to provide binding on our *SendBatch call.
static int connectionID = 0; // Start with a connection ID of 0.
/**
* \brief Validate the TNC flags byte to be sure that it is using a version we support, and doesn't
* have any of the reserved bits set.
*
* @param[in] flagsver The byte that we want to verify has the proper settings for TNC.
*
* \retval XENONE on success
* \retval XEINVALIDFLAGSVER on failure.
**/
int eaptnc_check_flags_ver(uint8_t flagsver)
{
int retval = XENONE;
// We don't want to terminate when we find an error. Instead, we want
// to kick back error message for each part of the check that fails.
if ((flagsver & TNC_VERSION_MASK) > TNC_MAX_VERSION_SUPPORTED)
{
debug_printf(DEBUG_NORMAL, "Invalid version number %d! We currently "
"only support up to version %d.\n",
(flagsver & TNC_VERSION_MASK), TNC_MAX_VERSION_SUPPORTED);
retval = XEINVALIDFLAGSVER;
}
if ((flagsver & TNC_RESERVED_FLAGS) != 0)
{
debug_printf(DEBUG_NORMAL, "Invalid flags set for EAP-TNC! Something "
"was set to 1 in bit positions 4 and/or 5.\n");
retval = XEINVALIDFLAGSVER;
}
return retval;
}
/**
* \brief Start a TNC conversation with the server.
*
* @param[in] eapdata A pointer to the EAP data that we may need to complete a TNC authentication.
*
* \retval XENONE on success
* \retval !XENONE on failure
**/
int eaptnc_do_start(eap_type_data *eapdata)
{
context *ctx = NULL;
// A start message should contain a single byte that contains the start
// flag, and a version flag. So, we should make sure that there isn't
// anything extra before we continue.
if (eap_type_common_get_eap_length(eapdata->eapReqData) >
(sizeof(struct eap_header)+1))
{
debug_printf(DEBUG_NORMAL, "The start message from the authenticator "
"contained data beyond the start flag. This is not "
"allowed!\n");
return XEGENERROR;
}
if (eapdata->eap_data != NULL)
{
debug_printf(DEBUG_NORMAL, "EAP data hook is unavailable! (Did the previous EAP method "
"free it?\n");
return XEGENERROR;
}
// Otherwise, create our structure.
eapdata->eap_data = Malloc(sizeof(struct tnc_data));
if (eapdata->eap_data == NULL)
{
debug_printf(DEBUG_NORMAL, "Couldn't allocate memory to store TNC stucture!!\n");
return XEMALLOC;
}
tncdatahook = (struct tnc_data *)eapdata->eap_data;
ctx = event_core_get_active_ctx();
if (ctx == NULL)
{
debug_printf(DEBUG_NORMAL, "Attempted to start a TNC session with an invalid context!?\n");
return XEGENERROR;
}
// Remember the TNC connection ID, so that we can operate on the right context if the IMC
// asks us to do something.
if (ctx->tnc_connID == -1) ctx->tnc_connID = connectionID;
if (libtnc_tncc_BeginSession(ctx->tnc_connID) != TNC_RESULT_SUCCESS)
{
debug_printf(DEBUG_NORMAL, "(EAP-TNC) Failed to start TNC session!\n");
return XETNCLIBFAILURE;
}
connectionID++;
debug_printf(DEBUG_NORMAL, "(EAP-TNC) Started IMC Handshake.\n");
return XENONE;
}
/**
* \brief Process a bulk TNC data request. (Basically, anything that isn't a TNC start message.)
*
* @param[in] eapdata A pointer to EAP data that may be needed to complete a TNC session.
*
* \retval XENONE on success
* \retval !XENONE on failure
**/
int eaptnc_do_bulk_data(eap_type_data *eapdata)
{
int retval = XENONE;
int err = 0;
uint8_t *dataptr = NULL;
uint16_t datalen = 0;
uint32_t value32 = 0;
uint32_t expected = 0;
uint8_t *tosend = NULL;
struct tnc_data *tnc = NULL;
context *ctx = NULL;
if (!xsup_assert((eapdata != NULL), "eapdata != NULL", FALSE))
return XEGENERROR;
if (!xsup_assert((eapdata->eap_data != NULL), "eapdata->eap_data != NULL", FALSE))
return XEGENERROR;
if (!xsup_assert((eapdata->eapReqData != NULL),
"eapdata->eapReqData != NULL", FALSE))
return XEGENERROR;
ctx = event_core_get_active_ctx();
if (ctx == NULL)
{
debug_printf(DEBUG_NORMAL, "Attempted to start a TNC bulk data transfer with an invalid context!?\n");
return XEGENERROR;
}
tnc = (struct tnc_data *)eapdata->eap_data;
datalen = eap_type_common_get_eap_length(eapdata->eapReqData);
datalen -= sizeof(struct eap_header);
dataptr = &eapdata->eapReqData[sizeof(struct eap_header)];
if (eap_type_common_get_eap_length(eapdata->eapReqData) <= (sizeof(struct eap_header)+1))
{
if (((dataptr[0] & TNC_MASK_OUT_VER) == 0x00) && (tnc->tncoutqueue == NULL))
{
debug_printf(DEBUG_NORMAL, "The server ACKed our ACK?\n");
eap_type_common_fail(eapdata);
return XEGENERROR;
}
}
if (dataptr[0] & TNC_LENGTH_FLAG)
{
dataptr++;
datalen--;
memcpy(&value32, dataptr, sizeof(uint32_t));
value32 = ntohl(value32);
debug_printf(DEBUG_AUTHTYPES, "Expecting %d byte(s) of data from "
"TNC authenticator.\n", value32);
tnc->expected_in = value32;
dataptr += 4;
datalen -= 4;
}
else
{
// Skip the flags byte.
dataptr++;
datalen--;
}
// Starting at the current position of dataptr, and going to dataptr+datalen
// is the next block of data we need.
if (tnc->tncinqueue == NULL)
{
if (queue_create(&tnc->tncinqueue) != 0)
{
debug_printf(DEBUG_NORMAL, "Couldn't create TNC queue!\n");
return XEMALLOC;
}
}
if (datalen > 0)
{
err = queue_enqueue(&tnc->tncinqueue, dataptr, datalen);
if (err != 0)
{
debug_printf(DEBUG_NORMAL, "Couldn't enqueue new incoming TNC data! (Error : %d)\n", err);
return XEMALLOC;
}
}
else
{
debug_printf(DEBUG_AUTHTYPES, "TNC appears to be an ACK.\n");
}
dataptr = &eapdata->eapReqData[sizeof(struct eap_header)];
if (!(dataptr[0] & TNC_MORE_FLAG))
{
// There is nothing more that will be sent to us (in this block).
// Check that we have enough data. If we don't have exactly the right
// amount, display a message, and continue.
err = queue_get_size(&tnc->tncinqueue, &value32);
if (err != 0)
{
debug_printf(DEBUG_NORMAL, "Couldn't determine queue depth! (Error : %d)\n", err);
return XEGENERROR;
}
if (value32 < tnc->expected_in)
{
debug_printf(DEBUG_NORMAL, "There is less data in the TNC buffer "
"than we expected. It is likely that TNC will "
"fail. (Expected : %d Got : %d)\n", tnc->expected_in, value32);
}
// Remember what we expected.
expected = value32;
if (queue_dequeue(&tnc->tncinqueue, &tosend, &value32) != 0)
{
debug_printf(DEBUG_AUTHTYPES, "Couldn't dequeue any data for TNC!\n");
return XEGENERROR;
}
if (expected != value32) // Uhh... This shouldn't be possible!
{
debug_printf(DEBUG_NORMAL, "Failed to dequeue as much data as the queue claimed it had! (Expected %d, got %d)\n", expected, value32);
FREE(tosend);
return XEGENERROR;
}
// We have an XML block to send.
if (libtnc_tncc_ReceiveBatch(ctx->tnc_connID, tosend, value32) != TNC_RESULT_SUCCESS)
{
debug_printf(DEBUG_NORMAL, "Couldn't send TNC batch to libtnc!\n");
if (queue_destroy(&tnc->tncinqueue) != 0)
{
debug_printf(DEBUG_NORMAL, "Couldn't destroy used queue!\n");
}
FREE(tosend);
return XEGENERROR;
}
FREE(tosend);
if (queue_queue_done(&tnc->tncinqueue) == 1)
{
queue_destroy(&tnc->tncinqueue);
tnc->expected_in = 0;
}
}
return retval;
}
/**
* \brief Process a version 1 TNC request.
*
* Right now, there is only 1 version of TNC. But, since a version is included it is reasonable that
* there may be other versions developed. If there are, we should be able to integrate them easily.
*
* @param[in] eapdata A pointer to EAP data that may be needed to complete a TNC session.
* @param[in] eapreq A pointer to a buffer containing the EAP request message.
* @param[in] size The size of the EAP request message.
*
* \retval XENONE on success
* \retval !XENONE on failure
**/
uint16_t eaptnc_process_version_1(eap_type_data *eapdata, uint8_t *eapreq,
uint16_t size)
{
int retval = XENONE;
if (eapreq[0] & TNC_START_FLAG)
{
// Process a start message.
debug_printf(DEBUG_AUTHTYPES, "(EAP-TNC) Process Start\n");
retval = eaptnc_do_start(eapdata);
}
else
{
// Process a bulk data frame.
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?