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 it
6 // under the terms of the GNU General Public License Version 2 as published
7 // by the Free Software Foundation.  You may not use, modify or distribute
8 // this program under any other version of the GNU General Public License.
9 //
10 // This program is distributed in the hope that it will be useful, but
11 // WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 // General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License along
16 // with this program; if not, write to the Free Software Foundation, Inc.,
17 // 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18 //--------------------------------------------------------------------------
19 
20 /* unified2.c
21  * Adam Keeton
22  *
23  * 09/26/06
24  * This file is literally unified.c converted to write unified2
25  *
26  */
27 
28 #ifdef HAVE_CONFIG_H
29 #include "config.h"
30 #endif
31 
32 #include <cassert>
33 
34 #include "detection/signature.h"
35 #include "detection/detection_util.h"
36 #include "events/event.h"
37 #include "framework/logger.h"
38 #include "framework/module.h"
39 #include "log/messages.h"
40 #include "log/obfuscator.h"
41 #include "log/unified2.h"
42 #include "log/u2_packet.h"
43 #include "main/snort_config.h"
44 #include "network_inspectors/appid/appid_api.h"
45 #include "packet_io/active.h"
46 #include "packet_io/sfdaq.h"
47 #include "protocols/icmp4.h"
48 #include "protocols/packet.h"
49 #include "protocols/vlan.h"
50 #include "stream/stream.h"
51 #include "utils/safec.h"
52 #include "utils/util.h"
53 #include "utils/util_cstring.h"
54 
55 using namespace snort;
56 using namespace std;
57 
58 #define S_NAME "unified2"
59 #define F_NAME S_NAME ".log"
60 
61 /* ------------------ Data structures --------------------------*/
62 
63 struct Unified2Config
64 {
65     size_t limit;
66     int nostamp;
67     bool legacy_events;
68 };
69 
70 struct U2
71 {
72     FILE* stream;
73     unsigned int current;
74     int base_proto;
75     uint32_t timestamp;
76     char filepath[STD_BUF];
77 };
78 
79 /* -------------------- Global Variables ----------------------*/
80 
81 static THREAD_LOCAL U2 u2;
82 
83 /* Used for buffering header and payload of unified records so only one
84  * write is necessary. */
85 constexpr unsigned u2_buf_sz =
86     sizeof(Serial_Unified2_Header) + sizeof(Unified2Event) + IP_MAXPACKET;
87 
88 static THREAD_LOCAL uint8_t* write_pkt_buffer = nullptr;
89 
90 #define MAX_XDATA_WRITE_BUF_LEN \
91     (MAX_XFF_WRITE_BUF_LENGTH - \
92     sizeof(struct in6_addr) + DECODE_BLEN)
93 
94 /* This buffer is used in lieu of the underlying default stream buf to
95  * prevent flushing in the middle of a record.  Every write is force
96  * flushed to disk immediately after the entire record is written so
97  * spoolers get an entire record */
98 
99 /* use the size of the buffer we copy record data into */
100 static THREAD_LOCAL char* io_buffer = nullptr;
101 
102 /* -------------------- Local Functions -----------------------*/
103 
104 static void Unified2Write(uint8_t*, uint32_t, Unified2Config*);
105 
Unified2InitFile(Unified2Config * config)106 static void Unified2InitFile(Unified2Config* config)
107 {
108     assert(config);
109 
110     char filepath[STD_BUF];
111     char* fname_ptr;
112 
113     u2.timestamp = (uint32_t)time(nullptr);
114 
115     if (!config->nostamp)
116     {
117         if (SnortSnprintf(filepath, sizeof(filepath), "%s.%u",
118             u2.filepath, u2.timestamp) != SNORT_SNPRINTF_SUCCESS)
119         {
120             FatalError("unified2 failed to copy file path.\n");
121         }
122 
123         fname_ptr = filepath;
124     }
125     else
126     {
127         fname_ptr = u2.filepath;
128     }
129 
130     if ((u2.stream = fopen(fname_ptr, "wb")) == nullptr)
131     {
132         FatalError("unified2 could not open %s: %s\n", fname_ptr, get_error(errno));
133     }
134 
135     /* Set buffer to size of record buffer so the system doesn't flush
136      * part of a record if it's greater than BUFSIZ */
137     if (setvbuf(u2.stream, io_buffer, _IOFBF, u2_buf_sz) != 0)
138     {
139         ErrorMessage("unified2 could not set I/O buffer: %s. "
140             "Using system default.\n", get_error(errno));
141     }
142 }
143 
Unified2RotateFile(Unified2Config * config)144 static inline void Unified2RotateFile(Unified2Config* config)
145 {
146     fclose(u2.stream);
147     u2.current = 0;
148     Unified2InitFile(config);
149 }
150 
get_version(const SfIp & addr)151 static inline unsigned get_version(const SfIp& addr)
152 {
153     uint16_t family = addr.get_family();
154     return (family == AF_INET) ? 0x4 : (family == AF_INET6 ? 0x6 : 0x0);
155 }
156 
copy_addr(const SfIp & src,const SfIp & dst,Unified2Event & e)157 static inline void copy_addr(const SfIp& src, const SfIp& dst, Unified2Event& e)
158 {
159     COPY4(e.pkt_src_ip, src.get_ip6_ptr());
160     COPY4(e.pkt_dst_ip, dst.get_ip6_ptr());
161     e.pkt_ip_ver = (get_version(src) << 4) | get_version(dst);
162 }
163 
alert_event(Packet * p,const char *,Unified2Config * config,const Event * event)164 static void alert_event(Packet* p, const char*, Unified2Config* config, const Event* event)
165 {
166     Unified2Event u2_event;
167     memset(&u2_event, 0, sizeof(u2_event));
168 
169     u2_event.snort_id = 0;  // FIXIT-H alert_event define / use
170 
171     u2_event.event_id = htonl(event->get_event_id());
172     u2_event.event_second = htonl(event->ref_time.tv_sec);
173     u2_event.event_microsecond = htonl(event->ref_time.tv_usec);
174 
175     u2_event.rule_gid = htonl(event->sig_info->gid);
176     u2_event.rule_sid = htonl(event->sig_info->sid);
177     u2_event.rule_rev = htonl(event->sig_info->rev);
178     u2_event.rule_class = htonl(event->sig_info->class_id);
179     u2_event.rule_priority = htonl(event->sig_info->priority);
180 
181     if ( p )
182     {
183         u2_event.policy_id_detect = htonl(p->user_ips_policy_id);
184         u2_event.policy_id_inspect = htonl(p->user_inspection_policy_id);
185         u2_event.policy_id_context = htonl(p->user_network_policy_id);
186 
187         if ( p->ptrs.ip_api.is_ip() )
188             copy_addr(*p->ptrs.ip_api.get_src(), *p->ptrs.ip_api.get_dst(), u2_event);
189 
190         else if (p->flow)
191         {
192             if (p->is_from_application_client())
193                 copy_addr(p->flow->client_ip, p->flow->server_ip, u2_event);
194             else
195                 copy_addr(p->flow->server_ip, p->flow->client_ip, u2_event);
196         }
197 
198         if ( p->type() == PktType::ICMP)
199         {
200             // If PktType == ICMP, icmph is set
201             u2_event.pkt_src_port_itype = htons(p->ptrs.icmph->type);
202             u2_event.pkt_dst_port_icode = htons(p->ptrs.icmph->code);
203         }
204         else
205         {
206             u2_event.pkt_src_port_itype = htons(p->ptrs.sp);
207             u2_event.pkt_dst_port_icode = htons(p->ptrs.dp);
208         }
209 
210         if ( p->proto_bits & PROTO_BIT__MPLS )
211             u2_event.pkt_mpls_label = htonl(p->ptrs.mplsHdr.label);
212 
213         if ( p->proto_bits & PROTO_BIT__VLAN )
214             u2_event.pkt_vlan_id = htons(layer::get_vlan_layer(p)->vid());
215 
216         u2_event.pkt_ip_proto = (uint8_t)p->get_ip_proto_next();
217 
218         const char* app_name = p->flow ?
219             appid_api.get_application_name(*p->flow, p->is_from_client()) : nullptr;
220 
221         if ( app_name )
222             memcpy_s(u2_event.app_name, sizeof(u2_event.app_name),
223                 app_name, strlen(app_name) + 1);
224 
225         u2_event.snort_status = p->active->get_status();
226         u2_event.snort_action = p->active->get_action();
227     }
228 
229     Serial_Unified2_Header hdr;
230     uint32_t write_len = sizeof(hdr) + sizeof(u2_event);
231 
232     if ( config->limit && (u2.current + write_len) > config->limit )
233         Unified2RotateFile(config);
234 
235     hdr.length = htonl(sizeof(Unified2Event));
236     hdr.type = htonl(UNIFIED2_EVENT3);
237 
238     memcpy_s(write_pkt_buffer, u2_buf_sz, &hdr, sizeof(hdr));
239 
240     size_t offset = sizeof(hdr);
241 
242     memcpy_s(write_pkt_buffer + offset, u2_buf_sz - offset, &u2_event, sizeof(u2_event));
243 
244     Unified2Write(write_pkt_buffer, write_len, config);
245 }
246 
_WriteExtraData(Unified2Config * config,uint32_t event_id,uint32_t event_second,const uint8_t * buffer,uint32_t len,uint32_t type)247 static void _WriteExtraData(Unified2Config* config,
248     uint32_t event_id,
249     uint32_t event_second,
250     const uint8_t* buffer,
251     uint32_t len,
252     uint32_t type)
253 {
254     Serial_Unified2_Header hdr;
255     SerialUnified2ExtraData alertdata;
256     Unified2ExtraDataHdr alertHdr;
257     uint8_t write_buffer[MAX_XDATA_WRITE_BUF_LEN];
258     uint8_t* ptr = nullptr;
259 
260     uint32_t write_len = sizeof(hdr) + sizeof(alertHdr);
261 
262     alertdata.sensor_id = 0;
263     alertdata.event_id = htonl(event_id);
264     alertdata.event_second = htonl(event_second);
265     alertdata.data_type = htonl(EVENT_DATA_TYPE_BLOB);
266 
267     alertdata.type = htonl(type);
268     alertdata.blob_length = htonl(sizeof(alertdata.data_type) +
269         sizeof(alertdata.blob_length) + len);
270 
271     write_len = write_len + sizeof(alertdata) + len;
272     alertHdr.event_type = htonl(EVENT_TYPE_EXTRA_DATA);
273     alertHdr.event_length = htonl(write_len - sizeof(hdr));
274 
275     if (write_len > sizeof(write_buffer))
276         return;
277 
278     if ( config->limit && (u2.current + write_len) > config->limit )
279         Unified2RotateFile(config);
280 
281     hdr.length = htonl(write_len - sizeof(hdr));
282     hdr.type = htonl(UNIFIED2_EXTRA_DATA);
283 
284     ptr = write_buffer;
285 
286     memcpy_s(ptr, sizeof(write_buffer), &hdr, sizeof(hdr));
287 
288     size_t offset = sizeof(hdr);
289 
290     memcpy_s(ptr + offset, sizeof(write_buffer) - offset, &alertHdr, sizeof(alertHdr));
291 
292     offset += sizeof(alertHdr);
293 
294     memcpy_s(ptr + offset, sizeof(write_buffer) - offset, &alertdata, sizeof(alertdata));
295 
296     offset += sizeof(alertdata);
297 
298     memcpy_s(ptr + offset, sizeof(write_buffer) - offset, buffer, len);
299 
300     Unified2Write(write_buffer, write_len, config);
301 }
302 
AlertExtraData(Flow * flow,void * data,LogFunction * log_funcs,uint32_t max_count,uint32_t xtradata_mask,uint32_t event_id,uint32_t event_second)303 static void AlertExtraData(
304     Flow* flow, void* data,
305     LogFunction* log_funcs, uint32_t max_count,
306     uint32_t xtradata_mask,
307     uint32_t event_id, uint32_t event_second)
308 {
309     Unified2Config* config = (Unified2Config*)data;
310     uint32_t xid;
311 
312     if ((config == nullptr) || !xtradata_mask || !event_second)
313         return;
314 
315     xid = ffs(xtradata_mask);
316 
317     while ( xid && (xid <= max_count) )
318     {
319         uint32_t len = 0;
320         uint32_t type = 0;
321         uint8_t* write_buffer;
322         LogFunction log_func = log_funcs[xid-1];
323 
324         if ( log_func(flow, &write_buffer, &len, &type) && (len > 0) )
325         {
326             _WriteExtraData(config, event_id, event_second, write_buffer, len, type);
327         }
328         xtradata_mask ^= BIT(xid);
329         xid = ffs(xtradata_mask);
330     }
331 }
332 
_Unified2LogPacketAlert(Packet * p,const char *,Unified2Config * config,const Event * event,unsigned u2_type,U2PseudoHeader * u2h=nullptr)333 static void _Unified2LogPacketAlert(
334     Packet* p, const char*, Unified2Config* config, const Event* event,
335     unsigned u2_type, U2PseudoHeader* u2h = nullptr)
336 {
337     Serial_Unified2_Header hdr;
338     Serial_Unified2Packet logheader = {};
339 
340     uint32_t pkt_length = 0;
341     uint32_t write_len = sizeof(hdr) + sizeof(Serial_Unified2Packet) - 4;
342     unsigned u2h_len = u2h ? u2h->get_size() : 0;
343 
344     logheader.sensor_id = 0;
345     logheader.linktype = u2.base_proto;
346 
347     logheader.event_id = htonl(event->get_event_reference());
348     logheader.event_second = htonl(event->ref_time.tv_sec);
349 
350     logheader.packet_second = htonl((uint32_t)p->pkth->ts.tv_sec);
351     logheader.packet_microsecond = htonl((uint32_t)p->pkth->ts.tv_usec);
352     pkt_length = ( p->is_rebuilt() ) ? p->dsize : p->pktlen;
353     logheader.packet_length = htonl(pkt_length + u2h_len);
354     write_len += pkt_length + u2h_len;
355 
356     if ( config->limit && (u2.current + write_len) > config->limit )
357         Unified2RotateFile(config);
358 
359     hdr.length = htonl(sizeof(Serial_Unified2Packet) - 4 + pkt_length + u2h_len);
360     hdr.type = htonl(u2_type);
361 
362     memcpy_s(write_pkt_buffer, u2_buf_sz, &hdr, sizeof(hdr));
363     size_t offset = sizeof(hdr);
364 
365     memcpy_s(write_pkt_buffer + offset, u2_buf_sz - offset, &logheader, sizeof(logheader) - 4);
366     offset += sizeof(logheader) - 4;
367 
368     if ( u2h_len > 0 )
369     {
370         assert(u2_buf_sz - offset > u2h_len);
371         memcpy_s(write_pkt_buffer + offset, u2_buf_sz - offset, u2h->get_data(), u2h_len);
372         offset += u2h_len;
373     }
374 
375     if (pkt_length != 0)
376     {
377         if (pkt_length > u2_buf_sz - offset)
378             return;
379 
380         uint8_t *start = write_pkt_buffer + offset;
381 
382         memcpy_s(start, u2_buf_sz - offset, p->is_data() ? p->data : p->pkt, pkt_length);
383 
384         if ( p->obfuscator )
385         {
386             off_t off = p->data - p->pkt;
387 
388             if ( p->is_data() )
389                 off = 0;
390 
391             for ( const auto& b : *p->obfuscator )
392                 memset(&start[ off + b.offset ], p->obfuscator->get_mask_char(), b.length);
393         }
394     }
395 
396     Unified2Write(write_pkt_buffer, write_len, config);
397 }
398 
399 /******************************************************************************
400  * Function: Unified2Write()
401  *
402  * Main function for writing to the unified2 file.
403  *
404  * For low level I/O errors, the current unified2 file is closed and a new
405  * one created and a write to the new unified2 file is done.  It was found
406  * that when writing to an NFS mounted share that is using a soft mount option,
407  * writes sometimes fail and leave the unified2 file corrupted.  If the write
408  * to the newly created unified2 file fails, Snort will fatal error.
409  *
410  * In the case of interrupt errors, the write is retried, but only for a
411  * finite number of times.
412  *
413  * All other errors are treated as non-recoverable and Snort will fatal error.
414  *
415  * Upon successful completion of write, the length of the data written is
416  * added to the current amount of total data written thus far to the
417  * unified2 file.
418  *
419  * Arguments
420  *  uint8_t *
421  *      The buffer containing the data to write
422  *  uint32_t
423  *      The length of the data to write
424  *  Unified2Config *
425  *      A pointer to the unified2 configuration data
426  *
427  * Returns: None
428  *
429  ******************************************************************************/
Unified2Write(uint8_t * buf,uint32_t buf_len,Unified2Config * config)430 static void Unified2Write(uint8_t* buf, uint32_t buf_len, Unified2Config* config)
431 {
432     size_t fwcount = 0;
433 
434     /* Nothing to write or nothing to write to */
435     if ((buf == nullptr) || (config == nullptr) || (u2.stream == nullptr))
436         return;
437 
438     /* Don't use fsync().  It is a total performance killer */
439     if (((fwcount = fwrite(buf, (size_t)buf_len, 1, u2.stream)) != 1) ||
440         (fflush(u2.stream) != 0))
441     {
442         /* errno is saved just to avoid other intervening calls
443          * (e.g. ErrorMessage) potentially resetting it to something else. */
444         int error = errno;
445         int max_retries = 3;
446 
447         /* On iterations other than the first, the only non-zero error will be
448          * EINTR or interrupt.  Only iterate a maximum of max_retries times so
449          * there is no chance of infinite looping if for some reason the write
450          * is constantly interrupted */
451         while ((error != 0) && (max_retries != 0))
452         {
453             if (config->nostamp)
454             {
455                 ErrorMessage("unified2 failed to write to file (%s): %s\n",
456                     u2.filepath, get_error(error));
457             }
458             else
459             {
460                 ErrorMessage("unified2 failed to write to file (%s.%u): %s\n",
461                     u2.filepath, u2.timestamp, get_error(error));
462             }
463 
464             while ((error == EINTR) && (max_retries != 0))
465             {
466                 max_retries--;
467 
468                 /* Supposedly an interrupt can only occur before anything
469                  * has been written.  Try again */
470                 if (fwcount != 1)
471                 {
472                     /* fwrite() failed.  Redo fwrite and fflush */
473                     if (((fwcount = fwrite(buf, (size_t)buf_len, 1, u2.stream)) == 1) &&
474                         fflush(u2.stream) == 0)
475                     {
476                         error = 0;
477                         break;
478                     }
479                 }
480                 else if (fflush(u2.stream) == 0)
481                 {
482                     error = 0;
483                     break;
484                 }
485 
486                 error = errno;
487             }
488 
489             /* If we've reached the maximum number of interrupt retries,
490              * just bail out of the main while loop */
491             if (max_retries == 0)
492                 continue;
493 
494             switch (error)
495             {
496             case 0:
497                 break;
498 
499             case EIO:
500                 ErrorMessage("unified2 file is possibly corrupt. "
501                     "Closing this unified2 file and creating a new one.\n");
502 
503                 Unified2RotateFile(config);
504 
505                 if (config->nostamp)
506                 {
507                     ErrorMessage("unified2 rotated file: %s\n", u2.filepath);
508                 }
509                 else
510                 {
511                     ErrorMessage("unified2 rotated file: %s.%u\n", u2.filepath, u2.timestamp);
512                 }
513 
514                 if (((fwcount = fwrite(buf, (size_t)buf_len, 1, u2.stream)) == 1) &&
515                     fflush(u2.stream) == 0)
516                 {
517                     error = 0;
518                     break;
519                 }
520 
521                 error = errno;
522 
523                 /* Loop again if interrupt */
524                 if (error == EINTR)
525                     break;
526 
527                 /* Write out error message again, then fall through and fatal */
528                 if (config->nostamp)
529                 {
530                     ErrorMessage("unified2 failed to write to file (%s): %s\n",
531                         u2.filepath, get_error(error));
532                 }
533                 else
534                 {
535                     ErrorMessage("unified2 failed to write to file (%s.%u): %s\n",
536                         u2.filepath, u2.timestamp, get_error(error));
537                 }
538 
539             /* Fall through */
540 
541             case EAGAIN:      /* We're not in non-blocking mode */
542             case EBADF:
543             case EFAULT:
544             case EFBIG:
545             case EINVAL:
546             case ENOSPC:
547             case EPIPE:
548             default:
549                 FatalError("unified2 cannot write to device.\n");
550             }
551         }
552 
553         if ((max_retries == 0) && (error != 0))
554         {
555             FatalError("unified2 cannot write to device. "
556                 "Maximum number of interrupts exceeded.\n");
557         }
558     }
559 
560     u2.current += buf_len;
561 }
562 
563 //--------------------------------------------------------------------------
564 // legacy event support
565 // FIXIT-L encode pseudo packets for buffers and extra data for out of date
566 //         barnyard2
567 //--------------------------------------------------------------------------
568 
569 #define U2_FLAG_BLOCKED 0x20
570 
571 /* New flags to set the pad field (corresponds to blocked column in UI) with packet action*/
572 #define U2_BLOCKED_FLAG_ALLOW 0x00
573 #define U2_BLOCKED_FLAG_BLOCK 0x01
574 #define U2_BLOCKED_FLAG_WOULD 0x02
575 #define U2_BLOCKED_FLAG_CANT  0x03
576 
577 static int s_blocked_flag[] =
578 {
579     U2_BLOCKED_FLAG_ALLOW,
580     U2_BLOCKED_FLAG_CANT,
581     U2_BLOCKED_FLAG_WOULD,
582     U2_BLOCKED_FLAG_BLOCK,
583 };
584 
GetU2Flags(const Packet * p,uint8_t * pimpact)585 static int GetU2Flags(const Packet* p, uint8_t* pimpact)
586 {
587     Active::ActiveStatus dispos = p->active->get_status();
588 
589     if ( dispos > Active::AST_ALLOW )
590         *pimpact = U2_FLAG_BLOCKED;
591 
592     return s_blocked_flag[dispos];
593 }
594 
_AlertIP4_v2(Packet * p,const char *,Unified2Config * config,const Event * event)595 static void _AlertIP4_v2(Packet* p, const char*, Unified2Config* config, const Event* event)
596 {
597     Serial_Unified2_Header hdr;
598     Unified2IDSEvent alertdata;
599     uint32_t write_len = sizeof(hdr) + sizeof(alertdata);
600 
601     memset(&alertdata, 0, sizeof(alertdata));
602 
603     alertdata.event_id = htonl(event->get_event_id());
604     alertdata.event_second = htonl(event->ref_time.tv_sec);
605     alertdata.event_microsecond = htonl(event->ref_time.tv_usec);
606     alertdata.generator_id = htonl(event->sig_info->gid);
607     alertdata.signature_id = htonl(event->sig_info->sid);
608     alertdata.signature_revision = htonl(event->sig_info->rev);
609     alertdata.classification_id = htonl(event->sig_info->class_id);
610     alertdata.priority_id = htonl(event->sig_info->priority);
611 
612     if (p)
613     {
614         alertdata.blocked = GetU2Flags(p, &alertdata.impact_flag);
615 
616         if (p->has_ip())
617         {
618             const ip::IP4Hdr* const iph = p->ptrs.ip_api.get_ip4h();
619             alertdata.ip_source = iph->get_src();
620             alertdata.ip_destination = iph->get_dst();
621         }
622         else if (p->flow)
623         {
624             if (p->is_from_application_client())
625             {
626                 alertdata.ip_source = *(p->flow->client_ip.get_ip4_ptr());
627                 alertdata.ip_destination = *(p->flow->server_ip.get_ip4_ptr());
628             }
629             else
630             {
631                 alertdata.ip_source = *(p->flow->server_ip.get_ip4_ptr());
632                 alertdata.ip_destination = *(p->flow->client_ip.get_ip4_ptr());
633             }
634         }
635 
636         alertdata.ip_proto = p->get_ip_proto_next();
637 
638         if ( p->type() == PktType::ICMP)
639         {
640             // If PktType == ICMP, icmph is set
641             alertdata.sport_itype = htons(p->ptrs.icmph->type);
642             alertdata.dport_icode = htons(p->ptrs.icmph->code);
643         }
644         else
645         {
646             alertdata.sport_itype = htons(p->ptrs.sp);
647             alertdata.dport_icode = htons(p->ptrs.dp);
648         }
649 
650         if ( p->proto_bits & PROTO_BIT__MPLS )
651             alertdata.mpls_label = htonl(p->ptrs.mplsHdr.label);
652 
653         if (p->proto_bits & PROTO_BIT__VLAN)
654             alertdata.vlanId = htons(layer::get_vlan_layer(p)->vid());
655 
656         alertdata.pad2 = htons((uint16_t)p->user_ips_policy_id);
657 
658         const char* app_name = p->flow ?
659             appid_api.get_application_name(*p->flow, p->is_from_client()) : nullptr;
660 
661         if ( app_name )
662             memcpy_s(alertdata.app_name, sizeof(alertdata.app_name),
663                 app_name, strlen(app_name) + 1);
664     }
665 
666     if ( config->limit && (u2.current + write_len) > config->limit )
667         Unified2RotateFile(config);
668 
669     hdr.length = htonl(sizeof(alertdata));
670     hdr.type = htonl(UNIFIED2_IDS_EVENT_VLAN);
671 
672     memcpy_s(write_pkt_buffer, u2_buf_sz, &hdr, sizeof(hdr));
673 
674     size_t offset = sizeof(hdr);
675 
676     memcpy_s(write_pkt_buffer + offset, u2_buf_sz - offset, &alertdata, sizeof(alertdata));
677 
678     Unified2Write(write_pkt_buffer, write_len, config);
679 }
680 
_AlertIP6_v2(Packet * p,const char *,Unified2Config * config,const Event * event)681 static void _AlertIP6_v2(Packet* p, const char*, Unified2Config* config, const Event* event)
682 {
683     Serial_Unified2_Header hdr;
684     Unified2IDSEventIPv6 alertdata;
685     uint32_t write_len = sizeof(Serial_Unified2_Header) + sizeof(Unified2IDSEventIPv6);
686 
687     memset(&alertdata, 0, sizeof(alertdata));
688 
689     alertdata.event_id = htonl(event->get_event_id());
690     alertdata.event_second = htonl(event->ref_time.tv_sec);
691     alertdata.event_microsecond = htonl(event->ref_time.tv_usec);
692     alertdata.generator_id = htonl(event->sig_info->gid);
693     alertdata.signature_id = htonl(event->sig_info->sid);
694     alertdata.signature_revision = htonl(event->sig_info->rev);
695     alertdata.classification_id = htonl(event->sig_info->class_id);
696     alertdata.priority_id = htonl(event->sig_info->priority);
697 
698     if (p)
699     {
700         alertdata.blocked = GetU2Flags(p, &alertdata.impact_flag);
701 
702         if(p->ptrs.ip_api.is_ip())
703         {
704             const SfIp* ip;
705             ip = p->ptrs.ip_api.get_src();
706             alertdata.ip_source = *(const struct in6_addr*)ip->get_ip6_ptr();
707             ip = p->ptrs.ip_api.get_dst();
708             alertdata.ip_destination = *(const struct in6_addr*)ip->get_ip6_ptr();
709         }
710         else if (p->flow)
711         {
712             if (p->is_from_application_client())
713             {
714                 alertdata.ip_source = *(const struct in6_addr*)p->flow->client_ip.get_ip6_ptr();
715                 alertdata.ip_destination = *(const struct in6_addr*)p->flow->server_ip.get_ip6_ptr();
716             }
717             else
718             {
719                 alertdata.ip_source = *(const struct in6_addr*)p->flow->server_ip.get_ip6_ptr();
720                 alertdata.ip_destination = *(const struct in6_addr*)p->flow->client_ip.get_ip6_ptr();
721             }
722         }
723 
724         alertdata.ip_proto = p->get_ip_proto_next();
725 
726         if ( p->type() == PktType::ICMP)
727         {
728             // If PktType == ICMP, icmph is set
729             alertdata.sport_itype = htons(p->ptrs.icmph->type);
730             alertdata.dport_icode = htons(p->ptrs.icmph->code);
731         }
732         else
733         {
734             alertdata.sport_itype = htons(p->ptrs.sp);
735             alertdata.dport_icode = htons(p->ptrs.dp);
736         }
737 
738         if ( p->proto_bits & PROTO_BIT__MPLS )
739             alertdata.mpls_label = htonl(p->ptrs.mplsHdr.label);
740 
741         if (p->proto_bits & PROTO_BIT__VLAN)
742             alertdata.vlanId = htons(layer::get_vlan_layer(p)->vid());
743 
744         alertdata.pad2 = htons((uint16_t)p->user_ips_policy_id);
745 
746         const char* app_name = p->flow ?
747             appid_api.get_application_name(*p->flow, p->is_from_client()) : nullptr;
748 
749         if ( app_name )
750             memcpy_s(alertdata.app_name, sizeof(alertdata.app_name),
751                 app_name, strlen(app_name) + 1);
752     }
753 
754     if ( config->limit && (u2.current + write_len) > config->limit )
755         Unified2RotateFile(config);
756 
757     hdr.length = htonl(sizeof(Unified2IDSEventIPv6));
758     hdr.type = htonl(UNIFIED2_IDS_EVENT_IPV6_VLAN);
759 
760     memcpy_s(write_pkt_buffer, u2_buf_sz, &hdr, sizeof(hdr));
761 
762     size_t offset = sizeof(hdr);
763 
764     memcpy_s(write_pkt_buffer + offset, u2_buf_sz - offset, &alertdata, sizeof(alertdata));
765 
766     Unified2Write(write_pkt_buffer, write_len, config);
767 }
768 
769 //-------------------------------------------------------------------------
770 // unified2 module
771 //-------------------------------------------------------------------------
772 
773 static const Parameter s_params[] =
774 {
775     { "legacy_events", Parameter::PT_BOOL, nullptr, "false",
776       "generate Snort 2.X style events for barnyard2 compatibility" },
777 
778     { "limit", Parameter::PT_INT, "0:maxSZ", "0",
779       "set maximum size in MB before rollover (0 is unlimited)" },
780 
781     { "nostamp", Parameter::PT_BOOL, nullptr, "true",
782       "append file creation time to name (in Unix Epoch format)" },
783 
784     { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
785 };
786 
787 #define s_help \
788     "output event and packet in unified2 format file"
789 
790 class U2Module : public Module
791 {
792 public:
U2Module()793     U2Module() : Module(S_NAME, s_help, s_params) { }
794 
795     bool set(const char*, Value&, SnortConfig*) override;
796     bool begin(const char*, int, SnortConfig*) override;
797 
get_usage() const798     Usage get_usage() const override
799     { return GLOBAL; }
800 
801 public:
802     size_t limit = 0;
803     bool nostamp = true;
804     bool legacy_events = false;
805 };
806 
set(const char *,Value & v,SnortConfig *)807 bool U2Module::set(const char*, Value& v, SnortConfig*)
808 {
809     if ( v.is("limit") )
810         limit = v.get_size() * 1024 * 1024;
811 
812     else if ( v.is("nostamp") )
813         nostamp = v.get_bool();
814 
815     else if ( v.is("legacy_events") )
816         legacy_events = v.get_bool();
817 
818     return true;
819 }
820 
begin(const char *,int,SnortConfig * sc)821 bool U2Module::begin(const char*, int, SnortConfig* sc)
822 {
823     limit = 0;
824     nostamp = sc->output_no_timestamp();
825     legacy_events = false;
826     return true;
827 }
828 
829 //-------------------------------------------------------------------------
830 // logger stuff
831 //-------------------------------------------------------------------------
832 
833 class U2Logger : public Logger
834 {
835 public:
836     U2Logger(U2Module*);
837 
838     void open() override;
839     void close() override;
840 
841     void alert(Packet*, const char* msg, const Event&) override;
842     void log(Packet*, const char* msg, Event*) override;
843 
844 private:
845     // alert_legacy() and friends retain compatibility with barnyard2
846     void alert_legacy(Packet*, const char* msg, const Event&);
847 
848 private:
849     Unified2Config config;
850 };
851 
U2Logger(U2Module * m)852 U2Logger::U2Logger(U2Module* m)
853 {
854     config.limit = m->limit;
855     config.nostamp = m->nostamp;
856     config.legacy_events = m->legacy_events;
857 }
858 
859 
open()860 void U2Logger::open()
861 {
862     int status;
863 
864     std::string name;
865     get_instance_file(name, F_NAME);
866 
867     status = SnortSnprintf(
868         u2.filepath, sizeof(u2.filepath), "%s", name.c_str());
869 
870     if (status != SNORT_SNPRINTF_SUCCESS)
871     {
872         FatalError("unified2 failed to copy file name\n");
873     }
874     u2.base_proto = htonl(SFDAQ::get_base_protocol());
875 
876     write_pkt_buffer = new uint8_t[u2_buf_sz];
877     io_buffer = new char[u2_buf_sz];
878 
879     Unified2InitFile(&config);
880 
881     Stream::reg_xtra_data_log(AlertExtraData, &config);
882 }
883 
close()884 void U2Logger::close()
885 {
886     if ( u2.stream )
887         fclose(u2.stream);
888 
889     delete[] write_pkt_buffer;
890     delete[] io_buffer;
891 
892     write_pkt_buffer = nullptr;
893     io_buffer = nullptr;
894 }
895 
alert_legacy(Packet * p,const char * msg,const Event & event)896 void U2Logger::alert_legacy(Packet* p, const char* msg, const Event& event)
897 {
898     if (p->ptrs.ip_api.is_ip6())
899     {
900         _AlertIP6_v2(p, msg, &config, &event);
901 
902         if (p->ptrs.ip_api.is_ip6())
903         {
904             const SfIp* ip = p->ptrs.ip_api.get_src();
905             _WriteExtraData(&config, event.get_event_id(), event.ref_time.tv_sec,
906                 (const uint8_t*) ip->get_ip6_ptr(), sizeof(struct in6_addr), EVENT_INFO_IPV6_SRC);
907             ip = p->ptrs.ip_api.get_dst();
908             _WriteExtraData(&config, event.get_event_id(), event.ref_time.tv_sec,
909                 (const uint8_t*) ip->get_ip6_ptr(), sizeof(struct in6_addr), EVENT_INFO_IPV6_DST);
910         }
911     }
912     else // ip4 or data
913     {
914         _AlertIP4_v2(p, msg, &config, &event);
915     }
916 
917     if ( p->flow )
918         Stream::update_flow_alert(
919             p->flow, p, event.sig_info->gid, event.sig_info->sid,
920             event.get_event_id(), event.ref_time.tv_sec);
921 
922     if ( p->xtradata_mask )
923     {
924         LogFunction* log_funcs;
925         uint32_t max_count = Stream::get_xtra_data_map(log_funcs);
926 
927         if ( max_count > 0 )
928             AlertExtraData(
929                 p->flow, &config, log_funcs, max_count, p->xtradata_mask,
930                 event.get_event_id(), event.ref_time.tv_sec);
931     }
932 }
933 
alert(Packet * p,const char * msg,const Event & event)934 void U2Logger::alert(Packet* p, const char* msg, const Event& event)
935 {
936     if ( config.legacy_events )
937     {
938         alert_legacy(p, msg, event);
939         return;
940     }
941     alert_event(p, msg, &config, &event);
942 
943     if ( p->flow )
944         Stream::update_flow_alert(
945             p->flow, p, event.sig_info->gid, event.sig_info->sid,
946             event.get_event_id(), event.ref_time.tv_sec);
947 
948     if ( p->xtradata_mask )
949     {
950         LogFunction* log_funcs;
951         uint32_t max_count = Stream::get_xtra_data_map(log_funcs);
952 
953         if ( max_count > 0 )
954             AlertExtraData(
955                 p->flow, &config, log_funcs, max_count, p->xtradata_mask,
956                 event.get_event_id(), event.ref_time.tv_sec);
957     }
958 }
959 
log(Packet * p,const char * msg,Event * event)960 void U2Logger::log(Packet* p, const char* msg, Event* event)
961 {
962     assert(p);
963 
964     // FIXIT-L convert to packet method
965     if ( !p->is_cooked() or p->pseudo_type == PSEUDO_PKT_IP )
966         _Unified2LogPacketAlert(p, msg, &config, event, UNIFIED2_PACKET);
967 
968     else if ( !config.legacy_events )
969         _Unified2LogPacketAlert(p, msg, &config, event, UNIFIED2_BUFFER);
970 
971     else
972     {
973         U2PseudoHeader u2h(p);
974         _Unified2LogPacketAlert(p, msg, &config, event, UNIFIED2_PACKET, &u2h);
975     }
976 }
977 
978 //-------------------------------------------------------------------------
979 // api stuff
980 //-------------------------------------------------------------------------
981 
mod_ctor()982 static Module* mod_ctor()
983 { return new U2Module; }
984 
mod_dtor(Module * m)985 static void mod_dtor(Module* m)
986 { delete m; }
987 
u2_ctor(Module * mod)988 static Logger* u2_ctor(Module* mod)
989 { return new U2Logger((U2Module*)mod); }
990 
u2_dtor(Logger * p)991 static void u2_dtor(Logger* p)
992 { delete p; }
993 
994 static LogApi u2_api
995 {
996     {
997         PT_LOGGER,
998         sizeof(LogApi),
999         LOGAPI_VERSION,
1000         0,
1001         API_RESERVED,
1002         API_OPTIONS,
1003         S_NAME,
1004         s_help,
1005         mod_ctor,
1006         mod_dtor
1007     },
1008     OUTPUT_TYPE_FLAG__LOG | OUTPUT_TYPE_FLAG__ALERT,
1009     u2_ctor,
1010     u2_dtor
1011 };
1012 
1013 #ifdef BUILDING_SO
1014 SO_PUBLIC const BaseApi* snort_plugins[] =
1015 #else
1016 const BaseApi* eh_unified2[] =
1017 #endif
1018 {
1019     &u2_api.base,
1020     nullptr
1021 };
1022 
1023