Added a EAP-SIM/AKA backend reading triplets/quintuplets from a SQL database
authorMartin Willi <martin@revosec.ch>
Wed, 2 Jun 2010 13:55:58 +0000 (15:55 +0200)
committerMartin Willi <martin@revosec.ch>
Wed, 2 Jun 2010 13:59:44 +0000 (15:59 +0200)
12 files changed:
configure.in
src/libcharon/Android.mk
src/libcharon/Makefile.am
src/libcharon/plugins/eap_simaka_sql/Makefile.am [new file with mode: 0644]
src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_card.c [new file with mode: 0644]
src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_card.h [new file with mode: 0644]
src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_plugin.c [new file with mode: 0644]
src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_plugin.h [new file with mode: 0644]
src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_provider.c [new file with mode: 0644]
src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_provider.h [new file with mode: 0644]
src/libcharon/plugins/eap_simaka_sql/sqlite.sql [new file with mode: 0644]
src/libcharon/plugins/eap_simaka_sql/test.sql [new file with mode: 0644]

index b1a4e74..b164b06 100644 (file)
@@ -101,6 +101,7 @@ ARG_ENABL_SET([unit-tests],     [enable unit tests on IKEv2 daemon startup.])
 ARG_ENABL_SET([load-tester],    [enable load testing plugin for IKEv2 daemon.])
 ARG_ENABL_SET([eap-sim],        [enable SIM authenication module for EAP.])
 ARG_ENABL_SET([eap-sim-file],   [enable EAP-SIM backend based on a triplet file.])
+ARG_ENABL_SET([eap-simaka-sql], [enable EAP-SIM/AKA backend based on a triplet/quintuplet SQL database.])
 ARG_ENABL_SET([eap-simaka-pseudonym], [enable EAP-SIM/AKA pseudonym storage plugin.])
 ARG_ENABL_SET([eap-simaka-reauth],    [enable EAP-SIM/AKA reauthentication data storage plugin.])
 ARG_ENABL_SET([eap-identity],   [enable EAP module providing EAP-Identity helper.])
@@ -815,6 +816,7 @@ AM_CONDITIONAL(USE_LOAD_TESTER, test x$load_tester = xtrue)
 AM_CONDITIONAL(USE_HA, test x$ha = 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_SIMAKA_SQL, test x$eap_simaka_sql = xtrue)
 AM_CONDITIONAL(USE_EAP_SIMAKA_PSEUDONYM, test x$eap_simaka_pseudonym = xtrue)
 AM_CONDITIONAL(USE_EAP_SIMAKA_REAUTH, test x$eap_simaka_reauth = xtrue)
 AM_CONDITIONAL(USE_EAP_IDENTITY, test x$eap_identity = xtrue)
@@ -939,6 +941,7 @@ AC_OUTPUT(
        src/libcharon/plugins/eap_gtc/Makefile
        src/libcharon/plugins/eap_sim/Makefile
        src/libcharon/plugins/eap_sim_file/Makefile
+       src/libcharon/plugins/eap_simaka_sql/Makefile
        src/libcharon/plugins/eap_simaka_pseudonym/Makefile
        src/libcharon/plugins/eap_simaka_reauth/Makefile
        src/libcharon/plugins/eap_mschapv2/Makefile
index d473b45..99fe31f 100644 (file)
@@ -129,6 +129,8 @@ LOCAL_SRC_FILES += $(call add_plugin, eap-mschapv2)
 
 LOCAL_SRC_FILES += $(call add_plugin, eap-sim)
 
+LOCAL_SRC_FILES += $(call add_plugin, eap-simaka-sql)
+
 LOCAL_SRC_FILES += $(call add_plugin, eap-simaka-pseudonym)
 
 LOCAL_SRC_FILES += $(call add_plugin, eap-simaka-reauth)
index baf568c..2616b8b 100644 (file)
@@ -271,6 +271,14 @@ if MONOLITHIC
 endif
 endif
 
+if USE_EAP_SIMAKA_SQL
+  SUBDIRS += plugins/eap_simaka_sql
+  PLUGINS += eap-simaka-sql
+if MONOLITHIC
+  libcharon_la_LIBADD += plugins/eap_simaka_sql/libstrongswan-eap-simaka-sql.la
+endif
+endif
+
 if USE_EAP_SIMAKA_PSEUDONYM
   SUBDIRS += plugins/eap_simaka_pseudonym
   PLUGINS += eap-simaka-pseudonym
diff --git a/src/libcharon/plugins/eap_simaka_sql/Makefile.am b/src/libcharon/plugins/eap_simaka_sql/Makefile.am
new file mode 100644 (file)
index 0000000..73768be
--- /dev/null
@@ -0,0 +1,18 @@
+
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \
+       -I$(top_srcdir)/src/libcharon
+
+AM_CFLAGS = -rdynamic -DIPSEC_CONFDIR=\"${sysconfdir}\"
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-eap-simaka-sql.la
+else
+plugin_LTLIBRARIES = libstrongswan-eap-simaka-sql.la
+endif
+
+libstrongswan_eap_simaka_sql_la_SOURCES = \
+       eap_simaka_sql_plugin.h eap_simaka_sql_plugin.c \
+       eap_simaka_sql_card.h eap_simaka_sql_card.c \
+       eap_simaka_sql_provider.h eap_simaka_sql_provider.c
+
+libstrongswan_eap_simaka_sql_la_LDFLAGS = -module -avoid-version
diff --git a/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_card.c b/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_card.c
new file mode 100644 (file)
index 0000000..b759040
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include "eap_simaka_sql_card.h"
+
+#include <time.h>
+
+#include <daemon.h>
+
+typedef struct private_eap_simaka_sql_card_t private_eap_simaka_sql_card_t;
+
+/**
+ * Private data of an eap_simaka_sql_card_t object.
+ */
+struct private_eap_simaka_sql_card_t {
+
+       /**
+        * Public eap_simaka_sql_card_t interface.
+        */
+       eap_simaka_sql_card_t public;
+
+       /**
+        * Triplet/quintuplet database
+        */
+       database_t *db;
+
+       /**
+        * Remove used triplets/quintuplets from database
+        */
+       bool remove_used;
+};
+
+METHOD(sim_card_t, get_triplet, bool,
+       private_eap_simaka_sql_card_t *this, identification_t *id,
+       char rand[SIM_RAND_LEN], char sres[SIM_SRES_LEN], char kc[SIM_KC_LEN])
+{
+       chunk_t sres_chunk, kc_chunk;
+       enumerator_t *query;
+       bool found = FALSE;
+       char buf[128];
+
+       snprintf(buf, sizeof(buf), "%Y", id);
+       query = this->db->query(this->db,
+                               "select sres, kc from triplets where rand = ? and id = ? "
+                               "order by use limit 1",
+                               DB_BLOB, chunk_create(rand, SIM_RAND_LEN), DB_TEXT, buf,
+                               DB_BLOB, DB_BLOB);
+       if (query)
+       {
+               if (query->enumerate(query, &sres_chunk, &kc_chunk))
+               {
+                       if (sres_chunk.len == SIM_SRES_LEN &&
+                               kc_chunk.len == SIM_KC_LEN)
+                       {
+                               memcpy(sres, sres_chunk.ptr, SIM_SRES_LEN);
+                               memcpy(kc, kc_chunk.ptr, SIM_KC_LEN);
+                               found = TRUE;
+                       }
+               }
+               query->destroy(query);
+       }
+       if (found)
+       {
+               if (this->remove_used)
+               {
+                       this->db->execute(this->db, NULL,
+                                       "delete from triplets where id = ? and rand = ?",
+                                       DB_TEXT, buf, DB_BLOB, chunk_create(rand, SIM_RAND_LEN));
+               }
+               else
+               {
+                       this->db->execute(this->db, NULL,
+                                       "update triplets set use = ? where id = ? and rand = ?",
+                                       DB_UINT, time(NULL), DB_TEXT, buf,
+                                       DB_BLOB, chunk_create(rand, SIM_RAND_LEN));
+               }
+       }
+       return found;
+}
+
+METHOD(sim_card_t, get_quintuplet, status_t,
+       private_eap_simaka_sql_card_t *this, identification_t *id,
+       char rand[AKA_RAND_LEN], char autn[AKA_AUTN_LEN], char ck[AKA_CK_LEN],
+       char ik[AKA_IK_LEN], char res[AKA_RES_MAX], int *res_len)
+{
+       chunk_t ck_chunk, ik_chunk, res_chunk;
+       enumerator_t *query;
+       status_t found = FAILED;
+       char buf[128];
+
+       snprintf(buf, sizeof(buf), "%Y", id);
+       query = this->db->query(this->db, "select ck, ik, res from quintuplets "
+                               "where rand = ? and autn = ? and id = ? order by use limit 1",
+                               DB_BLOB, chunk_create(rand, AKA_RAND_LEN),
+                               DB_BLOB, chunk_create(autn, AKA_AUTN_LEN), DB_TEXT, buf,
+                               DB_BLOB, DB_BLOB, DB_BLOB);
+       if (query)
+       {
+               if (query->enumerate(query, &ck_chunk, &ik_chunk, &res_chunk))
+               {
+                       if (ck_chunk.len == AKA_CK_LEN &&
+                               ik_chunk.len == AKA_IK_LEN &&
+                               res_chunk.len <= AKA_RES_MAX)
+                       {
+                               memcpy(ck, ck_chunk.ptr, AKA_CK_LEN);
+                               memcpy(ik, ik_chunk.ptr, AKA_IK_LEN);
+                               memcpy(res, res_chunk.ptr, res_chunk.len);
+                               *res_len = res_chunk.len;
+                               found = SUCCESS;
+                       }
+               }
+               query->destroy(query);
+       }
+       if (found == SUCCESS)
+       {
+               if (this->remove_used)
+               {
+                       this->db->execute(this->db, NULL,
+                                       "delete from quintuplets where id = ? and rand = ?",
+                                       DB_TEXT, buf, DB_BLOB, chunk_create(rand, SIM_RAND_LEN));
+               }
+               else
+               {
+                       this->db->execute(this->db, NULL,
+                                       "update quintuplets set use = ? where id = ? and rand = ?",
+                                       DB_UINT, time(NULL), DB_TEXT, buf,
+                                       DB_BLOB, chunk_create(rand, AKA_RAND_LEN));
+               }
+       }
+       return found;
+}
+
+METHOD(eap_simaka_sql_card_t, destroy, void,
+       private_eap_simaka_sql_card_t *this)
+{
+       free(this);
+}
+
+/**
+ * See header
+ */
+eap_simaka_sql_card_t *eap_simaka_sql_card_create(database_t *db,
+                                                                                                 bool remove_used)
+{
+       private_eap_simaka_sql_card_t *this;
+
+       INIT(this,
+               .public = {
+                       .card = {
+                               .get_triplet = _get_triplet,
+                               .get_quintuplet = _get_quintuplet,
+                               .resync = (void*)return_false,
+                               .get_pseudonym = (void*)return_null,
+                               .set_pseudonym = (void*)nop,
+                               .get_reauth = (void*)return_null,
+                               .set_reauth = (void*)nop,
+                       },
+                       .destroy = _destroy,
+               },
+               .db = db,
+               .remove_used = remove_used,
+       );
+
+       return &this->public;
+}
diff --git a/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_card.h b/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_card.h
new file mode 100644 (file)
index 0000000..46b7de2
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup eap_simaka_sql_card eap_simaka_sql_card
+ * @{ @ingroup eap_simaka_sql
+ */
+
+#ifndef EAP_SIMAKA_SQL_CARD_H_
+#define EAP_SIMAKA_SQL_CARD_H_
+
+#include <database/database.h>
+#include <sa/authenticators/eap/sim_manager.h>
+
+typedef struct eap_simaka_sql_card_t eap_simaka_sql_card_t;
+
+/**
+ * SIM card implementation using a triplet/quintuplet database backend.
+ */
+struct eap_simaka_sql_card_t {
+
+       /**
+        * Implements sim_card_t interface
+        */
+       sim_card_t card;
+
+       /**
+        * Destroy a eap_simaka_sql_card_t.
+        */
+       void (*destroy)(eap_simaka_sql_card_t *this);
+};
+
+/**
+ * Create a eap_simaka_sql_card instance.
+ *
+ * @param db           triplet/quintuplet database
+ * @param remove_used  TRUE to remove used triplets/quintuplets from db
+ */
+eap_simaka_sql_card_t *eap_simaka_sql_card_create(database_t *db,
+                                                                                                 bool remove_used);
+
+#endif /** EAP_SIMAKA_SQL_CARD_H_ @}*/
diff --git a/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_plugin.c b/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_plugin.c
new file mode 100644 (file)
index 0000000..0f53197
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include "eap_simaka_sql_plugin.h"
+#include "eap_simaka_sql_card.h"
+#include "eap_simaka_sql_provider.h"
+
+#include <daemon.h>
+
+typedef struct private_eap_simaka_sql_t private_eap_simaka_sql_t;
+
+/**
+ * Private data of an eap_simaka_sql_t object.
+ */
+struct private_eap_simaka_sql_t {
+
+       /**
+        * Public eap_simaka_sql_plugin_t interface.
+        */
+       eap_simaka_sql_plugin_t public;
+
+       /**
+        * (U)SIM card
+        */
+       eap_simaka_sql_card_t *card;
+
+       /**
+        * (U)SIM provider
+        */
+       eap_simaka_sql_provider_t *provider;
+
+       /**
+        * Database with triplets/quintuplets
+        */
+       database_t *db;
+};
+
+METHOD(plugin_t, destroy, void,
+       private_eap_simaka_sql_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->db->destroy(this->db);
+       free(this);
+}
+
+/**
+ * See header
+ */
+plugin_t *eap_simaka_sql_plugin_create()
+{
+       private_eap_simaka_sql_t *this;
+       database_t *db;
+       bool remove_used;
+       char *uri;
+
+       uri = lib->settings->get_str(lib->settings,
+                                                       "charon.plugins.eap-simaka-sql.database", NULL);
+       if (!uri)
+       {
+               DBG1(DBG_CFG, "eap-simaka-sql database URI missing");
+               return NULL;
+       }
+       db = lib->db->create(lib->db, uri);
+       if (!db)
+       {
+               DBG1(DBG_CFG, "opening eap-simaka-sql database failed");
+               return NULL;
+       }
+       remove_used = lib->settings->get_bool(lib->settings,
+                                                       "charon.plugins.eap-simaka-sql.remove_used", FALSE);
+
+       INIT(this,
+               .public.plugin =  {
+                       .destroy = _destroy,
+               },
+               .db = db,
+               .provider = eap_simaka_sql_provider_create(db, remove_used),
+               .card = eap_simaka_sql_card_create(db, remove_used),
+       );
+
+       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/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_plugin.h b/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_plugin.h
new file mode 100644 (file)
index 0000000..3064580
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup eap_simaka_sql eap_simaka_sql
+ * @ingroup cplugins
+ *
+ * @defgroup eap_simaka_sql_plugin eap_simaka_sql_plugin
+ * @{ @ingroup eap_simaka_sql
+ */
+
+#ifndef EAP_SIMAKA_SQL_PLUGIN_H_
+#define EAP_SIMAKA_SQL_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct eap_simaka_sql_plugin_t eap_simaka_sql_plugin_t;
+
+/**
+ * Plugin to provide SIM/AKA cards/providers using triplets from a database.
+ */
+struct eap_simaka_sql_plugin_t {
+
+       /**
+        * Implements plugin interface
+        */
+       plugin_t plugin;
+};
+
+#endif /** EAP_SIMAKA_SQL_PLUGIN_H_ @}*/
diff --git a/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_provider.c b/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_provider.c
new file mode 100644 (file)
index 0000000..73cccf5
--- /dev/null
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include "eap_simaka_sql_provider.h"
+
+#include <time.h>
+
+#include <daemon.h>
+
+typedef struct private_eap_simaka_sql_provider_t private_eap_simaka_sql_provider_t;
+
+/**
+ * Private data of an eap_simaka_sql_provider_t object.
+ */
+struct private_eap_simaka_sql_provider_t {
+
+       /**
+        * Public eap_simaka_sql_provider_t interface.
+        */
+       eap_simaka_sql_provider_t public;
+
+       /**
+        * Triplet/quintuplet database
+        */
+       database_t *db;
+
+       /**
+        * Remove used triplets/quintuplets from database
+        */
+       bool remove_used;
+};
+
+METHOD(sim_provider_t, get_triplet, bool,
+       private_eap_simaka_sql_provider_t *this, identification_t *id,
+       char rand[SIM_RAND_LEN], char sres[SIM_SRES_LEN], char kc[SIM_KC_LEN])
+{
+       chunk_t rand_chunk, sres_chunk, kc_chunk;
+       enumerator_t *query;
+       bool found = FALSE;
+       char buf[128];
+
+       snprintf(buf, sizeof(buf), "%Y", id);
+       query = this->db->query(this->db,
+                               "select rand, sres, kc from triplets where id = ? order by use",
+                               DB_TEXT, buf, DB_BLOB, DB_BLOB, DB_BLOB);
+       if (query)
+       {
+               if (query->enumerate(query, &rand_chunk, &sres_chunk, &kc_chunk))
+               {
+                       if (rand_chunk.len == SIM_RAND_LEN &&
+                               sres_chunk.len == SIM_SRES_LEN &&
+                               kc_chunk.len == SIM_KC_LEN)
+                       {
+                               memcpy(rand, rand_chunk.ptr, SIM_RAND_LEN);
+                               memcpy(sres, sres_chunk.ptr, SIM_SRES_LEN);
+                               memcpy(kc, kc_chunk.ptr, SIM_KC_LEN);
+                               found = TRUE;
+                       }
+               }
+               query->destroy(query);
+       }
+       if (found)
+       {
+               if (this->remove_used)
+               {
+                       this->db->execute(this->db, NULL,
+                                       "delete from triplets where id = ? and rand = ?",
+                                       DB_TEXT, buf, DB_BLOB, chunk_create(rand, SIM_RAND_LEN));
+               }
+               else
+               {
+                       this->db->execute(this->db, NULL,
+                                       "update triplets set use = ? where id = ? and rand = ?",
+                                       DB_UINT, time(NULL), DB_TEXT, buf,
+                                       DB_BLOB, chunk_create(rand, SIM_RAND_LEN));
+               }
+       }
+       return found;
+}
+
+METHOD(sim_provider_t, get_quintuplet, bool,
+       private_eap_simaka_sql_provider_t *this, identification_t *id,
+       char rand[AKA_RAND_LEN], char xres[AKA_RES_MAX], int *xres_len,
+       char ck[AKA_CK_LEN], char ik[AKA_IK_LEN], char autn[AKA_AUTN_LEN])
+{
+       chunk_t rand_chunk, xres_chunk, ck_chunk, ik_chunk, autn_chunk;
+       enumerator_t *query;
+       bool found = FALSE;
+       char buf[128];
+
+       snprintf(buf, sizeof(buf), "%Y", id);
+       query = this->db->query(this->db, "select rand, res, ck, ik, autn "
+                               "from quintuplets where id = ? order by use", DB_TEXT, buf,
+                               DB_BLOB, DB_BLOB, DB_BLOB, DB_BLOB, DB_BLOB);
+       if (query)
+       {
+               if (query->enumerate(query, &rand_chunk, &xres_chunk,
+                                                        &ck_chunk, &ik_chunk, &autn_chunk))
+               {
+                       if (rand_chunk.len == AKA_RAND_LEN &&
+                               xres_chunk.len <= AKA_RES_MAX &&
+                               ck_chunk.len == AKA_CK_LEN &&
+                               ik_chunk.len == AKA_IK_LEN &&
+                               autn_chunk.len == AKA_AUTN_LEN)
+                       {
+                               memcpy(rand, rand_chunk.ptr, AKA_RAND_LEN);
+                               memcpy(xres, xres_chunk.ptr, xres_chunk.len);
+                               *xres_len = xres_chunk.len;
+                               memcpy(ck, ck_chunk.ptr, AKA_CK_LEN);
+                               memcpy(ik, ik_chunk.ptr, AKA_IK_LEN);
+                               memcpy(autn, autn_chunk.ptr, AKA_AUTN_LEN);
+                               found = TRUE;
+                       }
+               }
+               query->destroy(query);
+       }
+       if (found)
+       {
+               if (this->remove_used)
+               {
+                       this->db->execute(this->db, NULL,
+                                       "delete from quintuplets where id = ? and rand = ?",
+                                       DB_TEXT, buf, DB_BLOB, chunk_create(rand, SIM_RAND_LEN));
+               }
+               else
+               {
+                       this->db->execute(this->db, NULL,
+                                       "update quintuplets set use = ? where id = ? and rand = ?",
+                                       DB_UINT, time(NULL), DB_TEXT, buf,
+                                       DB_BLOB, chunk_create(rand, AKA_RAND_LEN));
+               }
+       }
+       return found;
+}
+
+METHOD(eap_simaka_sql_provider_t, destroy, void,
+       private_eap_simaka_sql_provider_t *this)
+{
+       free(this);
+}
+
+/**
+ * See header
+ */
+eap_simaka_sql_provider_t *eap_simaka_sql_provider_create(database_t *db,
+                                                                                                                 bool remove_used)
+{
+       private_eap_simaka_sql_provider_t *this;
+
+       INIT(this,
+               .public = {
+                       .provider = {
+                               .get_triplet = _get_triplet,
+                               .get_quintuplet = _get_quintuplet,
+                               .resync = (void*)return_false,
+                               .is_pseudonym = (void*)return_null,
+                               .gen_pseudonym = (void*)return_null,
+                               .is_reauth = (void*)return_null,
+                               .gen_reauth = (void*)return_null,
+                       },
+                       .destroy = _destroy,
+               },
+               .db = db,
+               .remove_used = remove_used,
+       );
+
+       return &this->public;
+}
diff --git a/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_provider.h b/src/libcharon/plugins/eap_simaka_sql/eap_simaka_sql_provider.h
new file mode 100644 (file)
index 0000000..ecb0c8c
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup eap_simaka_sql_provider eap_simaka_sql_provider
+ * @{ @ingroup eap_simaka_sql
+ */
+
+#ifndef EAP_SIMAKA_SQL_PROVIDER_H_
+#define EAP_SIMAKA_SQL_PROVIDER_H_
+
+#include <database/database.h>
+#include <sa/authenticators/eap/sim_manager.h>
+
+typedef struct eap_simaka_sql_provider_t eap_simaka_sql_provider_t;
+
+/**
+ * SIM provider implementation using a triplet/quintuplet database backend.
+ */
+struct eap_simaka_sql_provider_t {
+
+       /**
+        * Implements sim_provider_t interface
+        */
+       sim_provider_t provider;
+
+       /**
+        * Destroy a eap_simaka_sql_provider_t.
+        */
+       void (*destroy)(eap_simaka_sql_provider_t *this);
+};
+
+/**
+ * Create a eap_simaka_sql_provider instance.
+ *
+ * @param db                   triplet/quintuplet database
+ * @param remove_used  TRUE to remove used triplets/quintuplets from db
+ */
+eap_simaka_sql_provider_t *eap_simaka_sql_provider_create(database_t *db,
+                                                                                                                 bool remove_used);
+
+#endif /** EAP_SIMAKA_SQL_PROVIDER_H_ @}*/
diff --git a/src/libcharon/plugins/eap_simaka_sql/sqlite.sql b/src/libcharon/plugins/eap_simaka_sql/sqlite.sql
new file mode 100644 (file)
index 0000000..d72053f
--- /dev/null
@@ -0,0 +1,19 @@
+DROP TABLE IF EXISTS triplets;
+CREATE TABLE triplets (
+  id TEXT NOT NULL,
+  use INTEGER NOT NULL,
+  rand BLOB NOT NULL,
+  sres BLOB NOT NULL,
+  kc BLOB NOT NULL
+);
+
+DROP TABLE IF EXISTS quintuplets;
+CREATE TABLE quintuplets (
+  id TEXT NOT NULL,
+  use INTEGER NOT NULL,
+  rand BLOB NOT NULL,
+  autn BLOB NOT NULL,
+  ck BLOB NOT NULL,
+  ik BLOB NOT NULL,
+  res BLOB NOT NULL
+);
diff --git a/src/libcharon/plugins/eap_simaka_sql/test.sql b/src/libcharon/plugins/eap_simaka_sql/test.sql
new file mode 100644 (file)
index 0000000..0c5c22f
--- /dev/null
@@ -0,0 +1,28 @@
+DELETE FROM triplets;
+DELETE FROM quintuplets;
+
+INSERT INTO triplets
+  (id, use, rand, sres, kc) VALUES
+  ('moon@strongswan.org', 0,
+   X'00112233445566778899AABBCCDDEEFF', X'01234567', X'0123456789ABCDEF'
+  );
+INSERT INTO triplets
+  (id, use, rand, sres, kc) VALUES
+  ('moon@strongswan.org', 0,
+   X'112233445566778899AABBCCDDEEFF00', X'12345678', X'123456789ABCDEF0'
+  );
+INSERT INTO triplets
+  (id, use, rand, sres, kc) VALUES
+  ('moon@strongswan.org', 0,
+   X'2233445566778899AABBCCDDEEFF0011', X'23456789', X'23456789ABCDEF01'
+  );
+
+INSERT INTO quintuplets
+  (id, use, rand, autn, ck, ik, res) VALUES
+  ('moon@strongswan.org', 0,
+   X'00112233445566778899AABBCCDDEEFF',
+   X'112233445566778899AABBCCDDEEFF00',
+   X'2233445566778899AABBCCDDEEFF0011',
+   X'33445566778899AABBCCDDEEFF001122',
+   X'00112233445566778899'
+  );