From 79a878466c6f9f2b40eba9e2723e732068146225 Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Fri, 10 Oct 2008 08:36:01 +0000 Subject: [PATCH] reintegrated two-sim branch providing SIM card plugin API --- configure.in | 10 + src/charon/Makefile.am | 6 + src/charon/daemon.c | 3 + src/charon/daemon.h | 6 + src/charon/plugins/eap_sim/Makefile.am | 8 +- src/charon/plugins/eap_sim/eap_sim.c | 161 +++++----- src/charon/plugins/eap_sim/eap_sim.h | 56 +--- src/charon/plugins/eap_sim/eap_sim_file.c | 283 ------------------ src/charon/plugins/eap_sim/eap_sim_plugin.h | 2 +- src/charon/plugins/eap_sim_file/Makefile.am | 14 + .../plugins/eap_sim_file/eap_sim_file_card.c | 108 +++++++ .../plugins/eap_sim_file/eap_sim_file_card.h | 55 ++++ .../eap_sim_file/eap_sim_file_plugin.c | 86 ++++++ .../eap_sim_file/eap_sim_file_plugin.h | 49 +++ .../eap_sim_file/eap_sim_file_provider.c | 88 ++++++ .../eap_sim_file/eap_sim_file_provider.h | 54 ++++ .../eap_sim_file/eap_sim_file_triplets.c | 263 ++++++++++++++++ .../eap_sim_file/eap_sim_file_triplets.h | 74 +++++ .../sa/authenticators/eap/sim_manager.c | 125 ++++++++ .../sa/authenticators/eap/sim_manager.h | 136 +++++++++ 20 files changed, 1164 insertions(+), 423 deletions(-) delete mode 100644 src/charon/plugins/eap_sim/eap_sim_file.c create mode 100644 src/charon/plugins/eap_sim_file/Makefile.am create mode 100644 src/charon/plugins/eap_sim_file/eap_sim_file_card.c create mode 100644 src/charon/plugins/eap_sim_file/eap_sim_file_card.h create mode 100644 src/charon/plugins/eap_sim_file/eap_sim_file_plugin.c create mode 100644 src/charon/plugins/eap_sim_file/eap_sim_file_plugin.h create mode 100644 src/charon/plugins/eap_sim_file/eap_sim_file_provider.c create mode 100644 src/charon/plugins/eap_sim_file/eap_sim_file_provider.h create mode 100644 src/charon/plugins/eap_sim_file/eap_sim_file_triplets.c create mode 100644 src/charon/plugins/eap_sim_file/eap_sim_file_triplets.h create mode 100644 src/charon/sa/authenticators/eap/sim_manager.c create mode 100644 src/charon/sa/authenticators/eap/sim_manager.h diff --git a/configure.in b/configure.in index 5c0cf3ab6..6c8c1accc 100644 --- a/configure.in +++ b/configure.in @@ -393,6 +393,14 @@ AC_ARG_ENABLE( fi] ) +AC_ARG_ENABLE( + [eap-sim-file], + AS_HELP_STRING([--enable-eap-sim-file],[build EAP-SIM backend based on a triplet file (default is NO).]), + [if test x$enableval = xyes; then + eap_sim_file=true + fi] +) + AC_ARG_ENABLE( [eap-identity], AS_HELP_STRING([--enable-eap-identity],[build EAP module providing EAP-Identity helper (default is NO).]), @@ -860,6 +868,7 @@ AM_CONDITIONAL(USE_SMP, test x$smp = xtrue) AM_CONDITIONAL(USE_SQL, test x$sql = xtrue) AM_CONDITIONAL(USE_UNIT_TESTS, test x$unittest = 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_IDENTITY, test x$eap_identity = xtrue) AM_CONDITIONAL(USE_EAP_MD5, test x$eap_md5 = xtrue) AM_CONDITIONAL(USE_EAP_GTC, test x$eap_gtc = xtrue) @@ -938,6 +947,7 @@ AC_OUTPUT( src/charon/plugins/eap_md5/Makefile src/charon/plugins/eap_gtc/Makefile src/charon/plugins/eap_sim/Makefile + src/charon/plugins/eap_sim_file/Makefile src/charon/plugins/kernel_netlink/Makefile src/charon/plugins/smp/Makefile src/charon/plugins/sql/Makefile diff --git a/src/charon/Makefile.am b/src/charon/Makefile.am index 464d82fe5..c9f63ac9d 100644 --- a/src/charon/Makefile.am +++ b/src/charon/Makefile.am @@ -66,6 +66,7 @@ sa/authenticators/authenticator.c sa/authenticators/authenticator.h \ sa/authenticators/eap_authenticator.c sa/authenticators/eap_authenticator.h \ sa/authenticators/eap/eap_method.c sa/authenticators/eap/eap_method.h \ sa/authenticators/eap/eap_manager.c sa/authenticators/eap/eap_manager.h \ +sa/authenticators/eap/sim_manager.c sa/authenticators/eap/sim_manager.h \ sa/authenticators/psk_authenticator.c sa/authenticators/psk_authenticator.h \ sa/authenticators/pubkey_authenticator.c sa/authenticators/pubkey_authenticator.h \ sa/child_sa.c sa/child_sa.h \ @@ -173,6 +174,11 @@ if USE_EAP_SIM PLUGINS += eapsim endif +if USE_EAP_SIM_FILE + SUBDIRS += plugins/eap_sim_file + PLUGINS += eapsim-file +endif + if USE_EAP_MD5 SUBDIRS += plugins/eap_md5 PLUGINS += eapmd5 diff --git a/src/charon/daemon.c b/src/charon/daemon.c index 05da3c61c..065f7d701 100644 --- a/src/charon/daemon.c +++ b/src/charon/daemon.c @@ -195,6 +195,7 @@ static void destroy(private_daemon_t *this) DESTROY_IF(this->public.scheduler); DESTROY_IF(this->public.controller); DESTROY_IF(this->public.eap); + DESTROY_IF(this->public.sim); #ifdef ME DESTROY_IF(this->public.connect_manager); DESTROY_IF(this->public.mediation_manager); @@ -357,6 +358,7 @@ static bool initialize(private_daemon_t *this, bool syslog, level_t levels[]) this->public.credentials = credential_manager_create(); this->public.controller = controller_create(); this->public.eap = eap_manager_create(); + this->public.sim = sim_manager_create(); this->public.backends = backend_manager_create(); this->public.attributes = attribute_manager_create(); this->public.kernel_interface = kernel_interface_create(); @@ -479,6 +481,7 @@ private_daemon_t *daemon_create(void) this->public.processor = NULL; this->public.controller = NULL; this->public.eap = NULL; + this->public.sim = NULL; this->public.bus = NULL; this->public.outlog = NULL; this->public.syslog = NULL; diff --git a/src/charon/daemon.h b/src/charon/daemon.h index 3bde9a25d..da7d4e6fe 100644 --- a/src/charon/daemon.h +++ b/src/charon/daemon.h @@ -163,6 +163,7 @@ typedef struct daemon_t daemon_t; #include #include #include +#include #ifdef ME #include @@ -280,6 +281,11 @@ struct daemon_t { */ eap_manager_t *eap; + /** + * SIM manager to maintain SIM cards/providers + */ + sim_manager_t *sim; + #ifdef ME /** * Connect manager diff --git a/src/charon/plugins/eap_sim/Makefile.am b/src/charon/plugins/eap_sim/Makefile.am index 63267b9d3..6cb53ebb5 100644 --- a/src/charon/plugins/eap_sim/Makefile.am +++ b/src/charon/plugins/eap_sim/Makefile.am @@ -3,11 +3,9 @@ INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon AM_CFLAGS = -rdynamic -DIPSEC_CONFDIR=\"${confdir}\" -DSIM_READER_LIB=\"${simreader}\" -plugin_LTLIBRARIES = libstrongswan-eapsim.la libeapsim-file.la +plugin_LTLIBRARIES = libstrongswan-eapsim.la -libstrongswan_eapsim_la_SOURCES = eap_sim_plugin.h eap_sim_plugin.c eap_sim.h eap_sim.c +libstrongswan_eapsim_la_SOURCES = eap_sim.h eap_sim.c \ + eap_sim_plugin.h eap_sim_plugin.c libstrongswan_eapsim_la_LDFLAGS = -module -libeapsim_file_la_SOURCES = eap_sim_file.c -libeapsim_file_la_LDFLAGS = -module - diff --git a/src/charon/plugins/eap_sim/eap_sim.c b/src/charon/plugins/eap_sim/eap_sim.c index 11d2e74bc..11e4adbe0 100644 --- a/src/charon/plugins/eap_sim/eap_sim.c +++ b/src/charon/plugins/eap_sim/eap_sim.c @@ -149,21 +149,6 @@ struct private_eap_sim_t { */ signer_t *signer; - /** - * SIM cardreader function loaded from library - */ - sim_algo_t alg; - - /** - * libraries get_triplet() function returning a triplet - */ - sim_get_triplet_t get_triplet; - - /** - * handle of the loaded library - */ - void *handle; - /** * how many times we try to authenticate */ @@ -215,7 +200,7 @@ struct private_eap_sim_t { chunk_t msk; /** - * EMSK, extendes MSK for further uses + * EMSK, extended MSK for further uses */ chunk_t emsk; }; @@ -556,6 +541,41 @@ static void derive_keys(private_eap_sim_t *this, chunk_t kcs) &this->k_encr, &this->k_auth, &this->msk, &this->emsk); } +/** + * Read a triplet from the SIM card + */ +static bool get_card_triplet(private_eap_sim_t *this, + char *rand, char *sres, char *kc) +{ + enumerator_t *enumerator; + sim_card_t *card = NULL, *current; + id_match_t match, best = ID_MATCH_NONE; + bool success = FALSE; + + /* find the best matching SIM */ + enumerator = charon->sim->create_card_enumerator(charon->sim); + while (enumerator->enumerate(enumerator, ¤t)) + { + match = this->peer->matches(this->peer, current->get_imsi(current)); + if (match > best) + { + card = current; + best = match; + break; + } + } + if (card) + { + success = card->get_triplet(card, rand, sres, kc); + } + enumerator->destroy(enumerator); + if (!card) + { + DBG1(DBG_IKE, "no SIM card found matching '%D'", this->peer); + } + return success; +} + /** * process an EAP-SIM/Request/Challenge message */ @@ -649,11 +669,9 @@ static status_t peer_process_challenge(private_eap_sim_t *this, /* get two or three KCs/SRESes from SIM using RANDs */ kcs = kc = chunk_alloca(rands.len / 2); sreses = sres = chunk_alloca(rands.len / 4); - while (rands.len > 0) - { - int kc_len = kc.len, sres_len = sres.len; - - if (this->alg(rands.ptr, RAND_LEN, sres.ptr, &sres_len, kc.ptr, &kc_len)) + while (rands.len >= RAND_LEN) + { + if (!get_card_triplet(this, rands.ptr, sres.ptr, kc.ptr)) { DBG1(DBG_IKE, "unable to get EAP-SIM triplet"); *out = build_payload(this, identifier, SIM_CLIENT_ERROR, @@ -662,9 +680,9 @@ static status_t peer_process_challenge(private_eap_sim_t *this, return NEED_MORE; } DBG3(DBG_IKE, "got triplet for RAND %b\n Kc %b\n SRES %b", - rands.ptr, RAND_LEN, sres.ptr, sres_len, kc.ptr, kc_len); - kc = chunk_skip(kc, kc_len); - sres = chunk_skip(sres, sres_len); + rands.ptr, RAND_LEN, sres.ptr, SRES_LEN, kc.ptr, KC_LEN); + kc = chunk_skip(kc, KC_LEN); + sres = chunk_skip(sres, SRES_LEN); rands = chunk_skip(rands, RAND_LEN); } @@ -736,6 +754,32 @@ static status_t server_process_challenge(private_eap_sim_t *this, return SUCCESS; } +/** + * Fetch a triplet from a provider + */ +static bool get_provider_triplet(private_eap_sim_t *this, + char *rand, char *sres, char *kc) +{ + enumerator_t *enumerator; + sim_provider_t *provider; + int tried = 0; + + enumerator = charon->sim->create_provider_enumerator(charon->sim); + while (enumerator->enumerate(enumerator, &provider)) + { + if (provider->get_triplet(provider, this->peer, rand, sres, kc)) + { + enumerator->destroy(enumerator); + return TRUE; + } + tried++; + } + enumerator->destroy(enumerator); + DBG1(DBG_IKE, "tried %d SIM providers, but none had a triplet for '%D'", + tried, this->peer); + return FALSE; +} + /** * process an EAP-SIM/Response/Start message */ @@ -746,9 +790,8 @@ static status_t server_process_start(private_eap_sim_t *this, sim_attribute_t attribute; bool supported = FALSE; chunk_t rands, rand, kcs, kc, sreses, sres; - char id[64]; - int len, i, rand_len, kc_len, sres_len; - + int i; + message = in->get_data(in); read_header(&message); @@ -779,11 +822,6 @@ static status_t server_process_start(private_eap_sim_t *this, DBG1(DBG_IKE, "received incomplete EAP-SIM/Response/Start"); return FAILED; } - len = snprintf(id, sizeof(id), "%D", this->peer); - if (len > sizeof(id) || len < 0) - { - return FAILED; - } /* read triplets from provider */ rand = rands = chunk_alloca(RAND_LEN * TRIPLET_COUNT); @@ -794,21 +832,17 @@ static status_t server_process_start(private_eap_sim_t *this, sreses.len = 0; for (i = 0; i < TRIPLET_COUNT; i++) { - rand_len = RAND_LEN; - kc_len = KC_LEN; - sres_len = SRES_LEN; - if (this->get_triplet(id, rand.ptr, &rand_len, sres.ptr, &sres_len, - kc.ptr, &kc_len)) + if (!get_provider_triplet(this, rand.ptr, sres.ptr, kc.ptr)) { DBG1(DBG_IKE, "getting EAP-SIM triplet %d failed", i); return FAILED; } - rands.len += rand_len; - kcs.len += kc_len; - sreses.len += sres_len; - rand = chunk_skip(rand, rand_len); - kc = chunk_skip(kc, kc_len); - sres = chunk_skip(sres, sres_len); + rands.len += RAND_LEN; + sreses.len += SRES_LEN; + kcs.len += KC_LEN; + rand = chunk_skip(rand, RAND_LEN); + sres = chunk_skip(sres, SRES_LEN); + kc = chunk_skip(kc, KC_LEN); } derive_keys(this, kcs); @@ -1017,7 +1051,7 @@ static bool is_mutual(private_eap_sim_t *this) static void destroy(private_eap_sim_t *this) { this->peer->destroy(this->peer); - dlclose(this->handle); + this->peer->destroy(this->peer); DESTROY_IF(this->hasher); DESTROY_IF(this->prf); DESTROY_IF(this->signer); @@ -1037,14 +1071,9 @@ static void destroy(private_eap_sim_t *this) eap_sim_t *eap_sim_create_generic(eap_role_t role, identification_t *server, identification_t *peer) { - private_eap_sim_t *this; + private_eap_sim_t *this = malloc_thing(private_eap_sim_t); rng_t *rng; - void *symbol; - char *name; - - this = malloc_thing(private_eap_sim_t); - this->alg = NULL; - this->get_triplet = NULL; + this->nonce = chunk_empty; this->sreses = chunk_empty; this->peer = peer->clone(peer); @@ -1061,46 +1090,16 @@ eap_sim_t *eap_sim_create_generic(eap_role_t role, identification_t *server, this->identifier = random(); } while (!this->identifier); - this->handle = dlopen(SIM_READER_LIB, RTLD_LAZY); - if (this->handle == NULL) - { - DBG1(DBG_IKE, "unable to open SIM reader '%s'", SIM_READER_LIB); - free(this); - return NULL; - } - switch (role) - { - case EAP_PEER: - name = SIM_READER_ALG; - break; - case EAP_SERVER: - name = SIM_READER_GET_TRIPLET; - break; - default: - free(this); - return NULL; - } - symbol = dlsym(this->handle, name); - if (symbol == NULL) - { - DBG1(DBG_IKE, "unable to open SIM function '%s' in '%s'", - name, SIM_READER_LIB); - dlclose(this->handle); - free(this); - return NULL; - } switch (role) { case EAP_SERVER: this->public.eap_method_interface.initiate = (status_t(*)(eap_method_t*,eap_payload_t**))server_initiate; this->public.eap_method_interface.process = (status_t(*)(eap_method_t*,eap_payload_t*,eap_payload_t**))server_process; - this->get_triplet = symbol; this->type = EAP_REQUEST; break; case EAP_PEER: this->public.eap_method_interface.initiate = (status_t(*)(eap_method_t*,eap_payload_t**))peer_initiate; this->public.eap_method_interface.process = (status_t(*)(eap_method_t*,eap_payload_t*,eap_payload_t**))peer_process; - this->alg = symbol; this->type = EAP_RESPONSE; rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK); if (!rng) diff --git a/src/charon/plugins/eap_sim/eap_sim.h b/src/charon/plugins/eap_sim/eap_sim.h index 65020aa64..ec061b6f4 100644 --- a/src/charon/plugins/eap_sim/eap_sim.h +++ b/src/charon/plugins/eap_sim/eap_sim.h @@ -25,62 +25,12 @@ typedef struct eap_sim_t eap_sim_t; #include -/** the library containing with the triplet functions */ -#ifndef SIM_READER_LIB -#error SIM_READER_LIB not specified, use --with-sim-reader option -#endif /* SIM_READER_LIB */ - -/** - * Cardreaders SIM function. - * - * @param rand RAND to run algo with - * @param rand_length length of value in rand - * @param sres buffer to get SRES - * @param sres_length size of buffer in sres, returns bytes written to SRES - * @param kc buffer to get Kc - * @param kc_length size of buffer in Kc, returns bytes written to Kc - * @return zero on success - */ -typedef int (*sim_algo_t)(const unsigned char *rand, int rand_length, - unsigned char *sres, int *sres_length, - unsigned char *kc, int *kc_length); - -#ifndef SIM_READER_ALG -/** the SIM_READER_LIB's algorithm, uses sim_algo_t signature */ -#define SIM_READER_ALG "sim_run_alg" -#endif /* SIM_READER_ALG */ - -/** - * Function to get a SIM triplet. - * - * @param identity identity (imsi) to get a triplet for - * @param rand buffer to get RAND - * @param rand_length size of buffer in rand, returns bytes written to RAND - * @param sres buffer to get SRES - * @param sres_length size of buffer in sres, returns bytes written to SRES - * @param kc buffer to get Kc - * @param kc_length size of buffer in Kc, returns bytes written to Kc - * @return zero on success - */ -typedef int (*sim_get_triplet_t)(char *identity, - unsigned char *rand, int *rand_length, - unsigned char *sres, int *sres_length, - unsigned char *kc, int *kc_length); - -#ifndef SIM_READER_GET_TRIPLET -/** the SIM_READER_LIB's get-triplet function, uses sim_get_triplet_t signature */ -#define SIM_READER_GET_TRIPLET "sim_get_triplet" -#endif /* SIM_READER_GET_TRIPLET */ - /** * Implementation of the eap_method_t interface using EAP-SIM. * - * This EAP-SIM client implementation uses another pluggable library to - * access the SIM card/triplet provider. This module is specified using the - * SIM_READER_LIB definition. It has to privde a sim_run_alg() function to - * calculate a triplet (client), and/or a sim_get_triplet() function to get - * a triplet (server). These functions are named to the SIM_READER_ALG and - * the SIM_READER_GET_TRIPLET definitions. + * This EAP-SIM client implementation handles the protocol level of EAP-SIM + * only, it does not provide triplet calculation/fetching. Other plugins may + * provide these services using the sim_manager_t of charon. */ struct eap_sim_t { diff --git a/src/charon/plugins/eap_sim/eap_sim_file.c b/src/charon/plugins/eap_sim/eap_sim_file.c deleted file mode 100644 index 7040a5ace..000000000 --- a/src/charon/plugins/eap_sim/eap_sim_file.c +++ /dev/null @@ -1,283 +0,0 @@ -/* - * Copyright (C) 2007 Martin Willi - * Hochschule fuer Technik Rapperswil - * - * 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 . - * - * 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. - * - * $Id$ - */ - -#include -#include -#include - -#include - -#define IMSI_LEN 64 -#define RAND_LEN 16 -#define SRES_LEN 4 -#define KC_LEN 8 - -typedef struct triplet_t triplet_t; - -struct triplet_t { - unsigned char imsi[IMSI_LEN]; - unsigned char rand[RAND_LEN]; - unsigned char sres[SRES_LEN]; - unsigned char kc[KC_LEN]; -}; - -static triplet_t *triplets = NULL; -static int triplet_count = 0; - -#define TRIPLET_FILE IPSEC_CONFDIR "/ipsec.d/triplets.dat" - -/** - * convert a single HEX char to its integer value - */ -static int hexchr(char chr) -{ - switch (chr) - { - case '0'...'9': - return chr - '0'; - case 'A'...'F': - return 10 + chr - 'A'; - case 'a'...'f': - return 10 + chr - 'a'; - } - return 0; -} - -/** - * convert a HEX string into a char array bin, limited by array length len - */ -static void hex2bin(char *hex, unsigned char *bin, size_t len) -{ - char *pos; - int i, even = 1; - - pos = hex - 1; - /* find the end, as we convert bottom up */ - while (TRUE) - { - switch (*(pos+1)) - { - case '0'...'9': - case 'A'...'F': - case 'a'...'f': - pos++; - continue; - } - break; - } - /* convert two hex chars into a single bin byte */ - for (i = 0; pos >= hex && i < len; pos--) - { - if (even) - { - bin[len - 1 - i] = hexchr(*pos); - } - else - { - bin[len - 1 - i] |= 16 * hexchr(*pos); - i++; - } - even = !even; - } -} - -/** - * free up allocated triplets - */ -static void __attribute__ ((destructor)) free_triplets() -{ - free(triplets); -} - -/** - * read the triplets from the file, using freeradius triplet file syntax: - * http://www.freeradius.org/radiusd/doc/rlm_sim_triplets - */ -static void __attribute__ ((constructor)) read_triplets() -{ - char line[512], *data[4], *pos; - FILE *file; - int i, nr = 0; - triplet_t *triplet; - - file = fopen(TRIPLET_FILE, "r"); - if (file == NULL) - { - DBG1(DBG_CFG, "opening triplet file %s failed: %s", - TRIPLET_FILE, strerror(errno)); - return; - } - - if (triplets) - { - free(triplets); - triplets = NULL; - triplet_count = 0; - } - - /* read line by line */ - while (fgets(line, sizeof(line), file)) - { - nr++; - /* skip comments, empty lines */ - switch (line[0]) - { - case '\n': - case '\r': - case '#': - case '\0': - continue; - default: - break; - } - /* read comma separated values */ - pos = line; - for (i = 0; i < 4; i++) - { - data[i] = pos; - pos = strchr(pos, ','); - if (pos) - { - *pos = '\0'; - pos++; - } - else if (i != 3) - { - DBG1(DBG_CFG, "error in triplet file, line %d", nr); - fclose(file); - return; - } - } - /* allocate new triplet */ - triplet_count++; - triplets = realloc(triplets, triplet_count * sizeof(triplet_t)); - triplet = &triplets[triplet_count - 1]; - memset(triplet, 0, sizeof(triplet_t)); - - /* convert/copy triplet data */ - for (i = 0; i < IMSI_LEN - 1; i++) - { - switch (data[0][i]) - { - case '\n': - case '\r': - case '\0': - break; - default: - triplet->imsi[i] = data[0][i]; - continue; - } - break; - } - hex2bin(data[1], triplet->rand, RAND_LEN); - hex2bin(data[2], triplet->sres, SRES_LEN); - hex2bin(data[3], triplet->kc, KC_LEN); - - DBG4(DBG_CFG, "triplet: imsi %b\nrand %b\nsres %b\nkc %b", - triplet->imsi, IMSI_LEN, triplet->rand, RAND_LEN, - triplet->sres, SRES_LEN, triplet->kc, KC_LEN); - } - fclose(file); - DBG2(DBG_CFG, "read %d triplets from %s", triplet_count, TRIPLET_FILE); -} - -/** - * Run the sim algorithm, see eap_sim.h - */ -int sim_run_alg(const unsigned char *rand, int rand_length, - unsigned char *sres, int *sres_length, - unsigned char *kc, int *kc_length) -{ - int current; - - if (rand_length != RAND_LEN || - *sres_length < SRES_LEN || - *kc_length < KC_LEN) - { - return 1; - } - - for (current = 0; current < triplet_count; current++) - { - if (memcmp(triplets[current].rand, rand, RAND_LEN) == 0) - { - memcpy(sres, triplets[current].sres, SRES_LEN); - memcpy(kc, triplets[current].kc, KC_LEN); - *sres_length = SRES_LEN; - *kc_length = KC_LEN; - return 0; - } - } - return 2; -} - -/** - * Get a single triplet, see_eap_sim.h - */ -int sim_get_triplet(char *imsi, - unsigned char *rand, int *rand_length, - unsigned char *sres, int *sres_length, - unsigned char *kc, int *kc_length) -{ - int current; - triplet_t *triplet; - static int skip = -1; - - DBG2(DBG_CFG, "getting triplet for %s", imsi); - - if (*rand_length < RAND_LEN || - *sres_length < SRES_LEN || - *kc_length < KC_LEN) - { - return 1; - } - if (triplet_count == 0) - { - return 2; - } - for (current = 0; current < triplet_count; current++) - { - triplet = &triplets[current]; - - if (streq(imsi, triplet->imsi)) - { - /* skip triplet if already used */ - if (skip >= current) - { - continue; - } - *rand_length = RAND_LEN; - *sres_length = SRES_LEN; - *kc_length = KC_LEN; - memcpy(rand, triplet->rand, RAND_LEN); - memcpy(sres, triplet->sres, SRES_LEN); - memcpy(kc, triplet->kc, KC_LEN); - /* remember used triplet */ - skip = current; - return 0; - } - } - if (skip > -1) - { - /* no triplet left, reuse triplets */ - skip = -1; - return sim_get_triplet(imsi, rand, rand_length, - sres, sres_length, kc, kc_length); - } - return 2; -} - diff --git a/src/charon/plugins/eap_sim/eap_sim_plugin.h b/src/charon/plugins/eap_sim/eap_sim_plugin.h index e142b8991..a12234157 100644 --- a/src/charon/plugins/eap_sim/eap_sim_plugin.h +++ b/src/charon/plugins/eap_sim/eap_sim_plugin.h @@ -31,7 +31,7 @@ typedef struct eap_sim_plugin_t eap_sim_plugin_t; /** - * EAP-sim plugin + * EAP-SIM plugin. */ struct eap_sim_plugin_t { diff --git a/src/charon/plugins/eap_sim_file/Makefile.am b/src/charon/plugins/eap_sim_file/Makefile.am new file mode 100644 index 000000000..fc3a0fa14 --- /dev/null +++ b/src/charon/plugins/eap_sim_file/Makefile.am @@ -0,0 +1,14 @@ + +INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon + +AM_CFLAGS = -rdynamic -DIPSEC_CONFDIR=\"${confdir}\" + +plugin_LTLIBRARIES = libstrongswan-eapsim-file.la + +libstrongswan_eapsim_file_la_SOURCES = \ + eap_sim_file_plugin.h eap_sim_file_plugin.c \ + eap_sim_file_card.h eap_sim_file_card.c \ + eap_sim_file_provider.h eap_sim_file_provider.c \ + eap_sim_file_triplets.h eap_sim_file_triplets.c +libstrongswan_eapsim_file_la_LDFLAGS = -module + diff --git a/src/charon/plugins/eap_sim_file/eap_sim_file_card.c b/src/charon/plugins/eap_sim_file/eap_sim_file_card.c new file mode 100644 index 000000000..7969007d0 --- /dev/null +++ b/src/charon/plugins/eap_sim_file/eap_sim_file_card.c @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2008 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * 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 . + * + * 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. + * + * $Id$ + */ + +#include "eap_sim_file_card.h" + +typedef struct private_eap_sim_file_card_t private_eap_sim_file_card_t; + +/** + * Private data of an eap_sim_file_card_t object. + */ +struct private_eap_sim_file_card_t { + + /** + * Public eap_sim_file_card_t interface. + */ + eap_sim_file_card_t public; + + /** + * IMSI, is ID_ANY for file implementation + */ + identification_t *imsi; + + /** + * source of triplets + */ + eap_sim_file_triplets_t *triplets; +}; + +#include + +/** + * Implementation of sim_card_t.get_triplet + */ +static bool get_triplet(private_eap_sim_file_card_t *this, + char *rand, char *sres, char *kc) +{ + enumerator_t *enumerator; + identification_t *id; + char *c_rand, *c_sres, *c_kc; + + + DBG1(DBG_CFG, "looking for rand: %b", rand, RAND_LEN); + + enumerator = this->triplets->create_enumerator(this->triplets); + while (enumerator->enumerate(enumerator, &id, &c_rand, &c_sres, &c_kc)) + { + DBG1(DBG_CFG, "found triplet: %b %b %b", c_rand, RAND_LEN, c_sres, SRES_LEN, c_kc, KC_LEN); + if (memeq(c_rand, rand, RAND_LEN)) + { + memcpy(sres, c_sres, SRES_LEN); + memcpy(kc, c_kc, KC_LEN); + enumerator->destroy(enumerator); + return TRUE; + } + } + enumerator->destroy(enumerator); + return FALSE; +} + +/** + * Implementation of sim_card_t.get_imsi + */ +static identification_t* get_imsi(private_eap_sim_file_card_t *this) +{ + return this->imsi; +} + +/** + * Implementation of eap_sim_file_card_t.destroy. + */ +static void destroy(private_eap_sim_file_card_t *this) +{ + this->imsi->destroy(this->imsi); + free(this); +} + +/** + * See header + */ +eap_sim_file_card_t *eap_sim_file_card_create(eap_sim_file_triplets_t *triplets) +{ + private_eap_sim_file_card_t *this = malloc_thing(private_eap_sim_file_card_t); + + this->public.card.get_triplet = (bool(*)(sim_card_t*, char *rand, char *sres, char *kc))get_triplet; + this->public.card.get_imsi = (identification_t*(*)(sim_card_t*))get_imsi; + this->public.destroy = (void(*)(eap_sim_file_card_t*))destroy; + + /* this SIM card implementation does not have an ID, serve ID_ANY */ + this->imsi = identification_create_from_encoding(ID_ANY, chunk_empty); + this->triplets = triplets; + + return &this->public; +} + diff --git a/src/charon/plugins/eap_sim_file/eap_sim_file_card.h b/src/charon/plugins/eap_sim_file/eap_sim_file_card.h new file mode 100644 index 000000000..953a3e915 --- /dev/null +++ b/src/charon/plugins/eap_sim_file/eap_sim_file_card.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2008 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * 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 . + * + * 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. + * + * $Id$ + */ + +/** + * @defgroup eap_sim_file_card eap_sim_file_card + * @{ @ingroup eap_sim_file + */ + +#ifndef EAP_SIM_FILE_CARD_H_ +#define EAP_SIM_FILE_CARD_H_ + +#include "eap_sim_file_triplets.h" + +#include + +typedef struct eap_sim_file_card_t eap_sim_file_card_t; + +/** + * SIM card implementation on top of a triplet file. + */ +struct eap_sim_file_card_t { + + /** + * Implements sim_card_t interface + */ + sim_card_t card; + + /** + * Destroy a eap_sim_file_card_t. + */ + void (*destroy)(eap_sim_file_card_t *this); +}; + +/** + * Create a eap_sim_file_card instance. + * + * @param triplets source of triplets + */ +eap_sim_file_card_t *eap_sim_file_card_create(eap_sim_file_triplets_t *triplets); + +#endif /* EAP_SIM_FILE_CARD_ @}*/ diff --git a/src/charon/plugins/eap_sim_file/eap_sim_file_plugin.c b/src/charon/plugins/eap_sim_file/eap_sim_file_plugin.c new file mode 100644 index 000000000..6129ebb72 --- /dev/null +++ b/src/charon/plugins/eap_sim_file/eap_sim_file_plugin.c @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2008 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * 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 . + * + * 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. + * + * $Id$ + */ + +#include "eap_sim_file_plugin.h" +#include "eap_sim_file_card.h" +#include "eap_sim_file_provider.h" +#include "eap_sim_file_triplets.h" + +#include + +#define TRIPLET_FILE IPSEC_CONFDIR "/ipsec.d/triplets.dat" + +typedef struct private_eap_sim_file_t private_eap_sim_file_t; + +/** + * Private data of an eap_sim_file_t object. + */ +struct private_eap_sim_file_t { + + /** + * Public eap_sim_file_plugin_t interface. + */ + eap_sim_file_plugin_t public; + + /** + * SIM card + */ + eap_sim_file_card_t *card; + + /** + * SIM provider + */ + eap_sim_file_provider_t *provider; + + /** + * Triplet source + */ + eap_sim_file_triplets_t *triplets; +}; + +/** + * Implementation of eap_sim_file_t.destroy. + */ +static void destroy(private_eap_sim_file_t *this) +{ + charon->sim->remove_card(charon->sim, &this->card->card); + charon->sim->remove_provider(charon->sim, &this->provider->provider); + this->card->destroy(this->card); + this->provider->destroy(this->provider); + this->triplets->destroy(this->triplets); + free(this); +} + +/** + * See header + */ +plugin_t *plugin_create() +{ + private_eap_sim_file_t *this = malloc_thing(private_eap_sim_file_t); + + this->public.plugin.destroy = (void(*)(plugin_t*))destroy; + + this->triplets = eap_sim_file_triplets_create(TRIPLET_FILE); + this->card = eap_sim_file_card_create(this->triplets); + this->provider = eap_sim_file_provider_create(this->triplets); + + charon->sim->add_card(charon->sim, &this->card->card); + charon->sim->add_provider(charon->sim, &this->provider->provider); + + return &this->public.plugin; +} + diff --git a/src/charon/plugins/eap_sim_file/eap_sim_file_plugin.h b/src/charon/plugins/eap_sim_file/eap_sim_file_plugin.h new file mode 100644 index 000000000..c1828527d --- /dev/null +++ b/src/charon/plugins/eap_sim_file/eap_sim_file_plugin.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2008 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * 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 . + * + * 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. + * + * $Id$ + */ + +/** + * @defgroup eap_sim_file eap_sim_file + * @ingroup cplugins + * + * @defgroup eap_sim_file_plugin eap_sim_file_plugin + * @{ @ingroup eap_sim_file + */ + +#ifndef EAP_SIM_FILE_PLUGIN_H_ +#define EAP_SIM_FILE_PLUGIN_H_ + +#include + +typedef struct eap_sim_file_plugin_t eap_sim_file_plugin_t; + +/** + * Plugin to provide a SIM card/provider on top of a triplet file. + */ +struct eap_sim_file_plugin_t { + + /** + * implements plugin interface + */ + plugin_t plugin; +}; + +/** + * Create a eap_sim_file_plugin instance. + */ +plugin_t *plugin_create(); + +#endif /* EAP_SIM_FILE_PLUGIN_H_ @}*/ diff --git a/src/charon/plugins/eap_sim_file/eap_sim_file_provider.c b/src/charon/plugins/eap_sim_file/eap_sim_file_provider.c new file mode 100644 index 000000000..ffb4b2901 --- /dev/null +++ b/src/charon/plugins/eap_sim_file/eap_sim_file_provider.c @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2008 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * 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 . + * + * 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. + * + * $Id$ + */ + +#include "eap_sim_file_provider.h" + +typedef struct private_eap_sim_file_provider_t private_eap_sim_file_provider_t; + +/** + * Private data of an eap_sim_file_provider_t object. + */ +struct private_eap_sim_file_provider_t { + + /** + * Public eap_sim_file_provider_t interface. + */ + eap_sim_file_provider_t public; + + /** + * source of triplets + */ + eap_sim_file_triplets_t *triplets; +}; + +/** + * Implementation of sim_provider_t.get_triplet + */ +static bool get_triplet(private_eap_sim_file_provider_t *this, + identification_t *imsi, + char *rand, char *sres, char *kc) +{ + enumerator_t *enumerator; + identification_t *id; + char *c_rand, *c_sres, *c_kc; + + enumerator = this->triplets->create_enumerator(this->triplets); + while (enumerator->enumerate(enumerator, &id, &c_rand, &c_sres, &c_kc)) + { + if (imsi->matches(imsi, id)) + { + memcpy(rand, c_rand, RAND_LEN); + memcpy(sres, c_sres, SRES_LEN); + memcpy(kc, c_kc, KC_LEN); + enumerator->destroy(enumerator); + return TRUE; + } + } + enumerator->destroy(enumerator); + return FALSE; +} + +/** + * Implementation of eap_sim_file_provider_t.destroy. + */ +static void destroy(private_eap_sim_file_provider_t *this) +{ + free(this); +} + +/** + * See header + */ +eap_sim_file_provider_t *eap_sim_file_provider_create( + eap_sim_file_triplets_t *triplets) +{ + private_eap_sim_file_provider_t *this = malloc_thing(private_eap_sim_file_provider_t); + + this->public.provider.get_triplet = (bool(*)(sim_provider_t*, identification_t *imsi, char rand[16], char sres[4], char kc[8]))get_triplet; + this->public.destroy = (void(*)(eap_sim_file_provider_t*))destroy; + + this->triplets = triplets; + + return &this->public; +} + diff --git a/src/charon/plugins/eap_sim_file/eap_sim_file_provider.h b/src/charon/plugins/eap_sim_file/eap_sim_file_provider.h new file mode 100644 index 000000000..bc8f6cca0 --- /dev/null +++ b/src/charon/plugins/eap_sim_file/eap_sim_file_provider.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2008 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * 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 . + * + * 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. + * + * $Id$ + */ + +/** + * @defgroup eap_sim_file_provider eap_sim_file_provider + * @{ @ingroup eap_sim_file + */ + +#ifndef EAP_SIM_FILE_PROVIDER_H_ +#define EAP_SIM_FILE_PROVIDER_H_ + +#include "eap_sim_file_triplets.h" + +#include + +typedef struct eap_sim_file_provider_t eap_sim_file_provider_t; + +/** + * SIM provider implementation on top of triplets file. + */ +struct eap_sim_file_provider_t { + + /** + * Implements sim_provider_t interface. + */ + sim_provider_t provider; + + /** + * Destroy a eap_sim_file_provider_t. + */ + void (*destroy)(eap_sim_file_provider_t *this); +}; + +/** + * Create a eap_sim_file_provider instance. + */ +eap_sim_file_provider_t *eap_sim_file_provider_create( + eap_sim_file_triplets_t *triplets); + +#endif /* EAP_SIM_FILE_PROVIDER_ @}*/ diff --git a/src/charon/plugins/eap_sim_file/eap_sim_file_triplets.c b/src/charon/plugins/eap_sim_file/eap_sim_file_triplets.c new file mode 100644 index 000000000..409e9cbd5 --- /dev/null +++ b/src/charon/plugins/eap_sim_file/eap_sim_file_triplets.c @@ -0,0 +1,263 @@ +/* + * Copyright (C) 2008 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * 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 . + * + * 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. + * + * $Id$ + */ + +#include "eap_sim_file_triplets.h" + +#include +#include + +#include +#include +#include + +typedef struct private_eap_sim_file_triplets_t private_eap_sim_file_triplets_t; + +/** + * Private data of an eap_sim_file_triplets_t object. + */ +struct private_eap_sim_file_triplets_t { + + /** + * Public eap_sim_file_triplets_t interface. + */ + eap_sim_file_triplets_t public; + + /** + * List of triplets, as triplet_t + */ + linked_list_t *triplets; + + /** + * mutex to lock triplets list + */ + mutex_t *mutex; +}; + +/** + * A single triplet + */ +typedef struct { + identification_t *imsi; + char rand[RAND_LEN]; + char sres[SRES_LEN]; + char kc[KC_LEN]; +} triplet_t; + +/** + * Destroy a triplet + */ +static void triplet_destroy(triplet_t *this) +{ + this->imsi->destroy(this->imsi); + free(this); +} + +/** + * triplet enumerator + */ +typedef struct { + /** implements enumerator */ + enumerator_t public; + /** inner enumerator */ + enumerator_t *inner; + /** current enumerating triplet */ + triplet_t *current; + /** back ptr */ + private_eap_sim_file_triplets_t *this; +} triplet_enumerator_t; + +/** + * destroy a triplet enumerator + */ +static void enumerator_destroy(triplet_enumerator_t *e) +{ + if (e->current) + { + /* We assume that the current element is used on invocation if destroy. + * We move that triplet to the end to avoid handout of the same triplet + * next time. */ + e->this->triplets->remove_at(e->this->triplets, e->inner); + e->this->triplets->insert_last(e->this->triplets, e->current); + } + e->inner->destroy(e->inner); + e->this->mutex->unlock(e->this->mutex); + free(e); +} + +/** + * enumerate through triplets + */ +static bool enumerator_enumerate(triplet_enumerator_t *e, identification_t **imsi, + char **rand, char **sres, char **kc) +{ + triplet_t *triplet; + + if (e->inner->enumerate(e->inner, &triplet)) + { + e->current = triplet; + *imsi = triplet->imsi; + *rand = triplet->rand; + *sres = triplet->sres; + *kc = triplet->kc; + return TRUE; + } + e->current = NULL; + return FALSE; +} + +/** + * Implementation of eap_sim_file_triplets_t.create_enumerator + */ +static enumerator_t* create_enumerator(private_eap_sim_file_triplets_t *this) +{ + triplet_enumerator_t *enumerator = malloc_thing(triplet_enumerator_t); + + this->mutex->lock(this->mutex); + enumerator->public.enumerate = (void*)enumerator_enumerate; + enumerator->public.destroy = (void*)enumerator_destroy; + enumerator->inner = this->triplets->create_enumerator(this->triplets); + enumerator->current = NULL; + enumerator->this = this; + + return &enumerator->public; +} + +/** + * convert to token into the array + */ +static void parse_token(char *to, char *from, size_t len) +{ + chunk_t chunk; + + chunk = chunk_create(from, min(strlen(from), len * 2)); + chunk = chunk_from_hex(chunk, NULL); + memset(to, 0, len); + memcpy(to + len - chunk.len, chunk.ptr, chunk.len); + free(chunk.ptr); +} + +/** + * Read the triplets from the file + */ +static void read_triplets(private_eap_sim_file_triplets_t *this, char *path) +{ + char line[512]; + FILE *file; + int i, nr = 0; + + file = fopen(path, "r"); + if (file == NULL) + { + DBG1(DBG_CFG, "opening triplet file %s failed: %s", + path, strerror(errno)); + return; + } + + /* read line by line */ + while (fgets(line, sizeof(line), file)) + { + triplet_t *triplet; + enumerator_t *enumerator; + char *token; + + nr++; + /* skip comments, empty lines */ + switch (line[0]) + { + case '\n': + case '\r': + case '#': + case '\0': + continue; + default: + break; + } + triplet = malloc_thing(triplet_t); + memset(triplet, 0, sizeof(triplet_t)); + + i = 0; + enumerator = enumerator_create_token(line, ",", " \n\r#"); + while (enumerator->enumerate(enumerator, &token)) + { + switch (i++) + { + case 0: /* IMSI */ + triplet->imsi = identification_create_from_encoding(ID_EAP, + chunk_create(token, strlen(token))); + continue; + case 1: /* rand */ + parse_token(triplet->rand, token, RAND_LEN); + continue; + case 2: /* sres */ + parse_token(triplet->sres, token, SRES_LEN); + continue; + case 3: /* kc */ + parse_token(triplet->kc, token, KC_LEN); + continue; + default: + break;; + } + break; + } + enumerator->destroy(enumerator); + if (i < 4) + { + DBG1(DBG_CFG, "error in triplet file, line %d", nr); + triplet_destroy(triplet); + continue; + } + + DBG1(DBG_CFG, "triplet: imsi %D\nrand %b\nsres %b\nkc %b", + triplet->imsi, triplet->rand, RAND_LEN, + triplet->sres, SRES_LEN, triplet->kc, KC_LEN); + + this->triplets->insert_last(this->triplets, triplet); + } + fclose(file); + + DBG1(DBG_CFG, "read %d triplets from %s", + this->triplets->get_count(this->triplets), path); +} + +/** + * Implementation of eap_sim_file_triplets_t.destroy. + */ +static void destroy(private_eap_sim_file_triplets_t *this) +{ + this->triplets->destroy_function(this->triplets, (void*)triplet_destroy); + this->mutex->destroy(this->mutex); + free(this); +} + +/** + * See header + */ +eap_sim_file_triplets_t *eap_sim_file_triplets_create(char *file) +{ + private_eap_sim_file_triplets_t *this = malloc_thing(private_eap_sim_file_triplets_t); + + this->public.create_enumerator = (enumerator_t*(*)(eap_sim_file_triplets_t*))create_enumerator; + this->public.destroy = (void(*)(eap_sim_file_triplets_t*))destroy; + + this->triplets = linked_list_create(); + this->mutex = mutex_create(MUTEX_DEFAULT); + + read_triplets(this, file); + + return &this->public; +} + diff --git a/src/charon/plugins/eap_sim_file/eap_sim_file_triplets.h b/src/charon/plugins/eap_sim_file/eap_sim_file_triplets.h new file mode 100644 index 000000000..5f3adfe62 --- /dev/null +++ b/src/charon/plugins/eap_sim_file/eap_sim_file_triplets.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2008 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * 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 . + * + * 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. + * + * $Id$ + */ + +/** + * @defgroup eap_sim_file_triplets eap_sim_file_triplets + * @{ @ingroup eap_sim_file + */ + +#ifndef EAP_SIM_FILE_TRIPLETS_H_ +#define EAP_SIM_FILE_TRIPLETS_H_ + +#include +#include + +/** + * size of RAND value + */ +#define RAND_LEN 16 + +/** + * size of SRES value + */ +#define SRES_LEN 4 + +/** + * size of KC value + */ +#define KC_LEN 8 + +typedef struct eap_sim_file_triplets_t eap_sim_file_triplets_t; + +/** + * Reads triplets from a triplets.dat file. + * + * The file is in freeradius triplet file syntax: + * http://www.freeradius.org/radiusd/doc/rlm_sim_triplets + */ +struct eap_sim_file_triplets_t { + + /** + * Create an enumerator over the file's triplets. + * + * @return enumerator over (identity, rand, sres, kc) + */ + enumerator_t* (*create_enumerator)(eap_sim_file_triplets_t *this); + + /** + * Destroy a eap_sim_file_triplets_t. + */ + void (*destroy)(eap_sim_file_triplets_t *this); +}; + +/** + * Create a eap_sim_file_triplets instance. + * + * @param file triplet file to read from + */ +eap_sim_file_triplets_t *eap_sim_file_triplets_create(char *file); + +#endif /* EAP_SIM_FILE_TRIPLETS_ @}*/ diff --git a/src/charon/sa/authenticators/eap/sim_manager.c b/src/charon/sa/authenticators/eap/sim_manager.c new file mode 100644 index 000000000..e6817ca20 --- /dev/null +++ b/src/charon/sa/authenticators/eap/sim_manager.c @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2008 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * 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 . + * + * 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. + * + * $Id$ + */ + +#include "sim_manager.h" + +#include + +typedef struct private_sim_manager_t private_sim_manager_t; + +/** + * Private data of an sim_manager_t object. + */ +struct private_sim_manager_t { + + /** + * Public sim_manager_t interface. + */ + sim_manager_t public; + + /** + * list of added cards + */ + linked_list_t *cards; + + /** + * list of added provider + */ + linked_list_t *provider; +}; + +/** + * Implementation of sim_manager_t.add_card + */ +static void add_card(private_sim_manager_t *this, sim_card_t *card) +{ + this->cards->insert_last(this->cards, card); +} + +/** + * Implementation of sim_manager_t.remove_card + */ +static void remove_card(private_sim_manager_t *this, sim_card_t *card) +{ + this->cards->remove(this->cards, card, NULL); +} + +/** + * Implementation of sim_manager_t.create_card_enumerator + */ +static enumerator_t* create_card_enumerator(private_sim_manager_t *this) +{ + return this->cards->create_enumerator(this->cards); +} + +/** + * Implementation of sim_manager_t.add_provider + */ +static void add_provider(private_sim_manager_t *this, + sim_provider_t *provider) +{ + this->provider->insert_last(this->provider, provider); +} + +/** + * Implementation of sim_manager_t.remove_provider + */ +static void remove_provider(private_sim_manager_t *this, + sim_provider_t *provider) +{ + this->provider->remove(this->provider, provider, NULL); +} + +/** + * Implementation of sim_manager_t.create_provider_enumerator + */ +static enumerator_t* create_provider_enumerator(private_sim_manager_t *this) +{ + return this->provider->create_enumerator(this->provider); +} + +/** + * Implementation of sim_manager_t.destroy. + */ +static void destroy(private_sim_manager_t *this) +{ + this->cards->destroy(this->cards); + this->provider->destroy(this->provider); + free(this); +} + +/** + * See header + */ +sim_manager_t *sim_manager_create() +{ + private_sim_manager_t *this = malloc_thing(private_sim_manager_t); + + this->public.add_card = (void(*)(sim_manager_t*, sim_card_t *card))add_card; + this->public.remove_card = (void(*)(sim_manager_t*, sim_card_t *card))remove_card; + this->public.create_card_enumerator = (enumerator_t*(*)(sim_manager_t*))create_card_enumerator; + this->public.add_provider = (void(*)(sim_manager_t*, sim_provider_t *provider))add_provider; + this->public.remove_provider = (void(*)(sim_manager_t*, sim_provider_t *provider))remove_provider; + this->public.create_provider_enumerator = (enumerator_t*(*)(sim_manager_t*))create_provider_enumerator; + this->public.destroy = (void(*)(sim_manager_t*))destroy; + + this->cards = linked_list_create(); + this->provider = linked_list_create(); + + return &this->public; +} + diff --git a/src/charon/sa/authenticators/eap/sim_manager.h b/src/charon/sa/authenticators/eap/sim_manager.h new file mode 100644 index 000000000..7fb1f2858 --- /dev/null +++ b/src/charon/sa/authenticators/eap/sim_manager.h @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2008 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * 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 . + * + * 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 sim_manager sim_manager + * @{ @ingroup eap + */ + +#ifndef SIM_MANAGER_H_ +#define SIM_MANAGER_H_ + +#include +#include + +typedef struct sim_manager_t sim_manager_t; +typedef struct sim_card_t sim_card_t; +typedef struct sim_provider_t sim_provider_t; + +/** + * Interface for a SIM card (used as EAP client). + */ +struct sim_card_t { + + /** + * Get the identity of a SIM card. + * + * The returned identity owned by the sim_card and not destroyed outside. + * The SIM card may return ID_ANY if it does not support/use an IMSI. + * + * @return identity of type ID_EAP/ID_ANY + */ + identification_t* (*get_imsi)(sim_card_t *this); + + /** + * Calculate SRES/KC from a RAND. + * + * @param rand RAND input buffer, fixed size 16 bytes + * @param sres SRES output buffer, fixed size 4 byte + * @param kc KC output buffer, fixed size 8 bytes + * @return TRUE if SRES/KC calculated, FALSE on error + */ + bool (*get_triplet)(sim_card_t *this, + char rand[16], char sres[4], char kc[8]); +}; + +/** + * Interface for a triplet provider (used as EAP server). + */ +struct sim_provider_t { + + /** + * Get a single triplet to authenticate a EAP client. + * + * @param imsi client identity of type ID_EAP + * @param rand RAND output buffer, fixed size 16 bytes + * @param sres SRES output buffer, fixed size 4 byte + * @param kc KC output buffer, fixed size 8 bytes + * @return TRUE if triplet received, FALSE otherwise + */ + bool (*get_triplet)(sim_provider_t *this, identification_t *imsi, + char rand[16], char sres[4], char kc[8]); +}; + +/** + * The EAP-SIM manager handles multiple SIM cards and providers. + */ +struct sim_manager_t { + + /** + * Register a SIM card (client) at the manager. + * + * @param card sim card to register + */ + void (*add_card)(sim_manager_t *this, sim_card_t *card); + + /** + * Unregister a previously registered card from the manager. + * + * @param card sim card to unregister + */ + void (*remove_card)(sim_manager_t *this, sim_card_t *card); + + /** + * Create an enumerator over all registered cards. + * + * @return enumerator over sim_card_t's + */ + enumerator_t* (*create_card_enumerator)(sim_manager_t *this); + + /** + * Register a triplet provider (server) at the manager. + * + * @param card sim card to register + */ + void (*add_provider)(sim_manager_t *this, sim_provider_t *provider); + + /** + * Unregister a previously registered provider from the manager. + * + * @param card sim card to unregister + */ + void (*remove_provider)(sim_manager_t *this, sim_provider_t *provider); + + /** + * Create an enumerator over all registered provider. + * + * @return enumerator over sim_provider_t's + */ + enumerator_t* (*create_provider_enumerator)(sim_manager_t *this); + + /** + * Destroy a manager instance. + */ + void (*destroy)(sim_manager_t *this); +}; + +/** + * Create an SIM manager to handle multiple SIM cards/providers. + * + * @return sim_t object + */ +sim_manager_t *sim_manager_create(); + +#endif /* SIM_MANAGER_H_ @}*/