eapaka.c
来自「linux 下通过802.1认证的安装包」· C语言 代码 · 共 664 行 · 第 1/2 页
C
664 行
/**
* EAPOL Function implementations for supplicant
*
* \file eapaka.c
*
* Licensed under a dual GPL/BSD license. (See LICENSE file for more info.)
*
* \author chris@open1x.org
*
* \todo Add IPC error message signaling.
* \todo Add support for temporary username/password pairs.
*
* $Id: eapaka.c,v 1.13.2.16 2007/07/02 22:36:33 chessing Exp $
* $Date: 2007/07/02 22:36:33 $
**/
/*******************************************************************
*
* The development of the EAP/AKA support was funded by Internet
* Foundation Austria (http://www.nic.at/ipa)
*
*******************************************************************/
#ifdef EAP_SIM_ENABLE // Only build this if it has been enabled.
#include <inttypes.h>
#include <stdio.h>
#include <openssl/hmac.h>
#include <openssl/sha.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include "winscard.h"
#include "profile.h"
#include "xsupconfig.h"
#include "xsup_common.h"
#include "eap_sm.h"
#include "eapaka.h"
#include "../sim/eapsim.h"
#include "../sim/sm_handler.h"
#include "../sim/fips.h"
#include "xsup_debug.h"
#include "xsup_err.h"
#include "aka.h"
#include "ipc_callout.h"
#include "xsup_ipc.h"
#include "frame_structs.h"
#ifdef USE_EFENCE
#include <efence.h>
#endif
/*************************************************************************
*
* Ask the SIM card what our IMSI is so that it can be used for our username
* during the authentication.
*
*************************************************************************/
int eapaka_get_username()
{
char *imsi;
char realm[25], card_mode=0;
char *readers, *username;
struct config_eap_aka *userdata;
struct config_network *network_data;
SCARDCONTEXT ctx;
SCARDHANDLE hdl;
network_data = config_get_network_config();
if (!xsup_assert((network_data != NULL), "network_data != NULL", FALSE))
return XEBADCONFIG;
userdata = (struct config_eap_aka *)network_data->methods->method_data;
// Initalize our smartcard context, and get ready to authenticate.
if (sm_handler_init_ctx(&ctx) != 0)
{
debug_printf(DEBUG_NORMAL, "Couldn't initialize smart card context!\n");
return XESIMGENERR;
}
readers = sm_handler_get_readers(&ctx);
if (readers == NULL)
{
debug_printf(DEBUG_NORMAL, "Couldn't list available readers!\n");
return XESIMGENERR;
}
// Connect to the smart card.
if (sm_handler_card_connect(&ctx, &hdl, readers) != 0)
{
debug_printf(DEBUG_NORMAL, "Error connecting to smart card reader!\n");
return XESIMGENERR;
}
// Wait for up to 10 seconds for the smartcard to become ready.
if (sm_handler_wait_card_ready(&hdl, 10) != 0)
{
debug_printf(DEBUG_NORMAL, "Smart Card wasn't ready after 10 seconds!\n");
return XESIMGENERR;
}
imsi = sm_handler_3g_imsi(&hdl, card_mode, userdata->password);
if (imsi == NULL)
{
debug_printf(DEBUG_NORMAL, "Error starting smart card, and getting IMSI!\n");
return XESIMGENERR;
}
debug_printf(DEBUG_AUTHTYPES, "SIM IMSI (AKA) : %s\n",imsi);
FREE(network_data->identity);
network_data->identity = (char *)Malloc(50); // 50 should be plenty!
if (network_data->identity == NULL)
{
debug_printf(DEBUG_NORMAL, "Couldn't allocate memory for identity!\n");
return XEMALLOC;
}
username = network_data->identity;
userdata->username = username;
memset(username, 0x00, 50);
username[0] = '1'; // An IMSI should always start with a 1.
if (Strncpy(&username[1], 50, imsi, 18) != 0)
{
debug_printf(DEBUG_NORMAL, "Attempted to overflow buffer in %s() at %d!\n",
__FUNCTION__, __LINE__);
return XEMALLOC;
}
if (userdata->auto_realm == TRUE)
{
memset(&realm, 0x00, 25);
sprintf((char *)&realm, "@mnc%c%c%c.mcc%c%c%c.owlan.org",
username[4], username[5], username[6], username[1], username[2],
username[3]);
debug_printf(DEBUG_AUTHTYPES, "Realm Portion : %s\n",realm);
if (Strcat(username, 50, realm) != 0)
{
fprintf(stderr, "Refusing to overwrite the string!\n");
return XEMALLOC;
}
}
// Close the smartcard, so that we know what state we are in.
sm_handler_close_sc(&hdl, &ctx);
FREE(imsi);
FREE(readers);
debug_printf(DEBUG_AUTHTYPES, "Username is now : %s\n", username);
return XENONE;
}
/*************************************************************************
*
* Allocate temporary memory, and determine if the card reader is attached.
*
*************************************************************************/
int eapaka_setup(eap_type_data *eapdata)
{
struct aka_eaptypedata *mydata;
struct config_eap_aka *userdata;
char *imsi;
debug_printf(DEBUG_AUTHTYPES, "(EAP-AKA) Initalized\n");
if (!xsup_assert((eapdata != NULL), "eapdata != NULL", FALSE))
return XEMALLOC;
if (eapdata->eap_data != NULL)
{
eapaka_deinit(eapdata);
}
eapdata->eap_data = (char *)Malloc(sizeof(struct aka_eaptypedata));
if (eapdata->eap_data == NULL)
{
debug_printf(DEBUG_NORMAL, "Couldn't allocate memory for EAP-AKA "
"specific data structure!\n");
return XEMALLOC;
}
mydata = (struct aka_eaptypedata *)eapdata->eap_data;
userdata = (struct config_eap_aka *)eapdata->eap_conf_data;
mydata->numrands = 0;
mydata->nonce_mt = NULL;
mydata->sync_fail = FALSE;
FREE(mydata->keyingMaterial);
eapdata->eap_data = (void *)mydata;
#ifndef RADIATOR_TEST
// Initalize our smartcard context, and get ready to authenticate.
if (sm_handler_init_ctx(&mydata->scntx) != 0)
{
debug_printf(DEBUG_NORMAL, "Couldn't initialize smart card context!\n");
return XESIMGENERR;
}
mydata->readers = sm_handler_get_readers(&mydata->scntx);
if (mydata->readers == NULL)
{
debug_printf(DEBUG_NORMAL, "Couldn't get any available readers!\n");
return XESIMGENERR;
}
// Connect to the smart card.
if (sm_handler_card_connect(&mydata->scntx, &mydata->shdl, mydata->readers) != 0)
{
debug_printf(DEBUG_NORMAL, "Error connecting to smart card reader!\n");
return XESIMGENERR;
}
// Wait for up to 20 seconds for the smartcard to become ready.
if (sm_handler_wait_card_ready(&mydata->shdl, 20) != 0)
{
debug_printf(DEBUG_NORMAL, "Smart Card wasn't ready after 20 seconds!\n");
return XESIMGENERR;
}
imsi = sm_handler_3g_imsi(&mydata->shdl, mydata->card_mode, userdata->password);
if (imsi == NULL)
{
debug_printf(DEBUG_NORMAL, "Error starting smart card, and getting IMSI!\n");
return XESIMGENERR;
}
#endif
if (userdata->username == NULL)
{
userdata->username = imsi;
} else {
#ifndef RADIATOR_TEST
FREE(imsi);
#endif
}
eap_type_common_init_eap_data(eapdata);
return XENONE;
}
/************************************************************************
*
* Determine if we are ready to do EAP-AKA.
*
************************************************************************/
void eapaka_check(eap_type_data *eapdata)
{
struct config_eap_aka *akaconf;
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;
}
akaconf = eapdata->eap_data;
if (akaconf->password == NULL)
{
debug_printf(DEBUG_NORMAL, "Don't have a valid password for EAP-AKA!\n");
eap_type_common_fail(eapdata);
return;
}
if (eapaka_setup(eapdata) != XENONE)
{
eap_type_common_fail(eapdata);
return;
}
}
/************************************************************************
*
* Process an EAP-AKA challenge message.
*
* The value passed in to eappayload should be the first byte following
* the challenge/response identifier.
*
************************************************************************/
void eapaka_do_challenge(eap_type_data *eapdata, uint8_t *eappayload,
uint16_t size)
{
uint16_t packet_offset = 0;
int retval = XENONE;
struct aka_eaptypedata *aka;
struct config_eap_aka *akaconf;
if (!xsup_assert((eapdata != NULL), "eapdata != NULL", FALSE))
return;
if (!xsup_assert((eappayload != NULL), "eappayload != NULL", FALSE))
return;
if (!xsup_assert((size < 1500), "size < 1500", FALSE))
return;
if (!xsup_assert((eapdata->eap_data != NULL), "eapdata->eap_data != NULL",
FALSE))
return;
if (!xsup_assert((eapdata->eap_conf_data != NULL),
"eapdata->eap_conf_data != NULL", FALSE))
return;
aka = (struct aka_eaptypedata *)eapdata->eap_data;
akaconf = (struct config_eap_aka *)eapdata->eap_conf_data;
while (packet_offset < size)
{
switch (eappayload[packet_offset])
{
case AT_RAND:
retval = aka_do_at_rand(aka, eappayload, &packet_offset);
if (retval != XENONE) return;
break;
case AT_AUTN:
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?