📄 eapmschapv2.c
字号:
/**
* EAP-MSCHAPv2 Function implementations
*
* Licensed under a dual GPL/BSD license. (See LICENSE file for more info.)
*
* \file eapmschapv2.c
*
* \author chris@open1x.org
*
* $Id: eapmschapv2.c,v 1.35.2.40 2007/09/01 00:38:27 chessing Exp $
* $Date: 2007/09/01 00:38:27 $
**/
#include <openssl/rand.h>
#include <string.h>
#ifndef WINDOWS
#include <netinet/in.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 "eapmschapv2.h"
#include "mschapv2.h"
#include "../../ipc_callout.h"
#include "../../xsup_ipc.h"
#include "../../eap_types/eap_type_common.h"
#include "../../ipc_events.h"
#include "../../ipc_events_index.h"
#ifdef USE_EFENCE
#include <efence.h>
#endif
static uint8_t *peer_challenge = NULL;
static uint8_t *authenticator_challenge = NULL;
static uint8_t eap_fast_mode = 0;
/******************************************************************
*
* *** NOTE *** This function must be called *BEFORE* the init
* phase of the EAP method. Calling it later will do nothing.
*
* Set the peer_challenge, and authenticator_challenge variables
* above so that we can know that we are in the goofy EAP-FAST mode
* of MS-CHAPv2 and act accordingly.
*
******************************************************************/
// XXX Store this someplace that isn't a global variable!!!
uint8_t eapmschapv2_set_challenges(uint8_t *pc, uint8_t *ac)
{
FREE(peer_challenge);
FREE(authenticator_challenge);
if ((ac == NULL) && (pc == NULL))
{
debug_printf(DEBUG_AUTHTYPES, "Cleared MS-CHAPv2 provisioning mode.\n");
return TRUE;
}
peer_challenge = Malloc(16);
if (peer_challenge == NULL)
{
ipc_events_malloc_failed(NULL);
return FALSE;
}
memcpy(peer_challenge, pc, 16);
debug_printf(DEBUG_AUTHTYPES, "Peer Challenge : ");
debug_hex_printf(DEBUG_AUTHTYPES, peer_challenge, 16);
authenticator_challenge = Malloc(16);
if (authenticator_challenge == NULL)
{
FREE(peer_challenge);
ipc_events_malloc_failed(NULL);
return FALSE;
}
memcpy(authenticator_challenge, ac, 16);
debug_printf(DEBUG_AUTHTYPES, "Authenticator Challenge : ");
debug_hex_printf(DEBUG_AUTHTYPES, authenticator_challenge, 16);
return TRUE;
}
/******************************************************************
*
* Configured EAP-MS-CHAPv2 to run in the weird EAP-FAST modes.
*
******************************************************************/
void eapmschapv2_set_eap_fast_mode(eap_type_data *ctx, uint8_t enable)
{
if (!xsup_assert((ctx != NULL), "ctx != NULL", FALSE))
return;
debug_printf(DEBUG_AUTHTYPES, "Setting EAP-FAST mode for MS-CHAPv2!\n");
eap_fast_mode = enable;
}
/******************************************************************
*
* Execute the INIT functions for this EAP method.
*
******************************************************************/
int eapmschapv2_init(eap_type_data *eapdata)
{
struct mschapv2_vars *mscv2data = NULL;
struct config_eap_mschapv2 *eapconf = NULL;
context *ctx = NULL;
if (!xsup_assert((eapdata != NULL), "eapdata != NULL", FALSE))
return XEMALLOC;
eapconf = (struct config_eap_mschapv2 *)eapdata->eap_conf_data;
if (eapconf == NULL)
{
debug_printf(DEBUG_NORMAL, "There is no valid configuration for "
"EAP-MSCHAPv2.\n");
eap_type_common_fail(eapdata);
return XEGENERROR;
}
// It is possible that this is a reauthentication, and something is
// already on our EAP data hook. So, clear it out.
eapmschapv2_deinit(eapdata);
eapdata->eap_data = (uint8_t *)Malloc(sizeof(struct mschapv2_vars));
if (eapdata->eap_data == NULL)
{
ipc_events_malloc_failed(NULL);
return XEMALLOC;
}
mscv2data = (struct mschapv2_vars *)eapdata->eap_data;
if ((peer_challenge != NULL) && (authenticator_challenge != NULL))
{
eap_fast_mode = TRUE;
mscv2data->AuthenticatorChallenge = authenticator_challenge;
mscv2data->PeerChallenge = peer_challenge;
}
ctx = event_core_get_active_ctx();
if (ctx == NULL)
{
debug_printf(DEBUG_NORMAL, "No password available for EAP-MSCHAPv2!\n");
eap_type_common_fail(eapdata);
return XEGENERROR;
}
if (ctx->prof->temp_password == NULL)
{
if (eapconf->password == NULL)
{
debug_printf(DEBUG_NORMAL, "No password available for EAP-MSCHAPv2!\n");
eap_type_common_fail(eapdata);
return XEGENERROR;
}
else
{
mscv2data->password = _strdup(eapconf->password);
}
}
else
{
mscv2data->password = _strdup(ctx->prof->temp_password);
}
eap_type_common_init_eap_data(eapdata);
return XENONE;
}
/******************************************************************
*
* Verify that this packet is really an EAP-MSCHAPv2 packet.
*
******************************************************************/
void eapmschapv2_check(eap_type_data *eapdata)
{
struct eap_header *myeap = NULL;
struct mschapv2_challenge *mv2 = NULL;
struct config_eap_mschapv2 *eapconf = NULL;
context *ctx = NULL;
if (!xsup_assert((eapdata != NULL), "eapdata != NULL", FALSE))
return;
myeap = (struct eap_header *)eapdata->eapReqData;
if (myeap == NULL)
{
debug_printf(DEBUG_NORMAL, "No valid packet was passed in to %s!\n",
__FUNCTION__);
eap_type_common_fail(eapdata);
return;
}
if (myeap->eap_code != EAP_REQUEST_PKT)
{
debug_printf(DEBUG_NORMAL, "EAP isn't a request packet!\n");
eap_type_common_fail(eapdata);
return;
}
if (ntohs(myeap->eap_length) < (2 + sizeof(struct eap_header)))
{
debug_printf(DEBUG_NORMAL, "Not enough data for valid EAP method.\n");
eap_type_common_fail(eapdata);
return;
}
mv2 = (struct mschapv2_challenge *)&eapdata->eapReqData[sizeof(struct eap_header)];
if ((mv2->OpCode < MS_CHAPV2_CHALLENGE) || (mv2->OpCode > MS_CHAPV2_FAILURE))
{
debug_printf(DEBUG_NORMAL, "Unsupported EAP-MSCHAPv2 OpCode! (Code : "
"%d)\n", mv2->OpCode);
eap_type_common_fail(eapdata);
return;
}
eapconf = (struct config_eap_mschapv2 *)eapdata->eap_conf_data;
if (eapconf == NULL)
{
debug_printf(DEBUG_NORMAL, "There is no valid configuration for "
"EAP-MSCHAPv2.\n");
eap_type_common_fail(eapdata);
return;
}
if (eapconf->password == NULL)
{
ctx = event_core_get_active_ctx();
if (ctx == NULL)
{
debug_printf(DEBUG_NORMAL, "No password available for EAP-MSCHAPv2!\n");
eap_type_common_fail(eapdata);
return;
}
if (ctx->prof->temp_password == NULL)
{
debug_printf(DEBUG_NORMAL, "No password available for EAP-MSCHAPv2!\n");
eap_type_common_fail(eapdata);
return;
}
}
}
/**
* \brief Strip the domain off the username (if present).
*
* \note The caller is expected to free the value returned in "shortname".
*
* @param[in] longname The username that MAY contain a DOMAIN\ format.
* @param[out] shortname The username without the DOMAIN\ format.
**/
void eapmschapv2_strip_backslash(char *longname, char **shortname)
{
char *substr = NULL;
if (longname == NULL)
{
(*shortname) = NULL;
return;
}
substr = strstr(longname, "\\");
if (substr == NULL)
{
(*shortname) = _strdup(longname);
return;
}
// Otherwise, return 1 character beyond the one we found.
(*shortname) = _strdup(substr+1); // Ick! Pointer math. ;)
}
/******************************************************************
*
* Process an MSCHAPv2 challenge message. It should return one of the
* eapMethod state values.
*
******************************************************************/
uint8_t eapmschapv2_challenge(eap_type_data *eapdata)
{
struct mschapv2_challenge *challenge = NULL;
struct mschapv2_vars *myvars = NULL;
struct config_eap_mschapv2 *eapconf = NULL;
char *username = NULL;
char *ident = NULL;
if (!xsup_assert((eapdata != NULL), "eapdata != NULL", FALSE))
return EAP_FAIL;
if (!xsup_assert((eapdata->eapReqData != NULL),
"eapdata->eapReqData != NULL", FALSE))
return EAP_FAIL;
if (!xsup_assert((eapdata->eap_data != NULL), "eapdata->eap_data != NULL",
FALSE))
return EAP_FAIL;
if (!xsup_assert((eapdata->eap_conf_data != NULL),
"eapdata->eap_conf_data != NULL", FALSE))
return EAP_FAIL;
eapconf = (struct config_eap_mschapv2 *)eapdata->eap_conf_data;
myvars = (struct mschapv2_vars *)eapdata->eap_data;
challenge = (struct mschapv2_challenge *)&eapdata->eapReqData[sizeof(struct eap_header)];
debug_printf(DEBUG_AUTHTYPES, "(EAP-MS-CHAPv2) ID : %02X\n",
challenge->MS_CHAPv2_ID);
// Store a copy for the response.
myvars->MS_CHAPv2_ID = challenge->MS_CHAPv2_ID;
// This value should *ALWAYS* be 0x10.
if (challenge->Value_Size != 0x10)
{
if (eapconf->ias_quirk == 1)
{
debug_printf(DEBUG_NORMAL, "(EAP-MS-CHAPv2) Invalid Value-Size! "
"(%d), forced to 0x10 (ias_quirk = yes)\n",
challenge->Value_Size);
challenge->Value_Size = 0x10;
}
else
{
debug_printf(DEBUG_NORMAL, "(EAP-MS-CHAPv2) Invalid Value-Size! (%d)"
"\n", challenge->Value_Size);
debug_printf(DEBUG_NORMAL, "(EAP-MS-CHAPv2) Should you enable "
"ias_quirk?\n");
return EAP_FAIL;
}
}
if (eap_fast_mode != TRUE)
{
FREE(myvars->AuthenticatorChallenge);
myvars->AuthenticatorChallenge = (uint8_t *)Malloc(16);
if (myvars->AuthenticatorChallenge == NULL)
{
debug_printf(DEBUG_NORMAL, "Couldn't allocate memory for the "
"Authenticator Challenge!\n");
ipc_events_malloc_failed(NULL);
return EAP_FAIL;
}
memcpy(myvars->AuthenticatorChallenge, &challenge->Challenge, 16);
}
debug_printf(DEBUG_AUTHTYPES, "Authenticator Challenge : ");
debug_hex_printf(DEBUG_AUTHTYPES, (uint8_t *) myvars->AuthenticatorChallenge,
16);
if (eap_fast_mode != TRUE)
{
FREE(myvars->PeerChallenge);
// Ignore the RADIUS host, we probably don't care.
myvars->PeerChallenge = (uint8_t *)Malloc(16);
if (myvars->PeerChallenge == NULL)
{
debug_printf(DEBUG_NORMAL, "Couldn't allocate memory for the "
"Peer Challenge!\n");
ipc_events_malloc_failed(NULL);
return EAP_FAIL;
}
RAND_bytes((uint8_t *) myvars->PeerChallenge, 16);
}
debug_printf(DEBUG_AUTHTYPES, "Generated PeerChallenge : ");
debug_hex_printf(DEBUG_AUTHTYPES, (uint8_t *) myvars->PeerChallenge,16);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -