eapfast_phase2.c
来自「linux 下通过802.1认证的安装包」· C语言 代码 · 共 1,907 行 · 第 1/4 页
C
1,907 行
tempaidi = Malloc(ntohs(fasttlv->length));
if (tempaidi == NULL)
{
debug_printf(DEBUG_NORMAL, "Couldn't allocate memory to store AID "
"info.\n");
return 0;
}
memcpy(tempaidi, indata+4, ntohs(fasttlv->length));
(*aid_info) = tempaidi;
return (ntohs(fasttlv->length)+4);
}
/*******************************************************************
*
* Process a PAC-Info Credential Lifetime message.
*
*******************************************************************/
uint16_t eapfast_phase2_process_cred_lifetime(uint8_t *indata, uint8_t *cred)
{
struct eapfast_tlv *fasttlv;
if (!xsup_assert((indata != NULL), "indata != NULL", FALSE))
return 0;
if (!xsup_assert((cred != NULL), "cred != NULL", FALSE))
return 0;
fasttlv = (struct eapfast_tlv *)cred;
if (fasttlv->length != 4)
{
debug_printf(DEBUG_NORMAL, "Invalid Credential length! Expected a "
"length of 4, got a length of %d.\n", fasttlv->length);
return fasttlv->length+4;
}
memcpy(cred, fasttlv->data, 4);
return fasttlv->length+4;
}
/*******************************************************************
*
* Process a PAC Info TLV and all of it's children.
*
*******************************************************************/
uint16_t eapfast_phase2_process_pac_info(uint8_t *indata,
struct pac_info *pacinfo)
{
struct eapfast_tlv *fasttlv;
uint16_t consumed = 0, result = 0, size = 0;
if (!xsup_assert((indata != NULL), "indata != NULL", FALSE))
return 0;
if (!xsup_assert((pacinfo != NULL), "pacinfo != NULL", FALSE))
return 0;
fasttlv = (struct eapfast_tlv *)indata;
size = ntohs(fasttlv->length);
debug_printf(DEBUG_AUTHTYPES, "Processing %d byte(s) of data.\n", size);
indata+=4;
while (consumed < size)
{
fasttlv = (struct eapfast_tlv *)&indata[consumed];
debug_printf(DEBUG_AUTHTYPES, "Data (%d) : \n", (size - consumed));
debug_hex_dump(DEBUG_AUTHTYPES, &indata[consumed], (size - consumed));
switch ((ntohs(fasttlv->type) & MANDATORY_TLV_MASK_OUT))
{
case FAST_CRED_LIFETIME:
debug_printf(DEBUG_AUTHTYPES, "Got a PAC-Info CRED_LIFETIME TLV\n");
result = eapfast_phase2_process_cred_lifetime(&indata[consumed],
(uint8_t *)&pacinfo->cred_lifetime);
break;
case FAST_AUTHORITY_ID:
debug_printf(DEBUG_AUTHTYPES, "Got a PAC-Info AUTHORITY_ID TLV.\n");
result = eapfast_phase2_process_aid(&indata[consumed],
&pacinfo->aid,
&pacinfo->aid_len);
break;
case FAST_INFO_ID:
debug_printf(DEBUG_AUTHTYPES, "Got a PAC-Info INFO_ID TLV.\n");
result = eapfast_phase2_process_iid(&indata[consumed],
&pacinfo->iid,
&pacinfo->iid_len);
break;
case FAST_AUTH_ID_INFO:
debug_printf(DEBUG_AUTHTYPES, "Got a PAC-Info AUTH_ID_INFO TLV.\n");
result = eapfast_phase2_process_pac_aidinfo(&indata[consumed],
&pacinfo->aid_info,
&pacinfo->aid_info_len);
break;
case FAST_PAC_TYPE:
debug_printf(DEBUG_AUTHTYPES, "Got a PAC-Info PAC_TYPE TLV.\n");
result = eapfast_phase2_process_pac_type(&indata[consumed],
&pacinfo->pac_type);
break;
default:
debug_printf(DEBUG_NORMAL, "Unknown/unexpected PAC-Info sub-value "
"of %d found!\n", ntohs(fasttlv->type));
return 0;
}
consumed += result;
}
return (consumed + 4);
}
/*******************************************************************
*
* Write the PAC to a file for later use.
*
*******************************************************************/
int eapfast_phase2_store_pac(eap_type_data *eapdata, struct pac_values *pacs)
{
xmlDocPtr doc;
struct config_eap_fast *fastconf;
if (!xsup_assert((eapdata != NULL), "eapdata != NULL", FALSE))
return -1;
if (!xsup_assert((eapdata->eap_conf_data != NULL),
"eapdata->eap_conf_data != NULL", FALSE))
return -1;
fastconf = (struct config_eap_fast *)eapdata->eap_conf_data;
eapfast_xml_init();
if (fastconf->pac_location == NULL)
{
debug_printf(DEBUG_NORMAL, "You need to specify a location to store PAC"
" data in your configuration file!\n");
return -1;
}
doc = eapfast_xml_open_pac(fastconf->pac_location);
if (doc == NULL)
{
// We need to create a new PAC file.
doc = eapfast_xml_create_pac_struct();
}
if (eapfast_xml_add_pac(doc, pacs) != 0)
{
debug_printf(DEBUG_NORMAL, "Error adding PAC data to PAC data structure "
"in memory!\n");
return -1;
}
if (eapfast_xml_save(fastconf->pac_location, doc) != 0)
{
debug_printf(DEBUG_NORMAL, "Couldn't save PAC file to location '%s'.\n");
debug_printf(DEBUG_NORMAL, "You will be forced to provision again.\n");
return -1;
}
return 0;
}
/*******************************************************************
*
* Send a PAC Acknowledgement.
*
*******************************************************************/
void eapfast_phase2_build_pac_ack(eap_type_data *eapdata)
{
// The ACK structure is the same as the TLV result. So we will just
// use that here.
struct eapfast_tlv_result *ack;
struct tls_vars *mytls_vars;
struct eapfast_phase2 *phase2;
struct eapfast_tlv *tlv;
if (!xsup_assert((eapdata != NULL), "eapdata != NULL", FALSE))
return;
debug_printf(DEBUG_AUTHTYPES, "Building PAC ACK!\n");
mytls_vars = (struct tls_vars *)eapdata->eap_data;
phase2 = (struct eapfast_phase2 *)mytls_vars->phase2data;
tlv = (struct eapfast_tlv *)&phase2->result_data[phase2->result_size];
tlv->type = htons(FAST_PAC_TLV | MANDATORY_TLV);
tlv->length = htons(sizeof(struct eapfast_tlv_result));
phase2->result_size += sizeof(struct eapfast_tlv);
ack = (struct eapfast_tlv_result *)&phase2->result_data[phase2->result_size];
ack->type = htons(FAST_PAC_ACK);
ack->length = htons(2);
ack->status = htons(1); // Success.
// And we are done.
eapdata->methodState = DONE;
phase2->result_size += sizeof(struct eapfast_tlv_result);
}
/*******************************************************************
*
* Process a PAC TLV.
*
*******************************************************************/
uint16_t eapfast_phase2_pac_process(eap_type_data *eapdata, uint8_t *indata,
uint16_t insize)
{
struct eapfast_tlv *fastlv;
uint16_t consumed = 0, result = 0, size = 0;
struct pac_values pacs;
struct tls_vars *mytls_vars;
struct eapfast_phase2 *phase2;
uint8_t *temp;
if (!xsup_assert((eapdata != NULL), "eapdata != NULL", FALSE))
return 0;
if (!xsup_assert((eapdata->eap_data != NULL), "eapdata->eap_data != NULL",
FALSE))
return 0;
if (!xsup_assert((indata != NULL), "indata != NULL", FALSE))
return 0;
// We need to loop through all of the TLVs that we have in this EAP message,
// and process each one.
fastlv = (struct eapfast_tlv *)indata;
mytls_vars = (struct tls_vars *)eapdata->eap_data;
phase2 = (struct eapfast_phase2 *)mytls_vars->phase2data;
size = ntohs(fastlv->length);
debug_printf(DEBUG_AUTHTYPES, "Processing %d byte(s) of data.\n", size);
indata+=4;
while (consumed < size)
{
fastlv = (struct eapfast_tlv *)&indata[consumed];
debug_printf(DEBUG_AUTHTYPES, "Remaining (%d) : \n", insize - consumed);
debug_hex_dump(DEBUG_AUTHTYPES, &indata[consumed], (insize - consumed));
switch ((ntohs(fastlv->type) & MANDATORY_TLV_MASK_OUT))
{
case FAST_PAC_KEY:
debug_printf(DEBUG_AUTHTYPES, "Got a PAC-Key TLV.\n");
result = eapfast_phase2_process_pac_key(&indata[consumed],
(uint8_t *)&pacs.pac_key);
break;
case FAST_PAC_OPAQUE:
debug_printf(DEBUG_AUTHTYPES, "Got a PAC-Opaque TLV.\n");
result = eapfast_phase2_process_pac_opaque(&indata[consumed],
&pacs.pac_opaque,
&pacs.pac_opaque_len);
break;
case FAST_PAC_INFO:
debug_printf(DEBUG_AUTHTYPES, "Got a PAC-Info TLV.\n");
result = eapfast_phase2_process_pac_info(&indata[consumed],
&pacs.pacinfo);
break;
default:
debug_printf(DEBUG_NORMAL, "Unknown/unexpected PAC TLV request %d."
"\n", fastlv->type);
result = 0;
break;
}
if (result == 0)
{
debug_printf(DEBUG_NORMAL, "An error occurred processing PAC "
"information. You will need to attempt to provision "
"again.\n");
return 0;
}
consumed += result;
}
if (eapfast_phase2_store_pac(eapdata, &pacs) == 0)
{
eapfast_phase2_build_pac_ack(eapdata);
}
else
{
// Return an error.
temp = eapfast_phase2_gen_error_tlv(FAST_TUNNEL_COMPROMISE_ERROR,
(ntohs(fastlv->type) & MANDATORY_TLV));
memcpy(&phase2->result_data[phase2->result_size], temp,
sizeof(struct eapfast_tlv_error));
FREE(temp);
phase2->result_size += sizeof(struct eapfast_tlv_error);
}
return (consumed + 4);
}
/**************************************************************
*
* Generate the values needed to crypto bind the tunnel, and to
* populate EAP-MSCHAPv2 if we are going anonymous provisioning.
*
**************************************************************/
void eapfast_phase2_provision_gen_crypt(eap_type_data *eapdata)
{
struct tls_vars *mytls_vars;
struct eapfast_phase2 *phase2;
uint8_t *keyblock, *temp;
int offset_to_prov_keys;
if (!xsup_assert((eapdata != NULL), "eapdata != NULL", FALSE))
return;
if (!xsup_assert((eapdata->eap_data != NULL), "eapdata->eap_data != NULL",
FALSE))
{
eap_type_common_fail(eapdata);
return;
}
mytls_vars = (struct tls_vars *)eapdata->eap_data;
phase2 = (struct eapfast_phase2 *)mytls_vars->phase2data;
offset_to_prov_keys = tls_funcs_get_keyblock_len(mytls_vars);
keyblock = tls_funcs_gen_keyblock(mytls_vars, TLS_FUNCS_SERVER_FIRST,
FAST_PROVISIONING_SESSION_KEY,
FAST_PROVISIONING_SESSION_KEY_LEN);
temp = &keyblock[offset_to_prov_keys];
phase2->pkeys = Malloc(sizeof (struct provisioning_keys));
if (phase2->pkeys == NULL)
{
debug_printf(DEBUG_NORMAL, "Failed to allocate memory to store keys "
"needed to complete provisioning.\n");
FREE(keyblock);
return;
}
memcpy(phase2->pkeys, temp, sizeof(struct provisioning_keys));
FREE(keyblock);
}
/**************************************************************
*
* Process a phase 2 EAP message.
*
**************************************************************/
uint16_t eapfast_phase2_eap_process(eap_type_data *eapdata, uint8_t *indata,
uint16_t insize)
{
struct tls_vars *mytls_vars;
struct eapfast_phase2 *phase2;
uint16_t eapsize;
uint8_t doneinit = 0;
struct eapfast_tlv *fasttlv;
struct config_eap_fast *fastconfig;
if (!xsup_assert((eapdata != NULL), "eapdata != NULL", FALSE))
return 0;
if (!xsup_assert((eapdata->eap_data != NULL), "eapdata->eap_data != NULL",
FALSE))
{
eap_type_common_fail(eapdata);
return 0;
}
if (!xsup_assert((eapdata->eap_conf_data != NULL),
"eapdata->eap_conf_data != NULL", FALSE))
{
eap_type_common_fail(eapdata);
return 0;
}
fasttlv = (struct eapfast_tlv *)indata;
debug_printf(DEBUG_AUTHTYPES, "Processing phase 2 EAP.\n");
debug_printf(DEBUG_AUTHTYPES, "EAP portion (%d) : \n", insize - 4);
debug_hex_dump(DEBUG_AUTHTYPES, indata + 4, ntohs(fasttlv->length));
mytls_vars = (struct tls_vars *)eapdata->eap_data;
phase2 = (struct eapfast_phase2 *)mytls_vars->phase2data;
fastconfig = (struct config_eap_fast *)eapdata->eap_conf_data;
phase2->sm->eapReqData = &indata[4];
phase2->sm->eapReq = TRUE;
if (phase2->sm->methodState == INIT)
{
doneinit = TRUE;
// Need to generate some crypto data.
eapfast_phase2_provision_gen_crypt(eapdata);
if ((phase2->provisioning == TRUE) &&
(fastconfig->phase2->method_num == EAP_TYPE_MSCHAPV2))
{
debug_printf(DEBUG_AUTHTYPES, "Setting up EAP-MS-CHAPv2.\n");
debug_printf(DEBUG_AUTHTYPES, "Peer Challenge : ");
debug_hex_printf(DEBUG_AUTHTYPES, phase2->pkeys->MSCHAPv2_ClientChallenge, 16);
debug_printf(DEBUG_AUTHTYPES, "Authenticator Challenge : ");
debug_hex_printf(DEBUG_AUTHTYPES, phase2->pkeys->MSCHAPv2_ServerChallenge, 16);
// Tweak MS-CHAPv2 to work properly for provisioning.
if (eapmschapv2_set_challenges(phase2->pkeys->MSCHAPv2_ClientChallenge,
phase2->pkeys->MSCHAPv2_ServerChallenge) != TRUE)
{
debug_printf(DEBUG_NORMAL, "Couldn't configure challenge values"
" needed for MS-CHAPv2.\n");
eap_type_common_fail(eapdata);
return 0;
}
}
if (phase2->provisioning == FALSE)
{
debug_printf(DEBUG_AUTHTYPES, "Clearing EAP-FAST provisioning mode "
"from MS-CHAPv2.\n");
if (eapmschapv2_set_challenges(NULL, NULL) != TRUE)
{
debug_printf(DEBUG_NORMAL, "Couldn't clear MS-CHAPv2 challenges"
"! If you are using MS-CHAPv2 as an inner "
"authentication method, it will probably fail!\n");
}
}
}
eap_sm_run(phase2->sm);
if (doneinit)
{
if (phase2->provisioning == TRUE)
{
eapmschapv2_set_eap_fast_mode((eap_type_data *)phase2->sm->active,
TRUE);
}
else
{
eapmschapv2_set_eap_fast_mode((eap_type_data *)phase2->sm->active,
FALSE);
}
}
if (phase2->sm->eapRespData != NULL)
{
// Build up the response data.
eapsize = eap_type_common_get_eap_length(phase2->sm->eapRespData);
memcpy(&phase2->result_data[phase2->result_size + 4],
phase2->sm->eapRespData, eapsize);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?