suricata
alert-prelude.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2017 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 Pierre Chifflier <chifflier@edenwall.com>
22  * \author Yoann Vandoorselaere <yoann.v@prelude-ids.com>
23  *
24  * Logs alerts to the Prelude system, using IDMEF (RFC 4765) messages.
25  *
26  * Each message contains the alert description and reference (using
27  * the SID/GID), and a normalized description (assessment, impact,
28  * sources etc.)
29  *
30  * libprelude handles the connection with the manager (collecting component),
31  * spooling and sending the event asynchronously. It also offers transport
32  * security (using TLS and trusted certificates) and reliability (events
33  * are retransmitted if not sent successfully).
34  *
35  * This modules requires a Prelude profile to work (see man prelude-admin
36  * and the Prelude Handbook for help).
37  */
38 
39 #include "suricata-common.h"
40 #include "debug.h"
41 #include "detect.h"
42 #include "flow.h"
43 #include "conf.h"
44 
45 #include "threads.h"
46 #include "threadvars.h"
47 #include "tm-threads.h"
48 
49 #include "util-unittest.h"
50 #include "util-time.h"
51 #include "util-debug.h"
52 #include "util-error.h"
53 #include "util-print.h"
54 
55 #include "output.h"
56 
57 #ifdef HAVE_LIBJANSSON
58 #include "output-json.h"
59 #include "output-json-http.h"
60 #include "output-json-tls.h"
61 #include "output-json-ssh.h"
62 #include "output-json-smtp.h"
64 #include <jansson.h>
65 #endif
66 
67 #include "util-privs.h"
68 #include "util-optimize.h"
69 
70 #include "stream.h"
71 
72 #include "alert-prelude.h"
73 
74 #ifndef PRELUDE
75 
76 /* Handle the case where no PRELUDE support is compiled in. */
77 
78 void AlertPreludeRegister(void)
79 {
80  SCLogDebug("Can't register Prelude output thread - Prelude support was disabled during build.");
81 }
82 
83 #else /* implied we do have PRELUDE support */
84 
85 #include <libprelude/prelude.h>
86 
87 #define ANALYZER_CLASS "NIDS"
88 #define ANALYZER_MODEL "Suricata"
89 #define ANALYZER_MANUFACTURER "http://www.openinfosecfoundation.org/"
90 #define ANALYZER_SID_URL "http://www.snort.org/search/sid/"
91 
92 #define SNORT_MAX_OWNED_SID 1000000
93 #define DEFAULT_ANALYZER_NAME "suricata"
94 
95 #define DEFAULT_PRELUDE_PROFILE "suricata"
96 
97 static unsigned int info_priority = 4;
98 static unsigned int low_priority = 3;
99 static unsigned int mid_priority = 2;
100 
101 /**
102  * This holds global structures and variables. Since libprelude is thread-safe,
103  * there is no need to store a mutex.
104  */
105 typedef struct AlertPreludeCtx_ {
106  /** The client (which has the send function) */
107  prelude_client_t *client;
111 
112 /**
113  * This holds per-thread specific structures and variables.
114  */
115 typedef struct AlertPreludeThread_ {
116  /** Pointer to the global context */
118  idmef_analyzer_t *analyzer;
120 
121 
122 /**
123  * \brief Initialize analyzer description
124  *
125  * \return 0 if ok
126  */
127 static int SetupAnalyzer(idmef_analyzer_t *analyzer)
128 {
129  int ret;
130  prelude_string_t *string;
131 
132  SCEnter();
133 
134  ret = idmef_analyzer_new_model(analyzer, &string);
135  if (unlikely(ret < 0)) {
136  SCLogDebug("%s: error creating analyzer model: %s.",
137  prelude_strsource(ret), prelude_strerror(ret));
138  SCReturnInt(ret);
139  }
140  ret = prelude_string_set_constant(string, ANALYZER_MODEL);
141  if (unlikely(ret < 0)) {
142  SCLogDebug("%s: error setting analyzer model: %s.",
143  prelude_strsource(ret), prelude_strerror(ret));
144  SCReturnInt(ret);
145  }
146 
147  ret = idmef_analyzer_new_class(analyzer, &string);
148  if (unlikely(ret < 0)) {
149  SCLogDebug("%s: error creating analyzer class: %s.",
150  prelude_strsource(ret), prelude_strerror(ret));
151  SCReturnInt(ret);
152  }
153  ret = prelude_string_set_constant(string, ANALYZER_CLASS);
154  if (unlikely(ret < 0)) {
155  SCLogDebug("%s: error setting analyzer class: %s.",
156  prelude_strsource(ret), prelude_strerror(ret));
157  SCReturnInt(ret);
158  }
159 
160  ret = idmef_analyzer_new_manufacturer(analyzer, &string);
161  if (unlikely(ret < 0)) {
162  SCLogDebug("%s: error creating analyzer manufacturer: %s.",
163  prelude_strsource(ret), prelude_strerror(ret));
164  SCReturnInt(ret);
165  }
166  ret = prelude_string_set_constant(string, ANALYZER_MANUFACTURER);
167  if (unlikely(ret < 0)) {
168  SCLogDebug("%s: error setting analyzer manufacturer: %s.",
169  prelude_strsource(ret), prelude_strerror(ret));
170  SCReturnInt(ret);
171  }
172 
173  ret = idmef_analyzer_new_version(analyzer, &string);
174  if (unlikely(ret < 0)) {
175  SCLogDebug("%s: error creating analyzer version: %s.",
176  prelude_strsource(ret), prelude_strerror(ret));
177  SCReturnInt(ret);
178  }
179  ret = prelude_string_set_constant(string, VERSION);
180  if (unlikely(ret < 0)) {
181  SCLogDebug("%s: error setting analyzer version: %s.",
182  prelude_strsource(ret), prelude_strerror(ret));
183  SCReturnInt(ret);
184  }
185 
186  SCReturnInt(0);
187 }
188 
189 /**
190  * \brief Create event impact description (see section
191  * 4.2.6.1 of RFC 4765).
192  * The impact contains the severity, completion (succeeded or failed)
193  * and basic classification of the attack type.
194  * Here, we don't set the completion since we don't know it (default
195  * is unknown).
196  *
197  * \return 0 if ok
198  */
199 static int EventToImpact(const PacketAlert *pa, const Packet *p, idmef_alert_t *alert)
200 {
201  int ret;
202  prelude_string_t *str;
203  idmef_impact_t *impact;
204  idmef_assessment_t *assessment;
205  idmef_impact_severity_t severity;
206 
207  SCEnter();
208 
209  ret = idmef_alert_new_assessment(alert, &assessment);
210  if (unlikely(ret < 0)) {
211  SCLogDebug("%s: error creating assessment: %s.",
212  prelude_strsource(ret), prelude_strerror(ret));
213  SCReturnInt(ret);
214  }
215 
216  ret = idmef_assessment_new_impact(assessment, &impact);
217  if (unlikely(ret < 0)) {
218  SCLogDebug("%s: error creating assessment impact: %s.",
219  prelude_strsource(ret), prelude_strerror(ret));
220  SCReturnInt(ret);
221  }
222 
223  if ( (unsigned int)pa->s->prio < mid_priority )
224  severity = IDMEF_IMPACT_SEVERITY_HIGH;
225 
226  else if ( (unsigned int)pa->s->prio < low_priority )
227  severity = IDMEF_IMPACT_SEVERITY_MEDIUM;
228 
229  else if ( (unsigned int)pa->s->prio < info_priority )
230  severity = IDMEF_IMPACT_SEVERITY_LOW;
231 
232  else
233  severity = IDMEF_IMPACT_SEVERITY_INFO;
234 
235  idmef_impact_set_severity(impact, severity);
236 
241  idmef_action_t *action;
242 
243  ret = idmef_action_new(&action);
244  if (unlikely(ret < 0))
245  SCReturnInt(ret);
246 
247  idmef_action_set_category(action, IDMEF_ACTION_CATEGORY_BLOCK_INSTALLED);
248  idmef_assessment_set_action(assessment, action, 0);
249  }
250 
251  if (pa->s->msg) {
252  ret = idmef_impact_new_description(impact, &str);
253  if (unlikely(ret < 0))
254  SCReturnInt(ret);
255 
256  prelude_string_set_ref(str, pa->s->msg);
257  }
258 
259  SCReturnInt(0);
260 }
261 
262 /**
263  * \brief Add Source and Target fields to the IDMEF alert.
264  * These objects contains IP addresses, source and destination
265  * ports (see sections 4.2.4.3 and 4.2.4.4 of RFC 4765).
266  *
267  * \return 0 if ok
268  */
269 static int EventToSourceTarget(const PacketAlert *pa, const Packet *p,
270  idmef_alert_t *alert)
271 {
272  int ret;
273  idmef_node_t *node;
274  idmef_source_t *source;
275  idmef_target_t *target;
276  idmef_address_t *address;
277  idmef_service_t *service;
278  prelude_string_t *string;
279  static char saddr[128], daddr[128];
280  uint8_t ip_vers;
281  uint8_t ip_proto;
282  uint16_t sp, dp;
283  uint8_t invert = 0;
284 
285  SCEnter();
286 
287  if ( !p )
288  SCReturnInt(0);
289 
290  if ( ! IPH_IS_VALID(p) )
291  SCReturnInt(0);
292 
293  if (pa->s->flags & SIG_FLAG_HAS_TARGET) {
294  if (pa->s->flags & SIG_FLAG_SRC_IS_TARGET) {
295  invert = 1;
296  } else {
297  invert = 0;
298  }
299  } else {
300  invert = 0;
301  }
302 
303  if (PKT_IS_IPV4(p)) {
304  ip_vers = 4;
305  ip_proto = IPV4_GET_RAW_IPPROTO(p->ip4h);
306  if (invert) {
307  PrintInet(AF_INET, (const void *)GET_IPV4_DST_ADDR_PTR(p), saddr, sizeof(saddr));
308  PrintInet(AF_INET, (const void *)GET_IPV4_SRC_ADDR_PTR(p), daddr, sizeof(daddr));
309  sp = p->dp;
310  dp = p->sp;
311  } else {
312  PrintInet(AF_INET, (const void *)GET_IPV4_SRC_ADDR_PTR(p), saddr, sizeof(saddr));
313  PrintInet(AF_INET, (const void *)GET_IPV4_DST_ADDR_PTR(p), daddr, sizeof(daddr));
314  sp = p->sp;
315  dp = p->dp;
316 
317  }
318  } else if (PKT_IS_IPV6(p)) {
319  ip_vers = 6;
320  ip_proto = IPV6_GET_L4PROTO(p);
321  if (invert) {
322  PrintInet(AF_INET6, (const void *)GET_IPV6_DST_ADDR(p), saddr, sizeof(saddr));
323  PrintInet(AF_INET6, (const void *)GET_IPV6_SRC_ADDR(p), daddr, sizeof(daddr));
324  sp = p->dp;
325  dp = p->sp;
326  } else {
327  PrintInet(AF_INET6, (const void *)GET_IPV6_SRC_ADDR(p), saddr, sizeof(saddr));
328  PrintInet(AF_INET6, (const void *)GET_IPV6_DST_ADDR(p), daddr, sizeof(daddr));
329  sp = p->sp;
330  dp = p->dp;
331  }
332  } else
333  SCReturnInt(0);
334 
335  ret = idmef_alert_new_source(alert, &source, IDMEF_LIST_APPEND);
336  if (unlikely(ret < 0))
337  SCReturnInt(ret);
338 
339  ret = idmef_source_new_service(source, &service);
340  if (unlikely(ret < 0))
341  SCReturnInt(ret);
342 
343  if ( p->tcph || p->udph )
344  idmef_service_set_port(service, sp);
345 
346  idmef_service_set_ip_version(service, ip_vers);
347  idmef_service_set_iana_protocol_number(service, ip_proto);
348 
349  ret = idmef_source_new_node(source, &node);
350  if (unlikely(ret < 0))
351  SCReturnInt(ret);
352 
353  ret = idmef_node_new_address(node, &address, IDMEF_LIST_APPEND);
354  if (unlikely(ret < 0))
355  SCReturnInt(ret);
356 
357  ret = idmef_address_new_address(address, &string);
358  if (unlikely(ret < 0))
359  SCReturnInt(ret);
360 
361  prelude_string_set_ref(string, saddr);
362 
363  ret = idmef_alert_new_target(alert, &target, IDMEF_LIST_APPEND);
364  if (unlikely(ret < 0))
365  SCReturnInt(ret);
366 
367  ret = idmef_target_new_service(target, &service);
368  if (unlikely(ret < 0))
369  SCReturnInt(ret);
370 
371  if ( p->tcph || p->udph )
372  idmef_service_set_port(service, dp);
373 
374  idmef_service_set_ip_version(service, ip_vers);
375  idmef_service_set_iana_protocol_number(service, ip_proto);
376 
377  ret = idmef_target_new_node(target, &node);
378  if (unlikely(ret < 0))
379  SCReturnInt(ret);
380 
381  ret = idmef_node_new_address(node, &address, IDMEF_LIST_APPEND);
382  if (unlikely(ret < 0))
383  SCReturnInt(ret);
384 
385  ret = idmef_address_new_address(address, &string);
386  if (unlikely(ret < 0))
387  SCReturnInt(ret);
388 
389  prelude_string_set_ref(string, daddr);
390 
391  SCReturnInt(0);
392 }
393 
394 /**
395  * \brief Add binary data, to be stored in the Additional Data
396  * field of the IDMEF alert (see section 4.2.4.6 of RFC 4765).
397  *
398  * \return 0 if ok
399  */
400 static int AddByteData(idmef_alert_t *alert, const char *meaning, const unsigned char *data, size_t size)
401 {
402  int ret;
403  prelude_string_t *str;
404  idmef_additional_data_t *ad;
405 
406  SCEnter();
407 
408  if ( ! data || ! size )
409  SCReturnInt(0);
410 
411  ret = idmef_alert_new_additional_data(alert, &ad, IDMEF_LIST_APPEND);
412  if (unlikely(ret < 0))
413  SCReturnInt(0);
414 
415  ret = idmef_additional_data_set_byte_string_ref(ad, data, size);
416  if (unlikely(ret < 0)) {
417  SCLogDebug("%s: error setting byte string data: %s.",
418  prelude_strsource(ret), prelude_strerror(ret));
419  SCReturnInt(-1);
420  }
421 
422  ret = idmef_additional_data_new_meaning(ad, &str);
423  if (unlikely(ret < 0)) {
424  SCLogDebug("%s: error creating additional-data meaning: %s.",
425  prelude_strsource(ret), prelude_strerror(ret));
426  SCReturnInt(-1);
427  }
428 
429  ret = prelude_string_set_ref(str, meaning);
430  if (unlikely(ret < 0)) {
431  SCLogDebug("%s: error setting byte string data meaning: %s.",
432  prelude_strsource(ret), prelude_strerror(ret));
433  SCReturnInt(-1);
434  }
435 
436  SCReturnInt(0);
437 }
438 
439 /**
440  * \brief Add integer data, to be stored in the Additional Data
441  * field of the IDMEF alert (see section 4.2.4.6 of RFC 4765).
442  *
443  * \return 0 if ok
444  */
445 static int AddIntData(idmef_alert_t *alert, const char *meaning, uint32_t data)
446 {
447  int ret;
448  prelude_string_t *str;
449  idmef_additional_data_t *ad;
450 
451  SCEnter();
452 
453  ret = idmef_alert_new_additional_data(alert, &ad, IDMEF_LIST_APPEND);
454  if (unlikely(ret < 0))
455  SCReturnInt(ret);
456 
457  idmef_additional_data_set_integer(ad, data);
458 
459  ret = idmef_additional_data_new_meaning(ad, &str);
460  if (unlikely(ret < 0)) {
461  SCLogDebug("%s: error creating additional-data meaning: %s.",
462  prelude_strsource(ret), prelude_strerror(ret));
463  SCReturnInt(-1);
464  }
465 
466  ret = prelude_string_set_ref(str, meaning);
467  if (unlikely(ret < 0)) {
468  SCLogDebug("%s: error setting integer data meaning: %s.",
469  prelude_strsource(ret), prelude_strerror(ret));
470  SCReturnInt(-1);
471  }
472 
473  SCReturnInt(0);
474 }
475 
476 #ifdef HAVE_LIBJANSSON
477 /**
478  * \brief Add string data, to be stored in the Additional Data
479  * field of the IDMEF alert (see section 4.2.4.6 of RFC 4765).
480  * \param alert IDMEF alert where to add additional data
481  * \param meaning Name of the value to add to IDMEF alert
482  * \param data String to add to IDMEF alert
483  * \return 0 if ok, else < 0
484  */
485 static int AddStringData(idmef_alert_t *alert, const char *meaning, const char *data)
486 {
487  int ret;
488  idmef_additional_data_t *ad;
489  prelude_string_t * p_str;
490 
491  SCEnter();
492 
493  ret = idmef_alert_new_additional_data(alert, &ad, IDMEF_LIST_APPEND);
494  if (unlikely(ret < 0))
495  SCReturnInt(ret);
496 
497  ret = idmef_additional_data_new_meaning(ad, &p_str);
498  if (ret < 0) {
499  idmef_additional_data_destroy(ad);
500  SCReturnInt(ret);
501  }
502 
503  ret = prelude_string_ncat(p_str, meaning, strlen(meaning));
504  if (ret < 0) {
505  idmef_additional_data_destroy(ad);
506  SCReturnInt(ret);
507  }
508 
509  ret = prelude_string_new(&p_str);
510  if (ret < 0) {
511  idmef_additional_data_destroy(ad);
512  SCReturnInt(ret);
513  }
514 
515  ret = prelude_string_ncat(p_str, data, strlen(data));
516  if (ret < 0) {
517  prelude_string_destroy(p_str);
518  idmef_additional_data_destroy(ad);
519  SCReturnInt(ret);
520  }
521 
522  ret = idmef_additional_data_set_string_dup_fast(ad, prelude_string_get_string(p_str), prelude_string_get_len(p_str));
523 
524  prelude_string_destroy(p_str);
525 
526  if (ret < 0) {
527  idmef_additional_data_destroy(ad);
528  SCReturnInt(ret);
529  }
530  SCReturnInt(0);
531 }
532 
533 /**
534  * \brief Add real data, to be stored in the Additional Data
535  * field of the IDMEF alert (see section 4.2.4.6 of RFC 4765).
536  * \param alert IDMEF alert where to add additional data
537  * \param meaning Name of the value to add to IDMEF alert
538  * \param data Real to add to IDMEF alert
539  * \return 0 if ok
540  */
541 static int AddRealData(idmef_alert_t *alert, const char *meaning, uint32_t data)
542 {
543  int ret;
544  prelude_string_t *str;
545  idmef_additional_data_t *ad;
546 
547  SCEnter();
548 
549  ret = idmef_alert_new_additional_data(alert, &ad, IDMEF_LIST_APPEND);
550  if (unlikely(ret < 0))
551  SCReturnInt(ret);
552 
553  idmef_additional_data_set_real(ad, data);
554 
555  ret = idmef_additional_data_new_meaning(ad, &str);
556  if (unlikely(ret < 0)) {
557  SCLogDebug("%s: error creating additional-data meaning: %s.",
558  prelude_strsource(ret), prelude_strerror(ret));
559  SCReturnInt(-1);
560  }
561 
562  ret = prelude_string_set_ref(str, meaning);
563  if (unlikely(ret < 0)) {
564  SCLogDebug("%s: error setting integer data meaning: %s.",
565  prelude_strsource(ret), prelude_strerror(ret));
566  SCReturnInt(-1);
567  }
568 
569  SCReturnInt(0);
570 }
571 #endif
572 
573 /**
574  * \brief Add IPv4 header data, to be stored in the Additional Data
575  * field of the IDMEF alert (see section 4.2.4.6 of RFC 4765).
576  *
577  * \return 0 if ok
578  */
579 static int PacketToDataV4(const Packet *p, const PacketAlert *pa, idmef_alert_t *alert)
580 {
581  SCEnter();
582 
583  AddIntData(alert, "ip_ver", IPV4_GET_RAW_VER(p->ip4h));
584  AddIntData(alert, "ip_hlen", IPV4_GET_RAW_HLEN(p->ip4h));
585  AddIntData(alert, "ip_tos", IPV4_GET_RAW_IPTOS(p->ip4h));
586  AddIntData(alert, "ip_len", SCNtohs(IPV4_GET_RAW_IPLEN(p->ip4h)));
587 
588  AddIntData(alert, "ip_id", SCNtohs(IPV4_GET_RAW_IPID(p->ip4h)));
589 
590  AddIntData(alert, "ip_off", SCNtohs(IPV4_GET_RAW_IPOFFSET(p->ip4h)));
591 
592  AddIntData(alert, "ip_ttl", IPV4_GET_RAW_IPTTL(p->ip4h));
593  AddIntData(alert, "ip_proto", IPV4_GET_RAW_IPPROTO(p->ip4h));
594 
595  AddIntData(alert, "ip_sum", SCNtohs(p->ip4h->ip_csum));
596 
597  SCReturnInt(0);
598 }
599 
600 /**
601  * \brief Add IPv6 header data, to be stored in the Additional Data
602  * field of the IDMEF alert (see section 4.2.4.6 of RFC 4765).
603  *
604  * \return 0 if ok
605  */
606 static int PacketToDataV6(const Packet *p, const PacketAlert *pa, idmef_alert_t *alert)
607 {
608  SCEnter();
609 
610  AddIntData(alert, "ip_ver", IPV6_GET_VER(p));
611  AddIntData(alert, "ip_class", IPV6_GET_CLASS(p));
612  AddIntData(alert, "ip_flow", IPV6_GET_FLOW(p));
613  AddIntData(alert, "ip_nh", IPV6_GET_NH(p));
614  AddIntData(alert, "ip_plen", IPV6_GET_PLEN(p));
615  AddIntData(alert, "ip_hlim", IPV6_GET_HLIM(p));
616  AddIntData(alert, "ip_proto", IPV6_GET_L4PROTO(p));
617 
618  SCReturnInt(0);
619 }
620 
621 #ifdef HAVE_LIBJANSSON
622 /**
623  * \brief Convert JSON object to Prelude additional data with
624  * the right type of data. Browse the JSON object to get
625  * the key=value information.
626  * \param key Name of the JSON value
627  * \param value JSON object to add to the IDMEF alert
628  * \param alert IDMEF alert
629  * \return 0 if ok
630  */
631 static int JsonToAdditionalData(const char * key, json_t * value, idmef_alert_t *alert)
632 {
633  SCEnter();
634 
635  int ret = 0;
636  const char *key_js;
637  char local_key[128];
638  json_t *value_js;
639  size_t index;
640 
641  if (!json_is_object(value) && key == NULL)
642  SCReturnInt(-1);
643 
644  if (json_is_object(value)) {
645  json_object_foreach(value, key_js, value_js) {
646  if (key != NULL) {
647  snprintf(local_key, sizeof(local_key), "%s_%s", key, key_js);
648  } else {
649  snprintf(local_key, sizeof(local_key), "%s", key_js);
650  }
651  ret = JsonToAdditionalData(local_key, value_js, alert);
652  }
653  } else if (json_is_array(value)) {
654  json_array_foreach(value, index, value_js) {
655  ret = snprintf(local_key, sizeof(local_key), "%s_%ju", key, (uintmax_t)index);
656  if (ret < 0 || (size_t)ret >= sizeof(local_key)) {
657  SCLogError(SC_ERR_SPRINTF,"failed to construct key");
658  continue;
659  }
660  ret = JsonToAdditionalData(local_key, value_js, alert);
661  }
662  } else if (json_is_integer(value)) {
663  ret = AddIntData(alert, key, json_integer_value(value));
664  } else if (json_is_real(value)) {
665  ret = AddRealData(alert, key, json_real_value(value));
666  } else if (json_is_boolean(value)) {
667  ret = AddIntData(alert, key, json_is_true(value));
668  } else if (json_is_string(value)) {
669  ret = AddStringData(alert, key, json_string_value(value));
670  } else {
671  ret = AddStringData(alert, key, json_dumps(value, 0));
672  }
673  SCReturnInt(ret);
674 }
675 
676 /**
677  * \brief Handle ALPROTO_HTTP JSON information
678  * \param p Packet where to extract data
679  * \param pa Packet alert information
680  * \param alert IDMEF alert
681  * \return void
682  */
683 static void PacketToDataProtoHTTP(const Packet *p, const PacketAlert *pa, idmef_alert_t *alert)
684 {
685  json_t *js;
686 
687  js = JsonHttpAddMetadata(p->flow, pa->tx_id);
688  if (js == NULL)
689  return;
690 
691  JsonToAdditionalData(NULL, js, alert);
692 
693  json_decref(js);
694 
695 }
696 
697 /**
698  * \brief Handle ALPROTO_TLS JSON information
699  * \param p Packet where to extract data
700  * \param pa Packet alert information
701  * \param alert IDMEF alert
702  * \return void
703  */
704 static void PacketToDataProtoTLS(const Packet *p, const PacketAlert *pa, idmef_alert_t *alert)
705 {
706  json_t *js;
707  SSLState *ssl_state = (SSLState *)FlowGetAppState(p->flow);
708 
709  if (ssl_state == NULL)
710  return;
711 
712  js = json_object();
713  if (js == NULL)
714  return;
715 
716  JsonTlsLogJSONBasic(js, ssl_state);
717  JsonTlsLogJSONExtended(js, ssl_state);
718  JsonToAdditionalData(NULL, js, alert);
719 
720  json_decref(js);
721 
722 }
723 
724 /**
725  * \brief Handle ALPROTO_SSH JSON information
726  * \param p Packet where to extract data
727  * \param pa Packet alert information
728  * \param alert IDMEF alert
729  * \return void
730  */
731 static void PacketToDataProtoSSH(const Packet *p, const PacketAlert *pa, idmef_alert_t *alert)
732 {
733  json_t *js, *s_js;
734  SshState *ssh_state = (SshState *)FlowGetAppState(p->flow);
735 
736  if (ssh_state == NULL)
737  return;
738 
739  js = json_object();
740  if (js == NULL)
741  return;
742 
743  JsonSshLogJSON(js, ssh_state);
744 
745  s_js = json_object_get(js, "server");
746  if (s_js != NULL) {
747  JsonToAdditionalData(NULL, s_js, alert);
748  }
749 
750  s_js = json_object_get(js, "client");
751  if (s_js != NULL) {
752  JsonToAdditionalData(NULL, s_js, alert);
753  }
754 
755  json_decref(js);
756 
757 }
758 
759 /**
760  * \brief Handle ALPROTO_SMTP JSON information
761  * \param p Packet where to extract data
762  * \param pa Packet alert information
763  * \param alert IDMEF alert
764  * \return void
765  */
766 static void PacketToDataProtoSMTP(const Packet *p, const PacketAlert *pa, idmef_alert_t *alert)
767 {
768  json_t *js;
769 
770  js = JsonSMTPAddMetadata(p->flow, pa->tx_id);
771  if (js == NULL)
772  return;
773 
774  JsonToAdditionalData(NULL, js, alert);
775 
776  json_decref(js);
777 
778 }
779 
780 /**
781  * \brief Handle ALPROTO_(SMTP|IMAP) Email JSON information
782  * \param p Packet where to extract data
783  * \param pa Packet alert information
784  * \param alert IDMEF alert
785  * \return void
786  */
787 static void PacketToDataProtoEmail(const Packet *p, const PacketAlert *pa, idmef_alert_t *alert)
788 {
789  json_t *js;
790 
791  js = JsonEmailAddMetadata(p->flow, pa->tx_id);
792  if (js == NULL)
793  return;
794 
795  JsonToAdditionalData(NULL, js, alert);
796 
797  json_decref(js);
798 
799 }
800 
801 #endif
802 
803 /**
804  * \brief Convert IP packet to an IDMEF alert (RFC 4765).
805  * This function stores the alert SID (description and reference),
806  * the payload of the packet, and pre-processed data.
807  *
808  * \return 0 if ok
809  */
810 static int PacketToData(const Packet *p, const PacketAlert *pa, idmef_alert_t *alert, AlertPreludeCtx *ctx)
811 {
812  SCEnter();
813 
814  if (unlikely(p == NULL))
815  SCReturnInt(0);
816 
817 #ifdef HAVE_LIBJANSSON
818  if (p->flow != NULL) {
819  uint16_t proto = FlowGetAppProtocol(p->flow);
820  switch (proto) {
821  case ALPROTO_HTTP:
822  PacketToDataProtoHTTP(p, pa, alert);
823  break;
824  case ALPROTO_TLS:
825  PacketToDataProtoTLS(p, pa, alert);
826  break;
827  case ALPROTO_SSH:
828  PacketToDataProtoSSH(p, pa, alert);
829  break;
830  case ALPROTO_SMTP:
831  case ALPROTO_IMAP:
832  PacketToDataProtoSMTP(p, pa, alert);
833  PacketToDataProtoEmail(p, pa, alert);
834  break;
835  }
836  }
837 #endif
838 
839  AddIntData(alert, "snort_rule_sid", pa->s->id);
840  AddIntData(alert, "snort_rule_rev", pa->s->rev);
841 
842  if (ctx->log_packet_header) {
843  if ( PKT_IS_IPV4(p) )
844  PacketToDataV4(p, pa, alert);
845 
846  else if ( PKT_IS_IPV6(p) )
847  PacketToDataV6(p, pa, alert);
848 
849  if ( PKT_IS_TCP(p) ) {
850  AddIntData(alert, "tcp_seq", TCP_GET_SEQ(p));
851  AddIntData(alert, "tcp_ack", TCP_GET_ACK(p));
852 
853  AddIntData(alert, "tcp_off", TCP_GET_OFFSET(p));
854  AddIntData(alert, "tcp_res", TCP_GET_X2(p));
855  AddIntData(alert, "tcp_flags", TCP_GET_FLAGS(p));
856 
857  AddIntData(alert, "tcp_win", TCP_GET_WINDOW(p));
858  AddIntData(alert, "tcp_sum", TCP_GET_SUM(p));
859  AddIntData(alert, "tcp_urp", TCP_GET_URG_POINTER(p));
860  if (p->tcpvars.ts_val != 0) {
861  AddIntData(alert, "tcp_tsval", TCP_GET_TSVAL(p));
862  }
863  if (p->tcpvars.ts_ecr != 0) {
864  AddIntData(alert, "tcp_tsecr", TCP_GET_TSECR(p));
865  }
866  if (p->tcph != NULL) {
867  AddIntData(alert, "tcp_wscale", TCP_GET_WSCALE(p));
868  }
869  if (TCP_HAS_SACKOK(p)) {
870  AddIntData(alert, "tcp_sackok", TCP_GET_SACKOK(p));
871  }
872  if (TCP_HAS_SACK(p)) {
873  AddIntData(alert, "tcp_sack_cnt", TCP_GET_SACK_CNT(p));
874  }
875  AddIntData(alert, "tcp_hlen", TCP_GET_HLEN(p));
876  }
877 
878  else if ( PKT_IS_UDP(p) ) {
879  AddIntData(alert, "udp_len", UDP_GET_LEN(p));
880  AddIntData(alert, "udp_sum", UDP_GET_SUM(p));
881  }
882 
883  else if ( PKT_IS_ICMPV4(p) ) {
884  AddIntData(alert, "icmp_type", ICMPV4_GET_TYPE(p));
885  AddIntData(alert, "icmp_code", ICMPV4_GET_CODE(p));
886  AddIntData(alert, "icmp_sum", ICMPV4_GET_RAW_CSUM(p));
887 
888  }
889 
890  else if ( PKT_IS_ICMPV6(p) ) {
891  AddIntData(alert, "icmp_type", ICMPV6_GET_TYPE(p));
892  AddIntData(alert, "icmp_code", ICMPV6_GET_CODE(p));
893  AddIntData(alert, "icmp_csum", ICMPV6_GET_RAW_CSUM(p));
894  }
895  }
896 
897  if (ctx->log_packet_content)
898  AddByteData(alert, "payload", p->payload, p->payload_len);
899 
900  SCReturnInt(0);
901 }
902 
903 /**
904  * \brief Store reference on rule (SID and GID) in the IDMEF alert,
905  * and embed an URL pointing to the rule description.
906  *
907  * \return 0 if ok
908  */
909 static int AddSnortReference(idmef_classification_t *class, int gen_id, int sig_id)
910 {
911  int ret;
912  prelude_string_t *str;
913  idmef_reference_t *ref;
914 
915  SCEnter();
916 
917  if ( sig_id >= SNORT_MAX_OWNED_SID )
918  SCReturnInt(0);
919 
920  ret = idmef_classification_new_reference(class, &ref, IDMEF_LIST_APPEND);
921  if (unlikely(ret < 0))
922  SCReturnInt(ret);
923 
924  ret = idmef_reference_new_name(ref, &str);
925  if (unlikely(ret < 0))
926  SCReturnInt(ret);
927 
928  idmef_reference_set_origin(ref, IDMEF_REFERENCE_ORIGIN_VENDOR_SPECIFIC);
929 
930  if ( gen_id == 0 )
931  ret = prelude_string_sprintf(str, "%u", sig_id);
932  else
933  ret = prelude_string_sprintf(str, "%u:%u", gen_id, sig_id);
934 
935  if (unlikely(ret < 0))
936  SCReturnInt(ret);
937 
938  ret = idmef_reference_new_meaning(ref, &str);
939  if (unlikely(ret < 0))
940  SCReturnInt(ret);
941 
942  ret = prelude_string_sprintf(str, "Snort Signature ID");
943  if (unlikely(ret < 0))
944  SCReturnInt(ret);
945 
946  ret = idmef_reference_new_url(ref, &str);
947  if (unlikely(ret < 0))
948  SCReturnInt(ret);
949 
950  if ( gen_id == 0 )
951  ret = prelude_string_sprintf(str, ANALYZER_SID_URL "%u", sig_id);
952  else
953  ret = prelude_string_sprintf(str, ANALYZER_SID_URL "%u-%u", gen_id, sig_id);
954 
955  SCReturnInt(ret);
956 }
957 
958 /**
959  * \brief Create event classification description (see section
960  * 4.2.4.2 of RFC 4765).
961  * The classification is the "name" of the alert, identification of the
962  * rule signature, and additional information on the rule.
963  *
964  * \return 0 if ok
965  */
966 static int EventToReference(const PacketAlert *pa, const Packet *p, idmef_classification_t *class)
967 {
968  int ret;
969  prelude_string_t *str;
970 
971  SCEnter();
972 
973  ret = idmef_classification_new_ident(class, &str);
974  if (unlikely(ret < 0))
975  SCReturnInt(ret);
976 
977  if ( pa->s->gid == 0 )
978  ret = prelude_string_sprintf(str, "%u", pa->s->id);
979  else
980  ret = prelude_string_sprintf(str, "%u:%u", pa->s->gid, pa->s->id);
981  if (unlikely(ret < 0))
982  SCReturnInt(ret);
983 
984  ret = AddSnortReference(class, pa->s->gid, pa->s->id);
985  if (unlikely(ret < 0))
986  SCReturnInt(ret);
987 
988  SCReturnInt(0);
989 }
990 
991 static int PreludePrintStreamSegmentCallback(const Packet *p, void *data, const uint8_t *buf, uint32_t buflen)
992 {
993  int ret;
994 
995  ret = AddByteData((idmef_alert_t *)data, "stream-segment", buf, buflen);
996  if (ret == 0)
997  return 1;
998  else
999  return -1;
1000 }
1001 
1002 /**
1003  * \brief Initialize thread-specific data. Each thread structure contains
1004  * a pointer to the \a AlertPreludeCtx context.
1005  *
1006  * \return TM_ECODE_OK if ok, else TM_ECODE_FAILED
1007  */
1008 static TmEcode AlertPreludeThreadInit(ThreadVars *t, const void *initdata, void **data)
1009 {
1010  int ret;
1011  AlertPreludeThread *aun;
1012 
1013  SCEnter();
1014 
1015  if (unlikely(initdata == NULL)) {
1017  "Error getting context for Prelude. \"initdata\" argument NULL");
1019  }
1020 
1021  aun = SCMalloc(sizeof(AlertPreludeThread));
1022  if (unlikely(aun == NULL))
1024  memset(aun, 0, sizeof(AlertPreludeThread));
1025 
1026  /* Use the Ouput Context */
1027  aun->ctx = ((OutputCtx *)initdata)->data;
1028 
1029  /* Create a per-thread idmef analyzer */
1030  ret = idmef_analyzer_clone(prelude_client_get_analyzer(aun->ctx->client), &aun->analyzer);
1031  if (unlikely(ret < 0)) {
1033  "Error creating idmef analyzer for Prelude.");
1034 
1035  SCFree(aun);
1037  }
1038 
1039  *data = (void *)aun;
1041 }
1042 
1043 /**
1044  * \brief Free thread-specific data.
1045  *
1046  * \return TM_ECODE_OK if ok, else TM_ECODE_FAILED
1047  */
1048 static TmEcode AlertPreludeThreadDeinit(ThreadVars *t, void *data)
1049 {
1050  AlertPreludeThread *aun = (AlertPreludeThread *)data;
1051 
1052  SCEnter();
1053 
1054  if (unlikely(aun == NULL)) {
1055  SCLogDebug("AlertPreludeThreadDeinit done (error)");
1057  }
1058 
1059  /* clear memory */
1060  idmef_analyzer_destroy(aun->analyzer);
1061  memset(aun, 0, sizeof(AlertPreludeThread));
1062  SCFree(aun);
1063 
1065 }
1066 
1067 static void AlertPreludeDeinitCtx(OutputCtx *output_ctx)
1068 {
1069  AlertPreludeCtx *ctx = (AlertPreludeCtx *)output_ctx->data;
1070 
1071  prelude_client_destroy(ctx->client, PRELUDE_CLIENT_EXIT_STATUS_SUCCESS);
1072  SCFree(output_ctx);
1073 }
1074 
1075 /** \brief Initialize the Prelude logging module: initialize
1076  * library, create the client and try to establish the connection
1077  * to the Prelude Manager.
1078  * Client flags are set to force asynchronous (non-blocking) mode for
1079  * both alerts and heartbeats.
1080  * This function requires an existing Prelude profile to work.
1081  *
1082  * \return A newly allocated AlertPreludeCtx structure, or NULL
1083  */
1084 static OutputInitResult AlertPreludeInitCtx(ConfNode *conf)
1085 {
1086  int ret;
1087  prelude_client_t *client;
1088  AlertPreludeCtx *ctx;
1089  const char *prelude_profile_name;
1090  const char *log_packet_content;
1091  const char *log_packet_header;
1092  OutputInitResult result = { NULL, false };
1093  OutputCtx *output_ctx;
1094 
1095  SCEnter();
1096 
1097  ret = prelude_init(0, NULL);
1098  if (unlikely(ret < 0)) {
1099  prelude_perror(ret, "unable to initialize the prelude library");
1100  SCReturnCT(result, "OutputInitResult");
1101  }
1102 
1103  prelude_profile_name = ConfNodeLookupChildValue(conf, "profile");
1104  if (prelude_profile_name == NULL)
1105  prelude_profile_name = DEFAULT_PRELUDE_PROFILE;
1106 
1107  log_packet_content = ConfNodeLookupChildValue(conf, "log-packet-content");
1108  log_packet_header = ConfNodeLookupChildValue(conf, "log-packet-header");
1109 
1110  ret = prelude_client_new(&client, prelude_profile_name);
1111  if ( unlikely(ret < 0 || client == NULL )) {
1112  prelude_perror(ret, "Unable to create a prelude client object");
1113  prelude_client_destroy(client, PRELUDE_CLIENT_EXIT_STATUS_SUCCESS);
1114  SCReturnCT(result, "OutputInitResult");
1115  }
1116 
1117  ret = prelude_client_set_flags(client, prelude_client_get_flags(client) | PRELUDE_CLIENT_FLAGS_ASYNC_TIMER|PRELUDE_CLIENT_FLAGS_ASYNC_SEND);
1118  if (unlikely(ret < 0)) {
1119  SCLogDebug("Unable to set asynchronous send and timer.");
1120  prelude_client_destroy(client, PRELUDE_CLIENT_EXIT_STATUS_SUCCESS);
1121  SCReturnCT(result, "OutputInitResult");
1122  }
1123 
1124  ret = SetupAnalyzer(prelude_client_get_analyzer(client));
1125  if (ret < 0) {
1126  SCLogDebug("Unable to setup prelude client analyzer.");
1127  prelude_client_destroy(client, PRELUDE_CLIENT_EXIT_STATUS_SUCCESS);
1128  SCReturnCT(result, "OutputInitResult");
1129  }
1130 
1131  ret = prelude_client_start(client);
1132  if (unlikely(ret < 0)) {
1133  prelude_perror(ret, "Unable to start prelude client");
1134  prelude_client_destroy(client, PRELUDE_CLIENT_EXIT_STATUS_SUCCESS);
1135  SCReturnCT(result, "OutputInitResult");
1136  }
1137 
1138  ctx = SCMalloc(sizeof(AlertPreludeCtx));
1139  if (unlikely(ctx == NULL)) {
1140  prelude_perror(ret, "Unable to allocate memory");
1141  prelude_client_destroy(client, PRELUDE_CLIENT_EXIT_STATUS_SUCCESS);
1142  SCReturnCT(result, "OutputInitResult");
1143  }
1144 
1145  ctx->client = client;
1146  ctx->log_packet_content = 0;
1147  ctx->log_packet_header = 1;
1148  if (log_packet_content && ConfValIsTrue(log_packet_content))
1149  ctx->log_packet_content = 1;
1150  if (log_packet_header && ConfValIsFalse(log_packet_header))
1151  ctx->log_packet_header = 0;
1152 
1153  output_ctx = SCMalloc(sizeof(OutputCtx));
1154  if (unlikely(output_ctx == NULL)) {
1155  SCFree(ctx);
1156  prelude_perror(ret, "Unable to allocate memory");
1157  prelude_client_destroy(client, PRELUDE_CLIENT_EXIT_STATUS_SUCCESS);
1158  SCReturnCT(result, "OutputInitResult");
1159  }
1160 
1161  output_ctx->data = ctx;
1162  output_ctx->DeInit = AlertPreludeDeinitCtx;
1163 
1164  result.ctx = output_ctx;
1165  result.ok = true;
1166  SCReturnCT(result, "OutputInitResult");
1167 }
1168 
1169 static int AlertPreludeCondition(ThreadVars *tv, const Packet *p)
1170 {
1171  if (p->alerts.cnt == 0)
1172  return FALSE;
1173  if (!IPH_IS_VALID(p))
1174  return FALSE;
1175  return TRUE;
1176 }
1177 
1178 /**
1179  * \brief Handle Suricata alert: convert it to and IDMEF alert (see RFC 4765)
1180  * and send it asynchronously (so, this function does not block and returns
1181  * immediately).
1182  * If the destination Prelude Manager is not available, the alert is spooled
1183  * (and the function also returns immediately).
1184  * An IDMEF object is created, and all available information is added: IP packet
1185  * header and data, rule signature ID, additional data like URL pointing to
1186  * rule description, CVE, etc.
1187  * The IDMEF alert has a reference to all created objects, so freeing it will
1188  * automatically free all allocated memory.
1189  *
1190  * \note This function is thread safe.
1191  *
1192  * \return TM_ECODE_OK if ok, else TM_ECODE_FAILED
1193  */
1194 static int AlertPreludeLogger(ThreadVars *tv, void *thread_data, const Packet *p)
1195 {
1196  AlertPreludeThread *apn = (AlertPreludeThread *)thread_data;
1197  int ret;
1198  idmef_time_t *time;
1199  idmef_alert_t *alert;
1200  prelude_string_t *str;
1201  idmef_message_t *idmef = NULL;
1202  idmef_classification_t *class;
1203  const PacketAlert *pa;
1204 
1205  SCEnter();
1206 
1207  if (unlikely(apn == NULL || apn->ctx == NULL)) {
1209  }
1210 
1211  if (p->alerts.cnt == 0)
1213 
1214  if ( !IPH_IS_VALID(p) )
1216 
1217  /* XXX which one to add to this alert? Lets see how Snort solves this.
1218  * For now just take last alert. */
1219  pa = &p->alerts.alerts[p->alerts.cnt-1];
1220  if (unlikely(pa->s == NULL))
1221  goto err;
1222 
1223  ret = idmef_message_new(&idmef);
1224  if (unlikely(ret < 0))
1226 
1227  ret = idmef_message_new_alert(idmef, &alert);
1228  if (unlikely(ret < 0))
1229  goto err;
1230 
1231  ret = idmef_alert_new_classification(alert, &class);
1232  if (unlikely(ret < 0))
1233  goto err;
1234 
1235  if (pa->s->class_msg) {
1236  ret = idmef_classification_new_text(class, &str);
1237  if (unlikely(ret < 0))
1238  goto err;
1239 
1240  prelude_string_set_ref(str, pa->s->class_msg);
1241  }
1242 
1243  ret = EventToImpact(pa, p, alert);
1244  if (unlikely(ret < 0))
1245  goto err;
1246 
1247  ret = EventToReference(pa, p, class);
1248  if (unlikely(ret < 0))
1249  goto err;
1250 
1251  ret = EventToSourceTarget(pa, p, alert);
1252  if (unlikely(ret < 0))
1253  goto err;
1254 
1255  ret = PacketToData(p, pa, alert, apn->ctx);
1256  if (unlikely(ret < 0))
1257  goto err;
1258 
1259  if (PKT_IS_TCP(p) && (pa->flags & PACKET_ALERT_FLAG_STATE_MATCH)) {
1260  uint8_t flag;
1261  if (p->flowflags & FLOW_PKT_TOSERVER) {
1262  flag = FLOW_PKT_TOCLIENT;
1263  } else {
1264  flag = FLOW_PKT_TOSERVER;
1265  }
1266  ret = StreamSegmentForEach(p, flag,
1267  PreludePrintStreamSegmentCallback,
1268  (void *)alert);
1269  }
1270  if (unlikely(ret < 0))
1271  goto err;
1272 
1273  ret = idmef_alert_new_detect_time(alert, &time);
1274  if (unlikely(ret < 0))
1275  goto err;
1276  idmef_time_set_from_timeval(time, &p->ts);
1277 
1278  ret = idmef_time_new_from_gettimeofday(&time);
1279  if (unlikely(ret < 0))
1280  goto err;
1281  idmef_alert_set_create_time(alert, time);
1282 
1283  idmef_alert_set_analyzer(alert, idmef_analyzer_ref(apn->analyzer), IDMEF_LIST_PREPEND);
1284 
1285  /* finally, send event */
1286  prelude_client_send_idmef(apn->ctx->client, idmef);
1287  idmef_message_destroy(idmef);
1288 
1290 
1291 err:
1292  if (idmef != NULL)
1293  idmef_message_destroy(idmef);
1295 }
1296 
1298 {
1299  OutputRegisterPacketModule(LOGGER_PRELUDE, "AlertPrelude", "alert-prelude",
1300  AlertPreludeInitCtx, AlertPreludeLogger, AlertPreludeCondition,
1301  AlertPreludeThreadInit, AlertPreludeThreadDeinit, NULL);
1302 }
1303 #endif /* PRELUDE */
#define GET_IPV4_SRC_ADDR_PTR(p)
Definition: decode.h:213
#define ANALYZER_SID_URL
Definition: alert-prelude.c:90
uint32_t ts_ecr
Definition: decode-tcp.h:151
#define ANALYZER_MODEL
Definition: alert-prelude.c:88
int StreamSegmentForEach(const Packet *p, uint8_t flag, StreamSegmentCallback CallbackFunc, void *data)
Run callback for all segments.
Definition: stream.c:39
#define ANALYZER_MANUFACTURER
Definition: alert-prelude.c:89
UDPHdr * udph
Definition: decode.h:527
#define SCLogDebug(...)
Definition: util-debug.h:335
struct Flow_ * flow
Definition: decode.h:444
uint8_t ip_proto
Definition: decode-ipv4.h:303
#define ACTION_REJECT_DST
#define PACKET_TEST_ACTION(p, a)
Definition: decode.h:870
uint32_t flags
Definition: detect.h:493
char * msg
Definition: detect.h:549
#define DEFAULT_PRELUDE_PROFILE
Definition: alert-prelude.c:95
uint32_t id
Definition: detect.h:525
#define FALSE
#define unlikely(expr)
Definition: util-optimize.h:35
#define TCP_GET_OFFSET(p)
Definition: decode-tcp.h:101
#define GET_IPV4_DST_ADDR_PTR(p)
Definition: decode.h:214
Port sp
Definition: decode.h:414
#define TCP_GET_SACKOK(p)
Definition: decode-tcp.h:97
struct AlertPreludeCtx_ AlertPreludeCtx
int prio
Definition: detect.h:528
Port dp
Definition: decode.h:422
#define ACTION_REJECT
idmef_analyzer_t * analyzer
#define IPV6_GET_HLIM(p)
Definition: decode-ipv6.h:89
#define PKT_IS_IPV6(p)
Definition: decode.h:251
#define TCP_GET_WINDOW(p)
Definition: decode-tcp.h:108
void(* DeInit)(struct OutputCtx_ *)
Definition: tm-modules.h:84
AppProto FlowGetAppProtocol(const Flow *f)
Definition: flow.c:992
#define TCP_GET_TSVAL(p)
Definition: decode-tcp.h:81
TCPHdr * tcph
Definition: decode.h:525
uint32_t ts_val
Definition: decode-tcp.h:150
#define IPV4_GET_RAW_IPTTL(ip4h)
Definition: decode-ipv4.h:100
#define ICMPV4_GET_TYPE(p)
#define TRUE
#define IPV4_GET_RAW_VER(ip4h)
Definition: decode-ipv4.h:94
#define PKT_IS_IPV4(p)
Definition: decode.h:250
#define TCP_GET_X2(p)
Definition: decode-tcp.h:102
#define SCReturnCT(x, type)
Definition: util-debug.h:351
#define SIG_FLAG_SRC_IS_TARGET
Definition: detect.h:256
#define IPV4_GET_RAW_IPLEN(ip4h)
Definition: decode-ipv4.h:97
PacketAlert alerts[PACKET_ALERT_MAX]
Definition: decode.h:293
const struct Signature_ * s
Definition: decode.h:272
SSLv[2.0|3.[0|1|2|3]] state structure.
void AlertPreludeRegister(void)
#define ICMPV6_GET_RAW_CSUM(p)
#define ICMPV6_GET_CODE(p)
#define str(s)
const char * ConfNodeLookupChildValue(const ConfNode *node, const char *name)
Lookup the value of a child configuration node by name.
Definition: conf.c:843
#define TCP_GET_SEQ(p)
Definition: decode-tcp.h:106
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:160
#define IPV6_GET_PLEN(p)
Definition: decode-ipv6.h:87
#define IPV4_GET_RAW_IPTOS(ip4h)
Definition: decode-ipv4.h:96
#define GET_IPV6_DST_ADDR(p)
Definition: decode.h:219
#define ACTION_REJECT_BOTH
#define TCP_HAS_SACK(p)
Definition: decode-tcp.h:87
#define IPV6_GET_VER(p)
Definition: decode-ipv6.h:79
#define ANALYZER_CLASS
Definition: alert-prelude.c:87
#define TCP_GET_WSCALE(p)
Definition: decode-tcp.h:93
#define TCP_GET_TSECR(p)
Definition: decode-tcp.h:84
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
Definition: util-debug.h:294
prelude_client_t * client
#define PKT_IS_ICMPV6(p)
Definition: decode.h:255
#define IPV6_GET_FLOW(p)
Definition: decode-ipv6.h:83
#define IPV4_GET_RAW_IPID(ip4h)
Definition: decode-ipv4.h:98
#define SCEnter(...)
Definition: util-debug.h:337
uint8_t flowflags
Definition: decode.h:438
int ConfValIsFalse(const char *val)
Check if a value is false.
Definition: conf.c:591
#define IPV4_GET_RAW_IPPROTO(ip4h)
Definition: decode-ipv4.h:101
#define FLOW_PKT_TOSERVER
Definition: flow.h:193
#define IPV6_GET_CLASS(p)
Definition: decode-ipv6.h:81
#define UDP_GET_LEN(p)
Definition: decode-udp.h:35
const char * PrintInet(int af, const void *src, char *dst, socklen_t size)
Definition: util-print.c:267
#define IPV6_GET_NH(p)
Definition: decode-ipv6.h:85
uint32_t gid
Definition: detect.h:526
uint8_t proto
#define TCP_GET_SUM(p)
Definition: decode-tcp.h:110
#define SCReturnInt(x)
Definition: util-debug.h:341
#define index
Definition: win32-misc.h:29
uint64_t tx_id
Definition: decode.h:273
#define IPV6_GET_L4PROTO(p)
Definition: decode-ipv6.h:92
int ConfValIsTrue(const char *val)
Check if a value is true.
Definition: conf.c:566
IPV4Hdr * ip4h
Definition: decode.h:503
char * class_msg
Definition: detect.h:552
struct AlertPreludeThread_ AlertPreludeThread
#define IPV4_GET_RAW_HLEN(ip4h)
Definition: decode-ipv4.h:95
Definition: conf.h:32
OutputCtx * ctx
Definition: output.h:42
#define TCP_GET_SACK_CNT(p)
Definition: decode-tcp.h:99
#define SCMalloc(a)
Definition: util-mem.h:174
#define GET_IPV6_SRC_ADDR(p)
Definition: decode.h:218
#define SIG_FLAG_HAS_TARGET
Definition: detect.h:260
#define SCFree(a)
Definition: util-mem.h:236
#define SCNtohs(x)
uint8_t address
Definition: decode-ppp.h:311
#define PKT_IS_TCP(p)
Definition: decode.h:252
uint8_t flags
Definition: decode.h:271
#define ICMPV6_GET_TYPE(p)
void * data
Definition: tm-modules.h:81
#define TCP_HAS_SACKOK(p)
Definition: decode-tcp.h:88
#define PKT_IS_ICMPV4(p)
Definition: decode.h:254
uint32_t rev
Definition: detect.h:527
PacketAlerts alerts
Definition: decode.h:560
void * FlowGetAppState(const Flow *f)
Definition: flow.c:997
#define IPH_IS_VALID(p)
Definition: decode.h:259
#define PACKET_ALERT_FLAG_STATE_MATCH
Definition: decode.h:281
#define TCP_GET_URG_POINTER(p)
Definition: decode-tcp.h:109
#define TCP_GET_FLAGS(p)
Definition: decode-tcp.h:111
#define TCP_GET_HLEN(p)
Definition: decode-tcp.h:103
uint16_t cnt
Definition: decode.h:292
TCPVars tcpvars
Definition: decode.h:517
#define PKT_IS_UDP(p)
Definition: decode.h:253
Per thread variable structure.
Definition: threadvars.h:57
struct timeval ts
Definition: decode.h:450
#define FLOW_PKT_TOCLIENT
Definition: flow.h:194
#define ACTION_DROP
#define ICMPV4_GET_RAW_CSUM(p)
#define TCP_GET_ACK(p)
Definition: decode-tcp.h:107
uint16_t payload_len
Definition: decode.h:546
#define SNORT_MAX_OWNED_SID
Definition: alert-prelude.c:92
uint8_t * payload
Definition: decode.h:545
#define UDP_GET_SUM(p)
Definition: decode-udp.h:38
#define IPV4_GET_RAW_IPOFFSET(ip4h)
Definition: decode-ipv4.h:99
AlertPreludeCtx * ctx
#define ICMPV4_GET_CODE(p)