📄 eapttls.c
字号:
/**
* EAPTTLS Function implementations
*
* Licensed under a dual GPL/BSD license. (See LICENSE file for more info.)
*
* \file eapttls.c
*
* \author chris@open1x.org
*
* $Id: eapttls.c,v 1.44.2.61 2008/01/21 22:51:50 chessing Exp $
* $Date: 2008/01/21 22:51:50 $
**/
#include <string.h>
#include <stdlib.h>
#ifdef WINDOWS
#include <Winsock2.h>
#endif
#include "../../../lib/libxsupconfig/xsupconfig_structs.h"
#include "../../xsup_common.h"
#include "../../../lib/libxsupconfig/xsupconfig.h"
#include "../../context.h"
#include "../../xsup_debug.h"
#include "../../xsup_err.h"
#include "../../frame_structs.h"
#include "../../eap_sm.h"
#include "../../eap_types/tls/eaptls.h"
#include "../../eap_types/ttls/eapttls.h"
#include "../../eap_types/ttls/ttlsphase2.h"
#include "pap.h"
#include "../../eap_types/tls/tls_funcs.h"
#include "../../eap_types/eap_type_common.h"
#include "../../ipc_callout.h"
#include "../../xsup_ipc.h"
#include "../../ipc_events.h"
#include "../../ipc_events_index.h"
#include "../tls/certificates.h"
#ifdef USE_EFENCE
#include <efence.h>
#endif
/**
* Init the memory needed for us to complete a TTLS authentication.
**/
int eapttls_init(eap_type_data *eapdata)
{
struct tls_vars *mytls_vars = NULL;
struct config_eap_ttls *userdata = NULL;
if (!xsup_assert((eapdata != NULL), "eapdata != NULL", FALSE))
return XEMALLOC;
debug_printf(DEBUG_AUTHTYPES, "(EAP-TTLS) Initing.\n");
userdata = (struct config_eap_ttls *)eapdata->eap_conf_data;
if (userdata == NULL)
{
debug_printf(DEBUG_NORMAL, "EAP-TTLS setup was passed NULL userdata! We"
" cannot continue with this attempt at authentication!\n");
return XENOUSERDATA;
}
// First, set up the structure to hold all of our instance specific
// variables.
if (eapdata->eap_data == NULL)
{
eapdata->eap_data = (char *)Malloc(sizeof(struct tls_vars));
if (eapdata->eap_data == NULL)
{
debug_printf(DEBUG_NORMAL, "Unable to allocate memory for "
"eapdata->eap_data in eapttls_setup()!\n");
ipc_events_malloc_failed(NULL);
return XEMALLOC;
}
mytls_vars = (struct tls_vars *)eapdata->eap_data;
}
else
{
mytls_vars = (struct tls_vars *)eapdata->eap_data;
}
mytls_vars->resume = userdata->session_resume;
if (userdata->validate_cert == FALSE)
{
mytls_vars->verify_cert = FALSE;
}
else
{
mytls_vars->verify_cert = TRUE;
}
FREE(mytls_vars->keyblock);
FREE(mytls_vars->sessionkeyconst);
mytls_vars->sessionkeyconst = (uint8_t *)_strdup(TTLS_SESSION_KEY_CONST);
mytls_vars->sessionkeylen = TTLS_SESSION_KEY_CONST_SIZE;
if (tls_funcs_init(mytls_vars, EAP_TYPE_TTLS) != XENONE)
{
debug_printf(DEBUG_NORMAL, "Couldn't initialize SSL!\n");
return XETLSINIT;
}
mytls_vars->handshake_done = FALSE;
mytls_vars->certs_loaded &= ~ROOT_CERTS_LOADED;
eap_type_common_init_eap_data(eapdata);
debug_printf(DEBUG_AUTHTYPES, "(EAP-TTLS) Initialized.\n");
return XENONE;
}
/***********************************************************************
*
* Once we are done with this EAP method, we need to clean up the memory
* we were using.
*
***********************************************************************/
void eapttls_deinit(eap_type_data *eapdata)
{
struct tls_vars *mytls_vars = NULL;
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;
// Call ttls_phase2_deinit first.
ttls_phase2_deinit(eapdata);
tls_funcs_deinit(mytls_vars);
FREE(mytls_vars->sessionkeyconst);
FREE(mytls_vars->keyblock);
FREE(eapdata->eap_data);
debug_printf(DEBUG_AUTHTYPES, "(EAP-TTLS) Cleaned up.\n");
}
/*****************************************************************
*
* Check to be sure we have everything we need to complete an authentication.
*
******************************************************************/
void eapttls_check(eap_type_data *eapdata)
{
struct config_eap_ttls *ttlsconf = NULL;
struct tls_vars *mytls_vars = NULL;
struct config_globals *globals = NULL;
if (!xsup_assert((eapdata != NULL), "eapdata != NULL", FALSE))
return;
if (!xsup_assert((eapdata->eap_conf_data != NULL),
"eapdata_conf_data != NULL", FALSE))
{
eap_type_common_fail(eapdata);
return;
}
if (eapdata->methodState == INIT)
{
debug_printf(DEBUG_AUTHTYPES, "(EAP-TTLS) Requesting Init.\n");
if (eapttls_init(eapdata) != XENONE)
{
debug_printf(DEBUG_NORMAL, "Failed to properly initialize "
"memory structures for EAP-TTLS!\n");
eap_type_common_fail(eapdata);
return;
}
}
mytls_vars = (struct tls_vars *)eapdata->eap_data;
ttlsconf = (struct config_eap_ttls *)eapdata->eap_conf_data;
if ((ttlsconf->user_key_pass == NULL) && (ttlsconf->user_key != NULL))
{
debug_printf(DEBUG_NORMAL, "No password available for TLS certificate in "
"EAP-TTLS phase 1!\n");
eap_type_common_fail(eapdata);
return;
}
if ((mytls_vars->certs_loaded & ROOT_CERTS_LOADED) != ROOT_CERTS_LOADED)
{
if (ttlsconf->validate_cert == FALSE)
{
// We were told not to verify certificates. Spew out a warning, and
// then do it!
mytls_vars->verify_cert = FALSE;
FREE(mytls_vars->cncheck);
globals = config_get_globals();
if (globals != NULL)
{
if (!TEST_FLAG(globals->flags, CONFIG_GLOBALS_NO_FRIENDLY_WARNINGS))
{
debug_printf(DEBUG_NORMAL, "WARNING - Verification of the Trusted Server's certificate is disabled. The connection's security could be compromised.\n");
}
}
} else {
mytls_vars->verify_cert = TRUE;
if (certificates_load_root(mytls_vars, ttlsconf->trusted_server) != XENONE)
{
debug_printf(DEBUG_NORMAL, "Unable to load root certificate(s)!\n");
eap_type_common_fail(eapdata);
return;
}
// The stuff below should be able to go soon.
}
mytls_vars->certs_loaded |= ROOT_CERTS_LOADED;
}
if ((mytls_vars->certs_loaded & USER_CERTS_LOADED) == 0x00)
{
if ((ttlsconf->user_cert != NULL) && ((ttlsconf->user_key_pass != NULL)))
{
debug_printf(DEBUG_NORMAL, "Using user certificate with TTLS!\n");
tls_funcs_load_user_cert(mytls_vars, ttlsconf->user_cert,
ttlsconf->user_key,
ttlsconf->user_key_pass);
}
mytls_vars->certs_loaded |= USER_CERTS_LOADED;
}
// Check our phase 2 data.
ttls_phase2_check(eapdata);
}
/******************************************************************
*
* Process an EAP-TTLS request, and prepare the data that is needed to
* build a valid response packet.
*
******************************************************************/
void eapttls_process(eap_type_data *eapdata)
{
struct tls_vars *mytls_vars = NULL;
uint8_t *resbuf = NULL;
int16_t bufsiz;
uint16_t resout;
struct eap_header *eaphdr = NULL;
if (!xsup_assert((eapdata != NULL), "eapdata != NULL", FALSE))
return;
if (!xsup_assert((eapdata->eap_conf_data != NULL),
"eapdata->eap_conf_data != NULL", FALSE))
{
eap_type_common_fail(eapdata);
return;
}
if (!xsup_assert((eapdata->eapReqData != NULL),
"eapdata->eapReqData != NULL", FALSE))
{
eap_type_common_fail(eapdata);
return;
}
debug_printf(DEBUG_AUTHTYPES, "(EAP-TTLS) Processing.\n");
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;
if ((eapdata->eapReqData[sizeof(struct eap_header)] == EAPTLS_START)
|| (mytls_vars->handshake_done != TRUE))
{
debug_printf(DEBUG_AUTHTYPES, "(EAP-TTLS) Processing packet.\n");
// Actually start to process the packet.
eapdata->methodState = tls_funcs_process(eapdata->eap_data,
eapdata->eapReqData);
if ((mytls_vars->handshake_done == TRUE) && (eapdata->methodState != DONE))
{
// Process phase 2 data.
debug_printf(DEBUG_AUTHTYPES, "Processing phase 2 data.\n");
ttls_phase2_process(eapdata, NULL, 0);
}
}
else
{
// We are in later packets of phase 2.
eaphdr = (struct eap_header *)eapdata->eapReqData;
resout = ntohs(eaphdr->eap_length) - sizeof(struct eap_header);
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);
switch (bufsiz)
{
case 0:
// Nothing to do yet.
break;
case -1:
// Got an error. Discard the frame.
eap_type_common_fail(eapdata);
break;
default:
// Data to be decrypted.
resbuf = Malloc(bufsiz);
if (resbuf == NULL)
{
debug_printf(DEBUG_NORMAL, "Couldn't allocate memory needed to"
" store decrypted data!\n");
ipc_events_malloc_failed(NULL);
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;
}
ttls_phase2_process(eapdata, resbuf, resout);
FREE(resbuf);
break;
}
}
}
/*********************************************************************
*
* Build an EAP-TTLS response message to be sent back to the authentication
* server.
*
*********************************************************************/
uint8_t *eapttls_buildResp(eap_type_data *eapdata)
{
uint8_t *res = NULL, *ttlsres = NULL;
uint16_t res_size = 0, total_size = 0;
struct eap_header *eaphdr = NULL;
uint8_t reqId;
uint8_t resbuf[1500];
struct tls_vars *mytls_vars = NULL;
struct config_eap_ttls *eapconf = 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)
{
ttls_phase2_buildResp(eapdata, (uint8_t *)&resbuf,
(uint16_t *)&res_size);
if (res_size == 0)
{
// Build ACK.
return eap_type_common_buildAck(eapdata, EAP_TYPE_TTLS);
}
else
{
tls_funcs_encrypt(eapdata->eap_data, resbuf, res_size);
}
}
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;
eaphdr = (struct eap_header *)eapdata->eapReqData;
reqId = eaphdr->eap_identifier;
ttlsres = Malloc(res_size + sizeof(struct eap_header));
if (ttlsres == NULL)
{
ipc_events_malloc_failed(NULL);
return NULL;
}
eaphdr = (struct eap_header *)ttlsres;
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_TTLS;
memcpy(&ttlsres[sizeof(struct eap_header)], res, res_size);
FREE(res);
return ttlsres;
}
/*******************************************************************
*
* Check to see if the EAP method returned any useful key material.
*
*******************************************************************/
uint8_t eapttls_isKeyAvailable(eap_type_data *eapdata)
{
struct tls_vars *mytls_vars = NULL;
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)
{
mytls_vars->keyblock = tls_funcs_gen_keyblock(mytls_vars,
TLS_FUNCS_CLIENT_FIRST,
mytls_vars->sessionkeyconst,
mytls_vars->sessionkeylen);
}
if (mytls_vars->keyblock == NULL) return FALSE;
return TRUE;
}
/*********************************************************************
*
* Actually get the key data and return it.
*
*********************************************************************/
uint8_t *eapttls_getKey(eap_type_data *eapdata)
{
struct tls_vars *mytls_vars = NULL;
uint8_t *keydata = 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;
mytls_vars = (struct tls_vars *)eapdata->eap_data;
keydata = Malloc(64);
if (keydata == NULL)
{
debug_printf(DEBUG_NORMAL, "Couldn't allocate memory to store keying "
"data!\n");
ipc_events_malloc_failed(NULL);
return NULL;
}
memcpy(keydata, mytls_vars->keyblock, 64);
return keydata;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -