⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sm_handler.c

📁 linux 下通过802.1认证的安装包
💻 C
📖 第 1 页 / 共 3 页
字号:
/**
 *
 * SIM Card Handler for PC/SC lite library
 *
 * This code was developed by Chris Hessing, using code written by :
 *
 * Michael Haberler mah@eunet.at 
 * based on original work by marek@bmlv.gv.at 2000
 * make it work with pcsclite-1.0.1: Vincent Guyot <vguyot@inf.enst.fr>  2002-07-12
 * some parts Chris Hessing chris.hessing@utah.edu
 *
 *
 * This code is released under dual BSD/GPL license.
 *
 **********************************************************************
 * --- BSD License ---
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  - Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *  - Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *  - All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *       This product includes software developed by the University of
 *       Maryland at College Park and its contributors.
 *  - Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

/**
 * Smart card handler functions.
 * 
 * \file sm_handler.c
 *
 * \author chris@open1x.org
 *
 * \todo Add IPC error events
 *
 * $Id: sm_handler.c,v 1.19.2.6 2007/04/20 18:35:54 chessing Exp $
 * $Date: 2007/04/20 18:35:54 $
 **/

/*******************************************************************
 *
 * The development of the EAP/SIM support was funded by Internet
 * Foundation Austria (http://www.nic.at/ipa)
 *
 *******************************************************************/


/* Interface to Smart Cards using PCSC with 802.1X.  */

#ifdef EAP_SIM_ENABLE

#include <stdio.h>
#include <winscard.h>
#include <string.h>
#include <ctype.h>
#include <strings.h>
#include <stdlib.h>
#include <unistd.h>

#include "xsup_debug.h"
#include "xsup_err.h"

#ifdef USE_EFENCE
#include <efence.h>
#endif

// 2G bytecodes
#define SELECT_MF       "A0A40000023F00"
#define SELECT_DF_GSM   "A0A40000027F20"
#define SELECT_EF_IMSI  "A0A40000026F07"
#define RUN_GSM         "A088000010"
#define GET_IMSI        "A0B0000009"

// 3G bytecodes
#define SELECT_MF_USIM  "00A4000C"
#define SELECT_EF_ICCID "00A40004022FE2"
#define SELECT_FCP      "00A4000C"
#define SELECT_EFDIR    "00A40004022F00"
#define EFDIR_READREC1  "00B20104FF"
#define CHV_RETRIES     "0020000100"
#define CHV_UNBLOCK     "002C000110"
#define CHV_ATTEMPT     "0020000108"
#define USELECT_EF_IMSI "00A40904026F07"
#define READ_IMSI       "00B0000009"

#define MODE2G          1
#define MODE3G          0

#define DO_DEBUG        1

#define MAXBUFF         512

typedef unsigned char u8;

/* structure of the EFdir AID (application ID) */
typedef struct t_efdir {
  u8 tag61;
  u8 length;

  u8 tag4f;
  u8 aid_len;

  /* application identifier value */
  u8 rid[5];
  u8 app_code[2];		/* 0x1002 for 3G USIM app */
  u8 country_code[2];
  u8 prov_code[3];
  u8 prov_field[4];

  u8 tag50;
  u8 al_len;
  u8 app_label[16];		/* like "Mobilkom Austria", 0xff padded */
} t_efdir;

typedef struct  { u8  msk[2], rsp[2], *text; } t_response;

const t_response response[]=    {

  { { 0xff, 0xff }, { 0x90, 0x00 } , "Ok" },

  { { 0xff, 0xff }, { 0x98, 0x02 } , "no CHV initialized" },
  { { 0xff, 0xff }, { 0x98, 0x04 } , "access condition not fulfilled" },
  { { 0xff, 0xff }, { 0x98, 0x08 } , "in contradiction with CHV status" },
  { { 0xff, 0xff }, { 0x98, 0x10 } , "in contradiction with invalidation status" },
  { { 0xff, 0xff }, { 0x98, 0x40 } , "unsuccessful CHV verification, no attempts left" },

  { { 0xff, 0xff }, { 0x98, 0x50 } , "decrease cannot be performed, maximum value reached" },
  { { 0xff, 0xff }, { 0x98, 0x62 } , "verify if MAC  == XMAC" },
  { { 0xff, 0xff }, { 0x98, 0x64 } , "Service not available" },

  { { 0xff, 0x00 }, { 0x9f, 0x00 } , "%d response bytes available" },

  { { 0xff, 0x00 }, { 0x61, 0x00 } , "%d response bytes available" },

  { { 0xff, 0xff }, { 0x62, 0x00 } , "curent file is already activated" },
  { { 0xff, 0xff }, { 0x62, 0x81 } , "returned data may be corrupt" },
  { { 0xff, 0xff }, { 0x62, 0x82 } , "EOF reached prematurely" },
  { { 0xff, 0xff }, { 0x62, 0x83 } , "selected file invalid" },
  { { 0xff, 0xff }, { 0x62, 0x84 } , "FCI not formated" },
  { { 0xff, 0x00 }, { 0x62, 0x00 } , "nvmem unchanged" },

  { { 0xff, 0x00 }, { 0x63, 0x81 } , "file filled up by last write" },
  { { 0xff, 0xf0 }, { 0x63, 0xc0 } , "Counter=%1.1X" },
  { { 0xff, 0x00 }, { 0x63, 0x00 } , "nvmem changed1" },

  { { 0xff, 0xff }, { 0x64, 0x00 } , "nvmem unchanged or no active application" },
  { { 0xff, 0x00 }, { 0x64, 0x00 } , "nvmem unchanged - RFU" },

  { { 0xff, 0xff }, { 0x65, 0x00 } , "nvmem changed2" },
  { { 0xff, 0xff }, { 0x65, 0x81 } , "nvmem changed - memory failure" },
  { { 0xff, 0x00 }, { 0x65, 0x00 } , "nvmem changed - unknown?" },

  { { 0xff, 0x00 }, { 0x66, 0x00 } , "security related %d" },

  { { 0xff, 0xff }, { 0x67, 0x00 } , "wrong length" },
  { { 0xff, 0x00 }, { 0x67, 0x00 } , "wrong length - %d expected" },

  { { 0xff, 0xff }, { 0x68, 0x81 } , "wrong cla - logical channel not supported" },
  { { 0xff, 0xff }, { 0x68, 0x82 } , "wrong cla - secure messaging not supported" },
  { { 0xff, 0x00 }, { 0x68, 0x00 } , "cla not supported" },

  { { 0xff, 0xff }, { 0x69, 0x81 } , "command incompatible with file structure" },
  { { 0xff, 0xff }, { 0x69, 0x82 } , "security status not satisfied (PIN1)" },
  { { 0xff, 0xff }, { 0x69, 0x83 } , "authentication method blocked - no PIN attempts left" },
  { { 0xff, 0xff }, { 0x69, 0x84 } , "referenced data invalid" },
  { { 0xff, 0xff }, { 0x69, 0x85 } , "conditions of use not satisfied" },
  { { 0xff, 0xff }, { 0x69, 0x86 } , "command not allowed - no current EF" },
  { { 0xff, 0xff }, { 0x69, 0x87 } , "expected SM data objects missing" },
  { { 0xff, 0xff }, { 0x69, 0x88 } , "SM data objects incorrect" },
  { { 0xff, 0x00 }, { 0x69, 0x00 } , "command not allowed" },

  { { 0xff, 0xff }, { 0x6a, 0x80 } , "P1-P2: incorrect parameters in data field" },
  { { 0xff, 0xff }, { 0x6a, 0x81 } , "P1-P2: function not supported" },
  { { 0xff, 0xff }, { 0x6a, 0x82 } , "P1-P2: file/search pattern not found" },
  { { 0xff, 0xff }, { 0x6a, 0x83 } , "P1-P2: record not found" },
  { { 0xff, 0xff }, { 0x6a, 0x84 } , "P1-P2: not enough memory space in file" },
  { { 0xff, 0xff }, { 0x6a, 0x85 } , "P1-P2: Lc inconsistent with TLV" },
  { { 0xff, 0xff }, { 0x6a, 0x86 } , "P1-P2 incorrect (out of range)" },
  { { 0xff, 0xff }, { 0x6a, 0x87 } , "P1-P2 inconsistent with Lc" },
  { { 0xff, 0xff }, { 0x6a, 0x88 } , "verify if EFkeyop exists attached to current file" },

  { { 0xff, 0xff }, { 0x6a, 0x88 } , "Referenced data not found" },
  { { 0xff, 0xff }, { 0x6a, 0x89 } , "File already exists in current DF" },

  { { 0xff, 0x00 }, { 0x6a, 0x00 } , "P1-P2 invalid" },

  { { 0xff, 0x00 }, { 0x6b, 0x00 } , "P1-P2 invalid" },

  { { 0xff, 0x00 }, { 0x6c, 0x00 } , "wrong length -  %d expected" },

  { { 0xff, 0x00 }, { 0x6d, 0x00 } , "INS code not supported or invalid" },

  { { 0xff, 0x00 }, { 0x6e, 0x00 } , "CLA %02X not supported" },

  { { 0xff, 0xff }, { 0x6f, 0x01 } , "no active application" },
  { { 0xff, 0xff }, { 0x6f, 0x06 } , "FCP formatting aborted" },
  { { 0xff, 0xff }, { 0x6f, 0x19 } , "no valid key attached to current file" },

  { { 0xff, 0xff }, { 0x6f, 0x00 } , "EF or DF integrity error" },
  { { 0xff, 0xff }, { 0x6f, 0x03 } , "Decrements number of the unblock mechanism (if not 0xff)" },
  { { 0xff, 0xff }, { 0x6f, 0x07 } , "incorrect child number" },
  { { 0xff, 0xff }, { 0x6f, 0x0d } , "Reset PIN/ADM retry counter or disable EFpin or EFadm" },
  { { 0xff, 0xff }, { 0x6f, 0x0e } , "Reset UNBLOCK PIN error counter to maximum value" },
  { { 0xff, 0xff }, { 0x6f, 0x15 } , "PIN/ADM enable/disable not allowed" },
  { { 0xff, 0xff }, { 0x6f, 0x16 } , "incorrect UNBLOCK pin" },
  { { 0xff, 0xff }, { 0x6f, 0x17 } , "number of unblock mechanism is not equal to 0x00" },
  { { 0xff, 0xff }, { 0x6f, 0x1e } , "no data waiting for GET RESPONSE" },
  { { 0xff, 0xff }, { 0x6f, 0x1f } , "File deactivated" },
  { { 0xff, 0xff }, { 0x6f, 0x22 } , "length of search pattern > 128 bytes" },
  { { 0xff, 0x00 }, { 0x6f, 0x00 } , "no precise diagnosis" },

  { { 0x00, 0x00 }, { 0x00, 0x00 } , "Unknown response" }
};


void print_sc_error(long err)
{
  switch (err)
    {
    case SCARD_E_CANCELLED:
      debug_printf(DEBUG_NORMAL, "Error : Card Request Cancelled!\n");
      break;
    case SCARD_E_CANT_DISPOSE:
      debug_printf(DEBUG_NORMAL, "Error : Can't dispose (!?)\n");
      break;
    case SCARD_E_INSUFFICIENT_BUFFER:
      debug_printf(DEBUG_NORMAL, "Error : Insufficient Buffer\n");
      break;
    case SCARD_E_INVALID_ATR:
      debug_printf(DEBUG_NORMAL, "Error : Invalid ATR\n");
      break;
    case SCARD_E_INVALID_HANDLE:
      debug_printf(DEBUG_NORMAL, "Error : Invalid handle\n");
      break;
    case SCARD_E_INVALID_PARAMETER:
      debug_printf(DEBUG_NORMAL, "Error : Invalid parameter\n");
      break;
    case SCARD_E_INVALID_TARGET:
      debug_printf(DEBUG_NORMAL, "Error : Invalid target\n");
      break;
    case SCARD_E_INVALID_VALUE:
      debug_printf(DEBUG_NORMAL, "Error : Invalid Value\n");
      break;
    case SCARD_E_NO_MEMORY:
      debug_printf(DEBUG_NORMAL, "Error : No memory\n");
      break;
    case SCARD_F_COMM_ERROR:
      debug_printf(DEBUG_NORMAL, "Error : Communication error \n");
      break;
    case SCARD_F_INTERNAL_ERROR:
      debug_printf(DEBUG_NORMAL, "Error : Internal error\n");
      break;
    case SCARD_F_WAITED_TOO_LONG:
      debug_printf(DEBUG_NORMAL, "Error : Waited too long\n");
      break;
    case SCARD_E_UNKNOWN_READER:
      debug_printf(DEBUG_NORMAL, "Error : Unknown reader\n");
      break;
    case SCARD_E_TIMEOUT:
      debug_printf(DEBUG_NORMAL, "Error : Timeout\n");
      break;
    case SCARD_E_SHARING_VIOLATION:
      debug_printf(DEBUG_NORMAL, "Error : Sharing Violation\n");
      break;
    case SCARD_E_NO_SMARTCARD:
      debug_printf(DEBUG_NORMAL, "Error : No smartcard!\n");
      break;
    case SCARD_E_UNKNOWN_CARD:
      debug_printf(DEBUG_NORMAL, "Error : Unknown card!\n");
      break;
    case SCARD_E_PROTO_MISMATCH:
      debug_printf(DEBUG_NORMAL, "Error : Protocol mismatch!\n");
      break;
    case SCARD_E_NOT_READY:
      debug_printf(DEBUG_NORMAL, "Error : Not ready!\n");
      break;
    case SCARD_E_SYSTEM_CANCELLED:
      debug_printf(DEBUG_NORMAL, "Error : System Cancelled\n");
      break;
    case SCARD_E_NOT_TRANSACTED:
      debug_printf(DEBUG_NORMAL, "Error : Not Transacted\n");
      break;
    case SCARD_E_READER_UNAVAILABLE:
      debug_printf(DEBUG_NORMAL, "Error : Reader unavailable\n");
      break;
    case SCARD_F_UNKNOWN_ERROR:
    default:
      debug_printf(DEBUG_NORMAL, "Unknown error!\n");
      break;
    }
}


int sm_handler_init_ctx(SCARDCONTEXT *card_ctx)
{
  long ret;
  
  if (!card_ctx)
    {
      debug_printf(DEBUG_NORMAL, "Invalid memory location for card context!\n");
      return -1;
    }

  *card_ctx = 0;

  ret = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, card_ctx);
  if (ret != SCARD_S_SUCCESS)
    {
      debug_printf(DEBUG_NORMAL, "Couldn't establish Smart Card context!  "
		   "(Is pcscd loaded?)\n");
      print_sc_error(ret);
      return -1;
    }

  return 0;
}

char *sm_handler_get_readers(SCARDCONTEXT *card_ctx)
{
  long readerstrlen;
  char *readername;
  int ret;

  ret = SCardListReaders(*card_ctx, NULL, NULL, &readerstrlen);
  if (ret != SCARD_S_SUCCESS)
    {
      debug_printf(DEBUG_NORMAL, "Error requesting list of smart card "
		   "readers! ");
      print_sc_error(ret);
      return NULL;
    }

  readername = (char *)Malloc(readerstrlen+1);
  if (readername == NULL) 
    {
      debug_printf(DEBUG_NORMAL, "Couldn't allocate memory for reader name! "
		   "(%s:%d)\n", __FUNCTION__, __LINE__);
      return NULL;
    }

  ret = SCardListReaders(*card_ctx, NULL, readername, &readerstrlen);
  if (ret != SCARD_S_SUCCESS)
    {
      debug_printf(DEBUG_NORMAL, "Error requesting list of smart card "
		   "readers! ");
      print_sc_error(ret);
      return NULL;
    }

  return readername;
}

long sm_handler_card_connect(SCARDCONTEXT *card_ctx, SCARDHANDLE *card_hdl, 
			     char *cardreader)
{
  long ret, activeprotocol;

  debug_printf(DEBUG_NORMAL, "Using reader : %s\n", cardreader);

  while (1)
    {
      ret = SCardConnect(*card_ctx, cardreader, SCARD_SHARE_SHARED,
			 SCARD_PROTOCOL_T0, card_hdl, &activeprotocol);
      if (ret == SCARD_S_SUCCESS) break;

      if (ret == SCARD_E_NO_SMARTCARD)
	{
	  // XXX This should be changed when we attach a GUI to Xsupplicant.
	  debug_printf(DEBUG_NORMAL, "Please insert a smart card!\n");
	  sleep(2);
	} else {
	  debug_printf(DEBUG_NORMAL, "Error attempting to connect to the "
		       "smart card!  ");
	  print_sc_error(ret);
	  return -1;
	  break;
	}
    }
  return 0;
}

int sm_handler_wait_card_ready(SCARDHANDLE *card_hdl, int waittime)
{
  DWORD dwState, dwProtocol, dwAtrLen, size;
  BYTE  pbAtr[MAX_ATR_SIZE];
  int loopcnt, ret;
  LPSTR mszReaders;

  loopcnt = 0;

  while (1)
    {
      dwState = 0;
      dwProtocol = 0;
      dwAtrLen = MAX_ATR_SIZE;
      size = 50;

      mszReaders = (LPSTR)Malloc(size);
      if (mszReaders == NULL) 
	{
	  debug_printf(DEBUG_NORMAL, "Error trying to allocate memory for "
		       "mszReaders!  (%s:%d)\n", __FUNCTION__, __LINE__);
	  return XEMALLOC;
	}

      memset(&pbAtr, 0x00, MAX_ATR_SIZE);
      ret = SCardStatus(*card_hdl, mszReaders, &size, &dwState, &dwProtocol, 
			pbAtr, &dwAtrLen);
      if (ret != SCARD_S_SUCCESS)
	{
	  debug_printf(DEBUG_NORMAL, "Error getting smart card status! ");
	  print_sc_error(ret);
	  FREE(mszReaders);

	  return -1;
	}

      // XXX We should pass these up to the GUI when we get that going!

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -