suricata
alert-syslog.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2014 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 in to syslog.
24  *
25  */
26 
27 #include "suricata-common.h"
28 #include "debug.h"
29 #include "flow.h"
30 #include "conf.h"
31 
32 #include "threads.h"
33 #include "tm-threads.h"
34 #include "threadvars.h"
35 
36 #include "detect.h"
37 #include "detect-parse.h"
38 #include "detect-engine.h"
39 #include "detect-engine-mpm.h"
40 #include "detect-reference.h"
41 
42 #include "output.h"
43 #include "alert-syslog.h"
44 
46 #include "util-debug.h"
47 #include "util-print.h"
48 #include "util-proto-name.h"
49 #include "util-syslog.h"
50 #include "util-optimize.h"
51 #include "util-logopenfile.h"
52 
53 #ifndef OS_WIN32
54 
55 #define DEFAULT_ALERT_SYSLOG_FACILITY_STR "local0"
56 #define DEFAULT_ALERT_SYSLOG_FACILITY LOG_LOCAL0
57 #define DEFAULT_ALERT_SYSLOG_LEVEL LOG_ERR
58 #define MODULE_NAME "AlertSyslog"
59 
60 static int alert_syslog_level = DEFAULT_ALERT_SYSLOG_LEVEL;
61 
62 typedef struct AlertSyslogThread_ {
63  /** LogFileCtx has the pointer to the file and a mutex to allow multithreading */
66 
67 /**
68  * \brief Function to clear the memory of the output context and closes the
69  * syslog interface
70  *
71  * \param output_ctx pointer to the output context to be cleared
72  */
73 static void AlertSyslogDeInitCtx(OutputCtx *output_ctx)
74 {
75  if (output_ctx != NULL) {
76  LogFileCtx *logfile_ctx = (LogFileCtx *)output_ctx->data;
77  if (logfile_ctx != NULL) {
78  LogFileFreeCtx(logfile_ctx);
79  }
80  SCFree(output_ctx);
81  }
82  closelog();
83 }
84 
85 /**
86  * \brief Create a new LogFileCtx for "syslog" output style.
87  *
88  * \param conf The configuration node for this output.
89  * \return A OutputCtx pointer on success, NULL on failure.
90  */
91 static OutputInitResult AlertSyslogInitCtx(ConfNode *conf)
92 {
93  OutputInitResult result = { NULL, false };
94  const char *facility_s = ConfNodeLookupChildValue(conf, "facility");
95  if (facility_s == NULL) {
97  }
98 
99  LogFileCtx *logfile_ctx = LogFileNewCtx();
100  if (logfile_ctx == NULL) {
101  SCLogDebug("AlertSyslogInitCtx: Could not create new LogFileCtx");
102  return result;
103  }
104 
105  int facility = SCMapEnumNameToValue(facility_s, SCSyslogGetFacilityMap());
106  if (facility == -1) {
107  SCLogWarning(SC_ERR_INVALID_ARGUMENT, "Invalid syslog facility: \"%s\","
108  " now using \"%s\" as syslog facility", facility_s,
111  }
112 
113  const char *level_s = ConfNodeLookupChildValue(conf, "level");
114  if (level_s != NULL) {
115  int level = SCMapEnumNameToValue(level_s, SCSyslogGetLogLevelMap());
116  if (level != -1) {
117  alert_syslog_level = level;
118  }
119  }
120 
121  const char *ident = ConfNodeLookupChildValue(conf, "identity");
122  /* if null we just pass that to openlog, which will then
123  * figure it out by itself. */
124 
125  openlog(ident, LOG_PID|LOG_NDELAY, facility);
126 
127  OutputCtx *output_ctx = SCMalloc(sizeof(OutputCtx));
128  if (unlikely(output_ctx == NULL)) {
129  SCLogDebug("could not create new OutputCtx");
130  LogFileFreeCtx(logfile_ctx);
131  return result;
132  }
133  memset(output_ctx, 0x00, sizeof(OutputCtx));
134 
135  output_ctx->data = logfile_ctx;
136  output_ctx->DeInit = AlertSyslogDeInitCtx;
137 
138  SCLogInfo("Syslog output initialized");
139 
140  result.ctx = output_ctx;
141  result.ok = true;
142  return result;
143 }
144 
145 /**
146  * \brief Function to initialize the AlertSystlogThread and sets the output
147  * context pointer
148  *
149  * \param tv Pointer to the threadvars
150  * \param initdata Pointer to the output context
151  * \param data pointer to pointer to point to the AlertSyslogThread
152  */
153 static TmEcode AlertSyslogThreadInit(ThreadVars *t, const void *initdata, void **data)
154 {
155  if(initdata == NULL) {
156  SCLogDebug("Error getting context for AlertSyslog. \"initdata\" "
157  "argument NULL");
158  return TM_ECODE_FAILED;
159  }
160 
162  if (unlikely(ast == NULL))
163  return TM_ECODE_FAILED;
164 
165  memset(ast, 0, sizeof(AlertSyslogThread));
166 
167  /** Use the Ouptut Context (file pointer and mutex) */
168  ast->file_ctx = ((OutputCtx *)initdata)->data;
169 
170  *data = (void *)ast;
171  return TM_ECODE_OK;
172 }
173 
174 /**
175  * \brief Function to deinitialize the AlertSystlogThread
176  *
177  * \param tv Pointer to the threadvars
178  * \param data pointer to the AlertSyslogThread to be cleared
179  */
180 static TmEcode AlertSyslogThreadDeinit(ThreadVars *t, void *data)
181 {
182  AlertSyslogThread *ast = (AlertSyslogThread *)data;
183  if (ast == NULL) {
184  return TM_ECODE_OK;
185  }
186 
187  /* clear memory */
188  memset(ast, 0, sizeof(AlertSyslogThread));
189 
190  SCFree(ast);
191  return TM_ECODE_OK;
192 }
193 
194 /**
195  * \brief Function which is called to print the IPv4 alerts to the syslog
196  *
197  * \param tv Pointer to the threadvars
198  * \param p Pointer to the packet
199  * \param data pointer to the AlertSyslogThread
200  *
201  * \return On succes return TM_ECODE_OK
202  */
203 static TmEcode AlertSyslogIPv4(ThreadVars *tv, const Packet *p, void *data)
204 {
205  AlertSyslogThread *ast = (AlertSyslogThread *)data;
206  int i;
207  const char *action = "";
208 
209  if (p->alerts.cnt == 0)
210  return TM_ECODE_OK;
211 
212  /* Not sure if this mutex is needed around calls to syslog. */
213  SCMutexLock(&ast->file_ctx->fp_mutex);
214 
215  for (i = 0; i < p->alerts.cnt; i++) {
216  const PacketAlert *pa = &p->alerts.alerts[i];
217  if (unlikely(pa->s == NULL)) {
218  continue;
219  }
220 
221  char srcip[16], dstip[16];
222 
223  PrintInet(AF_INET, (const void *)GET_IPV4_SRC_ADDR_PTR(p), srcip, sizeof(srcip));
224  PrintInet(AF_INET, (const void *)GET_IPV4_DST_ADDR_PTR(p), dstip, sizeof(dstip));
225 
226  if ((pa->action & ACTION_DROP) && EngineModeIsIPS()) {
227  action = "[Drop] ";
228  } else if (pa->action & ACTION_DROP) {
229  action = "[wDrop] ";
230  }
231 
233  syslog(alert_syslog_level, "%s[%" PRIu32 ":%" PRIu32 ":%"
234  PRIu32 "] %s [Classification: %s] [Priority: %"PRIu32"]"
235  " {%s} %s:%" PRIu32 " -> %s:%" PRIu32 "", action, pa->s->gid,
236  pa->s->id, pa->s->rev, pa->s->msg, pa->s->class_msg, pa->s->prio,
237  known_proto[IPV4_GET_IPPROTO(p)], srcip, p->sp, dstip, p->dp);
238  } else {
239  syslog(alert_syslog_level, "%s[%" PRIu32 ":%" PRIu32 ":%"
240  PRIu32 "] %s [Classification: %s] [Priority: %"PRIu32"]"
241  " {PROTO:%03" PRIu32 "} %s:%" PRIu32 " -> %s:%" PRIu32 "",
242  action, pa->s->gid, pa->s->id, pa->s->rev, pa->s->msg, pa->s->class_msg,
243  pa->s->prio, IPV4_GET_IPPROTO(p), srcip, p->sp, dstip, p->dp);
244  }
245  }
247 
248  return TM_ECODE_OK;
249 }
250 
251 /**
252  * \brief Function which is called to print the IPv6 alerts to the syslog
253  *
254  * \param tv Pointer to the threadvars
255  * \param p Pointer to the packet
256  * \param data pointer to the AlertSyslogThread
257  *
258  * \return On succes return TM_ECODE_OK
259  */
260 static TmEcode AlertSyslogIPv6(ThreadVars *tv, const Packet *p, void *data)
261 {
262  AlertSyslogThread *ast = (AlertSyslogThread *)data;
263  int i;
264  const char *action = "";
265 
266  if (p->alerts.cnt == 0)
267  return TM_ECODE_OK;
268 
269  SCMutexLock(&ast->file_ctx->fp_mutex);
270 
271  for (i = 0; i < p->alerts.cnt; i++) {
272  const PacketAlert *pa = &p->alerts.alerts[i];
273  if (unlikely(pa->s == NULL)) {
274  continue;
275  }
276 
277  char srcip[46], dstip[46];
278 
279  PrintInet(AF_INET6, (const void *)GET_IPV6_SRC_ADDR(p), srcip, sizeof(srcip));
280  PrintInet(AF_INET6, (const void *)GET_IPV6_DST_ADDR(p), dstip, sizeof(dstip));
281 
282  if ((pa->action & ACTION_DROP) && EngineModeIsIPS()) {
283  action = "[Drop] ";
284  } else if (pa->action & ACTION_DROP) {
285  action = "[wDrop] ";
286  }
287 
289  syslog(alert_syslog_level, "%s[%" PRIu32 ":%" PRIu32 ":%"
290  "" PRIu32 "] %s [Classification: %s] [Priority: %"
291  "" PRIu32 "] {%s} %s:%" PRIu32 " -> %s:%" PRIu32 "",
292  action, pa->s->gid, pa->s->id, pa->s->rev, pa->s->msg, pa->s->class_msg,
293  pa->s->prio, known_proto[IPV6_GET_L4PROTO(p)], srcip, p->sp,
294  dstip, p->dp);
295 
296  } else {
297  syslog(alert_syslog_level, "%s[%" PRIu32 ":%" PRIu32 ":%"
298  "" PRIu32 "] %s [Classification: %s] [Priority: %"
299  "" PRIu32 "] {PROTO:%03" PRIu32 "} %s:%" PRIu32 " -> %s:%" PRIu32 "",
300  action, pa->s->gid, pa->s->id, pa->s->rev, pa->s->msg, pa->s->class_msg,
301  pa->s->prio, IPV6_GET_L4PROTO(p), srcip, p->sp, dstip, p->dp);
302  }
303 
304  }
306 
307  return TM_ECODE_OK;
308 }
309 
310 /**
311  * \brief Function which is called to print the decode alerts to the syslog
312  *
313  * \param tv Pointer to the threadvars
314  * \param p Pointer to the packet
315  * \param data pointer to the AlertSyslogThread
316  *
317  * \return On succes return TM_ECODE_OK
318  */
319 static TmEcode AlertSyslogDecoderEvent(ThreadVars *tv, const Packet *p, void *data)
320 {
321  AlertSyslogThread *ast = (AlertSyslogThread *)data;
322  int i;
323  const char *action = "";
324 
325  if (p->alerts.cnt == 0)
326  return TM_ECODE_OK;
327 
328  SCMutexLock(&ast->file_ctx->fp_mutex);
329 
330  char temp_buf_hdr[512];
331  char temp_buf_pkt[65] = "";
332  char temp_buf_tail[32];
333  char alert[2048] = "";
334 
335  for (i = 0; i < p->alerts.cnt; i++) {
336  const PacketAlert *pa = &p->alerts.alerts[i];
337  if (unlikely(pa->s == NULL)) {
338  continue;
339  }
340 
341  if ((pa->action & ACTION_DROP) && EngineModeIsIPS()) {
342  action = "[Drop] ";
343  } else if (pa->action & ACTION_DROP) {
344  action = "[wDrop] ";
345  }
346 
347  snprintf(temp_buf_hdr, sizeof(temp_buf_hdr), "%s[%" PRIu32 ":%" PRIu32
348  ":%" PRIu32 "] %s [Classification: %s] [Priority: %" PRIu32
349  "] [**] [Raw pkt: ", action, pa->s->gid, pa->s->id, pa->s->rev, pa->s->msg,
350  pa->s->class_msg, pa->s->prio);
351  strlcpy(alert, temp_buf_hdr, sizeof(alert));
352 
353  PrintRawLineHexBuf(temp_buf_pkt, sizeof(temp_buf_pkt), GET_PKT_DATA(p), GET_PKT_LEN(p) < 32 ? GET_PKT_LEN(p) : 32);
354  strlcat(alert, temp_buf_pkt, sizeof(alert));
355 
356  if (p->pcap_cnt != 0) {
357  snprintf(temp_buf_tail, sizeof(temp_buf_tail), "] [pcap file packet: %"PRIu64"]",
358  p->pcap_cnt);
359  } else {
360  temp_buf_tail[0] = ']';
361  temp_buf_tail[1] = '\0';
362  }
363  strlcat(alert, temp_buf_tail, sizeof(alert));
364 
365  syslog(alert_syslog_level, "%s", alert);
366  }
368 
369  return TM_ECODE_OK;
370 }
371 
372 static int AlertSyslogCondition(ThreadVars *tv, const Packet *p)
373 {
374  return (p->alerts.cnt > 0 ? TRUE : FALSE);
375 }
376 
377 static int AlertSyslogLogger(ThreadVars *tv, void *thread_data, const Packet *p)
378 {
379  if (PKT_IS_IPV4(p)) {
380  return AlertSyslogIPv4(tv, p, thread_data);
381  } else if (PKT_IS_IPV6(p)) {
382  return AlertSyslogIPv6(tv, p, thread_data);
383  } else if (p->events.cnt > 0) {
384  return AlertSyslogDecoderEvent(tv, p, thread_data);
385  }
386 
387  return TM_ECODE_OK;
388 }
389 
390 #endif /* !OS_WIN32 */
391 
392 /** \brief Function to register the AlertSyslog module */
394 {
395 #ifndef OS_WIN32
397  AlertSyslogInitCtx, AlertSyslogLogger, AlertSyslogCondition,
398  AlertSyslogThreadInit, AlertSyslogThreadDeinit, NULL);
399 #endif /* !OS_WIN32 */
400 }
#define GET_IPV4_SRC_ADDR_PTR(p)
Definition: decode.h:215
char * known_proto[256]
void PrintRawLineHexBuf(char *retbuf, uint32_t retbuflen, uint8_t *buf, uint32_t buflen)
print a buffer as hex on a single line in to retbuf buffer
Definition: util-print.c:61
uint8_t SCProtoNameValid(uint16_t proto)
Function to check if the received protocol number is valid and do we have corresponding name entry fo...
#define SCLogDebug(...)
Definition: util-debug.h:335
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: util-strlcpyu.c:43
char * msg
Definition: detect.h:580
uint32_t id
Definition: detect.h:555
#define FALSE
#define IPV4_GET_IPPROTO(p)
Definition: decode-ipv4.h:148
#define DEFAULT_ALERT_SYSLOG_LEVEL
Definition: alert-syslog.c:57
#define unlikely(expr)
Definition: util-optimize.h:35
#define GET_IPV4_DST_ADDR_PTR(p)
Definition: decode.h:216
Port sp
Definition: decode.h:416
int prio
Definition: detect.h:558
Port dp
Definition: decode.h:424
uint8_t action
Definition: decode.h:272
size_t strlcat(char *, const char *src, size_t siz)
Definition: util-strlcatu.c:45
#define PKT_IS_IPV6(p)
Definition: decode.h:253
SCEnumCharMap * SCSyslogGetFacilityMap(void)
returns the syslog facility enum map
Definition: util-syslog.c:57
void(* DeInit)(struct OutputCtx_ *)
Definition: tm-modules.h:84
#define MODULE_NAME
Definition: alert-syslog.c:58
void AlertSyslogRegister(void)
Function to register the AlertSyslog module.
Definition: alert-syslog.c:393
uint64_t pcap_cnt
Definition: decode.h:562
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:41
int EngineModeIsIPS(void)
Definition: suricata.c:247
#define TRUE
#define SCMutexLock(mut)
#define PKT_IS_IPV4(p)
Definition: decode.h:252
PacketAlert alerts[PACKET_ALERT_MAX]
Definition: decode.h:295
const struct Signature_ * s
Definition: decode.h:274
#define openlog(__ident, __option, __facility)
Definition: win32-syslog.h:76
const char * ConfNodeLookupChildValue(const ConfNode *node, const char *name)
Lookup the value of a child configuration node by name.
Definition: conf.c:843
void OutputRegisterPacketModule(LoggerId id, const char *name, const char *conf_name, OutputInitFunc InitFunc, PacketLogger PacketLogFunc, PacketLogCondition PacketConditionFunc, ThreadInitFunc ThreadInit, ThreadDeinitFunc ThreadDeinit, ThreadExitPrintStatsFunc ThreadExitPrintStats)
Register a packet output module.
Definition: output.c:163
#define SCMutexUnlock(mut)
#define GET_IPV6_DST_ADDR(p)
Definition: decode.h:221
SCMutex fp_mutex
PacketEngineEvents events
Definition: decode.h:566
LogFileCtx * LogFileNewCtx(void)
LogFileNewCtx() Get a new LogFileCtx.
#define DEFAULT_ALERT_SYSLOG_FACILITY
Definition: alert-syslog.c:56
const char * PrintInet(int af, const void *src, char *dst, socklen_t size)
Definition: util-print.c:267
uint32_t gid
Definition: detect.h:556
#define closelog()
Definition: win32-syslog.h:75
#define SCLogWarning(err_code,...)
Macro used to log WARNING messages.
Definition: util-debug.h:281
#define IPV6_GET_L4PROTO(p)
Definition: decode-ipv6.h:93
char * class_msg
Definition: detect.h:583
Definition: conf.h:32
OutputCtx * ctx
Definition: output.h:42
#define SCMalloc(a)
Definition: util-mem.h:222
#define GET_IPV6_SRC_ADDR(p)
Definition: decode.h:220
int LogFileFreeCtx(LogFileCtx *lf_ctx)
LogFileFreeCtx() Destroy a LogFileCtx (Close the file and free memory)
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition: util-debug.h:254
#define SCFree(a)
Definition: util-mem.h:322
SCEnumCharMap * SCSyslogGetLogLevelMap(void)
returns the syslog facility enum map
Definition: util-syslog.c:75
void * data
Definition: tm-modules.h:81
uint32_t rev
Definition: detect.h:557
PacketAlerts alerts
Definition: decode.h:556
#define syslog(__pri, __fmt, __param)
Definition: win32-syslog.h:78
#define GET_PKT_DATA(p)
Definition: decode.h:226
#define DEFAULT_ALERT_SYSLOG_FACILITY_STR
Definition: alert-syslog.c:55
uint16_t cnt
Definition: decode.h:294
Per thread variable structure.
Definition: threadvars.h:57
#define GET_PKT_LEN(p)
Definition: decode.h:225
#define ACTION_DROP
LogFileCtx * file_ctx
Definition: alert-syslog.c:64
struct AlertSyslogThread_ AlertSyslogThread