Add an option to delete any established IKE_SA if RADIUS server is not responding
authorMartin Willi <martin@revosec.ch>
Thu, 14 Mar 2013 13:01:17 +0000 (14:01 +0100)
committerMartin Willi <martin@revosec.ch>
Thu, 14 Mar 2013 14:42:30 +0000 (15:42 +0100)
src/libcharon/plugins/eap_radius/eap_radius.c
src/libcharon/plugins/eap_radius/eap_radius_accounting.c
src/libcharon/plugins/eap_radius/eap_radius_plugin.c
src/libcharon/plugins/eap_radius/eap_radius_plugin.h

index a39eb80..7b3c152 100644 (file)
@@ -253,7 +253,7 @@ METHOD(eap_method_t, initiate, status_t,
        }
        else
        {
-               charon->bus->alert(charon->bus, ALERT_RADIUS_NOT_RESPONDING);
+               eap_radius_handle_timeout(NULL);
        }
        request->destroy(request);
        return status;
index 0764f33..7375937 100644 (file)
@@ -164,10 +164,6 @@ static bool send_message(private_eap_radius_accounting_t *this,
                        ack = response->get_code(response) == RMC_ACCOUNTING_RESPONSE;
                        response->destroy(response);
                }
-               else
-               {
-                       charon->bus->alert(charon->bus, ALERT_RADIUS_NOT_RESPONDING);
-               }
                client->destroy(client);
        }
        return ack;
@@ -268,6 +264,10 @@ static void send_start(private_eap_radius_accounting_t *this, ike_sa_t *ike_sa)
                entry = this->sessions->put(this->sessions, (void*)(uintptr_t)id, entry);
                this->mutex->unlock(this->mutex);
        }
+       else
+       {
+               eap_radius_handle_timeout(ike_sa->get_id(ike_sa));
+       }
        message->destroy(message);
        free(entry);
 }
@@ -323,7 +323,10 @@ static void send_stop(private_eap_radius_accounting_t *this, ike_sa_t *ike_sa)
                value = htonl(entry->cause);
                message->add(message, RAT_ACCT_TERMINATE_CAUSE, chunk_from_thing(value));
 
-               send_message(this, message);
+               if (!send_message(this, message))
+               {
+                       eap_radius_handle_timeout(NULL);
+               }
                message->destroy(message);
                free(entry);
        }
index 75d7f8b..c32f521 100644 (file)
 #include <radius_client.h>
 #include <radius_config.h>
 
-#include <daemon.h>
 #include <hydra.h>
 #include <threading/rwlock.h>
+#include <processing/jobs/callback_job.h>
+#include <processing/jobs/delete_ike_sa_job.h>
 
 /**
  * Default RADIUS server port for authentication
@@ -320,3 +321,48 @@ radius_client_t *eap_radius_create_client()
        }
        return NULL;
 }
+
+/**
+ * Job to delete all active IKE_SAs
+ */
+static job_requeue_t delete_all_async(void *data)
+{
+       enumerator_t *enumerator;
+       ike_sa_t *ike_sa;
+
+       enumerator = charon->ike_sa_manager->create_enumerator(
+                                                                                               charon->ike_sa_manager, TRUE);
+       while (enumerator->enumerate(enumerator, &ike_sa))
+       {
+               lib->processor->queue_job(lib->processor,
+                               (job_t*)delete_ike_sa_job_create(ike_sa->get_id(ike_sa), TRUE));
+       }
+       enumerator->destroy(enumerator);
+
+       return JOB_REQUEUE_NONE;
+}
+
+/**
+ * See header.
+ */
+void eap_radius_handle_timeout(ike_sa_id_t *id)
+{
+       charon->bus->alert(charon->bus, ALERT_RADIUS_NOT_RESPONDING);
+
+       if (lib->settings->get_bool(lib->settings,
+                                                               "%s.plugins.eap-radius.close_all_on_timeout",
+                                                               FALSE, charon->name))
+       {
+               DBG1(DBG_CFG, "deleting all IKE_SAs after RADIUS timeout");
+               lib->processor->queue_job(lib->processor,
+                               (job_t*)callback_job_create_with_prio(
+                                               (callback_job_cb_t)delete_all_async, NULL, NULL,
+                                               (callback_job_cancel_t)return_false, JOB_PRIO_CRITICAL));
+       }
+       else if (id)
+       {
+               DBG1(DBG_CFG, "deleting IKE_SA after RADIUS timeout");
+               lib->processor->queue_job(lib->processor,
+                               (job_t*)delete_ike_sa_job_create(id, TRUE));
+       }
+}
index 1570bd5..80fa209 100644 (file)
@@ -27,6 +27,7 @@
 #include <plugins/plugin.h>
 
 #include <radius_client.h>
+#include <daemon.h>
 
 typedef struct eap_radius_plugin_t eap_radius_plugin_t;
 
@@ -51,4 +52,14 @@ struct eap_radius_plugin_t {
  */
 radius_client_t *eap_radius_create_client();
 
+/**
+ * Handle a RADIUS request timeout.
+ *
+ * If an IKE_SA is given, it gets deleted (unless the policy says to delete
+ * any established IKE_SA).
+ *
+ * @param id           associated IKE_SA where timeout happened, or NULL
+ */
+void eap_radius_handle_timeout(ike_sa_id_t *id);
+
 #endif /** EAP_RADIUS_PLUGIN_H_ @}*/