📄 eapfast.c
字号:
phase2 = (struct eapfast_phase2 *)mytls_vars->phase2data;
if (packet[sizeof(struct eap_header)] & EAPTLS_LENGTH_INCL)
{
hello = (struct tls_server_hello *)&packet[sizeof(struct eap_header)+5];
}
else
{
hello = (struct tls_server_hello *)&packet[sizeof(struct eap_header)];
}
if (hello->content_type != TLS_HANDSHAKE_TYPE)
{
debug_printf(DEBUG_AUTHTYPES, "Packet is not a handshake packet, "
"ignoring.\n");
debug_printf(DEBUG_AUTHTYPES, "Expected %d, got %d.\n",
TLS_HANDSHAKE_TYPE, hello->content_type);
return;
}
if (ntohs(hello->rec_version) < ntohs(0x0301))
{
debug_printf(DEBUG_NORMAL, "TLS version is not 1.0 or greater!\n");
return;
}
if (hello->handshake_type != TLS_SERVER_HELLO)
{
debug_printf(DEBUG_AUTHTYPES, "Packet is not a server hello. "
"Ignoring.\n");
return;
}
if (ntohs(hello->shake_version) < ntohs(0x0301))
{
debug_printf(DEBUG_NORMAL, "Server Handshake version is not TLS 1.0 "
"or greater!\n");
return;
}
if (eapfast_calc_master_secret(mytls_vars, hello->server_random) == 0)
{
// We don't need to parse TLS packets anymore.
phase2->need_ms = FALSE;
}
}
/***************************************************************
*
* Process an EAP-FAST packet.
*
***************************************************************/
void eapfast_process(eap_type_data *eapdata)
{
uint8_t *tls_type = NULL, *resbuf = NULL;
uint8_t fast_version;
struct tls_vars *mytls_vars;
struct eapfast_phase2 *phase2;
uint8_t *aid = NULL;
uint16_t aid_len, resout;
int bufsiz;
struct config_eap_fast *fastconf;
debug_printf(DEBUG_AUTHTYPES, "(EAP-FAST) Processing.\n");
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;
}
if (!xsup_assert((eapdata->eap_conf_data != NULL),
"eapdata->eap_conf_data != NULL", FALSE))
{
eap_type_common_fail(eapdata);
return;
}
fastconf = (struct config_eap_fast *)eapdata->eap_conf_data;
mytls_vars = eapdata->eap_data;
tls_type = &eapdata->eapReqData[sizeof(struct eap_header)];
fast_version = (tls_type[0] & FAST_VERSION_MASK);
eapfast_set_ver(eapdata, fast_version);
debug_printf(DEBUG_AUTHTYPES, "Request EAP-FAST version is %d.\n",
fast_version);
tls_type[0] = (tls_type[0] & FAST_VERSION_MASK_OUT);
if ((eapdata->eapReqData[sizeof(struct eap_header)] == EAPTLS_START)
|| (mytls_vars->handshake_done != TRUE))
{
debug_printf(DEBUG_AUTHTYPES, "(EAP-FAST) Processing packet.\n");
if (eapdata->eapReqData[sizeof(struct eap_header)] == EAPTLS_START)
{
if (eapfast_get_aid(&eapdata->eapReqData[sizeof(struct eap_header)+1],
&aid, &aid_len) == TRUE)
{
debug_printf(DEBUG_AUTHTYPES, "Got AID (%d byte(s)) : ", aid_len);
debug_hex_printf(DEBUG_AUTHTYPES, aid, aid_len);
if (eapfast_check_pac(eapdata, aid, aid_len) == FALSE)
{
debug_printf(DEBUG_AUTHTYPES, "Couldn't locate a PAC file. "
"We will provision one.\n");
// We don't have a PAC, are we allowed to provision one?
if (fastconf->provision != RES_YES)
{
debug_printf(DEBUG_NORMAL, "We are not configured to "
"allow provisioning! Your authentication"
" cannot continue.\n");
eap_type_common_fail(eapdata);
return;
}
// Otherwise, determine how we can provision credentials.
// Right now, we only support unauthenticated mode.
// XXX - Add authenticated mode!
if (tls_funcs_set_anon_dh_aes(mytls_vars) == -1)
{
eap_type_common_fail(eapdata);
return;
}
phase2 = (struct eapfast_phase2 *)mytls_vars->phase2data;
phase2->provisioning = TRUE;
}
else
{
phase2 = (struct eapfast_phase2 *)mytls_vars->phase2data;
phase2->provisioning = FALSE;
// We have a PAC, so configure TLS, and move on.
if (tls_funcs_set_hello_extension(mytls_vars,
FAST_SESSION_TICKET,
phase2->pacs->pac_opaque,
phase2->pacs->pac_opaque_len) != 1)
{
debug_printf(DEBUG_NORMAL, "Error attempting to set the "
"session key data for EAP-FAST!\n");
eap_type_common_fail(eapdata);
return;
}
// Let us know that we need to "hand parse" the Server
// Hello packet to get the server random.
phase2->need_ms = TRUE;
}
}
else
{
eap_type_common_fail(eapdata);
return;
}
}
FREE(aid);
phase2 = (struct eapfast_phase2 *)mytls_vars->phase2data;
if (phase2->need_ms == 1)
{
eapfast_parse_tls(mytls_vars, eapdata->eapReqData);
}
eapdata->methodState = tls_funcs_process(eapdata->eap_data,
eapdata->eapReqData);
if ((mytls_vars->handshake_done == TRUE) && (phase2->provisioning == TRUE))
mytls_vars->send_ack = TRUE;
}
else
{
// Handle phase 2 stuff.
resout = eap_type_common_get_eap_length(eapdata->eapReqData);
if (tls_funcs_buffer(eapdata->eap_data,
&eapdata->eapReqData[sizeof(struct eap_header)],
resout) != XENONE)
{
debug_printf(DEBUG_NORMAL, "There was an error buffering data "
"fragments. Discarding fragment.\n");
eapdata->ignore = FALSE;
return;
}
bufsiz = tls_funcs_decrypt_ready(eapdata->eap_data);
debug_printf(DEBUG_AUTHTYPES, "Decrypt ready returned : %d\n", bufsiz);
switch (bufsiz)
{
case 0:
// Nothing to do yet.
break;
case -1:
// Got an error. Discard the frame.
eap_type_common_fail(eapdata);
break;
default:
resbuf = Malloc(bufsiz);
if (resbuf == NULL)
{
debug_printf(DEBUG_NORMAL, "Couldn't allocate memory needed to "
"store decrypted data!\n");
eap_type_common_fail(eapdata);
break;
}
resout = bufsiz;
if (tls_funcs_decrypt(eapdata->eap_data, resbuf, &resout) != XENONE)
{
debug_printf(DEBUG_NORMAL, "Decryption failed!\n");
eap_type_common_fail(eapdata);
break;
}
debug_printf(DEBUG_AUTHTYPES, "Inner dump (%d) :\n", resout);
debug_hex_dump(DEBUG_AUTHTYPES, resbuf, resout);
eapfast_phase2_process(eapdata, resbuf, resout);
FREE(resbuf);
break;
}
}
}
/***************************************************************
*
* Build a response to an EAP-FAST request.
*
***************************************************************/
uint8_t *eapfast_buildResp(eap_type_data *eapdata)
{
struct config_eap_fast *eapconf;
uint8_t *res = NULL, *fastres = NULL;
uint16_t res_size = 0, total_size = 0;
struct eap_header *eaphdr;
uint8_t reqId;
struct tls_vars *mytls_vars = NULL;
if (!xsup_assert((eapdata != NULL), "eapdata != NULL", FALSE))
return NULL;
if (!xsup_assert((eapdata->eap_data != NULL), "eapdata->eap_data != NULL",
FALSE))
return NULL;
if (!xsup_assert((eapdata->eap_conf_data != NULL),
"eapdata->eap_conf_data != NULL", FALSE))
return NULL;
eapconf = eapdata->eap_conf_data;
mytls_vars = (struct tls_vars *)eapdata->eap_data;
if ((mytls_vars->handshake_done == TRUE) &&
(tls_funcs_data_pending(mytls_vars) == 0))
{
if ((mytls_vars->handshake_done == TRUE) &&
(tls_funcs_decrypt_ready(mytls_vars) == 0) &&
(mytls_vars->send_ack == FALSE))
{
// Handle phase 2 stuff.
res = Malloc(1520);
if (res == NULL)
{
debug_printf(DEBUG_NORMAL, "Couldn't allocate memory to store "
"result.\n");
return NULL;
}
eapfast_phase2_buildResp(eapdata, res, &res_size);
tls_funcs_encrypt(eapdata->eap_data, res, res_size);
FREE(res);
}
}
if ((eapconf->chunk_size == 0) || (eapconf->chunk_size > MAX_CHUNK))
eapconf->chunk_size = MAX_CHUNK;
if (tls_funcs_get_packet(eapdata->eap_data, eapconf->chunk_size, &res,
&res_size) != XENONE)
{
return NULL;
}
if (res == NULL) return NULL;
mytls_vars->send_ack = FALSE;
eaphdr = (struct eap_header *)eapdata->eapReqData;
reqId = eaphdr->eap_identifier;
fastres = Malloc(res_size + sizeof(struct eap_header));
if (fastres == NULL) return NULL;
eaphdr = (struct eap_header *)fastres;
eaphdr->eap_code = EAP_RESPONSE_PKT;
eaphdr->eap_identifier = reqId;
total_size = res_size + sizeof(struct eap_header);
eaphdr->eap_length = htons(total_size);
eaphdr->eap_type = EAP_TYPE_FAST;
memcpy(&fastres[sizeof(struct eap_header)], res, res_size);
fastres[sizeof(struct eap_header)] |= eapfast_get_ver(eapdata);
FREE(res);
return fastres;
}
/***************************************************************
*
* Determine if we have keying material available.
*
***************************************************************/
uint8_t eapfast_isKeyAvailable(eap_type_data *eapdata)
{
struct tls_vars *mytls_vars;
uint8_t *simckj;
if (!xsup_assert((eapdata != NULL), "eapdata != NULL", FALSE))
return FALSE;
if (!xsup_assert((eapdata->eap_data != NULL), "eapdata->eap_data != NULL",
FALSE))
return FALSE;
mytls_vars = (struct tls_vars *)eapdata->eap_data;
if (mytls_vars->handshake_done == FALSE) return FALSE;
if (mytls_vars->keyblock != NULL)
{
FREE(mytls_vars->keyblock);
}
simckj = eapfast_phase2_get_simckj(eapdata);
if (simckj == NULL) return FALSE;
mytls_vars->keyblock = eapfast_phase2_t_prf(simckj, 40, FAST_SESSION_KEY,
NULL, 0, 64);
if (mytls_vars->keyblock != NULL) return TRUE;
return FALSE;
}
/***************************************************************
*
* If there is keying material available, then return a key.
*
***************************************************************/
uint8_t *eapfast_getKey(eap_type_data *eapdata)
{
struct tls_vars *mytls_vars;
uint8_t *retkey;
if (!xsup_assert((eapdata != NULL), "eapdata != NULL", FALSE))
return NULL;
if (!xsup_assert((eapdata->eap_data != NULL), "eapdata->eap_data != NULL",
FALSE))
return NULL;
mytls_vars = (struct tls_vars *)eapdata->eap_data;
retkey = Malloc(64);
if (retkey == NULL)
{
debug_printf(DEBUG_NORMAL, "Couldn't allocate memory to return key "
"data!\n");
return NULL;
}
memcpy(retkey, mytls_vars->keyblock, 64);
return retkey;
}
/***************************************************************
*
* Clean up any memory that we have used.
*
***************************************************************/
void eapfast_deinit(eap_type_data *eapdata)
{
struct tls_vars *mytls_vars;
if (!xsup_assert((eapdata != NULL), "eapdata != NULL", FALSE))
return;
if (!xsup_assert((eapdata->eap_data != NULL),
"eapdata->eap_data != NULL", FALSE))
return;
mytls_vars = (struct tls_vars *)eapdata->eap_data;
eapfast_phase2_deinit(eapdata);
tls_funcs_deinit(mytls_vars);
FREE(mytls_vars);
FREE(eapdata->eap_data);
debug_printf(DEBUG_DEINIT, "(EAP-FAST) Cleaned up.\n");
}
#endif // EAP_FAST
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -