execute an _imv_policy script
authorAndreas Steffen <andreas.steffen@strongswan.org>
Thu, 2 May 2013 20:15:12 +0000 (22:15 +0200)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Fri, 21 Jun 2013 21:25:22 +0000 (23:25 +0200)
src/libimcv/Makefile.am
src/libimcv/imv/_imv_policy [new file with mode: 0755]
src/libimcv/imv/imv_database.c
src/libimcv/imv/imv_database.h
src/libimcv/plugins/imv_os/imv_os.c
src/libimcv/plugins/imv_os/imv_os_database.c

index 470f309..50cfbf9 100644 (file)
@@ -39,6 +39,9 @@ libimcv_la_SOURCES = \
        pa_tnc/pa_tnc_msg.h pa_tnc/pa_tnc_msg.c \
        pa_tnc/pa_tnc_attr_manager.h pa_tnc/pa_tnc_attr_manager.c
 
+ipsec_SCRIPTS = imv/_imv_policy
+EXTRA_DIST = imv/_imv_policy
+
 SUBDIRS = .
 
 if USE_IMC_TEST
diff --git a/src/libimcv/imv/_imv_policy b/src/libimcv/imv/_imv_policy
new file mode 100755 (executable)
index 0000000..68a963c
--- /dev/null
@@ -0,0 +1,39 @@
+#! /bin/sh
+# default TNC policy command script
+#
+# Copyright 2013 Andreas Steffen
+# HSR 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.
+#
+# CAUTION:  Installing a new version of strongSwan will install a new
+# copy of this script, wiping out any custom changes you make.  If
+# you need changes, make a copy of this under another name, and customize
+# that, and use the "libimcv.policy_script = " option in strongswan.conf
+# to make strongSwan use yours instead of this default one.
+
+# Environment variables that this script gets 
+#
+#    TNC_SESSION_ID 
+#         unique session ID used as a reference by the policy 
+#         manager. 
+#
+case "$1" in
+start)
+       echo "start session $TNC_SESSION_ID"
+       ;;
+stop)
+       echo "stop session $TNC_SESSION_ID"
+       ;;
+*)     echo "$0: unknown command '$1'"
+       exit 1
+       ;;
+esac
index 1402e2e..b49677f 100644 (file)
  * for more details.
  */
 
-#include "imv_database.h"
-
-#include <utils/debug.h>
+#define _GNU_SOURCE
 
+#include <stdio.h>
 #include <string.h>
 #include <time.h>
 
+#include "imv_database.h"
+
+#include <utils/debug.h>
+
 typedef struct private_imv_database_t private_imv_database_t;
 
 #define SESSION_TIME_DELTA_MAX         2  /* seconds */
 
+#define DEFAULT_POLICY_SCRIPT          "ipsec _imv_policy"
+
 /**
  * Private data of a imv_database_t object.
  *
@@ -40,6 +45,11 @@ struct private_imv_database_t {
         */
        database_t *db;
 
+       /**
+        * policy script
+        */
+       char *script;
+
 };
 
 METHOD(imv_database_t, get_session_id, int,
@@ -165,6 +175,49 @@ METHOD(imv_database_t, add_device, int,
        return did;
 }
 
+METHOD(imv_database_t, policy_script, bool,
+       private_imv_database_t *this, int session_id, bool start)
+{
+       char command[512], resp[128], *last;
+       FILE *shell;
+
+       snprintf(command, sizeof(command), "2>&1 TNC_SESSION_ID='%d' %s %s",
+                        session_id, this->script, start ? "start" : "stop");
+       DBG3(DBG_IMV, "running policy script: %s", command);
+
+       shell = popen(command, "r");
+       if (shell == NULL)
+       {
+               DBG1(DBG_IMV, "could not execute policy script '%s'",
+                        this->script);
+               return FALSE;
+       }
+       while (TRUE)
+       {
+               if (fgets(resp, sizeof(resp), shell) == NULL)
+               {
+                       if (ferror(shell))
+                       {
+                               DBG1(DBG_IMV, "error reading output from policy script");
+                       }
+                       break;
+               }
+               else
+               {
+                       last = resp + strlen(resp) - 1;
+                       if (last >= resp && *last == '\n')
+                       {
+                               /* replace trailing '\n' */
+                               *last = '\0';
+                       }
+                       DBG1(DBG_IMV, "policy: %s", resp);
+               }
+       }
+       pclose(shell);
+
+       return TRUE;
+}
+
 METHOD(imv_database_t, get_database, database_t*,
        private_imv_database_t *this)
 {
@@ -190,10 +243,13 @@ imv_database_t *imv_database_create(char *uri)
                        .get_session_id = _get_session_id,
                        .add_product = _add_product,
                        .add_device = _add_device,
+                       .policy_script = _policy_script,
                        .get_database = _get_database,
                        .destroy = _destroy,
                },
                .db = lib->db->create(lib->db, uri),
+               .script = lib->settings->get_str(lib->settings,
+                                       "libimcv.policy_script", DEFAULT_POLICY_SCRIPT),
        );
 
        if (!this->db)
index 3b3cbd6..c49a941 100644 (file)
@@ -56,13 +56,22 @@ struct imv_database_t {
        /**
         * Add device identification to a session
         *
-        * @param session_id    Sessiion ID
+        * @param session_id    Session ID
         * @param device                Device identification
         * @return                              Device ID or 0 if not available
         */
         int (*add_device)(imv_database_t *this, int session_id, chunk_t device);
 
        /**
+        * Announce session start/stop to policy script
+        *
+        * @param session_id    Session ID
+        * @param start                 TRUE if session start, FALSE if session stop
+        * @return                              TRUE if command successful, FALSE otherwise
+        */
+        bool (*policy_script)(imv_database_t *this, int session_id, bool start);
+
+       /**
         * Get database handle
         *
         * @return                              Database handle
index 48af9c5..560b8bf 100644 (file)
@@ -96,6 +96,8 @@ TNC_Result TNC_IMV_NotifyConnectionChange(TNC_IMVID imv_id,
                                                                                  TNC_ConnectionState new_state)
 {
        imv_state_t *state;
+       imv_database_t *imv_db;
+       int session_id;
 
        if (!imv_os)
        {
@@ -108,6 +110,12 @@ TNC_Result TNC_IMV_NotifyConnectionChange(TNC_IMVID imv_id,
                        state = imv_os_state_create(connection_id);
                        return imv_os->create_state(imv_os, state);
                case TNC_CONNECTION_STATE_DELETE:
+                       imv_db = imv_os->get_database(imv_os);
+                       if (imv_db && imv_os->get_state(imv_os, connection_id, &state))
+                       {
+                               session_id = state->get_session_id(state);
+                               imv_db->policy_script(imv_db, session_id, FALSE);
+                       }
                        return imv_os->delete_state(imv_os, connection_id);
                default:
                        return imv_os->change_state(imv_os, connection_id,
@@ -284,7 +292,7 @@ static TNC_Result receive_message(imv_state_t *state, imv_msg_t *in_msg)
                                        ita_attr_settings_t *attr_cast;
                                        imv_database_t *imv_db;
                                        enumerator_t *e;
-                                       int did;
+                                       int session_id, device_id;
                                        char *name;
                                        chunk_t value;
 
@@ -304,9 +312,13 @@ static TNC_Result receive_message(imv_state_t *state, imv_msg_t *in_msg)
                                                        imv_db = imv_os->get_database(imv_os);
                                                        if (imv_db)
                                                        {
-                                                               did = imv_db->add_device(imv_db,
-                                                                               state->get_session_id(state), value);
-                                                               os_state->set_device_id(os_state, did);
+                                                               session_id = state->get_session_id(state);
+                                                               device_id = imv_db->add_device(imv_db,
+                                                                                                               session_id, value);
+                                                               os_state->set_device_id(os_state, device_id);
+
+                                                               /* trigger the policy manager */
+                                                               imv_db->policy_script(imv_db, session_id, TRUE);
                                                        }
                                                }
                                                DBG1(DBG_IMV, "setting '%s'\n  %.*s",
index 6f7b29b..c7f9b6b 100644 (file)
@@ -191,8 +191,6 @@ METHOD(imv_os_database_t, set_device_info, void,
        private_imv_os_database_t *this,  int session_id, int count,
        int count_update, int count_blacklist, u_int flags)
 {
-       enumerator_t *e;
-
        this->db->execute(this->db, NULL,
                        "INSERT INTO device_infos (session, count, count_update, "
                        "count_blacklist, flags) VALUES (?, ?, ?, ?, ?)",