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 + -
显示快捷键?