00001 //--------------------------------------------------------------------------
00002 // Copyright (C) 2014-2017 Cisco and/or its affiliates. All rights reserved.
00003 // Copyright (C) 2002-2013 Sourcefire, Inc.
00004 // Copyright (C) 1998-2002 Martin Roesch <roesch@sourcefire.com>
00005 // Copyright (C) 2000,2001 Andrew R. Baker <andrewb@uab.edu>
00006 //
00007 // This program is free software; you can redistribute it and/or modify it
00008 // under the terms of the GNU General Public License Version 2 as published
00009 // by the Free Software Foundation. You may not use, modify or distribute
00010 // this program under any other version of the GNU General Public License.
00011 //
00012 // This program is distributed in the hope that it will be useful, but
00013 // WITHOUT ANY WARRANTY; without even the implied warranty of
00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00015 // General Public License for more details.
00016 //
00017 // You should have received a copy of the GNU General Public License along
00018 // with this program; if not, write to the Free Software Foundation, Inc.,
00019 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020 //--------------------------------------------------------------------------
00021
00022 /* alert_fast
00023 *
00024 * Purpose: output plugin for fast alerting
00025 *
00026 * Arguments: alert file
00027 *
00028 * Effect:
00029 *
00030 * Alerts are written to a file in the snort fast alert format
00031 *
00032 * Comments: Allows use of fast alerts with other output plugin types
00033 *
00034 */
00035
00036 #ifdef HAVE_CONFIG_H
00037 #include "config.h"
00038 #endif
00039
00040 #include <vector>
00041
00042 #include "detection/detection_engine.h"
00043 #include "detection/signature.h"
00044 #include "events/event.h"
00045 #include "framework/logger.h"
00046 #include "framework/module.h"
00047 #include "log/log_text.h"
00048 #include "log/text_log.h"
00049 #include "log/obfuscator.h"
00050 #include "main/snort_config.h"
00051 #include "managers/inspector_manager.h"
00052 #include "packet_io/active.h"
00053 #include "packet_io/intf.h"
00054 #include "packet_io/sfdaq.h"
00055 #include "service_inspectors/http_inspect/http_enum.h"
00056
00057 using namespace std;
00058
00059 /* full buf was chosen to allow printing max size packets
00060 * in hex/ascii mode:
00061 * each byte => 2 nibbles + space + ascii + overhead
00062 */
00063 #define FULL_BUF (4*IP_MAXPACKET)
00064 #define FAST_BUF (4*K_BYTES)
00065
00066 static THREAD_LOCAL TextLog* fast_log = nullptr;
00067
00068 #define S_NAME "alert_fast"
00069 #define F_NAME S_NAME ".txt"
00070
00071 //-------------------------------------------------------------------------
00072 // module stuff
00073 //-------------------------------------------------------------------------
00074
00075 static const Parameter s_params[] =
00076 {
00077 { "file", Parameter::PT_BOOL, nullptr, "false",
00078 "output to " F_NAME " instead of stdout" },
00079
00080 { "packet", Parameter::PT_BOOL, nullptr, "false",
00081 "output packet dump with alert" },
00082
00083 { "limit", Parameter::PT_INT, "0:", "0",
00084 "set maximum size in MB before rollover (0 is unlimited)" },
00085
00086 { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
00087 };
00088
00089 #define s_help \
00090 "output event with brief text format"
00091
00092 class FastModule : public Module
00093 {
00094 public:
00095 FastModule() : Module(S_NAME, s_help, s_params) { }
00096
00097 bool set(const char*, Value&, SnortConfig*) override;
00098 bool begin(const char*, int, SnortConfig*) override;
00099
00100 Usage get_usage() const override
00101 { return CONTEXT; }
00102
00103 public:
00104 bool file;
00105 unsigned long limit;
00106 bool packet;
00107 };
00108
00109 bool FastModule::set(const char*, Value& v, SnortConfig*)
00110 {
00111 if ( v.is("file") )
00112 file = v.get_bool();
00113
00114 else if ( v.is("packet") )
00115 packet = v.get_bool();
00116
00117 else if ( v.is("limit") )
00118 limit = v.get_long() * 1024 * 1024;
00119
00120 else
00121 return false;
00122
00123 return true;
00124 }
00125
00126 bool FastModule::begin(const char*, int, SnortConfig*)
00127 {
00128 file = false;
00129 limit = 0;
00130 packet = false;
00131 return true;
00132 }
00133
00134 //-------------------------------------------------------------------------
00135 // helper
00136
00137 static void load_buf_ids(
00138 Inspector* ins, std::vector<const char*>& keys, std::vector<unsigned>& ids)
00139 {
00140 for ( auto key : keys )
00141 {
00142 unsigned id = ins->get_buf_id(key);
00143 assert(id);
00144 ids.push_back(id);
00145 }
00146 }
00147
00148 //-------------------------------------------------------------------------
00149 // logger stuff
00150 //-------------------------------------------------------------------------
00151
00152 class FastLogger : public Logger
00153 {
00154 public:
00155 FastLogger(FastModule*);
00156
00157 void open() override;
00158 void close() override;
00159
00160 void alert(Packet*, const char* msg, const Event&) override;
00161
00162 private:
00163 string file;
00164 unsigned long limit;
00165 bool packet;
00166
00167 std::vector<unsigned> req_ids;
00168 std::vector<unsigned> rsp_ids;
00169 };
00170
00171 FastLogger::FastLogger(FastModule* m)
00172 {
00173 file = m->file ? F_NAME : "stdout";
00174 limit = m->limit;
00175 packet = m->packet;
00176
00177 //-----------------------------------------------------------------
00178 // FIXIT-L generalize buffer sets when other inspectors get smarter
00179 // this is only applicable to http_inspect
00180 // could be configurable; and should be should be shared with u2
00181
00182 Inspector* ins = InspectorManager::get_inspector("http_inspect");
00183
00184 if ( !ins )
00185 return;
00186
00187 std::vector<const char*> req
00188 { "http_method", "http_version", "http_uri", "http_header", "http_cookie",
00189 "http_client_body" };
00190
00191 std::vector<const char*> rsp
00192 { "http_version", "http_stat_code", "http_stat_msg", "http_uri", "http_header",
00193 "http_cookie" };
00194 //-----------------------------------------------------------------
00195
00196 load_buf_ids(ins, req, req_ids);
00197 load_buf_ids(ins, rsp, rsp_ids);
00198 }
00199
00200 void FastLogger::open()
00201 {
00202 unsigned sz = packet ? FULL_BUF : FAST_BUF;
00203 fast_log = TextLog_Init(file.c_str(), sz, limit);
00204 }
00205
00206 void FastLogger::close()
00207 {
00208 if ( fast_log )
00209 TextLog_Term(fast_log);
00210 }
00211
00212 void FastLogger::alert(Packet* p, const char* msg, const Event& event)
00213 {
00214 LogTimeStamp(fast_log, p);
00215
00216 if ( Active::get_action() > Active::ACT_PASS )
00217 TextLog_Print(fast_log, " [%s]", Active::get_action_string());
00218
00219 TextLog_Puts(fast_log, " [**] ");
00220
00221 TextLog_Print(fast_log, "[%u:%u:%u] ",
00222 event.sig_info->gid, event.sig_info->sid, event.sig_info->rev);
00223
00224 if (SnortConfig::alert_interface())
00225 TextLog_Print(fast_log, " <%s> ", PRINT_INTERFACE(SFDAQ::get_interface_spec()));
00226
00227 if ( msg )
00228 TextLog_Puts(fast_log, msg);
00229
00230 TextLog_Puts(fast_log, " [**] ");
00231
00232 // print the packet header to the alert file
00233 LogPriorityData(fast_log, event);
00234 LogAppID(fast_log, p);
00235 TextLog_Print(fast_log, "{%s} ", p->get_type());
00236 LogIpAddrs(fast_log, p);
00237
00238 // log packet (p) if this is not an http request with one or more buffers
00239 // because in that case packet data is also in http_headers or http_client_body
00240 // only http provides buffers at present; http_raw_status is always
00241 // available if a response was processed by http_inspect
00242 bool log_pkt = true;
00243
00244 if ( packet || SnortConfig::output_app_data() )
00245 {
00246 TextLog_NewLine(fast_log);
00247 Inspector* gadget = p->flow ? p->flow->gadget : nullptr;
00248 const char** buffers = gadget ? gadget->get_api()->buffers : nullptr;
00249
00250 if ( buffers )
00251 {
00252 InspectionBuffer buf;
00253 const std::vector<unsigned>& idv = gadget->get_buf(HttpEnums::HTTP_BUFFER_RAW_STATUS,
00254 p, buf) ? rsp_ids : req_ids;
00255 bool rsp = (idv == rsp_ids);
00256
00257 for ( auto id : idv )
00258 {
00259
00260 if ( gadget->get_buf(id, p, buf) )
00261 LogNetData(fast_log, buf.data, buf.len, p, buffers[id-1]);
00262
00263 log_pkt = rsp;
00264 }
00265 }
00266 else if ( gadget )
00267 {
00268 InspectionBuffer buf;
00269
00270 if ( gadget->get_buf(InspectionBuffer::IBT_KEY, p, buf) )
00271 LogNetData(fast_log, buf.data, buf.len, p);
00272
00273 if ( gadget->get_buf(InspectionBuffer::IBT_HEADER, p, buf) )
00274 LogNetData(fast_log, buf.data, buf.len, p);
00275
00276 if ( gadget->get_buf(InspectionBuffer::IBT_BODY, p, buf) )
00277 LogNetData(fast_log, buf.data, buf.len, p);
00278 }
00279 if (p->has_ip())
00280 LogIPPkt(fast_log, p);
00281
00282 else if ( log_pkt and p->obfuscator )
00283 {
00284 // FIXIT-P avoid string copy
00285 std::string buf((const char*)p->data, p->dsize);
00286
00287 for ( const auto& b : *p->obfuscator )
00288 buf.replace(b.offset, b.length, b.length, p->obfuscator->get_mask_char());
00289
00290 LogNetData(fast_log, (const uint8_t*)buf.c_str(), p->dsize, p);
00291 }
00292 else if ( log_pkt )
00293 LogNetData(fast_log, p->data, p->dsize, p);
00294
00295 DataBuffer& buf = DetectionEngine::get_alt_buffer(p);
00296
00297 if ( buf.len and event.sig_info->gid != 116 )
00298 LogNetData(fast_log, buf.data, buf.len, p, "alt");
00299 }
00300 TextLog_NewLine(fast_log);
00301 TextLog_Flush(fast_log);
00302 }
00303
00304 //-------------------------------------------------------------------------
00305 // api stuff
00306 //-------------------------------------------------------------------------
00307
00308 static Module* mod_ctor()
00309 { return new FastModule; }
00310
00311 static void mod_dtor(Module* m)
00312 { delete m; }
00313
00314 static Logger* fast_ctor(SnortConfig*, Module* mod)
00315 { return new FastLogger((FastModule*)mod); }
00316
00317 static void fast_dtor(Logger* p)
00318 { delete p; }
00319
00320 static LogApi fast_api
00321 {
00322 {
00323 PT_LOGGER,
00324 sizeof(LogApi),
00325 LOGAPI_VERSION,
00326 0,
00327 API_RESERVED,
00328 API_OPTIONS,
00329 S_NAME,
00330 s_help,
00331 mod_ctor,
00332 mod_dtor
00333 },
00334 OUTPUT_TYPE_FLAG__ALERT,
00335 fast_ctor,
00336 fast_dtor
00337 };
00338
00339 #ifdef BUILDING_SO
00340 SO_PUBLIC const BaseApi* snort_plugins[] =
00341 #else
00342 const BaseApi* alert_fast[] =
00343 #endif
00344 {
00345 &fast_api.base,
00346 nullptr
00347 };
00348
END OF CODE