]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #856 in SNORT/snort3 from multiple_remotes to master
authorMichael Altizer (mialtize) <mialtize@cisco.com>
Fri, 21 Apr 2017 18:34:55 +0000 (14:34 -0400)
committerMichael Altizer (mialtize) <mialtize@cisco.com>
Fri, 21 Apr 2017 18:34:55 +0000 (14:34 -0400)
Squashed commit of the following:

commit 59aea04b2d7f4d4642df12d35b21e456a94a4916
Author: Bhagya Tholpady <bbantwal@cisco.com>
Date:   Wed Apr 12 10:28:09 2017 -0400

    allow multiple remote control channels

configure.ac
src/main.cc
src/main/CMakeLists.txt
src/main/Makefile.am
src/main/control.cc [new file with mode: 0644]
src/main/control.h [new file with mode: 0644]
src/main/snort.cc
src/main/snort.h
src/main/snort_config.cc
src/managers/module_manager.cc
src/managers/module_manager.h

index c32e6fb339dd41c1c22a335481d733c409303559..dab8c1d4e9d8fcd8d29cdc245261de882f0204ab 100644 (file)
@@ -323,6 +323,8 @@ if test "x$enable_shell" = "xyes"; then
     AC_DEFINE(SHELL, [1], [enable shell support])
 fi
 
+AM_CONDITIONAL(ENABLE_SHELL, test "x$enable_shell" = "xyes")
+
 AC_ARG_ENABLE(tsc-clock,
     AS_HELP_STRING([--enable-tsc-clock],[use timestamp counter register clock (x86 only)]),
     enable_tsc_clock="$enableval", enable_tsc_clock="no")
index fffa9ea502ce9300b083050bedf9e48b7b2126b4..fa68b123a5eee30aeab85728247a9c7e35b1dde8 100644 (file)
 #include "piglet/piglet.h"
 #endif
 
+#ifdef SHELL
+#include "main/control.h"
+#endif
+
 //-------------------------------------------------------------------------
 
 static bool exit_requested = false;
@@ -566,12 +570,10 @@ static bool house_keeping()
 
 #ifdef SHELL
 // FIXIT-M make these non-blocking
-// FIXIT-M allow at least 2 remote controls
 // FIXIT-M bind to configured ip including INADDR_ANY
 // (default is loopback if enabled)
 // FIXIT-M block on asynchronous analyzer commands until they complete
 static int listener = -1;
-static int local_control = STDIN_FILENO;
 static int remote_control = -1;
 
 static int socket_init()
@@ -607,8 +609,7 @@ static int socket_init()
 
 static int socket_term()
 {
-    if ( remote_control >= 0 )
-        close(remote_control);
+    Snort::delete_controls();
 
     if ( listener >= 0 )
         close(listener);
@@ -628,19 +629,20 @@ static int socket_conn()
     if ( remote_control < 0 )
         return -1;
 
+    Snort::add_control(remote_control, false);
+
     // FIXIT-L authenticate, use ssl ?
     return 0;
 }
 
-static void shell(int& fd)
+static void shell(int& fd, Shell* sh)
 {
     std::string rsp;
 
     if ( !request.read(fd) )
         return;
 
-    SnortConfig* sc = snort_conf;
-    sc->policy_map->get_shell()->execute(request.get(), rsp);
+    sh->execute(request.get(), rsp);
 
     if ( rsp.size() )
         request.respond(rsp.c_str());
@@ -649,27 +651,55 @@ static void shell(int& fd)
         request.show_prompt();
 }
 
+static bool process_control_commands(fd_set& inputs)
+{
+    bool ret = false;
+
+    for(std::vector<ControlConn*>::iterator control =
+            Snort::get_controls().begin(); control != Snort::get_controls().end();)
+    {
+        int fd = (*control)->get_fd();
+        if ( FD_ISSET(fd, &inputs) )
+        {
+            shell(fd, (*control)->get_shell());
+            if( fd < 0 )
+            {
+                Snort::delete_control(control);
+                ret = false;
+                continue;
+            }
+            else
+            {
+                if ( (*control)->is_local_control() )
+                    proc_stats.local_commands++;
+                else
+                    proc_stats.remote_commands++;
+                ret = true;
+            }
+        }
+        ++control;
+    }
+    return ret;
+}
+
 static bool service_users()
 {
     fd_set inputs;
     FD_ZERO(&inputs);
     int max_fd = -1;
+    bool ret = false;
 
-    if ( shell_enabled and local_control >= 0 )
-    {
-        FD_SET(local_control, &inputs);
-        max_fd = local_control;
-    }
-
-    if ( remote_control >= 0 )
+    for ( auto control : Snort::get_controls() )
     {
-        FD_SET(remote_control, &inputs);
-        if ( remote_control > max_fd )
-            max_fd = remote_control;
+        int fd = control->get_fd();
+        if ( fd >= 0 )
+        {
+            FD_SET(fd, &inputs);
+            if ( fd > max_fd )
+                max_fd = fd;
+        }
     }
-    // one remote at a time; the else prevents a new remote
-    // from taking control from an existing remote
-    else if ( listener >= 0 )
+    if ( listener >= 0 )
     {
         FD_SET(listener, &inputs);
         if ( listener > max_fd )
@@ -682,29 +712,19 @@ static bool service_users()
 
     if ( select(max_fd+1, &inputs, NULL, NULL, &timeout) > 0 )
     {
-        if ( FD_ISSET(local_control, &inputs) )
-        {
-            shell(local_control);
-            proc_stats.local_commands++;
-            return true;
-        }
-        else if ( FD_ISSET(remote_control, &inputs) )
-        {
-            shell(remote_control);
-            proc_stats.remote_commands++;
-            return true;
-        }
-        else if ( FD_ISSET(listener, &inputs) )
+        ret = process_control_commands(inputs);
+
+        if ( FD_ISSET(listener, &inputs) )
         {
             if ( !socket_conn() )
             {
                 request.set(remote_control);
                 request.show_prompt();
-                return true;
+                ret = true;
             }
         }
     }
-    return false;
+    return ret;
 }
 #endif
 
@@ -798,6 +818,7 @@ static bool set_mode()
     {
         LogMessage("Entering command shell\n");
         shell_enabled = true;
+        Snort::add_control(STDOUT_FILENO, true);
         request.set(STDOUT_FILENO, "");
         request.show_prompt();
     }
index cc22975f9d203fbe6cfae45bc6db4f32de01ea00..8bdf315ccd21dc9e7bd6b83dfdc8efdb8f5d1003 100644 (file)
@@ -11,6 +11,10 @@ if ( ENABLE_DEBUG_MSGS )
     set ( DEBUG_MSGS_SOURCES snort_debug.cc )
 endif ( ENABLE_DEBUG_MSGS )
 
+if ( ENABLE_SHELL )
+    set ( SHELL_SOURCES control.cc control.h )
+endif ( ENABLE_SHELL )
+
 add_library (main STATIC
     analyzer.cc
     analyzer.h
@@ -36,6 +40,7 @@ add_library (main STATIC
     thread_config.cc
     ${DEBUG_MSGS_SOURCES}
     ${INCLUDES}
+    ${SHELL_SOURCES}
 )
 
 
index e48596f79222faf9c29ae936fe9c15c4150c6202..9195ee7a199350226659582edf99172fdd76b5b8 100644 (file)
@@ -27,8 +27,11 @@ snort.cc \
 snort.h \
 snort_config.cc \
 snort_config.h \
+snort_module.cc \
+snort_module.h \
 swapper.cc \
 swapper.h \
+thread.cc \
 thread_config.h \
 thread_config.cc
 
@@ -36,7 +39,8 @@ if DEBUG_MSGS
 libmain_a_SOURCES += snort_debug.cc
 endif
 
+if ENABLE_SHELL
 libmain_a_SOURCES += \
-snort_module.cc \
-snort_module.h \
-thread.cc
+control.cc \
+control.h
+endif
diff --git a/src/main/control.cc b/src/main/control.cc
new file mode 100644 (file)
index 0000000..6896237
--- /dev/null
@@ -0,0 +1,53 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2017-2017 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation.  You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// 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.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//--------------------------------------------------------------------------
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "control.h"
+
+#include "managers/module_manager.h"
+#include "utils/util.h"
+#include "shell.h"
+
+using namespace std;
+
+//------------------------------------------------------------------------
+// control channel class
+// -----------------------------------------------------------------------
+
+ControlConn::ControlConn(int i, bool local)
+{
+    fd = i;
+    local_control = local;
+    sh = new Shell;
+    configure();
+}
+
+ControlConn::~ControlConn()
+{
+    if( !local_control )
+        close(fd);
+    delete sh;
+}
+
+void ControlConn::configure()
+{
+    ModuleManager::load_commands(sh);
+}
diff --git a/src/main/control.h b/src/main/control.h
new file mode 100644 (file)
index 0000000..48fb4fb
--- /dev/null
@@ -0,0 +1,41 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2017-2017 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation.  You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// 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.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//--------------------------------------------------------------------------
+
+#ifndef CONTROL_H
+#define CONTROL_H
+
+#include "main/snort_types.h"
+
+class ControlConn
+{
+public:
+    ControlConn(int fd, bool local_control);
+    ~ControlConn();
+
+    int get_fd() { return fd; }
+    class Shell* get_shell() { return sh; }
+    bool is_local_control() { return local_control; }
+    void configure();
+private:
+    int fd = -1;
+    bool local_control = false;
+    class Shell *sh;
+};
+
+#endif
+
index c1c1f42274c9d6b17e0850d30f6c7dd8321abccb..c4197104a637293c7eccc1e129dd4ff0bde28d5f 100644 (file)
 #include "piglet_plugins/piglet_plugins.h"
 #endif
 
+#ifdef SHELL
+#include "control.h"
+#endif
+
 #include "build.h"
 #include "snort_config.h"
 #include "thread_config.h"
@@ -528,6 +532,9 @@ void Snort::setup(int argc, char* argv[])
 
 void Snort::cleanup()
 {
+#ifdef SHELL
+    delete_controls();
+#endif
     TimeStop();
 
     SFDAQ::term();
@@ -562,6 +569,10 @@ SnortConfig* Snort::get_reload_config(const char* fname)
 
     sc->setup();
 
+#ifdef SHELL
+    reconfigure_controls();
+#endif
+
     if ( !InspectorManager::configure(sc) )
     {
         parser_term(sc);
@@ -905,3 +916,40 @@ DAQ_Verdict Snort::packet_callback(
 
     return verdict;
 }
+
+#ifdef SHELL
+std::vector<ControlConn*> Snort::controls;
+
+void Snort::add_control(int fd, bool local)
+{
+    controls.push_back(new ControlConn(fd, local));
+}
+
+void Snort::delete_control(std::vector<ControlConn*>::iterator& control)
+{
+    delete *control;
+    control = controls.erase(control);
+}
+
+void Snort::reconfigure_controls()
+{
+    for ( auto control : controls )
+    {
+        control->configure();
+    }
+}
+
+std::vector<ControlConn*>& Snort::get_controls()
+{
+    return controls;
+}
+
+void Snort::delete_controls()
+{
+    for ( auto control : controls )
+    {
+        delete control;
+    }
+    controls.clear();
+}
+#endif
index af7e41e53193d6083dac5972b3ee834d4040804e..e7f0962f62fdbd7e28b5713d2e2925492853321d 100644 (file)
 #define SNORT_H
 
 // Snort is the top-level application class.
-
+#include <vector>
 #include <daq_common.h>
 
 #include "main/snort_types.h"
 
 class Flow;
+class ControlConn;
 struct Packet;
 struct SnortConfig;
 
@@ -65,6 +66,14 @@ public:
 
     SO_PUBLIC static Packet* get_packet();
 
+#ifdef SHELL
+    static void add_control(int fd, bool local_control);
+    static void delete_control(std::vector<ControlConn*>::iterator& control);
+    static void reconfigure_controls();
+    static std::vector<ControlConn*>& get_controls();
+    static void delete_controls();
+#endif
+
 private:
     static void init(int, char**);
     static void term();
@@ -74,6 +83,9 @@ private:
     static bool initializing;
     static bool reloading;
     static bool privileges_dropped;
+#ifdef SHELL
+    static std::vector<ControlConn*> controls;
+#endif
 };
 
 #endif
index 825662d453715161a3893e96b2076c63bda9d717..06d8faed990cefc03801a631616224bbf1aa69c5 100644 (file)
@@ -284,7 +284,7 @@ void SnortConfig::setup()
 
     /* Need to do this after dynamic detection stuff is initialized, too */
     IpsManager::verify(this);
-    ModuleManager::load_commands(this);
+    ModuleManager::load_commands(policy_map->get_shell());
 
     fpCreateFastPacketDetection(this);
 }
index 16c4e0cc1310499bd627516b10b9b1c7535b5acb..269fedfafb6fff26bcb0313cc409004cee2c7087 100644 (file)
@@ -1164,11 +1164,10 @@ void ModuleManager::show_rules(const char* pfx, bool exact)
         cout << "no match" << endl;
 }
 
-void ModuleManager::load_commands(SnortConfig* sc)
+void ModuleManager::load_commands(Shell* sh)
 {
     // FIXIT-L ideally only install commands from configured modules
     // FIXIT-L install commands into working shell
-    Shell* sh = sc->policy_map->get_shell();
 
     for ( auto p : s_modules )
     {
index 60d989da779c4fe500e547ecca50d85676a412ca..60007fd93225181b1449802a943b2314fd9443e4 100644 (file)
@@ -30,6 +30,7 @@
 //-------------------------------------------------------------------------
 
 struct SnortConfig;
+class Shell;
 
 class ModuleManager
 {
@@ -60,7 +61,7 @@ public:
     static void dump_rules(const char* = nullptr);
     static void dump_defaults(const char* = nullptr);
 
-    static void load_commands(SnortConfig*);
+    static void load_commands(Shell*);
     static void load_rules(SnortConfig*);
     static void set_config(SnortConfig*);