suricata
alert-syslog.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2021 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /**
19  * \file
20  *
21  * \author Gurvinder Singh <gurvindersinghdahiya@gmail.com>
22  *
23  * Logs alerts in a line based text format into syslog.
24  *
25  */
26 
27 #include "suricata-common.h"
28 #include "suricata.h"
29 #include "flow.h"
30 #include "conf.h"
31 
32 #include "threads.h"
33 #include "tm-modules.h"
34 #include "threadvars.h"
35 
36 #include "detect.h"
37 #include "decode-ipv4.h"
38 #include "decode-ipv6.h"
39 
40 #include "output.h"
41 #include "alert-syslog.h"
42 
43 #include "util-debug.h"
44 #include "util-print.h"
45 #include "util-proto-name.h"
46 #include "util-syslog.h"
47 #include "util-logopenfile.h"
48 #include "util-enum.h"
49 #include "action-globals.h"
50 
51 #ifndef OS_WIN32
52 
53 #define MODULE_NAME "AlertSyslog"
54 
55 static int alert_syslog_level = DEFAULT_ALERT_SYSLOG_LEVEL;
56 
57 typedef struct AlertSyslogThread_ {
58  /** LogFileCtx has the pointer to the file and a mutex to allow multithreading */
61 
62 /**
63  * \brief Function to clear the memory of the output context and closes the
64  * syslog interface
65  *
66  * \param output_ctx pointer to the output context to be cleared
67  */
68 static void AlertSyslogDeInitCtx(OutputCtx *output_ctx)
69 {
70  if (output_ctx != NULL) {
71  LogFileCtx *logfile_ctx = (LogFileCtx *)output_ctx->data;
72  if (logfile_ctx != NULL) {
73  LogFileFreeCtx(logfile_ctx);
74  }
75  SCFree(output_ctx);
76  }
77  closelog();
78 }
79 
80 /**
81  * \brief Create a new LogFileCtx for "syslog" output style.
82  *
83  * \param conf The configuration node for this output.
84  * \return A OutputCtx pointer on success, NULL on failure.
85  */
86 static OutputInitResult AlertSyslogInitCtx(SCConfNode *conf)
87 {
88  SCLogWarning("The syslog output has been deprecated and will be removed in Suricata 9.0.");
89 
90  OutputInitResult result = { NULL, false };
91  const char *facility_s = SCConfNodeLookupChildValue(conf, "facility");
92  if (facility_s == NULL) {
94  }
95 
96  LogFileCtx *logfile_ctx = LogFileNewCtx();
97  if (logfile_ctx == NULL) {
98  SCLogDebug("AlertSyslogInitCtx: Could not create new LogFileCtx");
99  return result;
100  }
101 
102  int facility = SCMapEnumNameToValue(facility_s, SCSyslogGetFacilityMap());
103  if (facility == -1) {
104  SCLogWarning("Invalid syslog facility: \"%s\","
105  " now using \"%s\" as syslog facility",
108  }
109 
110  const char *level_s = SCConfNodeLookupChildValue(conf, "level");
111  if (level_s != NULL) {
112  int level = SCMapEnumNameToValue(level_s, SCSyslogGetLogLevelMap());
113  if (level != -1) {
114  alert_syslog_level = level;
115  }
116  }
117 
118  const char *ident = SCConfNodeLookupChildValue(conf, "identity");
119  /* if null we just pass that to openlog, which will then
120  * figure it out by itself. */
121 
122  openlog(ident, LOG_PID|LOG_NDELAY, facility);
123 
124  OutputCtx *output_ctx = SCCalloc(1, sizeof(OutputCtx));
125  if (unlikely(output_ctx == NULL)) {
126  SCLogDebug("could not create new OutputCtx");
127  LogFileFreeCtx(logfile_ctx);
128  return result;
129  }
130 
131  output_ctx->data = logfile_ctx;
132  output_ctx->DeInit = AlertSyslogDeInitCtx;
133 
134  SCLogInfo("Syslog output initialized");
135 
136  result.ctx = output_ctx;
137  result.ok = true;
138  return result;
139 }
140 
141 /**
142  * \brief Function to initialize the AlertSyslogThread and sets the output
143  * context pointer
144  *
145  * \param tv Pointer to the threadvars
146  * \param initdata Pointer to the output context
147  * \param data pointer to pointer to point to the AlertSyslogThread
148  */
149 static TmEcode AlertSyslogThreadInit(ThreadVars *t, const void *initdata, void **data)
150 {
151  if(initdata == NULL) {
152  SCLogDebug("Error getting context for AlertSyslog. \"initdata\" "
153  "argument NULL");
154  return TM_ECODE_FAILED;
155  }
156 
157  AlertSyslogThread *ast = SCCalloc(1, sizeof(AlertSyslogThread));
158  if (unlikely(ast == NULL))
159  return TM_ECODE_FAILED;
160 
161  /** Use the Output Context (file pointer and mutex) */
162  ast->file_ctx = ((OutputCtx *)initdata)->data;
163 
164  *data = (void *)ast;
165  return TM_ECODE_OK;
166 }
167 
168 /**
169  * \brief Function to deinitialize the AlertSyslogThread
170  *
171  * \param tv Pointer to the threadvars
172  * \param data pointer to the AlertSyslogThread to be cleared
173  */
174 static TmEcode AlertSyslogThreadDeinit(ThreadVars *t, void *data)
175 {
176  AlertSyslogThread *ast = (AlertSyslogThread *)data;
177  if (ast == NULL) {
178  return TM_ECODE_OK;
179  }
180 
181  /* clear memory */
182  memset(ast, 0, sizeof(AlertSyslogThread));
183 
184  SCFree(ast);
185  return TM_ECODE_OK;
186 }
187 
188 /**
189  * \brief Function which is called to print the IPv4 alerts to the syslog
190  *
191  * \param tv Pointer to the threadvars
192  * \param p Pointer to the packet
193  * \param data pointer to the AlertSyslogThread
194  *
195  * \return On succes return TM_ECODE_OK
196  */
197 static TmEcode AlertSyslogIPv4(ThreadVars *tv, const Packet *p, void *data)
198 {
199  AlertSyslogThread *ast = (AlertSyslogThread *)data;
200  const char *action = "";
201 
202  if (p->alerts.cnt == 0)
203  return TM_ECODE_OK;
204 
205  char proto[16] = "";
206  const char *protoptr;
207  const IPV4Hdr *ipv4h = PacketGetIPv4(p);
208  const uint8_t ipproto = IPV4_GET_RAW_IPPROTO(ipv4h);
209  if (SCProtoNameValid(ipproto)) {
210  protoptr = known_proto[ipproto];
211  } else {
212  snprintf(proto, sizeof(proto), "PROTO:%03" PRIu8, ipproto);
213  protoptr = proto;
214  }
215 
216  char srcip[16], dstip[16];
217  PrintInet(AF_INET, (const void *)GET_IPV4_SRC_ADDR_PTR(p), srcip, sizeof(srcip));
218  PrintInet(AF_INET, (const void *)GET_IPV4_DST_ADDR_PTR(p), dstip, sizeof(dstip));
219 
220  for (int i = 0; i < p->alerts.cnt; i++) {
221  const PacketAlert *pa = &p->alerts.alerts[i];
222  if (unlikely(pa->s == NULL || (pa->action & ACTION_ALERT) == 0)) {
223  continue;
224  }
225 
226  if ((pa->action & ACTION_DROP) && EngineModeIsIPS()) {
227  action = "[Drop] ";
228  } else if (pa->action & ACTION_DROP) {
229  action = "[wDrop] ";
230  }
231 
232  /* Not sure if this mutex is needed around calls to syslog. */
233  SCMutexLock(&ast->file_ctx->fp_mutex);
234  syslog(alert_syslog_level, "%s[%" PRIu32 ":%" PRIu32 ":%"
235  PRIu32 "] %s [Classification: %s] [Priority: %"PRIu32"]"
236  " {%s} %s:%" PRIu32 " -> %s:%" PRIu32 "", action, pa->s->gid,
237  pa->s->id, pa->s->rev, pa->s->msg, pa->s->class_msg, pa->s->prio,
238  protoptr, srcip, p->sp, dstip, p->dp);
240  }
241 
242  return TM_ECODE_OK;
243 }
244 
245 /**
246  * \brief Function which is called to print the IPv6 alerts to the syslog
247  *
248  * \param tv Pointer to the threadvars
249  * \param p Pointer to the packet
250  * \param data pointer to the AlertSyslogThread
251  *
252  * \return On succes return TM_ECODE_OK
253  */
254 static TmEcode AlertSyslogIPv6(ThreadVars *tv, const Packet *p, void *data)
255 {
256  AlertSyslogThread *ast = (AlertSyslogThread *)data;
257  const char *action = "";
258 
259  if (p->alerts.cnt == 0)
260  return TM_ECODE_OK;
261 
262  char proto[16] = "";
263  const char *protoptr;
264  const uint8_t ipproto = IPV6_GET_L4PROTO(p);
265  if (SCProtoNameValid(ipproto)) {
266  protoptr = known_proto[ipproto];
267  } else {
268  snprintf(proto, sizeof(proto), "PROTO:03%" PRIu8, ipproto);
269  protoptr = proto;
270  }
271 
272  char srcip[46], dstip[46];
274  (const void *)GET_IPV6_SRC_ADDR(p), srcip, sizeof(srcip), ast->file_ctx->compress_ipv6);
276  (const void *)GET_IPV6_DST_ADDR(p), dstip, sizeof(dstip), ast->file_ctx->compress_ipv6);
277 
278  for (int i = 0; i < p->alerts.cnt; i++) {
279  const PacketAlert *pa = &p->alerts.alerts[i];
280  if (unlikely(pa->s == NULL || (pa->action & ACTION_ALERT) == 0)) {
281  continue;
282  }
283 
284  if ((pa->action & ACTION_DROP) && EngineModeIsIPS()) {
285  action = "[Drop] ";
286  } else if (pa->action & ACTION_DROP) {
287  action = "[wDrop] ";
288  }
289 
290  SCMutexLock(&ast->file_ctx->fp_mutex);
291  syslog(alert_syslog_level, "%s[%" PRIu32 ":%" PRIu32 ":%"
292  "" PRIu32 "] %s [Classification: %s] [Priority: %"
293  "" PRIu32 "] {%s} %s:%" PRIu32 " -> %s:%" PRIu32 "",
294  action, pa->s->gid, pa->s->id, pa->s->rev, pa->s->msg, pa->s->class_msg,
295  pa->s->prio, protoptr, srcip, p->sp,
296  dstip, p->dp);
298  }
299 
300  return TM_ECODE_OK;
301 }
302 
303 /**
304  * \brief Function which is called to print the decode alerts to the syslog
305  *
306  * \param tv Pointer to the threadvars
307  * \param p Pointer to the packet
308  * \param data pointer to the AlertSyslogThread
309  *
310  * \return On succes return TM_ECODE_OK
311  */
312 static TmEcode AlertSyslogDecoderEvent(ThreadVars *tv, const Packet *p, void *data)
313 {
314  AlertSyslogThread *ast = (AlertSyslogThread *)data;
315  const char *action = "";
316 
317  if (p->alerts.cnt == 0)
318  return TM_ECODE_OK;
319 
320  char temp_buf_hdr[512];
321  char temp_buf_pkt[65] = "";
322  char temp_buf_tail[64];
323  char alert[2048] = "";
324 
325  for (int i = 0; i < p->alerts.cnt; i++) {
326  const PacketAlert *pa = &p->alerts.alerts[i];
327  if (unlikely(pa->s == NULL || (pa->action & ACTION_ALERT) == 0)) {
328  continue;
329  }
330 
331  if ((pa->action & ACTION_DROP) && EngineModeIsIPS()) {
332  action = "[Drop] ";
333  } else if (pa->action & ACTION_DROP) {
334  action = "[wDrop] ";
335  }
336 
337  snprintf(temp_buf_hdr, sizeof(temp_buf_hdr), "%s[%" PRIu32 ":%" PRIu32
338  ":%" PRIu32 "] %s [Classification: %s] [Priority: %" PRIu32
339  "] [**] [Raw pkt: ", action, pa->s->gid, pa->s->id, pa->s->rev, pa->s->msg,
340  pa->s->class_msg, pa->s->prio);
341  strlcpy(alert, temp_buf_hdr, sizeof(alert));
342 
343  PrintRawLineHexBuf(temp_buf_pkt, sizeof(temp_buf_pkt), GET_PKT_DATA(p), GET_PKT_LEN(p) < 32 ? GET_PKT_LEN(p) : 32);
344  strlcat(alert, temp_buf_pkt, sizeof(alert));
345 
346  uint64_t pcap_cnt = PcapPacketCntGet(p);
347  if (pcap_cnt != 0) {
348  snprintf(temp_buf_tail, sizeof(temp_buf_tail), "] [pcap file packet: %" PRIu64 "]",
349  pcap_cnt);
350  } else {
351  temp_buf_tail[0] = ']';
352  temp_buf_tail[1] = '\0';
353  }
354  strlcat(alert, temp_buf_tail, sizeof(alert));
355 
356  SCMutexLock(&ast->file_ctx->fp_mutex);
357  syslog(alert_syslog_level, "%s", alert);
359  }
360 
361  return TM_ECODE_OK;
362 }
363 
364 static bool AlertSyslogCondition(ThreadVars *tv, void *thread_data, const Packet *p)
365 {
366  return (p->alerts.cnt > 0);
367 }
368 
369 static int AlertSyslogLogger(ThreadVars *tv, void *thread_data, const Packet *p)
370 {
371  if (PacketIsIPv4(p)) {
372  return AlertSyslogIPv4(tv, p, thread_data);
373  } else if (PacketIsIPv6(p)) {
374  return AlertSyslogIPv6(tv, p, thread_data);
375  } else if (p->events.cnt > 0) {
376  return AlertSyslogDecoderEvent(tv, p, thread_data);
377  }
378 
379  return TM_ECODE_OK;
380 }
381 
382 #endif /* !OS_WIN32 */
383 
384 /** \brief Function to register the AlertSyslog module */
386 {
387 #ifndef OS_WIN32
388  OutputPacketLoggerFunctions output_logger_functions = {
389  .LogFunc = AlertSyslogLogger,
390  .ConditionFunc = AlertSyslogCondition,
391  .ThreadInitFunc = AlertSyslogThreadInit,
392  .ThreadDeinitFunc = AlertSyslogThreadDeinit,
393  .ThreadExitPrintStatsFunc = NULL,
394  };
395  OutputRegisterPacketModule(LOGGER_ALERT_SYSLOG, MODULE_NAME, "syslog", AlertSyslogInitCtx,
396  &output_logger_functions);
397 #endif /* !OS_WIN32 */
398 }
PacketAlert_::s
const struct Signature_ * s
Definition: decode.h:254
syslog
#define syslog(__pri, __fmt, __param)
Definition: win32-syslog.h:78
IPV4_GET_RAW_IPPROTO
#define IPV4_GET_RAW_IPPROTO(ip4h)
Definition: decode-ipv4.h:103
LogFileCtx_::fp_mutex
SCMutex fp_mutex
Definition: util-logopenfile.h:101
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
LOGGER_ALERT_SYSLOG
@ LOGGER_ALERT_SYSLOG
Definition: suricata-common.h:500
LogFileNewCtx
LogFileCtx * LogFileNewCtx(void)
LogFileNewCtx() Get a new LogFileCtx.
Definition: util-logopenfile.c:734
PcapPacketCntGet
uint64_t PcapPacketCntGet(const Packet *p)
Definition: decode.c:1193
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:282
PacketAlerts_::cnt
uint16_t cnt
Definition: decode.h:289
action-globals.h
threads.h
PrintInetIPv6
const char * PrintInetIPv6(const void *src, char *dst, socklen_t size, bool compress_ipv6)
Definition: util-print.c:209
util-syslog.h
LogFileCtx_
Definition: util-logopenfile.h:77
PacketAlerts_::alerts
PacketAlert * alerts
Definition: decode.h:293
SCProtoNameValid
bool SCProtoNameValid(uint16_t proto)
Function to check if the received protocol number is valid and do we have corresponding name entry fo...
Definition: util-proto-name.c:449
AlertSyslogRegister
void AlertSyslogRegister(void)
Function to register the AlertSyslog module.
Definition: alert-syslog.c:385
SCMutexLock
#define SCMutexLock(mut)
Definition: threads-debug.h:117
tm-modules.h
IPV6_GET_L4PROTO
#define IPV6_GET_L4PROTO(p)
Definition: decode-ipv6.h:75
known_proto
const char * known_proto[256]
Definition: util-proto-name.c:39
p
Packet * p
Definition: fuzz_dataset.c:30
proto
uint8_t proto
Definition: decode-template.h:0
SCConfNodeLookupChildValue
const char * SCConfNodeLookupChildValue(const SCConfNode *node, const char *name)
Lookup the value of a child configuration node by name.
Definition: conf.c:877
TM_ECODE_FAILED
@ TM_ECODE_FAILED
Definition: tm-threads-common.h:82
GET_IPV6_DST_ADDR
#define GET_IPV6_DST_ADDR(p)
Definition: decode.h:205
Packet_::alerts
PacketAlerts alerts
Definition: decode.h:637
alert-syslog.h
Packet_::events
PacketEngineEvents events
Definition: decode.h:643
OutputCtx_::data
void * data
Definition: tm-modules.h:91
TM_ECODE_OK
@ TM_ECODE_OK
Definition: tm-threads-common.h:81
closelog
#define closelog()
Definition: win32-syslog.h:75
OutputCtx_
Definition: tm-modules.h:88
DEFAULT_ALERT_SYSLOG_FACILITY
#define DEFAULT_ALERT_SYSLOG_FACILITY
Definition: util-syslog.h:39
PacketAlert_::action
uint8_t action
Definition: decode.h:251
strlcpy
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: util-strlcpyu.c:43
Signature_::gid
uint32_t gid
Definition: detect.h:742
DEFAULT_ALERT_SYSLOG_LEVEL
#define DEFAULT_ALERT_SYSLOG_LEVEL
Definition: util-syslog.h:40
decode-ipv6.h
util-debug.h
GET_IPV4_DST_ADDR_PTR
#define GET_IPV4_DST_ADDR_PTR(p)
Definition: decode.h:200
OutputInitResult_::ctx
OutputCtx * ctx
Definition: output.h:47
strlcat
size_t strlcat(char *, const char *src, size_t siz)
Definition: util-strlcatu.c:45
SCSyslogGetFacilityMap
SCEnumCharMap * SCSyslogGetFacilityMap(void)
returns the syslog facility enum map
Definition: util-syslog.c:61
SCMutexUnlock
#define SCMutexUnlock(mut)
Definition: threads-debug.h:120
DEFAULT_ALERT_SYSLOG_FACILITY_STR
#define DEFAULT_ALERT_SYSLOG_FACILITY_STR
Definition: util-syslog.h:38
util-print.h
GET_PKT_DATA
#define GET_PKT_DATA(p)
Definition: decode.h:210
detect.h
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:57
PrintInet
const char * PrintInet(int af, const void *src, char *dst, socklen_t size)
Definition: util-print.c:238
Packet_::sp
Port sp
Definition: decode.h:523
OutputInitResult_::ok
bool ok
Definition: output.h:48
SCLogWarning
#define SCLogWarning(...)
Macro used to log WARNING messages.
Definition: util-debug.h:262
ACTION_ALERT
#define ACTION_ALERT
Definition: action-globals.h:29
Packet_
Definition: decode.h:516
GET_PKT_LEN
#define GET_PKT_LEN(p)
Definition: decode.h:209
conf.h
TmEcode
TmEcode
Definition: tm-threads-common.h:80
SCSyslogGetLogLevelMap
SCEnumCharMap * SCSyslogGetLogLevelMap(void)
returns the syslog facility enum map
Definition: util-syslog.c:79
util-proto-name.h
LogFileCtx_::compress_ipv6
bool compress_ipv6
Definition: util-logopenfile.h:156
SCLogInfo
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition: util-debug.h:232
Signature_::class_msg
char * class_msg
Definition: detect.h:767
IPV4Hdr_
Definition: decode-ipv4.h:72
decode-ipv4.h
OutputInitResult_
Definition: output.h:46
GET_IPV4_SRC_ADDR_PTR
#define GET_IPV4_SRC_ADDR_PTR(p)
Definition: decode.h:199
SCMapEnumNameToValue
int SCMapEnumNameToValue(const char *enum_name, SCEnumCharMap *table)
Maps a string name to an enum value from the supplied table. Please specify the last element of any m...
Definition: util-enum.c:40
suricata-common.h
OutputCtx_::DeInit
void(* DeInit)(struct OutputCtx_ *)
Definition: tm-modules.h:94
ACTION_DROP
#define ACTION_DROP
Definition: action-globals.h:30
OutputPacketLoggerFunctions_::LogFunc
PacketLogger LogFunc
Definition: output.h:87
OutputRegisterPacketModule
void OutputRegisterPacketModule(LoggerId id, const char *name, const char *conf_name, OutputInitFunc InitFunc, OutputPacketLoggerFunctions *output_module_functions)
Register a packet output module.
Definition: output.c:193
Signature_::rev
uint32_t rev
Definition: detect.h:743
LogFileFreeCtx
int LogFileFreeCtx(LogFileCtx *lf_ctx)
LogFileFreeCtx() Destroy a LogFileCtx (Close the file and free memory)
Definition: util-logopenfile.c:951
tv
ThreadVars * tv
Definition: fuzz_decodepcapfile.c:34
Signature_::prio
int prio
Definition: detect.h:744
threadvars.h
AlertSyslogThread_
Definition: alert-syslog.c:57
GET_IPV6_SRC_ADDR
#define GET_IPV6_SRC_ADDR(p)
Definition: decode.h:204
SCFree
#define SCFree(p)
Definition: util-mem.h:61
util-logopenfile.h
Signature_::id
uint32_t id
Definition: detect.h:741
AlertSyslogThread_::file_ctx
LogFileCtx * file_ctx
Definition: alert-syslog.c:59
EngineModeIsIPS
int EngineModeIsIPS(void)
Definition: suricata.c:247
suricata.h
PacketAlert_
Definition: decode.h:249
MODULE_NAME
#define MODULE_NAME
Definition: alert-syslog.c:53
AlertSyslogThread
struct AlertSyslogThread_ AlertSyslogThread
Signature_::msg
char * msg
Definition: detect.h:764
flow.h
openlog
#define openlog(__ident, __option, __facility)
Definition: win32-syslog.h:76
Packet_::dp
Port dp
Definition: decode.h:531
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
util-enum.h
SCConfNode_
Definition: conf.h:37
OutputPacketLoggerFunctions_
Definition: output.h:86
PrintRawLineHexBuf
void PrintRawLineHexBuf(char *retbuf, uint32_t retbuflen, const uint8_t *buf, uint32_t buflen)
print a buffer as hex on a single line into retbuf buffer
Definition: util-print.c:61
output.h
PacketEngineEvents_::cnt
uint8_t cnt
Definition: decode.h:310