From: Michael Altizer (mialtize) Date: Fri, 21 Apr 2017 18:34:55 +0000 (-0400) Subject: Merge pull request #856 in SNORT/snort3 from multiple_remotes to master X-Git-Tag: 3.0.0-233~21 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=021cebe890eeb60f3476bd67975147da66756d24;p=thirdparty%2Fsnort3.git Merge pull request #856 in SNORT/snort3 from multiple_remotes to master Squashed commit of the following: commit 59aea04b2d7f4d4642df12d35b21e456a94a4916 Author: Bhagya Tholpady Date: Wed Apr 12 10:28:09 2017 -0400 allow multiple remote control channels --- diff --git a/configure.ac b/configure.ac index c32e6fb33..dab8c1d4e 100644 --- a/configure.ac +++ b/configure.ac @@ -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") diff --git a/src/main.cc b/src/main.cc index fffa9ea50..fa68b123a 100644 --- a/src/main.cc +++ b/src/main.cc @@ -59,6 +59,10 @@ #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::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(); } diff --git a/src/main/CMakeLists.txt b/src/main/CMakeLists.txt index cc22975f9..8bdf315cc 100644 --- a/src/main/CMakeLists.txt +++ b/src/main/CMakeLists.txt @@ -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} ) diff --git a/src/main/Makefile.am b/src/main/Makefile.am index e48596f79..9195ee7a1 100644 --- a/src/main/Makefile.am +++ b/src/main/Makefile.am @@ -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 index 000000000..68962374b --- /dev/null +++ b/src/main/control.cc @@ -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 index 000000000..48fb4fbee --- /dev/null +++ b/src/main/control.h @@ -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 + diff --git a/src/main/snort.cc b/src/main/snort.cc index c1c1f4227..c4197104a 100644 --- a/src/main/snort.cc +++ b/src/main/snort.cc @@ -87,6 +87,10 @@ #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 Snort::controls; + +void Snort::add_control(int fd, bool local) +{ + controls.push_back(new ControlConn(fd, local)); +} + +void Snort::delete_control(std::vector::iterator& control) +{ + delete *control; + control = controls.erase(control); +} + +void Snort::reconfigure_controls() +{ + for ( auto control : controls ) + { + control->configure(); + } +} + +std::vector& Snort::get_controls() +{ + return controls; +} + +void Snort::delete_controls() +{ + for ( auto control : controls ) + { + delete control; + } + controls.clear(); +} +#endif diff --git a/src/main/snort.h b/src/main/snort.h index af7e41e53..e7f0962f6 100644 --- a/src/main/snort.h +++ b/src/main/snort.h @@ -22,12 +22,13 @@ #define SNORT_H // Snort is the top-level application class. - +#include #include #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::iterator& control); + static void reconfigure_controls(); + static std::vector& 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 controls; +#endif }; #endif diff --git a/src/main/snort_config.cc b/src/main/snort_config.cc index 825662d45..06d8faed9 100644 --- a/src/main/snort_config.cc +++ b/src/main/snort_config.cc @@ -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); } diff --git a/src/managers/module_manager.cc b/src/managers/module_manager.cc index 16c4e0cc1..269fedfaf 100644 --- a/src/managers/module_manager.cc +++ b/src/managers/module_manager.cc @@ -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 ) { diff --git a/src/managers/module_manager.h b/src/managers/module_manager.h index 60d989da7..60007fd93 100644 --- a/src/managers/module_manager.h +++ b/src/managers/module_manager.h @@ -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*);