reintegrated two-sim branch providing SIM card plugin API
authorMartin Willi <martin@strongswan.org>
Fri, 10 Oct 2008 08:36:01 +0000 (08:36 -0000)
committerMartin Willi <martin@strongswan.org>
Fri, 10 Oct 2008 08:36:01 +0000 (08:36 -0000)
20 files changed:
configure.in
src/charon/Makefile.am
src/charon/daemon.c
src/charon/daemon.h
src/charon/plugins/eap_sim/Makefile.am
src/charon/plugins/eap_sim/eap_sim.c
src/charon/plugins/eap_sim/eap_sim.h
src/charon/plugins/eap_sim/eap_sim_file.c [deleted file]
src/charon/plugins/eap_sim/eap_sim_plugin.h
src/charon/plugins/eap_sim_file/Makefile.am [new file with mode: 0644]
src/charon/plugins/eap_sim_file/eap_sim_file_card.c [new file with mode: 0644]
src/charon/plugins/eap_sim_file/eap_sim_file_card.h [new file with mode: 0644]
src/charon/plugins/eap_sim_file/eap_sim_file_plugin.c [new file with mode: 0644]
src/charon/plugins/eap_sim_file/eap_sim_file_plugin.h [new file with mode: 0644]
src/charon/plugins/eap_sim_file/eap_sim_file_provider.c [new file with mode: 0644]
src/charon/plugins/eap_sim_file/eap_sim_file_provider.h [new file with mode: 0644]
src/charon/plugins/eap_sim_file/eap_sim_file_triplets.c [new file with mode: 0644]
src/charon/plugins/eap_sim_file/eap_sim_file_triplets.h [new file with mode: 0644]
src/charon/sa/authenticators/eap/sim_manager.c [new file with mode: 0644]
src/charon/sa/authenticators/eap/sim_manager.h [new file with mode: 0644]

index 5c0cf3a..6c8c1ac 100644 (file)
@@ -394,6 +394,14 @@ AC_ARG_ENABLE(
 )
 
 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).]),
        [if test x$enableval = xyes; then
@@ -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
index 464d82f..c9f63ac 100644 (file)
@@ -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
index 05da3c6..065f7d7 100644 (file)
@@ -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;
index 3bde9a2..da7d4e6 100644 (file)
@@ -163,6 +163,7 @@ typedef struct daemon_t daemon_t;
 #include <config/attributes/attribute_manager.h>
 #include <credentials/credential_manager.h>
 #include <sa/authenticators/eap/eap_manager.h>
+#include <sa/authenticators/eap/sim_manager.h>
 
 #ifdef ME
 #include <sa/connect_manager.h>
@@ -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
index 63267b9..6cb53eb 100644 (file)
@@ -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
-
index 11d2e74..11e4adb 100644 (file)
@@ -150,21 +150,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
         */
        int tries;
@@ -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;
 };
@@ -557,6 +542,41 @@ static void derive_keys(private_eap_sim_t *this, chunk_t kcs)
 }
 
 /**
+ * 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, &current))
+       {
+               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
  */
 static status_t peer_process_challenge(private_eap_sim_t *this,
@@ -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);
        }
        
@@ -737,6 +755,32 @@ static status_t server_process_challenge(private_eap_sim_t *this,
 }
 
 /**
+ * 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
  */
 static status_t server_process_start(private_eap_sim_t *this,
@@ -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)
index 65020aa..ec061b6 100644 (file)
@@ -25,62 +25,12 @@ typedef struct eap_sim_t eap_sim_t;
 
 #include <sa/authenticators/eap/eap_method.h>
 
-/** 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 (file)
index 7040a5a..0000000
+++ /dev/null
@@ -1,283 +0,0 @@
-/*\r
- * Copyright (C) 2007 Martin Willi\r
- * Hochschule fuer Technik Rapperswil\r
- *\r
- * This program is free software; you can redistribute it and/or modify it\r
- * under the terms of the GNU General Public License as published by the\r
- * Free Software Foundation; either version 2 of the License, or (at your\r
- * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.\r
- *\r
- * This program is distributed in the hope that it will be useful, but\r
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\r
- * for more details.
- *
- * $Id$
- */\r
-\r
-#include <string.h>\r
-#include <stdio.h>\r
-#include <errno.h>\r
-\r
-#include <daemon.h>\r
-\r
-#define IMSI_LEN 64\r
-#define RAND_LEN 16\r
-#define SRES_LEN 4\r
-#define KC_LEN 8\r
-\r
-typedef struct triplet_t triplet_t;\r
-\r
-struct triplet_t {\r
-       unsigned char imsi[IMSI_LEN];\r
-       unsigned char rand[RAND_LEN];\r
-       unsigned char sres[SRES_LEN];\r
-       unsigned char kc[KC_LEN];\r
-};\r
-\r
-static triplet_t *triplets = NULL;\r
-static int triplet_count = 0;\r
-\r
-#define TRIPLET_FILE IPSEC_CONFDIR "/ipsec.d/triplets.dat"\r
-\r
-/**\r
- * convert a single HEX char to its integer value\r
- */\r
-static int hexchr(char chr)\r
-{\r
-       switch (chr)\r
-       {\r
-               case '0'...'9':\r
-                       return chr - '0';\r
-               case 'A'...'F':\r
-                       return 10 + chr - 'A';\r
-               case 'a'...'f':\r
-                       return 10 + chr - 'a';\r
-       }\r
-       return 0;\r
-}\r
-\r
-/**\r
- * convert a HEX string into a char array bin, limited by array length len\r
- */\r
-static void hex2bin(char *hex, unsigned char *bin, size_t len)\r
-{\r
-       char *pos;\r
-       int i, even = 1;\r
-       \r
-       pos = hex - 1;\r
-       /* find the end, as we convert bottom up */\r
-       while (TRUE)\r
-       {\r
-               switch (*(pos+1))\r
-               {\r
-                       case '0'...'9':\r
-                       case 'A'...'F':\r
-                       case 'a'...'f':\r
-                               pos++;\r
-                               continue;\r
-               }\r
-               break;\r
-       }\r
-       /* convert two hex chars into a single bin byte */\r
-       for (i = 0; pos >= hex && i < len; pos--)\r
-       {\r
-               if (even)\r
-               {\r
-                       bin[len - 1 - i] = hexchr(*pos);\r
-               }\r
-               else\r
-               {\r
-                       bin[len - 1 - i] |= 16 * hexchr(*pos);\r
-                       i++;\r
-               }\r
-               even = !even;\r
-       }\r
-}\r
-\r
-/**\r
- * free up allocated triplets\r
- */\r
-static void __attribute__ ((destructor)) free_triplets()\r
-{\r
-       free(triplets);\r
-}\r
-\r
-/**\r
- * read the triplets from the file, using freeradius triplet file syntax:\r
- * http://www.freeradius.org/radiusd/doc/rlm_sim_triplets\r
- */\r
-static void __attribute__ ((constructor)) read_triplets()\r
-{\r
-       char line[512], *data[4], *pos;\r
-       FILE *file;\r
-       int i, nr = 0;\r
-       triplet_t *triplet;\r
-       \r
-       file = fopen(TRIPLET_FILE, "r");\r
-       if (file == NULL)\r
-       {\r
-               DBG1(DBG_CFG, "opening triplet file %s failed: %s",\r
-                        TRIPLET_FILE, strerror(errno));\r
-               return;\r
-       }\r
-       \r
-       if (triplets)\r
-       {\r
-               free(triplets);\r
-               triplets = NULL;\r
-               triplet_count = 0;\r
-       }\r
-       \r
-       /* read line by line */\r
-       while (fgets(line, sizeof(line), file))\r
-       {\r
-               nr++;\r
-               /* skip comments, empty lines */\r
-               switch (line[0])\r
-               {\r
-                       case '\n':\r
-                       case '\r':\r
-                       case '#':\r
-                       case '\0':\r
-                               continue;\r
-                       default:\r
-                               break;\r
-               }\r
-               /* read comma separated values */\r
-               pos = line;\r
-               for (i = 0; i < 4; i++)\r
-               {\r
-                       data[i] = pos;\r
-                       pos = strchr(pos, ',');\r
-                       if (pos)\r
-                       {\r
-                               *pos = '\0';\r
-                               pos++;\r
-                       }\r
-                       else if (i != 3)\r
-                       {\r
-                               DBG1(DBG_CFG, "error in triplet file, line %d", nr);\r
-                               fclose(file);\r
-                               return;\r
-                       }\r
-               }\r
-               /* allocate new triplet */\r
-               triplet_count++;\r
-               triplets = realloc(triplets, triplet_count * sizeof(triplet_t));\r
-               triplet = &triplets[triplet_count - 1];\r
-               memset(triplet, 0, sizeof(triplet_t));\r
-               \r
-               /* convert/copy triplet data */\r
-               for (i = 0; i < IMSI_LEN - 1; i++)\r
-               {\r
-                       switch (data[0][i])\r
-                       {\r
-                               case '\n':\r
-                               case '\r':\r
-                               case '\0':\r
-                                       break;\r
-                               default:\r
-                                       triplet->imsi[i] = data[0][i];\r
-                                       continue;\r
-                       }\r
-                       break;\r
-               }\r
-               hex2bin(data[1], triplet->rand, RAND_LEN);\r
-               hex2bin(data[2], triplet->sres, SRES_LEN);\r
-               hex2bin(data[3], triplet->kc, KC_LEN);\r
-               \r
-               DBG4(DBG_CFG, "triplet: imsi %b\nrand %b\nsres %b\nkc %b",\r
-                        triplet->imsi, IMSI_LEN, triplet->rand, RAND_LEN,\r
-                        triplet->sres, SRES_LEN, triplet->kc, KC_LEN);\r
-       }\r
-       fclose(file);\r
-       DBG2(DBG_CFG, "read %d triplets from %s", triplet_count, TRIPLET_FILE);\r
-}\r
-\r
-/**\r
- * Run the sim algorithm, see eap_sim.h\r
- */\r
-int sim_run_alg(const unsigned char *rand, int rand_length,\r
-                               unsigned char *sres, int *sres_length, \r
-                               unsigned char *kc, int *kc_length)\r
-{\r
-       int current;\r
-       \r
-       if (rand_length != RAND_LEN ||\r
-               *sres_length < SRES_LEN ||\r
-               *kc_length < KC_LEN)\r
-       {\r
-               return 1;\r
-       }\r
-       \r
-       for (current = 0; current < triplet_count; current++)\r
-       {\r
-               if (memcmp(triplets[current].rand, rand, RAND_LEN) == 0)\r
-               {\r
-                       memcpy(sres, triplets[current].sres, SRES_LEN);\r
-                       memcpy(kc, triplets[current].kc, KC_LEN);\r
-                       *sres_length = SRES_LEN;\r
-                       *kc_length = KC_LEN;\r
-                       return 0;\r
-               }\r
-       }\r
-       return 2;\r
-}\r
-\r
-/**\r
- * Get a single triplet, see_eap_sim.h\r
- */\r
-int sim_get_triplet(char *imsi,\r
-                                       unsigned char *rand, int *rand_length,\r
-                                       unsigned char *sres, int *sres_length, \r
-                                       unsigned char *kc, int *kc_length)\r
-{\r
-       int current;\r
-       triplet_t *triplet;\r
-       static int skip = -1;\r
-       \r
-       DBG2(DBG_CFG, "getting triplet for %s", imsi);\r
-       \r
-       if (*rand_length < RAND_LEN ||\r
-               *sres_length < SRES_LEN ||\r
-               *kc_length < KC_LEN)\r
-       {\r
-               return 1;\r
-       }\r
-       if (triplet_count == 0)\r
-       {\r
-               return 2;\r
-       }\r
-       for (current = 0; current < triplet_count; current++)\r
-       {\r
-               triplet = &triplets[current];\r
-       \r
-               if (streq(imsi, triplet->imsi))\r
-               {\r
-                       /* skip triplet if already used */\r
-                       if (skip >= current)\r
-                       {\r
-                               continue;\r
-                       }\r
-                       *rand_length = RAND_LEN;\r
-                       *sres_length = SRES_LEN;\r
-                       *kc_length = KC_LEN;\r
-                       memcpy(rand, triplet->rand, RAND_LEN);\r
-                       memcpy(sres, triplet->sres, SRES_LEN);\r
-                       memcpy(kc, triplet->kc, KC_LEN);\r
-                       /* remember used triplet */\r
-                       skip = current;\r
-                       return 0;\r
-               }\r
-       }\r
-       if (skip > -1)\r
-       {\r
-               /* no triplet left, reuse triplets */\r
-               skip = -1;\r
-               return sim_get_triplet(imsi, rand, rand_length,\r
-                                                          sres, sres_length, kc, kc_length);\r
-       }\r
-       return 2;\r
-}\r
-\r
index e142b89..a122341 100644 (file)
@@ -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 (file)
index 0000000..fc3a0fa
--- /dev/null
@@ -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 (file)
index 0000000..7969007
--- /dev/null
@@ -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 <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.
+ *
+ * $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 <daemon.h>
+
+/**
+ * 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 (file)
index 0000000..953a3e9
--- /dev/null
@@ -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 <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.
+ *
+ * $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 <sa/authenticators/eap/sim_manager.h>
+
+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 (file)
index 0000000..6129ebb
--- /dev/null
@@ -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 <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.
+ *
+ * $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 <daemon.h>
+\r
+#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 (file)
index 0000000..c182852
--- /dev/null
@@ -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 <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.
+ *
+ * $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 <plugins/plugin.h>
+
+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 (file)
index 0000000..ffb4b29
--- /dev/null
@@ -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 <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.
+ *
+ * $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 (file)
index 0000000..bc8f6cc
--- /dev/null
@@ -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 <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.
+ *
+ * $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 <sa/authenticators/eap/sim_manager.h>
+
+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 (file)
index 0000000..409e9cb
--- /dev/null
@@ -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 <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.
+ *
+ * $Id$
+ */
+
+#include "eap_sim_file_triplets.h"
+
+#include <stdio.h>
+#include <errno.h>
+
+#include <daemon.h>
+#include <utils/linked_list.h>
+#include <utils/mutex.h>
+
+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;
+};\r
+
+/**
+ * A single triplet
+ */\r
+typedef struct  {\r
+       identification_t *imsi;\r
+       char rand[RAND_LEN];\r
+       char sres[SRES_LEN];\r
+       char kc[KC_LEN];\r
+} 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);
+}\r
+\r
+/**\r
+ * Read the triplets from the file\r
+ */\r
+static void read_triplets(private_eap_sim_file_triplets_t *this, char *path)\r
+{\r
+       char line[512];\r
+       FILE *file;\r
+       int i, nr = 0;\r
+       \r
+       file = fopen(path, "r");\r
+       if (file == NULL)\r
+       {\r
+               DBG1(DBG_CFG, "opening triplet file %s failed: %s", 
+                        path, strerror(errno));\r
+               return;\r
+       }\r
+       \r
+       /* read line by line */\r
+       while (fgets(line, sizeof(line), file))\r
+       {\r
+               triplet_t *triplet;
+               enumerator_t *enumerator;
+               char *token;
+               \r
+               nr++;\r
+               /* skip comments, empty lines */\r
+               switch (line[0])\r
+               {\r
+                       case '\n':\r
+                       case '\r':\r
+                       case '#':\r
+                       case '\0':\r
+                               continue;\r
+                       default:\r
+                               break;\r
+               }
+               triplet = malloc_thing(triplet_t);\r
+               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)
+               {\r
+                       DBG1(DBG_CFG, "error in triplet file, line %d", nr);
+                       triplet_destroy(triplet);
+                       continue;
+               }\r
+               \r
+               DBG1(DBG_CFG, "triplet: imsi %D\nrand %b\nsres %b\nkc %b",\r
+                        triplet->imsi, triplet->rand, RAND_LEN,\r
+                        triplet->sres, SRES_LEN, triplet->kc, KC_LEN);
+                        
+               this->triplets->insert_last(this->triplets, triplet);\r
+       }\r
+       fclose(file);
+       \r
+       DBG1(DBG_CFG, "read %d triplets from %s",
+                this->triplets->get_count(this->triplets), path);\r
+}
+
+/**
+ * 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 (file)
index 0000000..5f3adfe
--- /dev/null
@@ -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 <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.
+ *
+ * $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 <utils/enumerator.h>
+#include <utils/identification.h>
+
+/**
+ * size of RAND value
+ */\r
+#define RAND_LEN 16
+
+/**
+ * size of SRES value
+ */\r
+#define SRES_LEN 4
+
+/**
+ * size of KC value
+ */\r
+#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:\r
+ * 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 (file)
index 0000000..e6817ca
--- /dev/null
@@ -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 <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.
+ *
+ * $Id$
+ */
+
+#include "sim_manager.h"
+
+#include <utils/linked_list.h>
+
+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 (file)
index 0000000..7fb1f28
--- /dev/null
@@ -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 <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 sim_manager sim_manager
+ * @{ @ingroup eap
+ */
+
+#ifndef SIM_MANAGER_H_
+#define SIM_MANAGER_H_
+
+#include <utils/identification.h>
+#include <utils/enumerator.h>
+
+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_ @}*/