1 /*
2 ** Copyright (C) 2014-2021 Cisco and/or its affiliates. All rights reserved.
3 ** Copyright (C) 2007-2013 Sourcefire, Inc.
4 **
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License Version 2 as
7 ** published by the Free Software Foundation. You may not use, modify or
8 ** distribute this program under any other version of the GNU General
9 ** Public License.
10 **
11 ** This program is distributed in the hope that it will be useful,
12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ** GNU General Public License for more details.
15 **
16 ** You should have received a copy of the GNU General Public License
17 ** along with this program; if not, write to the Free Software
18 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 */
20
21 /* spo_unified2.c
22 * Adam Keeton
23 *
24 * 09/26/06
25 * This file is litterally spo_unified.c converted to write unified2
26 *
27 */
28
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32
33 #include <sys/types.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #ifdef HAVE_STRINGS_H
37 #include <strings.h>
38 #endif
39 #include <errno.h>
40 #include <time.h>
41
42 #include "sfutil/Unified2_common.h"
43 #include "spo_unified2.h"
44 #include "decode.h"
45 #include "rules.h"
46 #include "treenodes.h"
47 #include "util.h"
48 #include "plugbase.h"
49 #include "spo_plugbase.h"
50 #include "parser.h"
51 #include "snort_debug.h"
52 #include "mstring.h"
53 #include "event.h"
54 #include "generators.h"
55 #include "snort_debug.h"
56 #include "snort_bounds.h"
57 #include "obfuscation.h"
58 #include "active.h"
59 #include "detection_util.h"
60 #include "detect.h"
61
62 #include "snort.h"
63 #include "pcap_pkthdr32.h"
64
65 /* For the traversal of reassembled packets */
66 #include "stream_api.h"
67 #include "snort_httpinspect.h"
68
69
70 /* ------------------ Data structures --------------------------*/
71 typedef struct _Unified2Config
72 {
73 char *base_filename;
74 char filepath[STD_BUF];
75 uint32_t timestamp;
76 FILE *stream;
77 unsigned int limit;
78 unsigned int current;
79 int nostamp;
80 #ifdef MPLS
81 int mpls_event_types;
82 #endif
83 int vlan_event_types;
84 int base_proto;
85 #if defined(FEAT_OPEN_APPID)
86 int appid_event_types;
87 #endif /* defined(FEAT_OPEN_APPID) */
88 } Unified2Config;
89
90 typedef struct _Unified2LogCallbackData
91 {
92 Serial_Unified2Packet *logheader;
93 Unified2Config *config;
94 Event *event;
95 uint32_t num_bytes;
96
97 } Unified2LogCallbackData;
98
99 Unified2Config *log_config = NULL;
100 Unified2Config *alert_config = NULL;
101
102
103 /* ----------------External variables -------------------- */
104 /* From fpdetect.c, for logging reassembled packets */
105 extern OptTreeNode *otn_tmp;
106
107 /* -------------------- Global Variables ----------------------*/
108 /* Used for buffering header and payload of unified records so only one
109 * write is necessary. Serial_Unified2IDSEventIPv6_legacy is used as Serial_Unified2IDSEvent_legacy size
110 * since it is the largest */
111 static uint8_t write_pkt_buffer[sizeof(Serial_Unified2_Header) +
112 sizeof(Serial_Unified2IDSEventIPv6_legacy) + IP_MAXPACKET];
113 #define write_pkt_end (write_pkt_buffer + sizeof(write_pkt_buffer))
114
115 static uint8_t write_pkt_buffer_v2[sizeof(Serial_Unified2_Header) +
116 sizeof(Unified2IDSEventIPv6) + IP_MAXPACKET];
117 #define write_pkt_end_v2 (write_pkt_buffer_v2 + sizeof(write_pkt_buffer_v2))
118
119 #define MAX_XDATA_WRITE_BUF_LEN (MAX_XFF_WRITE_BUF_LENGTH - \
120 sizeof(struct in6_addr) + DECODE_BLEN)
121
122 /* This is the buffer to use for I/O. Try to make big enough so the system
123 * doesn't potentially flush in the middle of a record. Every write is
124 * force flushed to disk immediately after the entire record is written so
125 * spoolers get an entire record */
126 #define UNIFIED2_SETVBUF
127 #ifndef WIN32
128 /* use the size of the buffer we copy record data into */
129 static char io_buffer[sizeof(write_pkt_buffer_v2)];
130 #else
131 # ifdef _MSC_VER
132 # if _MSC_VER <= 1200
133 /* use maximum size defined by VC++ 6.0 */
134 static char io_buffer[32768];
135 # else
136 static char io_buffer[sizeof(write_pkt_buffer_v2)];
137 # endif /* _MSC_VER <= 1200 */
138 # else
139 /* no _MSC_VER, don't set I/O buffer */
140 # undef UNIFIED2_SETVBUF
141 # endif /* _MSC_VER */
142 #endif /* WIN32 */
143
144 /* -------------------- Local Functions -----------------------*/
145 static Unified2Config * Unified2ParseArgs(char *, char *);
146 static void Unified2CleanExit(int, void *);
147 #ifdef SNORT_RELOAD
148 static void Unified2Reload(struct _SnortConfig *, int, void *);
149 #endif
150
151 /* Unified2 Output functions */
152 static void Unified2Init(struct _SnortConfig *, char *);
153 static void Unified2PostConfig(struct _SnortConfig *, int, void *);
154 static void Unified2InitFile(Unified2Config *);
155 static inline void Unified2RotateFile(Unified2Config *);
156 static void Unified2LogAlert(Packet *, const char *, void *, Event *);
157 static void _AlertIP4(Packet *, const char *, Unified2Config *, Event *);
158 static void _AlertIP6(Packet *, const char *, Unified2Config *, Event *);
159 static void Unified2LogPacketAlert(Packet *, const char *, void *, Event *);
160 static void _Unified2LogPacketAlert(Packet *, const char *, Unified2Config *, Event *);
161 static void _Unified2LogStreamAlert(Packet *, const char *, Unified2Config *, Event *);
162 static int Unified2LogStreamCallback(DAQ_PktHdr_t *, uint8_t *, void *);
163 static void Unified2Write(uint8_t *, uint32_t, Unified2Config *);
164
165 static void _AlertIP4_v2(Packet *, const char *, Unified2Config *, Event *);
166 static void _AlertIP6_v2(Packet *, const char *, Unified2Config *, Event *);
167
168 /* Unified2 Alert functions (deprecated) */
169 static void Unified2AlertInit(struct _SnortConfig *, char *);
170
171 /* Unified2 Packet Log functions (deprecated) */
172 static void Unified2LogInit(struct _SnortConfig *, char *);
173
174 static ObRet Unified2LogObfuscationCallback(const DAQ_PktHdr_t *pkth,
175 const uint8_t *packet_data, ob_size_t length, ob_char_t ob_char, void *userdata);
176
177 static void AlertExtraData(void *ssnptr, void *data, LogFunction *log_funcs, uint32_t max_count, uint32_t xtradata_mask, uint32_t event_id, uint32_t event_second);
178
179 #define U2_PACKET_FLAG 1
180 /* Obsolete flag as UI wont check the impact_flag field anymore.*/
181 #define U2_FLAG_BLOCKED 0x20
182 /* New flags to set the pad field (corresponds to blocked column in UI) with packet action*/
183 #define U2_BLOCKED_FLAG_ALLOW 0x00
184 #define U2_BLOCKED_FLAG_BLOCK 0x01
185 #define U2_BLOCKED_FLAG_WOULD 0x02
186 #define U2_BLOCKED_FLAG_CANT 0x03
187
188 /*
189 * Function: SetupUnified2()
190 *
191 * Purpose: Registers the output plugin keyword and initialization
192 * function into the output plugin list. This is the function that
193 * gets called from InitOutputPlugins() in plugbase.c.
194 *
195 * Arguments: None.
196 *
197 * Returns: void function
198 *
199 */
Unified2Setup(void)200 void Unified2Setup(void)
201 {
202 /* link the preprocessor keyword to the init function in
203 the preproc list */
204 RegisterOutputPlugin("log_unified2", OUTPUT_TYPE_FLAG__LOG, Unified2LogInit);
205 RegisterOutputPlugin("alert_unified2", OUTPUT_TYPE_FLAG__ALERT, Unified2AlertInit);
206 RegisterOutputPlugin("unified2", OUTPUT_TYPE_FLAG__LOG | OUTPUT_TYPE_FLAG__ALERT, Unified2Init);
207
208 DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Output plugin: Unified2 "
209 "logging/alerting is setup...\n"););
210 }
211
212 /*
213 * Function: Unified2Init(char *)
214 *
215 * Purpose: Calls the argument parsing function, performs final setup on data
216 * structs, links the preproc function into the function list.
217 *
218 * Arguments: args => ptr to argument string
219 *
220 * Returns: void function
221 *
222 */
Unified2Init(struct _SnortConfig * sc,char * args)223 static void Unified2Init(struct _SnortConfig *sc, char *args)
224 {
225 Unified2Config *config;
226
227 /* parse the argument list from the rules file */
228 config = Unified2ParseArgs(args, "snort-unified");
229
230 /* Set the preprocessor function into the function list */
231 AddFuncToOutputList(sc, Unified2LogAlert, OUTPUT_TYPE__ALERT, config);
232 AddFuncToOutputList(sc, Unified2LogPacketAlert, OUTPUT_TYPE__LOG, config);
233
234 AddFuncToCleanExitList(Unified2CleanExit, config);
235 #ifdef SNORT_RELOAD
236 AddFuncToReloadList(Unified2Reload, config);
237 #endif
238 AddFuncToPostConfigList(sc, Unified2PostConfig, config);
239 }
240
Unified2PostConfig(struct _SnortConfig * sc,int unused,void * data)241 static void Unified2PostConfig(struct _SnortConfig *sc, int unused, void *data)
242 {
243 Unified2Config *config = (Unified2Config *)data;
244 int status;
245
246 if (config == NULL || config->base_filename == NULL)
247 {
248 FatalError("%s(%d) Could not initialize unified2 file: Unified2 "
249 "configuration data or file name is NULL.\n",
250 __FILE__, __LINE__);
251 }
252
253 #ifndef WIN32
254 if (config->base_filename[0] == '/')
255 {
256 status = SnortSnprintf(config->filepath, sizeof(config->filepath),
257 "%s", config->base_filename);
258 }
259 else
260 #endif
261 {
262 status = SnortSnprintf(config->filepath, sizeof(config->filepath),
263 "%s/%s", sc->log_dir, config->base_filename);
264 }
265
266 if (status != SNORT_SNPRINTF_SUCCESS)
267 {
268 FatalError("%s(%d) Failed to copy unified2 file name\n",
269 __FILE__, __LINE__);
270 }
271 config->base_proto = htonl(DAQ_GetBaseProtocol());
272
273
274 Unified2InitFile(config);
275
276 if(stream_api)
277 {
278 stream_api->reg_xtra_data_log(AlertExtraData, (void *)config);
279 }
280 }
281
282 /*
283 * Function: Unified2InitFile()
284 *
285 * Purpose: Initialize the unified2 ouput file
286 *
287 * Arguments: config => pointer to the plugin's reference data struct
288 *
289 * Returns: void function
290 */
Unified2InitFile(Unified2Config * config)291 static void Unified2InitFile(Unified2Config *config)
292 {
293 char filepath[STD_BUF];
294 char *fname_ptr;
295
296 if (config == NULL)
297 {
298 FatalError("%s(%d) Could not initialize unified2 file: Unified2 "
299 "configuration data is NULL.\n", __FILE__, __LINE__);
300 }
301
302 config->timestamp = (uint32_t)time(NULL);
303
304 if (!config->nostamp)
305 {
306 if (SnortSnprintf(filepath, sizeof(filepath), "%s.%u",
307 config->filepath, config->timestamp) != SNORT_SNPRINTF_SUCCESS)
308 {
309 FatalError("%s(%d) Failed to copy unified2 file path.\n",
310 __FILE__, __LINE__);
311 }
312
313 fname_ptr = filepath;
314 }
315 else
316 {
317 fname_ptr = config->filepath;
318 }
319
320 if ((config->stream = fopen(fname_ptr, "wb")) == NULL)
321 {
322 FatalError("%s(%d) Could not open %s: %s\n",
323 __FILE__, __LINE__, fname_ptr, strerror(errno));
324 }
325
326 #ifdef UNIFIED2_SETVBUF
327 /* Set buffer to size of record buffer so the system doesn't flush
328 * part of a record if it's greater than BUFSIZ */
329 if (setvbuf(config->stream, io_buffer, _IOFBF, sizeof(io_buffer)) != 0)
330 {
331 ErrorMessage("%s(%d) Could not set I/O buffer: %s. "
332 "Using system default.\n",
333 __FILE__, __LINE__, strerror(errno));
334 }
335 #endif
336
337 /* If test mode, close and delete the file */
338 if (ScTestMode())
339 {
340 fclose(config->stream);
341 config->stream = NULL;
342 if (unlink(fname_ptr) == -1)
343 {
344 ErrorMessage("%s(%d) Running in test mode so we want to remove "
345 "test unified2 file. Could not unlink file \"%s\": %s\n",
346 __FILE__, __LINE__, fname_ptr, strerror(errno));
347 }
348 }
349 }
350
Unified2RotateFile(Unified2Config * config)351 static inline void Unified2RotateFile(Unified2Config *config)
352 {
353 fclose(config->stream);
354 config->current = 0;
355 Unified2InitFile(config);
356 }
357
358 static int s_blocked_flag[] =
359 {
360 U2_BLOCKED_FLAG_ALLOW,
361 U2_BLOCKED_FLAG_CANT,
362 U2_BLOCKED_FLAG_WOULD,
363 U2_BLOCKED_FLAG_BLOCK,
364 U2_BLOCKED_FLAG_BLOCK
365 };
366
GetU2Flags(const Packet * p,uint8_t * pimpact)367 static int GetU2Flags(const Packet* p, uint8_t* pimpact)
368 {
369 tActiveDrop dispos = Active_GetDisposition();
370
371 if ( dispos >= ACTIVE_DROP )
372 {
373 *pimpact = U2_FLAG_BLOCKED;
374 return U2_BLOCKED_FLAG_BLOCK;
375 }
376 return s_blocked_flag[dispos];
377 }
378
_AlertIP4(Packet * p,const char * msg,Unified2Config * config,Event * event)379 static void _AlertIP4(Packet *p, const char *msg, Unified2Config *config, Event *event)
380 {
381 Serial_Unified2_Header hdr;
382 Serial_Unified2IDSEvent_legacy alertdata;
383 uint32_t write_len = sizeof(Serial_Unified2_Header) + sizeof(Serial_Unified2IDSEvent_legacy);
384
385 memset(&alertdata, 0, sizeof(alertdata));
386
387 alertdata.event_id = htonl(event->event_id);
388 alertdata.event_second = htonl(event->ref_time.tv_sec);
389 alertdata.event_microsecond = htonl(event->ref_time.tv_usec);
390 alertdata.generator_id = htonl(event->sig_generator);
391 alertdata.signature_id = htonl(event->sig_id);
392 alertdata.signature_revision = htonl(event->sig_rev);
393 alertdata.classification_id = htonl(event->classification);
394 alertdata.priority_id = htonl(event->priority);
395
396 if (p != NULL)
397 {
398 alertdata.blocked = GetU2Flags(p, &alertdata.impact_flag);
399
400 if(IPH_IS_VALID(p))
401 {
402 alertdata.ip_source = p->iph->ip_src.s_addr;
403 alertdata.ip_destination = p->iph->ip_dst.s_addr;
404 alertdata.protocol = GetEventProto(p);
405
406 if ((alertdata.protocol == IPPROTO_ICMP) && p->icmph)
407 {
408 alertdata.sport_itype = htons(p->icmph->type);
409 alertdata.dport_icode = htons(p->icmph->code);
410 }
411 else if (!IsPortscanPacket(p))
412 {
413 alertdata.sport_itype = htons(p->sp);
414 alertdata.dport_icode = htons(p->dp);
415 }
416 }
417 }
418
419 if ((config->current + write_len) > config->limit)
420 Unified2RotateFile(config);
421
422 hdr.length = htonl(sizeof(Serial_Unified2IDSEvent_legacy));
423 hdr.type = htonl(UNIFIED2_IDS_EVENT);
424
425 if (SafeMemcpy(write_pkt_buffer, &hdr, sizeof(Serial_Unified2_Header),
426 write_pkt_buffer, write_pkt_end) != SAFEMEM_SUCCESS)
427 {
428 ErrorMessage("%s(%d) Failed to copy Serial_Unified2_Header. "
429 "Not writing unified2 event.\n", __FILE__, __LINE__);
430 return;
431 }
432
433 if (SafeMemcpy(write_pkt_buffer + sizeof(Serial_Unified2_Header),
434 &alertdata, sizeof(Serial_Unified2IDSEvent_legacy),
435 write_pkt_buffer, write_pkt_end) != SAFEMEM_SUCCESS)
436 {
437 ErrorMessage("%s(%d) Failed to copy Serial_Unified2IDSEvent_legacy. "
438 "Not writing unified2 event.\n", __FILE__, __LINE__);
439 return;
440 }
441
442 Unified2Write(write_pkt_buffer, write_len, config);
443 }
444
_AlertIP4_v2(Packet * p,const char * msg,Unified2Config * config,Event * event)445 static void _AlertIP4_v2(Packet *p, const char *msg, Unified2Config *config, Event *event)
446 {
447 Serial_Unified2_Header hdr;
448 Unified2IDSEvent alertdata;
449 uint32_t write_len = sizeof(Serial_Unified2_Header) + sizeof(Unified2IDSEvent);
450
451 memset(&alertdata, 0, sizeof(alertdata));
452
453 alertdata.event_id = htonl(event->event_id);
454 alertdata.event_second = htonl(event->ref_time.tv_sec);
455 alertdata.event_microsecond = htonl(event->ref_time.tv_usec);
456 alertdata.generator_id = htonl(event->sig_generator);
457 alertdata.signature_id = htonl(event->sig_id);
458 alertdata.signature_revision = htonl(event->sig_rev);
459 alertdata.classification_id = htonl(event->classification);
460 alertdata.priority_id = htonl(event->priority);
461 #if defined(FEAT_OPEN_APPID)
462 memcpy(alertdata.app_name, event->app_name, sizeof(alertdata.app_name));
463 #endif /* defined(FEAT_OPEN_APPID) */
464
465 if(p)
466 {
467 alertdata.blocked = GetU2Flags(p, &alertdata.impact_flag);
468
469 if(IPH_IS_VALID(p))
470 {
471 alertdata.ip_source = p->iph->ip_src.s_addr;
472 alertdata.ip_destination = p->iph->ip_dst.s_addr;
473 alertdata.protocol = GetEventProto(p);
474
475 if ((alertdata.protocol == IPPROTO_ICMP) && p->icmph)
476 {
477 alertdata.sport_itype = htons(p->icmph->type);
478 alertdata.dport_icode = htons(p->icmph->code);
479 }
480 else if (!IsPortscanPacket(p))
481 {
482 alertdata.sport_itype = htons(p->sp);
483 alertdata.dport_icode = htons(p->dp);
484 }
485
486 #ifdef MPLS
487 if((p->mpls) && (config->mpls_event_types))
488 {
489 alertdata.mpls_label = htonl(p->mplsHdr.label);
490 }
491 #endif
492 if(config->vlan_event_types)
493 {
494 if(p->vh)
495 {
496 alertdata.vlanId = htons(VTH_VLAN(p->vh));
497 }
498
499 alertdata.pad2 = htons(p->configPolicyId);
500 }
501
502 #if defined(FEAT_OPEN_APPID)
503 if((event->app_name[0]) && (config->appid_event_types))
504 {
505 memcpy(alertdata.app_name, event->app_name, sizeof(alertdata.app_name));
506 }
507 #endif /* defined(FEAT_OPEN_APPID) */
508 }
509 }
510
511 if ((config->current + write_len) > config->limit)
512 Unified2RotateFile(config);
513
514 hdr.length = htonl(sizeof(Unified2IDSEvent));
515 #if !defined(FEAT_OPEN_APPID)
516 hdr.type = htonl(UNIFIED2_IDS_EVENT_VLAN);
517 #else /* defined(FEAT_OPEN_APPID) */
518 hdr.type = htonl(UNIFIED2_IDS_EVENT_APPID);
519 #endif /* defined(FEAT_OPEN_APPID) */
520
521 if (SafeMemcpy(write_pkt_buffer_v2, &hdr, sizeof(Serial_Unified2_Header),
522 write_pkt_buffer_v2, write_pkt_end_v2) != SAFEMEM_SUCCESS)
523 {
524 ErrorMessage("%s(%d) Failed to copy Serial_Unified2_Header. "
525 "Not writing unified2 event.\n", __FILE__, __LINE__);
526 return;
527 }
528
529 if (SafeMemcpy(write_pkt_buffer_v2 + sizeof(Serial_Unified2_Header),
530 &alertdata, sizeof(Unified2IDSEvent),
531 write_pkt_buffer_v2, write_pkt_end_v2) != SAFEMEM_SUCCESS)
532 {
533 ErrorMessage("%s(%d) Failed to copy Serial_Unified2IDSEvent_legacy. "
534 "Not writing unified2 event.\n", __FILE__, __LINE__);
535 return;
536 }
537
538 Unified2Write(write_pkt_buffer_v2, write_len, config);
539 }
540
_AlertIP6(Packet * p,const char * msg,Unified2Config * config,Event * event)541 static void _AlertIP6(Packet *p, const char *msg, Unified2Config *config, Event *event)
542 {
543 Serial_Unified2_Header hdr;
544 Serial_Unified2IDSEventIPv6_legacy alertdata;
545 uint32_t write_len = sizeof(Serial_Unified2_Header) + sizeof(Serial_Unified2IDSEventIPv6_legacy);
546
547 memset(&alertdata, 0, sizeof(alertdata));
548
549 alertdata.event_id = htonl(event->event_id);
550 alertdata.event_second = htonl(event->ref_time.tv_sec);
551 alertdata.event_microsecond = htonl(event->ref_time.tv_usec);
552 alertdata.generator_id = htonl(event->sig_generator);
553 alertdata.signature_id = htonl(event->sig_id);
554 alertdata.signature_revision = htonl(event->sig_rev);
555 alertdata.classification_id = htonl(event->classification);
556 alertdata.priority_id = htonl(event->priority);
557
558 if(p)
559 {
560 alertdata.blocked = GetU2Flags(p, &alertdata.impact_flag);
561
562 if(IPH_IS_VALID(p))
563 {
564 sfaddr_t* ip;
565
566 ip = GET_SRC_IP(p);
567 alertdata.ip_source = *(struct in6_addr*)sfaddr_get_ip6_ptr(ip);
568
569 ip = GET_DST_IP(p);
570 alertdata.ip_destination = *(struct in6_addr*)sfaddr_get_ip6_ptr(ip);
571
572 alertdata.protocol = GetEventProto(p);
573
574 if ((alertdata.protocol == IPPROTO_ICMP) && p->icmph)
575 {
576 alertdata.sport_itype = htons(p->icmph->type);
577 alertdata.dport_icode = htons(p->icmph->code);
578 }
579 else if (!IsPortscanPacket(p))
580 {
581 alertdata.sport_itype = htons(p->sp);
582 alertdata.dport_icode = htons(p->dp);
583 }
584 }
585 }
586
587 if ((config->current + write_len) > config->limit)
588 Unified2RotateFile(config);
589
590 hdr.length = htonl(sizeof(Serial_Unified2IDSEventIPv6_legacy));
591 hdr.type = htonl(UNIFIED2_IDS_EVENT_IPV6);
592
593 if (SafeMemcpy(write_pkt_buffer, &hdr, sizeof(Serial_Unified2_Header),
594 write_pkt_buffer, write_pkt_end) != SAFEMEM_SUCCESS)
595 {
596 ErrorMessage("%s(%d) Failed to copy Serial_Unified2_Header. "
597 "Not writing unified2 event.\n", __FILE__, __LINE__);
598 return;
599 }
600
601 if (SafeMemcpy(write_pkt_buffer + sizeof(Serial_Unified2_Header),
602 &alertdata, sizeof(Serial_Unified2IDSEventIPv6_legacy),
603 write_pkt_buffer, write_pkt_end) != SAFEMEM_SUCCESS)
604 {
605 ErrorMessage("%s(%d) Failed to copy Serial_Unified2IDSEventIPv6_legacy. "
606 "Not writing unified2 event.\n", __FILE__, __LINE__);
607 return;
608 }
609
610 Unified2Write(write_pkt_buffer, write_len, config);
611 }
612
_AlertIP6_v2(Packet * p,const char * msg,Unified2Config * config,Event * event)613 static void _AlertIP6_v2(Packet *p, const char *msg, Unified2Config *config, Event *event)
614 {
615 Serial_Unified2_Header hdr;
616 Unified2IDSEventIPv6 alertdata;
617 uint32_t write_len = sizeof(Serial_Unified2_Header) + sizeof(Unified2IDSEventIPv6);
618
619 memset(&alertdata, 0, sizeof(alertdata));
620
621 alertdata.event_id = htonl(event->event_id);
622 alertdata.event_second = htonl(event->ref_time.tv_sec);
623 alertdata.event_microsecond = htonl(event->ref_time.tv_usec);
624 alertdata.generator_id = htonl(event->sig_generator);
625 alertdata.signature_id = htonl(event->sig_id);
626 alertdata.signature_revision = htonl(event->sig_rev);
627 alertdata.classification_id = htonl(event->classification);
628 alertdata.priority_id = htonl(event->priority);
629 #if defined(FEAT_OPEN_APPID)
630 memcpy(alertdata.app_name, event->app_name, sizeof(alertdata.app_name));
631 #endif /* defined(FEAT_OPEN_APPID) */
632
633 if(p)
634 {
635 alertdata.blocked = GetU2Flags(p, &alertdata.impact_flag);
636
637 if(IPH_IS_VALID(p))
638 {
639 sfaddr_t* ip;
640
641 ip = GET_SRC_IP(p);
642 alertdata.ip_source = *(struct in6_addr*)sfaddr_get_ip6_ptr(ip);
643
644 ip = GET_DST_IP(p);
645 alertdata.ip_destination = *(struct in6_addr*)sfaddr_get_ip6_ptr(ip);
646
647 alertdata.protocol = GetEventProto(p);
648
649 if ((alertdata.protocol == IPPROTO_ICMP) && p->icmph)
650 {
651 alertdata.sport_itype = htons(p->icmph->type);
652 alertdata.dport_icode = htons(p->icmph->code);
653 }
654 else if (!IsPortscanPacket(p))
655 {
656 alertdata.sport_itype = htons(p->sp);
657 alertdata.dport_icode = htons(p->dp);
658 }
659
660 #ifdef MPLS
661 if((p->mpls) && (config->mpls_event_types))
662 {
663 alertdata.mpls_label = htonl(p->mplsHdr.label);
664 }
665 #endif
666 if(config->vlan_event_types)
667 {
668 if(p->vh)
669 {
670 alertdata.vlanId = htons(VTH_VLAN(p->vh));
671 }
672
673 alertdata.pad2 = htons(p->configPolicyId);
674 }
675 #if defined(FEAT_OPEN_APPID)
676
677 if((event->app_name[0]) && (config->appid_event_types))
678 {
679 memcpy(alertdata.app_name, event->app_name, sizeof(alertdata.app_name));
680 }
681 #endif /* defined(FEAT_OPEN_APPID) */
682 }
683 }
684
685 if ((config->current + write_len) > config->limit)
686 Unified2RotateFile(config);
687
688 hdr.length = htonl(sizeof(Unified2IDSEventIPv6));
689 #if !defined(FEAT_OPEN_APPID)
690 hdr.type = htonl(UNIFIED2_IDS_EVENT_IPV6_VLAN);
691 #else
692 hdr.type = htonl(UNIFIED2_IDS_EVENT_APPID_IPV6);
693 #endif
694
695 if (SafeMemcpy(write_pkt_buffer_v2, &hdr, sizeof(Serial_Unified2_Header),
696 write_pkt_buffer_v2, write_pkt_end_v2) != SAFEMEM_SUCCESS)
697 {
698 ErrorMessage("%s(%d) Failed to copy Serial_Unified2_Header. "
699 "Not writing unified2 event.\n", __FILE__, __LINE__);
700 return;
701 }
702
703 if (SafeMemcpy(write_pkt_buffer_v2 + sizeof(Serial_Unified2_Header),
704 &alertdata, sizeof(Unified2IDSEventIPv6),
705 write_pkt_buffer_v2, write_pkt_end_v2) != SAFEMEM_SUCCESS)
706 {
707 ErrorMessage("%s(%d) Failed to copy Unified2IDSEventIPv6. "
708 "Not writing unified2 event.\n", __FILE__, __LINE__);
709 return;
710 }
711
712 Unified2Write(write_pkt_buffer_v2, write_len, config);
713 }
714
_WriteExtraData(Unified2Config * config,uint32_t event_id,uint32_t event_second,uint8_t * buffer,uint32_t len,uint32_t type)715 void _WriteExtraData(Unified2Config *config, uint32_t event_id, uint32_t event_second, uint8_t *buffer, uint32_t len, uint32_t type )
716 {
717
718 Serial_Unified2_Header hdr;
719 SerialUnified2ExtraData alertdata;
720 Unified2ExtraDataHdr alertHdr;
721 uint8_t write_buffer[MAX_XDATA_WRITE_BUF_LEN];
722 uint8_t *write_end = NULL;
723 uint8_t *ptr = NULL;
724
725
726 uint32_t write_len;
727
728 write_len = sizeof(Serial_Unified2_Header) + sizeof(Unified2ExtraDataHdr);
729
730 alertdata.sensor_id = 0;
731 alertdata.event_id = htonl(event_id);
732 alertdata.event_second = htonl(event_second);
733 alertdata.data_type = htonl(EVENT_DATA_TYPE_BLOB);
734
735 alertdata.type = htonl(type);
736 alertdata.blob_length = htonl(sizeof(alertdata.data_type) +
737 sizeof(alertdata.blob_length) + len);
738
739
740 write_len = write_len + sizeof(alertdata) + len;
741 alertHdr.event_type = htonl(EVENT_TYPE_EXTRA_DATA);
742 alertHdr.event_length = htonl(write_len - sizeof(Serial_Unified2_Header));
743
744
745 if ((config->current + write_len) > config->limit)
746 Unified2RotateFile(config);
747
748 hdr.length = htonl(write_len - sizeof(Serial_Unified2_Header));
749 hdr.type = htonl(UNIFIED2_EXTRA_DATA);
750
751 write_end = write_buffer + sizeof(write_buffer);
752
753
754 ptr = write_buffer;
755
756 if (SafeMemcpy(ptr, &hdr, sizeof(hdr),
757 write_buffer, write_end) != SAFEMEM_SUCCESS)
758 {
759 ErrorMessage("%s(%d) Failed to copy Serial_Unified2_Header. "
760 "Not writing unified2 event.\n", __FILE__, __LINE__);
761 return;
762 }
763
764 ptr = ptr + sizeof(hdr);
765
766 if (SafeMemcpy(ptr, &alertHdr, sizeof(alertHdr),
767 write_buffer, write_end) != SAFEMEM_SUCCESS)
768 {
769 ErrorMessage("%s(%d) Failed to copy Unified2ExtraDataHdr. "
770 "Not writing unified2 event.\n", __FILE__, __LINE__);
771 return;
772 }
773
774 ptr = ptr + sizeof(alertHdr);
775
776 if (SafeMemcpy(ptr, &alertdata, sizeof(alertdata),
777 write_buffer, write_end) != SAFEMEM_SUCCESS)
778 {
779 ErrorMessage("%s(%d) Failed to copy SerialUnified2ExtraData. "
780 "Not writing unified2 event.\n", __FILE__, __LINE__);
781 return;
782 }
783
784 ptr = ptr + sizeof(alertdata);
785
786 if (SafeMemcpy(ptr, buffer, len,
787 write_buffer, write_end) != SAFEMEM_SUCCESS)
788 {
789 ErrorMessage("%s(%d) Failed to copy Gzip Decompressed Buffer. "
790 "Not writing unified2 event.\n", __FILE__, __LINE__);
791 return;
792 }
793
794 Unified2Write(write_buffer, write_len, config);
795 }
796
AlertExtraData(void * ssnptr,void * data,LogFunction * log_funcs,uint32_t max_count,uint32_t xtradata_mask,uint32_t event_id,uint32_t event_second)797 static void AlertExtraData(
798 void *ssnptr, void *data,
799 LogFunction *log_funcs, uint32_t max_count,
800 uint32_t xtradata_mask,
801 uint32_t event_id, uint32_t event_second)
802 {
803 Unified2Config *config = (Unified2Config *)data;
804 uint32_t xid;
805
806 if((config == NULL) || !xtradata_mask || !event_second)
807 return;
808
809 xid = ffs(xtradata_mask);
810
811 while ( xid && (xid <= max_count) )
812 {
813 uint32_t len = 0;
814 uint32_t type = 0;
815 uint8_t *write_buffer;
816
817 if ( log_funcs[xid-1](ssnptr, &write_buffer, &len, &type) && (len > 0) )
818 {
819 _WriteExtraData(config, event_id, event_second, write_buffer, len, type);
820 }
821 xtradata_mask ^= BIT(xid);
822 xid = ffs(xtradata_mask);
823 }
824 }
825
Unified2LogAlert(Packet * p,const char * msg,void * arg,Event * event)826 static void Unified2LogAlert(Packet *p, const char *msg, void *arg, Event *event)
827 {
828 Unified2Config *config = (Unified2Config *)arg;
829
830 if (config == NULL)
831 return;
832
833 if(!event) return;
834
835 if(IS_IP4(p))
836 {
837 #ifdef MPLS
838 #if !defined(FEAT_OPEN_APPID)
839 if((config->vlan_event_types) || (config->mpls_event_types))
840 #else /* defined(FEAT_OPEN_APPID) */
841 if((config->vlan_event_types) || (config->mpls_event_types) || (config->appid_event_types))
842 #endif /* defined(FEAT_OPEN_APPID) */
843 #else
844 #if !defined(FEAT_OPEN_APPID)
845 if(config->vlan_event_types)
846 #else /* defined(FEAT_OPEN_APPID) */
847 if(config->vlan_event_types || config->appid_event_types)
848 #endif /* defined(FEAT_OPEN_APPID) */
849 #endif
850 {
851 _AlertIP4_v2(p, msg, config, event);
852 }
853 else
854 _AlertIP4(p, msg, config, event);
855 }
856 else
857 {
858 #ifdef MPLS
859 #if !defined(FEAT_OPEN_APPID)
860 if((config->vlan_event_types) || (config->mpls_event_types))
861 #else /* defined(FEAT_OPEN_APPID) */
862 if((config->vlan_event_types) || (config->mpls_event_types) || (config->appid_event_types))
863 #endif /* defined(FEAT_OPEN_APPID) */
864 #else
865 #if !defined(FEAT_OPEN_APPID)
866 if(config->vlan_event_types)
867 #else /* defined(FEAT_OPEN_APPID) */
868 if(config->vlan_event_types || config->appid_event_types)
869 #endif /* defined(FEAT_OPEN_APPID) */
870 #endif
871 {
872 _AlertIP6_v2(p, msg, config, event);
873 }
874 else
875 _AlertIP6(p, msg, config, event);
876
877 if(ScLogIPv6Extra() && IS_IP6(p))
878 {
879 sfaddr_t* ip = GET_SRC_IP(p);
880 _WriteExtraData(config, event->event_id, event->ref_time.tv_sec,
881 (uint8_t*)sfaddr_get_ip6_ptr(ip), sizeof(struct in6_addr), EVENT_INFO_IPV6_SRC);
882 ip = GET_DST_IP(p);
883 _WriteExtraData(config, event->event_id, event->ref_time.tv_sec,
884 (uint8_t*)sfaddr_get_ip6_ptr(ip), sizeof(struct in6_addr), EVENT_INFO_IPV6_DST);
885 }
886 }
887
888 if ( p->ssnptr )
889 stream_api->update_session_alert(
890 p->ssnptr, p, event->sig_generator, event->sig_id,
891 event->event_id, event->ref_time.tv_sec);
892
893 if ( p->xtradata_mask && !(p->packet_flags & PKT_STREAM_INSERT)
894 && !(p->packet_flags & PKT_REBUILT_STREAM) )
895 {
896 LogFunction *log_funcs;
897 uint32_t max_count = stream_api->get_xtra_data_map(&log_funcs);
898
899 if ( max_count > 0 )
900 AlertExtraData(
901 p->ssnptr, config, log_funcs, max_count, p->xtradata_mask,
902 event->event_id, event->ref_time.tv_sec);
903 }
904
905 return;
906 }
907
Unified2LogPacketAlert(Packet * p,const char * msg,void * arg,Event * event)908 static void Unified2LogPacketAlert(Packet *p, const char *msg, void *arg, Event *event)
909 {
910 Unified2Config *config = (Unified2Config *)arg;
911
912 if (config == NULL)
913 return;
914
915 if(p)
916 {
917 if ((p->packet_flags & PKT_REBUILT_STREAM) && stream_api)
918 {
919 DEBUG_WRAP(DebugMessage(DEBUG_LOG,
920 "[*] Reassembled packet, dumping stream packets\n"););
921 _Unified2LogStreamAlert(p, msg, config, event);
922 }
923 else
924 {
925 DEBUG_WRAP(DebugMessage(DEBUG_LOG, "[*] Logging unified 2 packets...\n"););
926 _Unified2LogPacketAlert(p, msg, config, event);
927 }
928 }
929 }
930
_Unified2LogPacketAlert(Packet * p,const char * msg,Unified2Config * config,Event * event)931 static void _Unified2LogPacketAlert(Packet *p, const char *msg,
932 Unified2Config *config, Event *event)
933 {
934 Serial_Unified2_Header hdr;
935 Serial_Unified2Packet logheader;
936 uint32_t pkt_length = 0;
937 uint32_t write_len = sizeof(Serial_Unified2_Header) + sizeof(Serial_Unified2Packet) - 4;
938
939 logheader.sensor_id = 0;
940 logheader.linktype = config->base_proto;
941
942 if (event != NULL)
943 {
944 logheader.event_id = htonl(event->event_reference);
945 logheader.event_second = htonl(event->ref_time.tv_sec);
946
947 DEBUG_WRAP(DebugMessage(DEBUG_LOG, "------------\n"));
948 }
949 else
950 {
951 logheader.event_id = 0;
952 logheader.event_second = 0;
953 }
954
955 if ((p != NULL) && (p->pkt != NULL) && (p->pkth != NULL)
956 && obApi->payloadObfuscationRequired(p))
957 {
958 Unified2LogCallbackData unifiedData;
959
960 unifiedData.logheader = &logheader;
961 unifiedData.config = config;
962 unifiedData.event = event;
963 unifiedData.num_bytes = 0;
964
965 if (obApi->obfuscatePacket(p, Unified2LogObfuscationCallback,
966 (void *)&unifiedData) == OB_RET_SUCCESS)
967 {
968 /* Write the last record */
969 if (unifiedData.num_bytes != 0)
970 Unified2Write(write_pkt_buffer, unifiedData.num_bytes, config);
971 return;
972 }
973 }
974
975 if(p && p->pkt && p->pkth)
976 {
977 logheader.packet_second = htonl((uint32_t)p->pkth->ts.tv_sec);
978 logheader.packet_microsecond = htonl((uint32_t)p->pkth->ts.tv_usec);
979 logheader.packet_length = htonl(p->pkth->caplen);
980
981 pkt_length = p->pkth->caplen;
982 write_len += pkt_length;
983 }
984 else
985 {
986 logheader.packet_second = 0;
987 logheader.packet_microsecond = 0;
988 logheader.packet_length = 0;
989 }
990
991 if ((config->current + write_len) > config->limit)
992 Unified2RotateFile(config);
993
994 hdr.length = htonl(sizeof(Serial_Unified2Packet) - 4 + pkt_length);
995 hdr.type = htonl(UNIFIED2_PACKET);
996
997 if (SafeMemcpy(write_pkt_buffer, &hdr, sizeof(Serial_Unified2_Header),
998 write_pkt_buffer, write_pkt_end) != SAFEMEM_SUCCESS)
999 {
1000 ErrorMessage("%s(%d) Failed to copy Serial_Unified2_Header. "
1001 "Not writing unified2 event.\n", __FILE__, __LINE__);
1002 return;
1003 }
1004
1005 if (SafeMemcpy(write_pkt_buffer + sizeof(Serial_Unified2_Header),
1006 &logheader, sizeof(Serial_Unified2Packet) - 4,
1007 write_pkt_buffer, write_pkt_end) != SAFEMEM_SUCCESS)
1008 {
1009 ErrorMessage("%s(%d) Failed to copy Serial_Unified2Packet. "
1010 "Not writing unified2 event.\n", __FILE__, __LINE__);
1011 return;
1012 }
1013
1014 if (pkt_length != 0)
1015 {
1016 if (SafeMemcpy(write_pkt_buffer + sizeof(Serial_Unified2_Header) +
1017 sizeof(Serial_Unified2Packet) - 4,
1018 p->pkt, pkt_length,
1019 write_pkt_buffer, write_pkt_end) != SAFEMEM_SUCCESS)
1020 {
1021 ErrorMessage("%s(%d) Failed to copy packet data. "
1022 "Not writing unified2 event.\n", __FILE__, __LINE__);
1023 return;
1024 }
1025 }
1026
1027 Unified2Write(write_pkt_buffer, write_len, config);
1028
1029 if ( p->xtradata_mask && (Active_GetDisposition() >= ACTIVE_DROP) )
1030 {
1031 LogFunction *log_funcs;
1032 uint32_t max_count = stream_api->get_xtra_data_map(&log_funcs);
1033
1034 if ( max_count > 0 )
1035 AlertExtraData(
1036 p->ssnptr, config, log_funcs, max_count, p->xtradata_mask,
1037 event->event_id, event->ref_time.tv_sec);
1038 }
1039 }
1040
1041 /**
1042 * Callback for the Stream reassembler to log packets
1043 *
1044 */
Unified2LogStreamCallback(DAQ_PktHdr_t * pkth,uint8_t * packet_data,void * userdata)1045 static int Unified2LogStreamCallback(DAQ_PktHdr_t *pkth,
1046 uint8_t *packet_data, void *userdata)
1047 {
1048 Unified2LogCallbackData *unifiedData = (Unified2LogCallbackData *)userdata;
1049 Serial_Unified2_Header hdr;
1050 uint32_t write_len = sizeof(Serial_Unified2_Header) + sizeof(Serial_Unified2Packet) - 4;
1051
1052 if (!userdata || !pkth || !packet_data)
1053 return -1;
1054
1055 write_len += pkth->caplen;
1056 if ((unifiedData->config->current + write_len) > unifiedData->config->limit)
1057 Unified2RotateFile(unifiedData->config);
1058
1059 hdr.type = htonl(UNIFIED2_PACKET);
1060 hdr.length = htonl(sizeof(Serial_Unified2Packet) - 4 + pkth->caplen);
1061
1062 /* Event data will already be set */
1063
1064 unifiedData->logheader->packet_second = htonl((uint32_t)pkth->ts.tv_sec);
1065 unifiedData->logheader->packet_microsecond = htonl((uint32_t)pkth->ts.tv_usec);
1066 unifiedData->logheader->packet_length = htonl(pkth->caplen);
1067
1068 if (SafeMemcpy(write_pkt_buffer, &hdr, sizeof(Serial_Unified2_Header),
1069 write_pkt_buffer, write_pkt_end) != SAFEMEM_SUCCESS)
1070 {
1071 ErrorMessage("%s(%d) Failed to copy Serial_Unified2_Header. "
1072 "Not writing unified2 event.\n", __FILE__, __LINE__);
1073 return -1;
1074 }
1075
1076 if (SafeMemcpy(write_pkt_buffer + sizeof(Serial_Unified2_Header),
1077 unifiedData->logheader, sizeof(Serial_Unified2Packet) - 4,
1078 write_pkt_buffer, write_pkt_end) != SAFEMEM_SUCCESS)
1079 {
1080 ErrorMessage("%s(%d) Failed to copy Serial_Unified2Packet. "
1081 "Not writing unified2 event.\n", __FILE__, __LINE__);
1082 return -1;
1083 }
1084
1085 if (SafeMemcpy(write_pkt_buffer + sizeof(Serial_Unified2_Header) +
1086 sizeof(Serial_Unified2Packet) - 4,
1087 packet_data, pkth->caplen,
1088 write_pkt_buffer, write_pkt_end) != SAFEMEM_SUCCESS)
1089 {
1090 ErrorMessage("%s(%d) Failed to copy packet data. "
1091 "Not writing unified2 event.\n", __FILE__, __LINE__);
1092 return -1;
1093 }
1094
1095 Unified2Write(write_pkt_buffer, write_len, unifiedData->config);
1096
1097 #if 0
1098 /* DO NOT DO THIS FOR UNIFIED2.
1099 * The event referenced below in the unifiedData is a pointer
1100 * to the actual event and this changes its gid & sid to 2:1.
1101 * That is baaaaad.
1102 */
1103 /* after the first logged packet modify the event headers */
1104 if(!unifiedData->once++)
1105 {
1106 unifiedData->event->sig_generator = GENERATOR_TAG;
1107 unifiedData->event->sig_id = TAG_LOG_PKT;
1108 unifiedData->event->sig_rev = 1;
1109 unifiedData->event->classification = 0;
1110 unifiedData->event->priority = unifiedData->event->priority;
1111 /* Note that event_id is now incorrect.
1112 * See OldUnified2LogPacketAlert() for details. */
1113 }
1114 #endif
1115
1116 return 0;
1117 }
1118
Unified2LogObfuscationCallback(const DAQ_PktHdr_t * pkth,const uint8_t * packet_data,ob_size_t length,ob_char_t ob_char,void * userdata)1119 static ObRet Unified2LogObfuscationCallback(const DAQ_PktHdr_t *pkth,
1120 const uint8_t *packet_data, ob_size_t length,
1121 ob_char_t ob_char, void *userdata)
1122 {
1123 Unified2LogCallbackData *unifiedData = (Unified2LogCallbackData *)userdata;
1124
1125 if (userdata == NULL)
1126 return OB_RET_ERROR;
1127
1128 if (pkth != NULL)
1129 {
1130 Serial_Unified2_Header hdr;
1131 uint32_t record_len = (pkth->caplen + sizeof(Serial_Unified2_Header)
1132 + (sizeof(Serial_Unified2Packet) - 4));
1133
1134 /* Write the last buffer if present. Want to write an entire record
1135 * at a time in case of failures, we don't corrupt the log file. */
1136 if (unifiedData->num_bytes != 0)
1137 Unified2Write(write_pkt_buffer, unifiedData->num_bytes, unifiedData->config);
1138
1139 if ((write_pkt_buffer + record_len) > write_pkt_end)
1140 {
1141 ErrorMessage("%s(%d) Too much data. Not writing unified2 event.\n",
1142 __FILE__, __LINE__);
1143 return OB_RET_ERROR;
1144 }
1145
1146 if ((unifiedData->config->current + record_len) > unifiedData->config->limit)
1147 Unified2RotateFile(unifiedData->config);
1148
1149 hdr.type = htonl(UNIFIED2_PACKET);
1150 hdr.length = htonl((sizeof(Serial_Unified2Packet) - 4) + pkth->caplen);
1151
1152 /* Event data will already be set */
1153
1154 unifiedData->logheader->packet_second = htonl((uint32_t)pkth->ts.tv_sec);
1155 unifiedData->logheader->packet_microsecond = htonl((uint32_t)pkth->ts.tv_usec);
1156 unifiedData->logheader->packet_length = htonl(pkth->caplen);
1157
1158 if (SafeMemcpy(write_pkt_buffer, &hdr, sizeof(Serial_Unified2_Header),
1159 write_pkt_buffer, write_pkt_end) != SAFEMEM_SUCCESS)
1160 {
1161 ErrorMessage("%s(%d) Failed to copy Serial_Unified2_Header. "
1162 "Not writing unified2 event.\n", __FILE__, __LINE__);
1163 return OB_RET_ERROR;
1164 }
1165
1166 if (SafeMemcpy(write_pkt_buffer + sizeof(Serial_Unified2_Header),
1167 unifiedData->logheader, sizeof(Serial_Unified2Packet) - 4,
1168 write_pkt_buffer, write_pkt_end) != SAFEMEM_SUCCESS)
1169 {
1170 ErrorMessage("%s(%d) Failed to copy Serial_Unified2Packet. "
1171 "Not writing unified2 event.\n", __FILE__, __LINE__);
1172 return OB_RET_ERROR;
1173 }
1174
1175 /* Reset this for the new record */
1176 unifiedData->num_bytes = (record_len - pkth->caplen);
1177 }
1178
1179 if (packet_data != NULL)
1180 {
1181 if (SafeMemcpy(write_pkt_buffer + unifiedData->num_bytes,
1182 packet_data, (size_t)length,
1183 write_pkt_buffer, write_pkt_end) != SAFEMEM_SUCCESS)
1184 {
1185 ErrorMessage("%s(%d) Failed to copy packet data "
1186 "Not writing unified2 event.\n", __FILE__, __LINE__);
1187 return OB_RET_ERROR;
1188 }
1189 }
1190 else
1191 {
1192 if (SafeMemset(write_pkt_buffer + unifiedData->num_bytes,
1193 (uint8_t)ob_char, (size_t)length,
1194 write_pkt_buffer, write_pkt_end) != SAFEMEM_SUCCESS)
1195 {
1196 ErrorMessage("%s(%d) Failed to obfuscate packet data "
1197 "Not writing unified2 event.\n", __FILE__, __LINE__);
1198 return OB_RET_ERROR;
1199 }
1200 }
1201
1202 unifiedData->num_bytes += length;
1203
1204 return OB_RET_SUCCESS;
1205 }
1206
1207
1208 /**
1209 * Log a set of packets stored in the stream reassembler
1210 *
1211 */
_Unified2LogStreamAlert(Packet * p,const char * msg,Unified2Config * config,Event * event)1212 static void _Unified2LogStreamAlert(Packet *p, const char *msg, Unified2Config *config, Event *event)
1213 {
1214 Unified2LogCallbackData unifiedData;
1215 Serial_Unified2Packet logheader;
1216
1217 logheader.sensor_id = 0;
1218 logheader.linktype = config->base_proto;
1219
1220 /* setup the event header */
1221 if (event != NULL)
1222 {
1223 logheader.event_id = htonl(event->event_reference);
1224 logheader.event_second = htonl(event->ref_time.tv_sec);
1225 }
1226 else
1227 {
1228 logheader.event_id = 0;
1229 logheader.event_second = 0;
1230 }
1231
1232 /* queue up the stream for logging */
1233 unifiedData.logheader = &logheader;
1234 unifiedData.config = config;
1235 unifiedData.event = event;
1236 unifiedData.num_bytes = 0;
1237
1238 if ((p != NULL) && (p->pkt != NULL) && (p->pkth != NULL)
1239 && obApi->payloadObfuscationRequired(p))
1240 {
1241 if (obApi->obfuscatePacketStreamSegments(p, Unified2LogObfuscationCallback,
1242 (void *)&unifiedData) == OB_RET_SUCCESS)
1243 {
1244 /* Write the last record */
1245 if (unifiedData.num_bytes != 0)
1246 Unified2Write(write_pkt_buffer, unifiedData.num_bytes, config);
1247 return;
1248 }
1249
1250 /* Reset since we failed */
1251 unifiedData.num_bytes = 0;
1252 }
1253
1254 if (!p)
1255 return;
1256
1257 stream_api->traverse_reassembled(p, Unified2LogStreamCallback, &unifiedData);
1258 }
1259
1260 /*
1261 * Function: Unified2ParseArgs(char *)
1262 *
1263 * Purpose: Process the preprocessor arguments from the rules file and
1264 * initialize the preprocessor's data struct. This function doesn't
1265 * have to exist if it makes sense to parse the args in the init
1266 * function.
1267 *
1268 * Arguments: args => argument list
1269 *
1270 * Returns: void function
1271 *
1272 */
Unified2ParseArgs(char * args,char * default_filename)1273 static Unified2Config * Unified2ParseArgs(char *args, char *default_filename)
1274 {
1275 Unified2Config *config = (Unified2Config *)SnortAlloc(sizeof(Unified2Config));
1276
1277 /* This is so the if 'nostamps' option is used on the command line,
1278 * it will be honored by unified2, and only one variable is used. */
1279 config->nostamp = ScNoOutputTimestamp();
1280
1281 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Args: %s\n", args););
1282
1283 if(args != NULL)
1284 {
1285 char **toks;
1286 int num_toks;
1287 int i = 0;
1288 toks = mSplit((char *)args, ",", 31, &num_toks, '\\');
1289 for(i = 0; i < num_toks; ++i)
1290 {
1291 char **stoks;
1292 int num_stoks;
1293 char *index = toks[i];
1294 while(isspace((int)*index))
1295 ++index;
1296
1297 stoks = mSplit(index, " \t", 2, &num_stoks, 0);
1298
1299 if(strcasecmp("filename", stoks[0]) == 0)
1300 {
1301 if(num_stoks > 1 && config->base_filename == NULL)
1302 config->base_filename = SnortStrdup(stoks[1]);
1303 else
1304 FatalError("Argument Error in %s(%i): %s\n",
1305 file_name, file_line, index);
1306 }
1307 else if(strcasecmp("limit", stoks[0]) == 0)
1308 {
1309 char *end;
1310
1311 if ((num_stoks > 1) && (config->limit == 0))
1312 {
1313 config->limit = SnortStrtoul(stoks[1], &end, 10);
1314 if ((stoks[1] == end) || (errno == ERANGE))
1315 {
1316 FatalError("Argument Error in %s(%i): %s\n",
1317 file_name, file_line, index);
1318 }
1319 }
1320 else
1321 {
1322 FatalError("Argument Error in %s(%i): %s\n",
1323 file_name, file_line, index);
1324 }
1325 }
1326 else if(strcasecmp("nostamp", stoks[0]) == 0)
1327 {
1328 config->nostamp = 1;
1329 }
1330 #ifdef MPLS
1331 else if(strcasecmp("mpls_event_types", stoks[0]) == 0)
1332 {
1333 config->mpls_event_types = 1;
1334 }
1335 #endif
1336 else if(strcasecmp("vlan_event_types", stoks[0]) == 0)
1337 {
1338 config->vlan_event_types = 1;
1339 #if defined(FEAT_OPEN_APPID)
1340 }
1341 else if(strcasecmp("appid_event_types", stoks[0]) == 0)
1342 {
1343 config->appid_event_types = 1;
1344 #endif /* defined(FEAT_OPEN_APPID) */
1345 }
1346 else
1347 {
1348 FatalError("Argument Error in %s(%i): %s\n",
1349 file_name, file_line, index);
1350 }
1351
1352 mSplitFree(&stoks, num_stoks);
1353 }
1354 mSplitFree(&toks, num_toks);
1355 }
1356
1357 if (config->base_filename == NULL)
1358 config->base_filename = SnortStrdup(default_filename);
1359
1360 if (config->limit == 0)
1361 {
1362 config->limit = 128;
1363 }
1364 else if (config->limit > 512)
1365 {
1366 LogMessage("spo_unified2 %s(%d)=> Lowering limit of %iMB to 512MB\n",
1367 file_name, file_line, config->limit);
1368 config->limit = 512;
1369 }
1370
1371 /* convert the limit to "MB" */
1372 config->limit <<= 20;
1373
1374 return config;
1375 }
1376
1377 /*
1378 * Function: Unified2CleanExitFunc()
1379 *
1380 * Purpose: Cleanup at exit time
1381 *
1382 * Arguments: signal => signal that caused this event
1383 * arg => data ptr to reference this plugin's data
1384 *
1385 * Returns: void function
1386 */
Unified2CleanExit(int signal,void * arg)1387 static void Unified2CleanExit(int signal, void *arg)
1388 {
1389 /* cast the arg pointer to the proper type */
1390 Unified2Config *config = (Unified2Config *)arg;
1391
1392 DEBUG_WRAP(DebugMessage(DEBUG_FLOW, "SpoUnified2: CleanExit\n"););
1393
1394 /* free up initialized memory */
1395 if (config != NULL)
1396 {
1397 if (config->stream != NULL)
1398 fclose(config->stream);
1399
1400 if (config->base_filename != NULL)
1401 free(config->base_filename);
1402
1403 free(config);
1404 }
1405 }
1406
1407 #ifdef SNORT_RELOAD
1408 /*
1409 * Function: Reload()
1410 *
1411 * Purpose: For reloads (SIGHUP usually), over the output
1412 *
1413 * Arguments: signal => signal that caused this event
1414 * arg => data ptr to reference this plugin's data
1415 *
1416 * Returns: void function
1417 */
Unified2Reload(struct _SnortConfig * sc,int signal,void * arg)1418 static void Unified2Reload(struct _SnortConfig *sc, int signal, void *arg)
1419 {
1420 Unified2Config *config = (Unified2Config *)arg;
1421
1422 DEBUG_WRAP(DebugMessage(DEBUG_FLOW, "SpoUnified2: Reload\n"););
1423
1424 Unified2RotateFile(config);
1425 }
1426 #endif
1427
1428 /* Unified2 Alert functions (deprecated) */
Unified2AlertInit(struct _SnortConfig * sc,char * args)1429 static void Unified2AlertInit(struct _SnortConfig *sc, char *args)
1430 {
1431 Unified2Config *config;
1432 int signal = 0;
1433
1434 DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Output: Unified2 Alert Initialized\n"););
1435
1436 /* parse the argument list from the rules file */
1437 config = Unified2ParseArgs(args, "snort-unified.alert");
1438
1439 alert_config = config;
1440
1441 if(log_config && log_config->base_filename)
1442 {
1443 if(strcmp(config->base_filename, log_config->base_filename) == 0)
1444 {
1445 Unified2CleanExit(signal , (void *)log_config);
1446 Unified2CleanExit(signal, (void *)config);
1447 FatalError("Argument Error in %s(%i). Cannot reuse the filename in config option '%s'\n",
1448 file_name, file_line, "alert_unified2");
1449 }
1450 }
1451
1452 /* Set the preprocessor function into the function list */
1453 AddFuncToOutputList(sc, Unified2LogAlert, OUTPUT_TYPE__ALERT, config);
1454 AddFuncToCleanExitList(Unified2CleanExit, config);
1455 #ifdef SNORT_RELOAD
1456 AddFuncToReloadList(Unified2Reload, config);
1457 #endif
1458 AddFuncToPostConfigList(sc, Unified2PostConfig, config);
1459 }
1460
1461 /* Unified2 Packet Log functions (deprecated) */
Unified2LogInit(struct _SnortConfig * sc,char * args)1462 static void Unified2LogInit(struct _SnortConfig *sc, char *args)
1463 {
1464 Unified2Config *config;
1465 int signal = 0;
1466
1467 DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Output: Unified2 Log Initialized\n"););
1468
1469 /* parse the argument list from the rules file */
1470 config = Unified2ParseArgs(args, "snort-unified.log");
1471
1472 log_config = config;
1473
1474 if(alert_config && alert_config->base_filename)
1475 {
1476 if(strcmp(config->base_filename, alert_config->base_filename) == 0)
1477 {
1478 Unified2CleanExit(signal, (void *)alert_config);
1479 Unified2CleanExit(signal, (void *)config);
1480 FatalError("Argument Error in %s(%i). Cannot reuse the filename in config option '%s'\n",
1481 file_name, file_line, "log_unified2");
1482 }
1483 }
1484
1485 //LogMessage("Unified2LogFilename = %s\n", Unified2Info->filename);
1486
1487 /* Set the preprocessor function into the function list */
1488 AddFuncToOutputList(sc, Unified2LogPacketAlert, OUTPUT_TYPE__LOG, config);
1489 AddFuncToCleanExitList(Unified2CleanExit, config);
1490 #ifdef SNORT_RELOAD
1491 AddFuncToReloadList(Unified2Reload, config);
1492 #endif
1493 AddFuncToPostConfigList(sc, Unified2PostConfig, config);
1494 }
1495
1496 /******************************************************************************
1497 * Function: Unified2Write()
1498 *
1499 * Main function for writing to the unified2 file.
1500 *
1501 * For low level I/O errors, the current unified2 file is closed and a new
1502 * one created and a write to the new unified2 file is done. It was found
1503 * that when writing to an NFS mounted share that is using a soft mount option,
1504 * writes sometimes fail and leave the unified2 file corrupted. If the write
1505 * to the newly created unified2 file fails, Snort will fatal error.
1506 *
1507 * In the case of interrupt errors, the write is retried, but only for a
1508 * finite number of times.
1509 *
1510 * All other errors are treated as non-recoverable and Snort will fatal error.
1511 *
1512 * Upon successful completion of write, the length of the data written is
1513 * added to the current amount of total data written thus far to the
1514 * unified2 file.
1515 *
1516 * Arguments
1517 * uint8_t *
1518 * The buffer containing the data to write
1519 * uint32_t
1520 * The length of the data to write
1521 * Unified2Config *
1522 * A pointer to the unified2 configuration data
1523 *
1524 * Returns: None
1525 *
1526 ******************************************************************************/
Unified2Write(uint8_t * buf,uint32_t buf_len,Unified2Config * config)1527 static void Unified2Write(uint8_t *buf, uint32_t buf_len, Unified2Config *config)
1528 {
1529 size_t fwcount = 0;
1530 int ffstatus = 0;
1531
1532 /* Nothing to write or nothing to write to */
1533 if ((buf == NULL) || (config == NULL) || (config->stream == NULL))
1534 return;
1535
1536 /* Don't use fsync(). It is a total performance killer */
1537 if (((fwcount = fwrite(buf, (size_t)buf_len, 1, config->stream)) != 1) ||
1538 ((ffstatus = fflush(config->stream)) != 0))
1539 {
1540 /* errno is saved just to avoid other intervening calls
1541 * (e.g. ErrorMessage) potentially reseting it to something else. */
1542 int error = errno;
1543 int max_retries = 3;
1544
1545 /* On iterations other than the first, the only non-zero error will be
1546 * EINTR or interrupt. Only iterate a maximum of max_retries times so
1547 * there is no chance of infinite looping if for some reason the write
1548 * is constantly interrupted */
1549 while ((error != 0) && (max_retries != 0))
1550 {
1551 if (config->nostamp)
1552 {
1553 ErrorMessage("%s(%d) Failed to write to unified2 file (%s): %s\n",
1554 __FILE__, __LINE__, config->filepath, strerror(error));
1555 }
1556 else
1557 {
1558 ErrorMessage("%s(%d) Failed to write to unified2 file (%s.%u): %s\n",
1559 __FILE__, __LINE__, config->filepath,
1560 config->timestamp, strerror(error));
1561 }
1562
1563 while ((error == EINTR) && (max_retries != 0))
1564 {
1565 max_retries--;
1566
1567 /* Supposedly an interrupt can only occur before anything
1568 * has been written. Try again */
1569 ErrorMessage("%s(%d) Got interrupt. Retry write to unified2 "
1570 "file.\n", __FILE__, __LINE__);
1571
1572 if (fwcount != 1)
1573 {
1574 /* fwrite() failed. Redo fwrite and fflush */
1575 if (((fwcount = fwrite(buf, (size_t)buf_len, 1, config->stream)) == 1) &&
1576 ((ffstatus = fflush(config->stream)) == 0))
1577 {
1578 ErrorMessage("%s(%d) Write to unified2 file succeeded!\n",
1579 __FILE__, __LINE__);
1580 error = 0;
1581 break;
1582 }
1583 }
1584 else if ((ffstatus = fflush(config->stream)) == 0)
1585 {
1586 ErrorMessage("%s(%d) Write to unified2 file succeeded!\n",
1587 __FILE__, __LINE__);
1588 error = 0;
1589 break;
1590 }
1591
1592 error = errno;
1593
1594 ErrorMessage("%s(%d) Retrying write to unified2 file failed.\n",
1595 __FILE__, __LINE__);
1596 }
1597
1598 /* If we've reached the maximum number of interrupt retries,
1599 * just bail out of the main while loop */
1600 if (max_retries == 0)
1601 continue;
1602
1603 switch (error)
1604 {
1605 case 0:
1606 break;
1607
1608 case EIO:
1609 ErrorMessage("%s(%d) Unified2 file is possibly corrupt. "
1610 "Closing this unified2 file and creating "
1611 "a new one.\n", __FILE__, __LINE__);
1612
1613 Unified2RotateFile(config);
1614
1615 if (config->nostamp)
1616 {
1617 ErrorMessage("%s(%d) New unified2 file: %s\n",
1618 __FILE__, __LINE__, config->filepath);
1619 }
1620 else
1621 {
1622 ErrorMessage("%s(%d) New unified2 file: %s.%u\n",
1623 __FILE__, __LINE__,
1624 config->filepath, config->timestamp);
1625 }
1626
1627 if (((fwcount = fwrite(buf, (size_t)buf_len, 1, config->stream)) == 1) &&
1628 ((ffstatus = fflush(config->stream)) == 0))
1629 {
1630 ErrorMessage("%s(%d) Write to unified2 file succeeded!\n",
1631 __FILE__, __LINE__);
1632 error = 0;
1633 break;
1634 }
1635
1636 error = errno;
1637
1638 /* Loop again if interrupt */
1639 if (error == EINTR)
1640 break;
1641
1642 /* Write out error message again, then fall through and fatal */
1643 if (config->nostamp)
1644 {
1645 ErrorMessage("%s(%d) Failed to write to unified2 file (%s): %s\n",
1646 __FILE__, __LINE__, config->filepath, strerror(error));
1647 }
1648 else
1649 {
1650 ErrorMessage("%s(%d) Failed to write to unified2 file (%s.%u): %s\n",
1651 __FILE__, __LINE__, config->filepath,
1652 config->timestamp, strerror(error));
1653 }
1654
1655 /* Fall through */
1656
1657 case EAGAIN: /* We're not in non-blocking mode */
1658 case EBADF:
1659 case EFAULT:
1660 case EFBIG:
1661 case EINVAL:
1662 case ENOSPC:
1663 case EPIPE:
1664 default:
1665 FatalError("%s(%d) Cannot write to device.\n", __FILE__, __LINE__);
1666 }
1667 }
1668
1669 if ((max_retries == 0) && (error != 0))
1670 {
1671 FatalError("%s(%d) Maximum number of interrupts exceeded. "
1672 "Cannot write to device.\n", __FILE__, __LINE__);
1673 }
1674 }
1675
1676 config->current += buf_len;
1677 }
1678
1679