eaptnc.c
来自「linux 下通过802.1认证的安装包」· C语言 代码 · 共 698 行 · 第 1/2 页
C
698 行
debug_printf(DEBUG_AUTHTYPES, "(EAP-TNC) Process bulk data\n");
retval = eaptnc_do_bulk_data(eapdata);
}
return retval;
}
/**
* \brief Verify that we have everything we need to run TNC.
*
* @param[in] eapdata A pointer to EAP data that may be needed to complete a TNC session.
**/
void eaptnc_check(eap_type_data *eapdata)
{
if (eapdata->eap_data != NULL)
tncdatahook = (struct tnc_data *)eapdata->eap_data;
}
/**
* \brief Process a TNC request.
*
* @param[in] eapdata A pointer to EAP data that may be needed to complete this TNC session.
**/
void eaptnc_process(eap_type_data *eapdata)
{
uint16_t retval = 0, eapsize = 0;
struct eap_header *eaphdr;
uint8_t *tnc_data;
if (!xsup_assert((eapdata != NULL), "eapdata != NULL", FALSE))
return;
if (!xsup_assert((eapdata->eapReqData != NULL),
"eapdata->eapReqData != NULL", FALSE))
{
eapdata->ignore = TRUE;
eapdata->decision = EAP_FAIL;
return;
}
eaphdr = (struct eap_header *)eapdata->eapReqData;
eapsize = ntohs(eaphdr->eap_length) - sizeof(struct eap_header);
tnc_data = &eapdata->eapReqData[sizeof(struct eap_header)];
// The code, identifier, length, and type should be stripped at this point.
// So start by validating the Flags/Ver byte, and process from there.
retval = eaptnc_check_flags_ver(tnc_data[0]);
if (retval != XENONE) return;
// This is overkill for now, but since there is a version, we implement
// this now, so we can expand it later.
switch ((tnc_data[0] & TNC_VERSION_MASK))
{
case 1:
// Process a version 1 request.
retval = eaptnc_process_version_1(eapdata, tnc_data, eapsize);
break;
default:
debug_printf(DEBUG_NORMAL, "Unknown TNC version in request! (Version %d)\n",
(tnc_data[0] & TNC_VERSION_MASK));
eap_type_common_fail(eapdata);
break;
}
}
/**
* \brief Build a TNC response.
*
* @param[in] eapdata A pointer to EAP data that may be needed to complete a TNC session.
*
* \retval ptr to the resulting EAP packet that is to be sent to the authenticator.
* \retval NULL on failure
**/
uint8_t *eaptnc_buildResp(eap_type_data *eapdata)
{
uint8_t *resdata = NULL, *resdataptr = NULL, *retdata = NULL, *dataptr = NULL, *dequeue_data = NULL;
struct eap_header *eaphdr = NULL;
uint32_t value32 = 0, cpysize = 0, extra = 0, totalsize = 0, queuesize = 0, res_size = 0, retlen = 0;
uint16_t value16 = 0;
struct tnc_data *tnc = NULL;
uint8_t *tosend = NULL;
int maxsize = TNC_MAX_FRAG;
int more = 0;
int athead = 0;
if (eapdata == NULL) return NULL;
if (eapdata->eap_data == NULL) return NULL;
tnc = (struct tnc_data *)eapdata->eap_data;
// XXX Need to set a way to specify a fragment size.
resdata = Malloc(1010);
if (resdata == NULL)
{
debug_printf(DEBUG_NORMAL, "Couldn't allocate memory to store TNC "
"result fragment.\n");
return NULL;
}
resdataptr = resdata;
// Build an EAP header.
eaphdr = (struct eap_header *)resdata;
eaphdr->eap_code = EAP_RESPONSE_PKT;
eaphdr->eap_identifier = eap_type_common_get_eap_reqid(eapdata->eapReqData);
eaphdr->eap_type = EAP_TYPE_TNC;
resdataptr += sizeof(struct eap_header);
// Otherwise, return some data from the buffer.
if (tnc->tncoutqueue == NULL)
{
// Send an ACK.
debug_printf(DEBUG_AUTHTYPES, "(EAP-TNC) ACKing.\n");
eaphdr->eap_length = htons(sizeof(struct eap_header)+1);
resdataptr[0] = 0x00 | TNC_MAX_VERSION_SUPPORTED; // TNC-ACK.
return resdata;
}
FREE(resdata); // This memory was only needed if we sent an ACK.
if (queue_get_size(&tnc->tncoutqueue, &queuesize) < 0)
{
debug_printf(DEBUG_NORMAL, "Error getting queue depth!\n");
return NULL;
}
athead = queue_at_head(&tnc->tncoutqueue);
if (queuesize == 0)
{
debug_printf(DEBUG_AUTHTYPES, "No data left to send.\n");
return NULL;
}
res_size = maxsize - 6; // Leave room in case we need to slap a length header on.
more = queue_dequeue(&tnc->tncoutqueue, &dequeue_data, &res_size);
if (more < 0)
{
debug_printf(DEBUG_NORMAL, "Couldn't get more fragments to send to authenticator.\n");
return NULL;
}
// If we are at the head of the list, we need to send a length.
if (athead == TRUE)
{
retdata = Malloc(res_size + 5 + sizeof(struct eap_header));
if (retdata == NULL)
{
FREE(dequeue_data);
return NULL;
}
dataptr = (uint8_t *)&retdata[5];
retdata[0] = TNC_LENGTH_FLAG; // Length is included in this message.
cpysize = res_size;
retlen = htonl(queuesize);
memcpy(&retdata[1], &retlen, sizeof(uint32_t));
res_size+=5;
}
else
{
retdata = Malloc(res_size+1+sizeof(struct eap_header));
if (retdata == NULL)
{
FREE(dequeue_data);
return NULL;
}
cpysize = res_size;
dataptr = (uint8_t *)&retdata[1];
res_size++;
}
// If more == TRUE then we have more fragments, and need to include that indication
if (more == TRUE)
{
retdata[0] |= TNC_MORE_FLAG;
}
memcpy(dataptr, dequeue_data, cpysize);
FREE(dequeue_data);
if (queue_queue_done(&tnc->tncoutqueue) != 0)
{
debug_printf(DEBUG_TLS_CORE, "Finished with queue... Freeing.\n");
if (queue_destroy(&tnc->tncoutqueue) != 0)
{
debug_printf(DEBUG_NORMAL, "Couldn't destroy queue data! (We will probably leak memory.)\n");
}
}
retdata[0] |= TNC_MAX_VERSION_SUPPORTED;
resdata = malloc(res_size + sizeof(struct eap_header));
if (resdata == NULL) return NULL;
eaphdr = (struct eap_header *)resdata;
eaphdr->eap_code = EAP_RESPONSE_PKT;
eaphdr->eap_identifier = eap_type_common_get_eap_reqid(eapdata->eapReqData);
eaphdr->eap_type = EAP_TYPE_TNC;
resdataptr = resdata;
resdataptr += sizeof(struct eap_header);
value16 = res_size+sizeof(struct eap_header);
eaphdr->eap_length = htons(value16);
memcpy(&resdata[sizeof(struct eap_header)], retdata, res_size);
FREE(retdata);
debug_printf(DEBUG_AUTHTYPES, "TNC returns (%d) : \n", res_size+sizeof(struct eap_header));
debug_hex_dump(DEBUG_AUTHTYPES, resdata, res_size + sizeof(struct eap_header));
eapdata->methodState = MAY_CONT;
eapdata->decision = COND_SUCC;
eapdata->ignore = FALSE;
return resdata;
}
/**
* \brief Check to see if keys are available. (For EAP-TNC there NEVER will be!)
*
* There will never be keying material available from the current
* incarnation of this standard!
*
* @param[in] eapdata The EAP data that may be needed to complete a TNC session.
*
* \retval FALSE since TNC should *NEVER* be used as a phase 1 method, and should *NEVER* have keying material.
**/
uint8_t eaptnc_isKeyAvailable(eap_type_data *eapdata)
{
return FALSE;
}
/**
* \brief Return any EAP specific keying material. (None will be returned because TNC doesn't generate
* any, and it isn't a valid phase 1 method.)
*
* @param[in] eapdata A pointer to EAP specific data that may be used to complete a TNC session.
*
* \retval NULL since keying material will *NEVER* be generated!
**/
uint8_t *eaptnc_getKey(eap_type_data *eapdata)
{
debug_printf(DEBUG_NORMAL, "EAP-TNC was asked to provide keying material! "
"If you ever see this message, then there is something badly "
"broken in the code! Please report it along with a full "
"debug output!\n");
return NULL;
}
/**
* \brief Clean up any memory that was used by EAP TNC.
*
* @param[in] eapdata A pointer to a buffer that we would have used to store EAP specific data. This
* buffer is what we need to clean up.
**/
void eaptnc_deinit(eap_type_data *eapdata)
{
struct tnc_data *tnc = NULL;
debug_printf(DEBUG_AUTHTYPES, "(EAP-TNC) Deinit.\n");
if (eapdata == NULL) return;
if (eapdata->eap_data == NULL) return;
tnc = (struct tnc_data *)eapdata->eap_data;
if (tnc->tncinqueue != NULL)
{
if (queue_destroy(&tnc->tncinqueue) != 0)
{
debug_printf(DEBUG_NORMAL, "Couldn't clean up incoming queue!\n");
}
}
if (tnc->tncoutqueue != NULL)
{
if (queue_destroy(&tnc->tncoutqueue) != 0)
{
debug_printf(DEBUG_NORMAL, "Couldn't clean up outgoing queue!\n");
}
}
tnc->expected_in = 0;
FREE(eapdata->eap_data);
tnc = NULL;
tncdatahook = NULL;
}
/**
* \brief Callback used by TNCC when it has a finished batch that is ready to
* be sent.
*
* @param[in] connectionID The connectionID used by the IMC to keep track of the connection.
* @param[in] messageBuffer The message that should be sent to the server.
* @param[in] messageLength The length of the buffer pointed to by messageBuffer.
*
* \retval TNC_RESULT_FATAL on error
* \retval TNC_RESULT_SUCCESS on success
*
**/
TNC_Result TNC_TNCC_SendBatch(
/*in*/ TNC_ConnectionID connectionID,
/*in*/ const char* messageBuffer,
/*in*/ size_t messageLength)
{
if (tncdatahook == NULL)
{
debug_printf(DEBUG_NORMAL, "TNC data hook not available.\n");
return TNC_RESULT_FATAL;
}
if (tncdatahook->tncoutqueue == NULL)
{
if (queue_create(&tncdatahook->tncoutqueue) != 0)
{
debug_printf(DEBUG_NORMAL, "Couldn't create outbound queue!\n");
return TNC_RESULT_FATAL;
}
}
if (queue_enqueue(&tncdatahook->tncoutqueue, (uint8_t *)messageBuffer, messageLength) != 0)
{
debug_printf(DEBUG_NORMAL, "Couldn't enqueue data in outbound queue.\n");
return TNC_RESULT_FATAL;
}
return TNC_RESULT_SUCCESS;
}
#endif /* HAVE_TNC */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?