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