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