Added SIM card backend based on pcsc-lite
parent
4ceb31f941
commit
80dca77a50
10
configure.in
10
configure.in
|
@ -112,6 +112,7 @@ ARG_ENABL_SET([unit-tests], [enable unit tests on IKEv2 daemon startup.])
|
|||
ARG_ENABL_SET([load-tester], [enable load testing plugin for IKEv2 daemon.])
|
||||
ARG_ENABL_SET([eap-sim], [enable SIM authentication module for EAP.])
|
||||
ARG_ENABL_SET([eap-sim-file], [enable EAP-SIM backend based on a triplet file.])
|
||||
ARG_ENABL_SET([eap-sim-pcsc], [enable EAP-SIM backend based on a smartcard reader. Requires libpcsclite.])
|
||||
ARG_ENABL_SET([eap-simaka-sql], [enable EAP-SIM/AKA backend based on a triplet/quintuplet SQL database.])
|
||||
ARG_ENABL_SET([eap-simaka-pseudonym], [enable EAP-SIM/AKA pseudonym storage plugin.])
|
||||
ARG_ENABL_SET([eap-simaka-reauth], [enable EAP-SIM/AKA reauthentication data storage plugin.])
|
||||
|
@ -632,6 +633,12 @@ if test x$maemo = xtrue; then
|
|||
AC_SUBST(dbusservicedir)
|
||||
fi
|
||||
|
||||
if test x$eap_sim_pcsc = xtrue; then
|
||||
PKG_CHECK_MODULES(pcsclite, [libpcsclite])
|
||||
AC_SUBST(pcsclite_CFLAGS)
|
||||
AC_SUBST(pcsclite_LIBS)
|
||||
fi
|
||||
|
||||
if test x$nm = xtrue; then
|
||||
PKG_CHECK_EXISTS([libnm-glib],
|
||||
[PKG_CHECK_MODULES(nm, [NetworkManager gthread-2.0 libnm-glib libnm-glib-vpn])],
|
||||
|
@ -761,6 +768,7 @@ ADD_PLUGIN([updown], [c libcharon])
|
|||
ADD_PLUGIN([eap-identity], [c libcharon])
|
||||
ADD_PLUGIN([eap-sim], [c libcharon])
|
||||
ADD_PLUGIN([eap-sim-file], [c libcharon])
|
||||
ADD_PLUGIN([eap-sim-pcsc], [c libcharon])
|
||||
ADD_PLUGIN([eap-simaka-sql], [c libcharon])
|
||||
ADD_PLUGIN([eap-simaka-pseudonym], [c libcharon])
|
||||
ADD_PLUGIN([eap-simaka-reauth], [c libcharon])
|
||||
|
@ -872,6 +880,7 @@ AM_CONDITIONAL(USE_DUPLICHECK, test x$duplicheck = xtrue)
|
|||
AM_CONDITIONAL(USE_COUPLING, test x$coupling = xtrue)
|
||||
AM_CONDITIONAL(USE_EAP_SIM, test x$eap_sim = xtrue)
|
||||
AM_CONDITIONAL(USE_EAP_SIM_FILE, test x$eap_sim_file = xtrue)
|
||||
AM_CONDITIONAL(USE_EAP_SIM_PCSC, test x$eap_sim_pcsc = xtrue)
|
||||
AM_CONDITIONAL(USE_EAP_SIMAKA_SQL, test x$eap_simaka_sql = xtrue)
|
||||
AM_CONDITIONAL(USE_EAP_SIMAKA_PSEUDONYM, test x$eap_simaka_pseudonym = xtrue)
|
||||
AM_CONDITIONAL(USE_EAP_SIMAKA_REAUTH, test x$eap_simaka_reauth = xtrue)
|
||||
|
@ -1027,6 +1036,7 @@ AC_OUTPUT(
|
|||
src/libcharon/plugins/eap_gtc/Makefile
|
||||
src/libcharon/plugins/eap_sim/Makefile
|
||||
src/libcharon/plugins/eap_sim_file/Makefile
|
||||
src/libcharon/plugins/eap_sim_pcsc/Makefile
|
||||
src/libcharon/plugins/eap_simaka_sql/Makefile
|
||||
src/libcharon/plugins/eap_simaka_pseudonym/Makefile
|
||||
src/libcharon/plugins/eap_simaka_reauth/Makefile
|
||||
|
|
|
@ -223,6 +223,13 @@ if MONOLITHIC
|
|||
endif
|
||||
endif
|
||||
|
||||
if USE_EAP_SIM_PCSC
|
||||
SUBDIRS += plugins/eap_sim_pcsc
|
||||
if MONOLITHIC
|
||||
libcharon_la_LIBADD += plugins/eap_sim_pcsc/libstrongswan-eap-sim-pcsc.la
|
||||
endif
|
||||
endif
|
||||
|
||||
if USE_EAP_SIMAKA_SQL
|
||||
SUBDIRS += plugins/eap_simaka_sql
|
||||
if MONOLITHIC
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
|
||||
INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
|
||||
-I$(top_srcdir)/src/libcharon ${pcsclite_CFLAGS}
|
||||
|
||||
AM_CFLAGS = -rdynamic -DIPSEC_CONFDIR=\"${sysconfdir}\"
|
||||
|
||||
if MONOLITHIC
|
||||
noinst_LTLIBRARIES = libstrongswan-eap-sim-pcsc.la
|
||||
else
|
||||
plugin_LTLIBRARIES = libstrongswan-eap-sim-pcsc.la
|
||||
endif
|
||||
|
||||
libstrongswan_eap_sim_pcsc_la_SOURCES = \
|
||||
eap_sim_pcsc_plugin.h eap_sim_pcsc_plugin.c \
|
||||
eap_sim_pcsc_card.h eap_sim_pcsc_card.c
|
||||
|
||||
libstrongswan_eap_sim_pcsc_la_LDFLAGS = -module -avoid-version
|
||||
libstrongswan_eap_sim_pcsc_la_LIBADD = ${pcsclite_LIBS}
|
|
@ -0,0 +1,342 @@
|
|||
/*
|
||||
* Copyright (C) 2011 Duncan Salerno
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include "eap_sim_pcsc_card.h"
|
||||
|
||||
#include <PCSC/wintypes.h>
|
||||
#include <PCSC/winscard.h>
|
||||
#include <daemon.h>
|
||||
|
||||
typedef struct private_eap_sim_pcsc_card_t private_eap_sim_pcsc_card_t;
|
||||
|
||||
/**
|
||||
* Private data of an eap_sim_pcsc_card_t object.
|
||||
*/
|
||||
struct private_eap_sim_pcsc_card_t {
|
||||
|
||||
/**
|
||||
* Public eap_sim_pcsc_card_t interface.
|
||||
*/
|
||||
eap_sim_pcsc_card_t public;
|
||||
};
|
||||
|
||||
/**
|
||||
* Maximum length for an IMSI.
|
||||
*/
|
||||
#define SIM_IMSI_MAX_LEN 15
|
||||
|
||||
/**
|
||||
* Length of the status at the end of response APDUs.
|
||||
*/
|
||||
#define APDU_STATUS_LEN 2
|
||||
|
||||
/**
|
||||
* First byte of status word indicating success.
|
||||
*/
|
||||
#define APDU_SW1_SUCCESS 0x90
|
||||
|
||||
/**
|
||||
* First byte of status word indicating there is response data to be read.
|
||||
*/
|
||||
#define APDU_SW1_RESPONSE_DATA 0x9f
|
||||
|
||||
/**
|
||||
* Decode IMSI EF (Elementary File) into an ASCII string
|
||||
*/
|
||||
static bool decode_imsi_ef(unsigned char *input, int input_len, char *output)
|
||||
{
|
||||
/* Only digits 0-9 valid in IMSIs */
|
||||
static const char bcd_num_digits[] = {
|
||||
'0', '1', '2', '3', '4', '5', '6', '7',
|
||||
'8', '9', '\0', '\0', '\0', '\0', '\0', '\0'
|
||||
};
|
||||
int i;
|
||||
|
||||
/* Check length byte matches how many bytes we have, and that input is correct length for an IMSI */
|
||||
if (input[0] != input_len-1 || input_len < 2 || input_len > 9)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Check type byte is IMSI */
|
||||
if ((input[1] & 0xf) != 0x9)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
*output++ = bcd_num_digits[input[1] >> 4];
|
||||
|
||||
for (i = 2; i < input_len; i++)
|
||||
{
|
||||
*output++ = bcd_num_digits[input[i] & 0xf];
|
||||
*output++ = bcd_num_digits[input[i] >> 4];
|
||||
}
|
||||
|
||||
*output++ = '\0';
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of sim_card_t.get_triplet
|
||||
*/
|
||||
static bool get_triplet(private_eap_sim_pcsc_card_t *this,
|
||||
identification_t *id, char *rand, char *sres, char *kc)
|
||||
{
|
||||
status_t found = FALSE;
|
||||
LONG rv;
|
||||
SCARDCONTEXT hContext;
|
||||
DWORD dwReaders;
|
||||
LPSTR mszReaders;
|
||||
char *cur_reader;
|
||||
char full_nai[128];
|
||||
|
||||
snprintf(full_nai, sizeof(full_nai), "%Y", id);
|
||||
|
||||
DBG2(DBG_IKE, "looking for triplet: %Y rand %b", id, rand, SIM_RAND_LEN);
|
||||
|
||||
rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
|
||||
if (rv != SCARD_S_SUCCESS)
|
||||
{
|
||||
DBG1(DBG_IKE, "SCardEstablishContext: %s", pcsc_stringify_error(rv));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
rv = SCardListReaders(hContext, NULL, NULL, &dwReaders);
|
||||
if (rv != SCARD_S_SUCCESS)
|
||||
{
|
||||
DBG1(DBG_IKE, "SCardListReaders: %s", pcsc_stringify_error(rv));
|
||||
return FALSE;
|
||||
}
|
||||
mszReaders = malloc(sizeof(char)*dwReaders);
|
||||
|
||||
rv = SCardListReaders(hContext, NULL, mszReaders, &dwReaders);
|
||||
if (rv != SCARD_S_SUCCESS)
|
||||
{
|
||||
DBG1(DBG_IKE, "SCardListReaders: %s", pcsc_stringify_error(rv));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* mszReaders is a multi-string of readers, separated by '\0' and terminated by an additional '\0' */
|
||||
for (cur_reader = mszReaders; *cur_reader != '\0' && found == FALSE; cur_reader += strlen(cur_reader)+1)
|
||||
{
|
||||
DWORD dwActiveProtocol = -1;
|
||||
SCARDHANDLE hCard;
|
||||
SCARD_IO_REQUEST *pioSendPci;
|
||||
SCARD_IO_REQUEST pioRecvPci;
|
||||
BYTE pbRecvBuffer[64];
|
||||
DWORD dwRecvLength;
|
||||
char imsi[SIM_IMSI_MAX_LEN+1];
|
||||
|
||||
/* See GSM 11.11 for SIM APDUs */
|
||||
BYTE pbSelectMF[] = { 0xa0, 0xa4, 0x00, 0x00, 0x02, 0x3f, 0x00 };
|
||||
BYTE pbSelectDFGSM[] = { 0xa0, 0xa4, 0x00, 0x00, 0x02, 0x7f, 0x20 };
|
||||
BYTE pbSelectIMSI[] = { 0xa0, 0xa4, 0x00, 0x00, 0x02, 0x6f, 0x07 };
|
||||
BYTE pbReadBinary[] = { 0xa0, 0xb0, 0x00, 0x00, 0x09 };
|
||||
BYTE pbRunGSMAlgorithm[] = { 0xa0, 0x88, 0x00, 0x00, 0x10, /*RAND*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
BYTE pbGetResponse[] = { 0xa0, 0xc0, 0x00, 0x00, 0x0c };
|
||||
|
||||
/* Copy RAND into APDU */
|
||||
memcpy(pbRunGSMAlgorithm+5, rand, SIM_RAND_LEN);
|
||||
|
||||
rv = SCardConnect(hContext, cur_reader, SCARD_SHARE_SHARED,
|
||||
SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &hCard, &dwActiveProtocol);
|
||||
if (rv != SCARD_S_SUCCESS)
|
||||
{
|
||||
DBG1(DBG_IKE, "SCardConnect: %s", pcsc_stringify_error(rv));
|
||||
continue;
|
||||
}
|
||||
|
||||
switch(dwActiveProtocol)
|
||||
{
|
||||
case SCARD_PROTOCOL_T0:
|
||||
pioSendPci = SCARD_PCI_T0;
|
||||
break;
|
||||
case SCARD_PROTOCOL_T1:
|
||||
pioSendPci = SCARD_PCI_T1;
|
||||
break;
|
||||
default:
|
||||
DBG1(DBG_IKE, "Unknown SCARD_PROTOCOL");
|
||||
continue;
|
||||
}
|
||||
|
||||
/* APDU: Select MF */
|
||||
dwRecvLength = sizeof(pbRecvBuffer);
|
||||
rv = SCardTransmit(hCard, pioSendPci, pbSelectMF, sizeof(pbSelectMF),
|
||||
&pioRecvPci, pbRecvBuffer, &dwRecvLength);
|
||||
if (rv != SCARD_S_SUCCESS)
|
||||
{
|
||||
DBG1(DBG_IKE, "SCardTransmit: %s", pcsc_stringify_error(rv));
|
||||
continue;
|
||||
}
|
||||
if( dwRecvLength < APDU_STATUS_LEN || pbRecvBuffer[dwRecvLength-APDU_STATUS_LEN] != APDU_SW1_RESPONSE_DATA )
|
||||
{
|
||||
DBG1(DBG_IKE, "Select MF failed: %b", pbRecvBuffer, dwRecvLength);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* APDU: Select DF GSM */
|
||||
dwRecvLength = sizeof(pbRecvBuffer);
|
||||
rv = SCardTransmit(hCard, pioSendPci, pbSelectDFGSM, sizeof(pbSelectDFGSM),
|
||||
&pioRecvPci, pbRecvBuffer, &dwRecvLength);
|
||||
if (rv != SCARD_S_SUCCESS)
|
||||
{
|
||||
DBG1(DBG_IKE, "SCardTransmit: %s", pcsc_stringify_error(rv));
|
||||
continue;
|
||||
}
|
||||
if( dwRecvLength < APDU_STATUS_LEN || pbRecvBuffer[dwRecvLength-APDU_STATUS_LEN] != APDU_SW1_RESPONSE_DATA )
|
||||
{
|
||||
DBG1(DBG_IKE, "Select DF GSM failed: %b", pbRecvBuffer, dwRecvLength);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* APDU: Select IMSI */
|
||||
dwRecvLength = sizeof(pbRecvBuffer);
|
||||
rv = SCardTransmit(hCard, pioSendPci, pbSelectIMSI, sizeof(pbSelectIMSI),
|
||||
&pioRecvPci, pbRecvBuffer, &dwRecvLength);
|
||||
if (rv != SCARD_S_SUCCESS)
|
||||
{
|
||||
DBG1(DBG_IKE, "SCardTransmit: %s", pcsc_stringify_error(rv));
|
||||
continue;
|
||||
}
|
||||
if( dwRecvLength < APDU_STATUS_LEN || pbRecvBuffer[dwRecvLength-APDU_STATUS_LEN] != APDU_SW1_RESPONSE_DATA )
|
||||
{
|
||||
DBG1(DBG_IKE, "Select IMSI failed: %b", pbRecvBuffer, dwRecvLength);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* APDU: Read Binary (of IMSI) */
|
||||
dwRecvLength = sizeof(pbRecvBuffer);
|
||||
rv = SCardTransmit(hCard, pioSendPci, pbReadBinary, sizeof(pbReadBinary),
|
||||
&pioRecvPci, pbRecvBuffer, &dwRecvLength);
|
||||
if (rv != SCARD_S_SUCCESS)
|
||||
{
|
||||
DBG1(DBG_IKE, "SCardTransmit: %s", pcsc_stringify_error(rv));
|
||||
continue;
|
||||
}
|
||||
if( dwRecvLength < APDU_STATUS_LEN || pbRecvBuffer[dwRecvLength-APDU_STATUS_LEN] != APDU_SW1_SUCCESS )
|
||||
{
|
||||
DBG1(DBG_IKE, "Select IMSI failed: %b", pbRecvBuffer, dwRecvLength);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!decode_imsi_ef(pbRecvBuffer, dwRecvLength-APDU_STATUS_LEN, imsi) )
|
||||
{
|
||||
DBG1(DBG_IKE, "Couldn't decode IMSI EF: %b", pbRecvBuffer, dwRecvLength);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* The IMSI could be post/prefixed in the full NAI, so just make sure it's in there */
|
||||
if( !(strlen(full_nai) && strstr(full_nai, imsi)) )
|
||||
{
|
||||
DBG1(DBG_IKE, "Not the SIM we're looking for, IMSI: %s", imsi);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* APDU: Run GSM Algorithm */
|
||||
dwRecvLength = sizeof(pbRecvBuffer);
|
||||
rv = SCardTransmit(hCard, pioSendPci, pbRunGSMAlgorithm, sizeof(pbRunGSMAlgorithm),
|
||||
&pioRecvPci, pbRecvBuffer, &dwRecvLength);
|
||||
if (rv != SCARD_S_SUCCESS)
|
||||
{
|
||||
DBG1(DBG_IKE, "SCardTransmit: %s", pcsc_stringify_error(rv));
|
||||
continue;
|
||||
}
|
||||
if( dwRecvLength < APDU_STATUS_LEN || pbRecvBuffer[dwRecvLength-APDU_STATUS_LEN] != APDU_SW1_RESPONSE_DATA )
|
||||
{
|
||||
DBG1(DBG_IKE, "Run GSM Algorithm failed: %b", pbRecvBuffer, dwRecvLength);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* APDU: Get Response (of Run GSM Algorithm) */
|
||||
dwRecvLength = sizeof(pbRecvBuffer);
|
||||
rv = SCardTransmit(hCard, pioSendPci, pbGetResponse, sizeof(pbGetResponse),
|
||||
&pioRecvPci, pbRecvBuffer, &dwRecvLength);
|
||||
if (rv != SCARD_S_SUCCESS)
|
||||
{
|
||||
DBG1(DBG_IKE, "SCardTransmit: %s", pcsc_stringify_error(rv));
|
||||
continue;
|
||||
}
|
||||
|
||||
if( dwRecvLength < APDU_STATUS_LEN || pbRecvBuffer[dwRecvLength-APDU_STATUS_LEN] != APDU_SW1_SUCCESS )
|
||||
{
|
||||
DBG1(DBG_IKE, "Get Response failed: %b", pbRecvBuffer, dwRecvLength);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Extract out Kc and SRES from response */
|
||||
if( dwRecvLength == SIM_SRES_LEN + SIM_KC_LEN + APDU_STATUS_LEN )
|
||||
{
|
||||
memcpy(sres, pbRecvBuffer, SIM_SRES_LEN);
|
||||
memcpy(kc, pbRecvBuffer+4, SIM_KC_LEN);
|
||||
/* This will also cause the loop to exit */
|
||||
found = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG1(DBG_IKE, "Get Response incorrect length: %b", pbRecvBuffer, dwRecvLength);
|
||||
continue;
|
||||
}
|
||||
|
||||
rv = SCardDisconnect(hCard, SCARD_LEAVE_CARD);
|
||||
if (rv != SCARD_S_SUCCESS)
|
||||
{
|
||||
DBG1(DBG_IKE, "SCardDisconnect: %s", pcsc_stringify_error(rv));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
rv = SCardReleaseContext(hContext);
|
||||
if (rv != SCARD_S_SUCCESS)
|
||||
{
|
||||
DBG1(DBG_IKE, "SCardReleaseContext: %s", pcsc_stringify_error(rv));
|
||||
}
|
||||
|
||||
free(mszReaders);
|
||||
return found;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of sim_card_t.get_quintuplet
|
||||
*/
|
||||
static status_t get_quintuplet()
|
||||
{
|
||||
return NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of eap_sim_pcsc_card_t.destroy.
|
||||
*/
|
||||
static void destroy(private_eap_sim_pcsc_card_t *this)
|
||||
{
|
||||
free(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* See header
|
||||
*/
|
||||
eap_sim_pcsc_card_t *eap_sim_pcsc_card_create()
|
||||
{
|
||||
private_eap_sim_pcsc_card_t *this = malloc_thing(private_eap_sim_pcsc_card_t);
|
||||
|
||||
this->public.card.get_triplet = (bool(*)(sim_card_t*, identification_t *id, char rand[SIM_RAND_LEN], char sres[SIM_SRES_LEN], char kc[SIM_KC_LEN]))get_triplet;
|
||||
this->public.card.get_quintuplet = (status_t(*)(sim_card_t*, identification_t *id, char rand[AKA_RAND_LEN], char autn[AKA_AUTN_LEN], char ck[AKA_CK_LEN], char ik[AKA_IK_LEN], char res[AKA_RES_MAX], int *res_len))get_quintuplet;
|
||||
this->public.card.resync = (bool(*)(sim_card_t*, identification_t *id, char rand[AKA_RAND_LEN], char auts[AKA_AUTS_LEN]))return_false;
|
||||
this->public.card.get_pseudonym = (identification_t*(*)(sim_card_t*, identification_t *perm))return_null;
|
||||
this->public.card.set_pseudonym = (void(*)(sim_card_t*, identification_t *id, identification_t *pseudonym))nop;
|
||||
this->public.card.get_reauth = (identification_t*(*)(sim_card_t*, identification_t *id, char mk[HASH_SIZE_SHA1], u_int16_t *counter))return_null;
|
||||
this->public.card.set_reauth = (void(*)(sim_card_t*, identification_t *id, identification_t* next, char mk[HASH_SIZE_SHA1], u_int16_t counter))nop;
|
||||
this->public.destroy = (void(*)(eap_sim_pcsc_card_t*))destroy;
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright (C) 2011 Duncan Salerno
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup eap_sim_pcsc_card eap_sim_pcsc_card
|
||||
* @{ @ingroup eap_sim_pcsc
|
||||
*/
|
||||
|
||||
#ifndef EAP_SIM_PCSC_CARD_H_
|
||||
#define EAP_SIM_PCSC_CARD_H_
|
||||
|
||||
#include <sa/authenticators/eap/sim_manager.h>
|
||||
|
||||
typedef struct eap_sim_pcsc_card_t eap_sim_pcsc_card_t;
|
||||
|
||||
/**
|
||||
* SIM card implementation using a PCSC reader.
|
||||
*/
|
||||
struct eap_sim_pcsc_card_t {
|
||||
|
||||
/**
|
||||
* Implements sim_card_t interface
|
||||
*/
|
||||
sim_card_t card;
|
||||
|
||||
/**
|
||||
* Destroy a eap_sim_pcsc_card_t.
|
||||
*/
|
||||
void (*destroy)(eap_sim_pcsc_card_t *this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a eap_sim_pcsc_card instance.
|
||||
*/
|
||||
eap_sim_pcsc_card_t *eap_sim_pcsc_card_create();
|
||||
|
||||
#endif /** EAP_SIM_PCSC_CARD_H_ @}*/
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Copyright (C) 2011 Duncan Salerno
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include "eap_sim_pcsc_plugin.h"
|
||||
#include "eap_sim_pcsc_card.h"
|
||||
|
||||
#include <daemon.h>
|
||||
|
||||
typedef struct private_eap_sim_pcsc_t private_eap_sim_pcsc_t;
|
||||
|
||||
/**
|
||||
* Private data of an eap_sim_pcsc_t object.
|
||||
*/
|
||||
struct private_eap_sim_pcsc_t {
|
||||
|
||||
/**
|
||||
* Public eap_sim_pcsc_plugin_t interface.
|
||||
*/
|
||||
eap_sim_pcsc_plugin_t public;
|
||||
|
||||
/**
|
||||
* SIM card
|
||||
*/
|
||||
eap_sim_pcsc_card_t *card;
|
||||
};
|
||||
|
||||
/**
|
||||
* Implementation of eap_sim_pcsc_t.destroy.
|
||||
*/
|
||||
static void destroy(private_eap_sim_pcsc_t *this)
|
||||
{
|
||||
charon->sim->remove_card(charon->sim, &this->card->card);
|
||||
this->card->destroy(this->card);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* See header
|
||||
*/
|
||||
plugin_t *eap_sim_pcsc_plugin_create()
|
||||
{
|
||||
private_eap_sim_pcsc_t *this = malloc_thing(private_eap_sim_pcsc_t);
|
||||
|
||||
this->public.plugin.destroy = (void(*)(plugin_t*))destroy;
|
||||
this->card = eap_sim_pcsc_card_create();
|
||||
charon->sim->add_card(charon->sim, &this->card->card);
|
||||
|
||||
return &this->public.plugin;
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright (C) 2011 Duncan Salerno
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup eap_sim_pcsc eap_sim_pcsc
|
||||
* @ingroup cplugins
|
||||
*
|
||||
* @defgroup eap_sim_pcsc_plugin eap_sim_pcsc_plugin
|
||||
* @{ @ingroup eap_sim_pcsc
|
||||
*/
|
||||
|
||||
#ifndef EAP_SIM_PCSC_PLUGIN_H_
|
||||
#define EAP_SIM_PCSC_PLUGIN_H_
|
||||
|
||||
#include <plugins/plugin.h>
|
||||
|
||||
typedef struct eap_sim_pcsc_plugin_t eap_sim_pcsc_plugin_t;
|
||||
|
||||
/**
|
||||
* Plugin to provide a SIM card from a PCSC reader.
|
||||
*/
|
||||
struct eap_sim_pcsc_plugin_t {
|
||||
|
||||
/**
|
||||
* implements plugin interface
|
||||
*/
|
||||
plugin_t plugin;
|
||||
};
|
||||
|
||||
#endif /** EAP_SIM_PCSC_PLUGIN_H_ @}*/
|
Loading…
Reference in New Issue