1 /*
2 ** Copyright (C) 2008-2013 Ian Firns (SecurixLive) <dev@securixlive.com>
3 ** Copyright (C) 2002-2005 Robert (Bamm) Visscher <bamm@sguil.net>
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 **
20 **
21 */
22
23 /*
24 ** Description:
25 ** A sguil output plugin. For further information regarding sguil see
26 ** http://www.sguil.net
27 **
28 ** TODO:
29 ** 1. Test signal handling of sleep.
30 ** 2. Convert noisy LogMessages to DEBUG_WRAP()
31 */
32
33 /*
34 ** INCLUDES
35 */
36 #ifdef HAVE_CONFIG_H
37 #include "config.h"
38 #endif
39
40 #include <stdio.h>
41 #include <string.h>
42 #include <stdlib.h>
43 #include <sys/types.h>
44 #include <netinet/in.h>
45 #include <time.h>
46 #include <errno.h>
47 #include <unistd.h>
48 #include <ctype.h>
49 #include <sys/socket.h>
50 #include <netinet/in.h>
51 #include <arpa/inet.h>
52 #include <netdb.h>
53
54
55 #include "barnyard2.h"
56 #include "debug.h"
57 #include "decode.h"
58 #include "map.h"
59 #include "mstring.h"
60 #include "plugbase.h"
61 #include "strlcpyu.h"
62 #include "unified2.h"
63 #include "util.h"
64
65 /* Yeah TCL! */
66 #ifdef ENABLE_TCL
67 #include <tcl.h>
68 #endif
69
70 typedef struct _SpoSguilData
71 {
72 char *sensor_name;
73 char *tag_path;
74 char *passwd;
75 u_int16_t sensor_id;
76 /** lowest event_id we submitted, but that wasn't confirmed yet,
77 * should only be lower than event_id_max on server timeouts. */
78 u_int32_t event_id_min;
79 /** higest event_id sent to the server, normally we expect a confirm for
80 * this id. */
81 u_int32_t event_id_max;
82 u_int16_t agent_port;
83 int agent_sock;
84
85 char *args;
86 } SpoSguilData;
87
88 /* constants */
89 #define KEYWORD_AGENTPORT "agent_port"
90 #define KEYWORD_SENSORNAME "sensor_name"
91 #define KEYWORD_TAGPATH "tag_path"
92 #define KEYWORD_PASSWORD "passwd"
93
94 #define MAX_MSG_LEN 2048
95 #define TMP_BUFFER 128
96
97 /* output plug-in API functions */
98 void SguilInit(char *args);
99 void SguilInitFinalize(int unused, void *arg);
100
101 SpoSguilData *InitSguilData(char *);
102 void ParseSguilArgs(SpoSguilData *ssd_data);
103
104 void SguilCleanExitFunc(int, void *);
105 void SguilRestartFunc(int, void *);
106
107
108 /* internal sguil functions */
109 void Sguil(Packet *, void *, uint32_t, void *);
110
111 int SguilSensorAgentConnect(SpoSguilData *);
112 int SguilSensorAgentInit(SpoSguilData *);
113 int SguilRTEventMsg(SpoSguilData *, char *);
114 int SguilSendAgentMsg(SpoSguilData *, char *);
115 int SguilRecvAgentMsg(SpoSguilData *, char *);
116
117 char *SguilTimestamp(u_int32_t);
118
119 #ifdef ENABLE_TCL
120 int SguilAppendIPHdrDataEVT(Tcl_DString *, void *);
121 int SguilAppendIPHdrData(Tcl_DString *, Packet *);
122 int SguilAppendICMPData(Tcl_DString *, Packet *);
123 int SguilAppendTCPData(Tcl_DString *, Packet *);
124 int SguilAppendUDPData(Tcl_DString *, Packet *);
125 int SguilAppendPayloadData(Tcl_DString *, Packet *);
126 #endif
127
128 /* init routine makes this processor available for dataprocessor directives */
SguilSetup()129 void SguilSetup()
130 {
131 /* link the preprocessor keyword to the init function in
132 the preproc list */
133 RegisterOutputPlugin("sguil", OUTPUT_TYPE_FLAG__ALERT, SguilInit);
134
135 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Output: Sguil is setup\n"););
136 }
137
SguilInit(char * args)138 void SguilInit(char *args)
139 {
140 SpoSguilData *ssd_data;
141
142 DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Output: Sguil initialized\n"););
143
144 #ifndef ENABLE_TCL
145 ErrorMessage("sguil: Tcl support is not compiled into this build of barnyard2\n\n");
146 FatalError("If this build of barnyard was obtained as a binary distribution (e.g., rpm,\n"
147 "or Windows), then check for alternate builds that contains the necessary Tcl\n"
148 "support.\n\n"
149 "If this build of barnyard was compiled by you, then re-run the ./configure\n"
150 "script using the '--with-tcl' switch to specify the location of the\n"
151 "tclConfig.sh for your system.\n\n");
152 #endif
153
154 /* parse the argument list from the rules file`*/
155 ssd_data = InitSguilData(args);
156
157 AddFuncToPostConfigList(SguilInitFinalize, ssd_data);
158 }
159
InitSguilData(char * args)160 SpoSguilData *InitSguilData(char *args)
161 {
162 SpoSguilData *data;
163
164 /* setup the internal structures and parse any arguments */
165 data = (SpoSguilData *)SnortAlloc(sizeof(SpoSguilData));
166
167 if (args == NULL)
168 {
169 ErrorMessage("sguil: you must supply arguments for sguil plugin\n");
170 //PrintSguilUsage();
171 FatalError("");
172 }
173
174 data->args = SnortStrdup(args);
175
176 return data;
177 }
178
SguilInitFinalize(int unused,void * arg)179 void SguilInitFinalize(int unused, void *arg)
180 {
181 SpoSguilData *ssd_data = (SpoSguilData *)arg;
182
183 if (!ssd_data)
184 {
185 FatalError("sguil: data uninitialized\n");
186 }
187
188 ParseSguilArgs(ssd_data);
189
190 /* identify the sensor_name */
191 if(ssd_data->sensor_name == NULL)
192 {
193 ssd_data->sensor_name = SnortStrdup(GetUniqueName(PRINT_INTERFACE(barnyard2_conf->interface)));
194 if(ssd_data->sensor_name)
195 {
196 if( ssd_data->sensor_name[strlen(ssd_data->sensor_name)-1] == '\n' )
197 {
198 ssd_data->sensor_name[strlen(ssd_data->sensor_name)-1] = '\0';
199 }
200 }
201 }
202
203 if (!BcLogQuiet())
204 {
205 LogMessage("sguil: sensor name = %s\n", ssd_data->sensor_name);
206 LogMessage("sguil: agent port = %u\n", ssd_data->agent_port);
207 }
208
209 /* connect to sensor_agent */
210 SguilSensorAgentConnect(ssd_data);
211
212 /* initialise the sensor agent - get sid and next cid */
213 if(BcLogVerbose())
214 LogMessage("sguil: Waiting for sid and cid from sensor_agent.\n");
215
216 /* try to connect, if we are not getting retval 0 it timed out
217 * so we try again, and again, and again... */
218 do {
219 if (SguilSensorAgentInit(ssd_data) == 0)
220 break;
221 } while (1);
222
223 /* set the preprocessor function into the function list */
224 AddFuncToOutputList(Sguil, OUTPUT_TYPE__ALERT, ssd_data);
225 AddFuncToCleanExitList(SguilCleanExitFunc, ssd_data);
226 AddFuncToRestartList(SguilRestartFunc, ssd_data);
227 }
228
Sguil(Packet * p,void * event,uint32_t event_type,void * arg)229 void Sguil(Packet *p, void *event, uint32_t event_type, void *arg)
230 {
231 #ifdef ENABLE_TCL
232 char *timestamp_string;
233 char buffer[TMP_BUFFER];
234 SpoSguilData *data;
235 SigNode *sn = NULL;
236 ClassType *cn = NULL;
237 Tcl_DString list;
238
239 memset(buffer, 0, TMP_BUFFER); /* bzero() deprecated, replaced by memset() */
240
241 if ( event == NULL || arg == NULL )
242 {
243 return;
244 }
245
246 if(p != NULL)
247 {
248 if(p->ip6h != NULL)
249 {
250 LogMessage("[%s] Received a IPv6 Packets, ignoring \n",
251 __FUNCTION__);
252 return;
253 }
254 }
255
256 data = (SpoSguilData *)arg;
257
258 /* grab the appropriate signature and classification information */
259 sn = GetSigByGidSid(ntohl(((Unified2EventCommon *)event)->generator_id),
260 ntohl(((Unified2EventCommon *)event)->signature_id),
261 ntohl(((Unified2EventCommon *)event)->signature_revision));
262
263 cn = ClassTypeLookupById(barnyard2_conf, ntohl(((Unified2EventCommon *)event)->classification_id));
264
265 /* Here we build our RT event to send to sguild. The event is built with a
266 ** proper tcl list format.
267 ** RT FORMAT:
268 **
269 ** 0 1 2 3 4 5 6 7
270 ** {RTEVENT} {0} {sid} {cid} {sensor name} {snort event_id} {snort event_ref} {snort ref_time}
271 **
272 ** 8 9 10 11 12 13 14
273 ** {sig_gen} {sig id} {rev} {message} {timestamp} {priority} {class_type}
274 **
275 ** 15 16 17 18 19 20 21
276 ** {sip (dec)} {sip (string)} {dip (dec)} {dip (string)} {ip proto} {ip ver} {ip hlen}
277 **
278 ** 22 23 24 25 26 27 28
279 ** {ip tos} {ip len} {ip id} {ip flags} {ip off} {ip ttl} {ip csum}
280 **
281 ** 29 30 31 32 33
282 ** {icmp type} {icmp code} {icmp csum} {icmp id} {icmp seq}
283 **
284 ** 34 35
285 ** {src port} {dst port}
286 **
287 ** 36 37 38 39 40 41 42 43
288 ** {tcp seq} {tcp ack} {tcp off} {tcp res} {tcp flags} {tcp win} {tcp csum} {tcp urp}
289 **
290 ** 44 45
291 ** {udp len} {udp csum}
292 **
293 ** 46
294 ** {data payload}
295 */
296
297 Tcl_DStringInit(&list);
298
299 /* RTEVENT */
300 Tcl_DStringAppendElement(&list, "RTEVENT");
301
302 /* Status - 0 */
303 Tcl_DStringAppendElement(&list, "0");
304
305 /* Sensor ID (sid) */
306 SnortSnprintf(buffer, TMP_BUFFER, "%u", data->sensor_id);
307 Tcl_DStringAppendElement(&list, buffer);
308
309 /* Event ID (cid) */
310 SnortSnprintf(buffer, TMP_BUFFER, "%u", data->event_id_max);
311 Tcl_DStringAppendElement(&list, buffer);
312
313 /* Sensor Name */
314 Tcl_DStringAppendElement(&list, data->sensor_name);
315
316 /* Snort Event ID */
317 SnortSnprintf(buffer, TMP_BUFFER, "%u",
318 ntohl(((Unified2EventCommon *)event)->event_id));
319 Tcl_DStringAppendElement(&list, buffer);
320
321 /* Snort Event Ref */
322 SnortSnprintf(buffer, TMP_BUFFER, "%u",
323 ntohl(((Unified2EventCommon *)event)->event_id));
324 Tcl_DStringAppendElement(&list, buffer);
325
326 /* Snort Event Ref Time */
327 timestamp_string = SguilTimestamp(ntohl(((Unified2EventCommon *)event)->event_second));
328
329 if(ntohl(((Unified2EventCommon *)event)->event_second) == 0)
330 Tcl_DStringAppendElement(&list, "");
331 else
332 Tcl_DStringAppendElement(&list, timestamp_string);
333
334 /* Generator ID */
335 SnortSnprintf(buffer, TMP_BUFFER, "%d",
336 ntohl(((Unified2EventCommon *)event)->generator_id));
337 Tcl_DStringAppendElement(&list, buffer);
338
339 /* Signature ID */
340 SnortSnprintf(buffer, TMP_BUFFER, "%d",
341 ntohl(((Unified2EventCommon *)event)->signature_id));
342 Tcl_DStringAppendElement(&list, buffer);
343
344 /* Signature Revision */
345 SnortSnprintf(buffer, TMP_BUFFER, "%d",
346 ntohl(((Unified2EventCommon *)event)->signature_revision));
347 Tcl_DStringAppendElement(&list, buffer);
348
349 /* Signature Msg */
350 Tcl_DStringAppendElement(&list, sn->msg);
351
352 /* Packet Timestamp = Event Timestamp*/
353 Tcl_DStringAppendElement(&list, timestamp_string);
354
355 /* Alert Priority */
356 SnortSnprintf(buffer, TMP_BUFFER, "%u",
357 ntohl(((Unified2EventCommon *)event)->priority_id));
358 Tcl_DStringAppendElement(&list, buffer);
359
360 /* Alert Classification */
361 if (cn == NULL)
362 Tcl_DStringAppendElement(&list, "unknown");
363 else
364 Tcl_DStringAppendElement(&list, cn->type);
365
366 /* Pull decoded info from the packet */
367 if(p != NULL)
368 {
369 if(p->iph)
370 {
371 int i;
372
373 /* add IP header */
374 SguilAppendIPHdrData(&list, p);
375
376 /* add ICMP || UDP || TCP data */
377 if ( !(p->packet_flags & PKT_REBUILT_FRAG) )
378 {
379 switch(p->iph->ip_proto)
380 {
381 case IPPROTO_ICMP:
382 SguilAppendICMPData(&list, p);
383 break;
384
385 case IPPROTO_TCP:
386 SguilAppendTCPData(&list, p);
387 break;
388
389 case IPPROTO_UDP:
390 SguilAppendUDPData(&list, p);
391 break;
392
393 default:
394 for(i = 0; i < 17; ++i)
395 Tcl_DStringAppendElement(&list, "");
396 break;
397 }
398 }
399 else
400 {
401 /* null out TCP/UDP/ICMP fields */
402 for(i = 0; i < 17; ++i)
403 Tcl_DStringAppendElement(&list, "");
404 }
405 }
406 else
407 {
408 /* no IP Header. */
409 int i;
410 for(i = 0; i < 31; ++i)
411 Tcl_DStringAppendElement(&list, "");
412 }
413
414 /* add payload data */
415 SguilAppendPayloadData(&list, p);
416 }
417 else
418 {
419 /* ack! an event without a packet. Append IP data from event struct and append
420 26 fillers */
421 if ( (event_type == UNIFIED2_IDS_EVENT_VLAN)||
422 (event_type == UNIFIED2_IDS_EVENT_MPLS) ||
423 (event_type == UNIFIED2_IDS_EVENT_VLAN)){
424 SguilAppendIPHdrDataEVT(&list, event);
425 int i;
426 for(i = 0; i < 26; ++i)
427 Tcl_DStringAppendElement(&list, "");
428 } else {
429 /* ack! an event without a packet. and no IP Data in eventAppend 32 fillers */
430 int i;
431 for(i = 0; i < 32; ++i)
432 Tcl_DStringAppendElement(&list, "");
433 }
434
435 }
436
437 /* send msg to sensor_agent */
438 if (SguilRTEventMsg(data, Tcl_DStringValue(&list)))
439 FatalError("Unable to send RT Events to sensor agent.\n");
440
441 /* free the mallocs! */
442 Tcl_DStringFree(&list);
443 free(timestamp_string);
444
445 /* bump the event id */
446 data->event_id_max++;
447 #endif
448 }
449
450 static unsigned int sguil_agent_setup_timeouts = 0;
451
SguilRTEventMsg(SpoSguilData * data,char * msg)452 int SguilRTEventMsg(SpoSguilData *data, char *msg)
453 {
454
455 char tmpRecvMsg[MAX_MSG_LEN];
456
457 /* Send Msg */
458 SguilSendAgentMsg(data, msg);
459
460 /* Get confirmation */
461 memset(tmpRecvMsg, 0x0, MAX_MSG_LEN);
462 if (SguilRecvAgentMsg(data, tmpRecvMsg) == 1)
463 {
464 if (BcLogVerbose())
465 LogMessage("sguil: Retrying\n");
466
467 SguilRTEventMsg(data, msg);
468 }
469 else
470 {
471 char **toks;
472 int num_toks;
473
474 if (BcLogVerbose())
475 LogMessage("sguil: Received: %s", tmpRecvMsg);
476
477 /* Parse the response */
478 toks = mSplit(tmpRecvMsg, " ", 2, &num_toks, 0);
479
480 /* if the agent registration timed out once or several times we can
481 * receive unexpected SidCidResponse messages. */
482 if (sguil_agent_setup_timeouts > 0 && strcasecmp("SidCidResponse", toks[0]) == 0)
483 {
484 sguil_agent_setup_timeouts--;
485
486 if (BcLogVerbose())
487 LogMessage("sguil: Ignored: %s", tmpRecvMsg);
488 }
489 else
490 {
491 int event_id = atoi(toks[1]);
492 if (event_id < 0)
493 {
494 FatalError("sguil: Malformed response, expected \"Confirm %u\", got: %s\n",
495 data->event_id_max, tmpRecvMsg);
496 }
497
498 if(strcasecmp("Confirm", toks[0]) != 0) {
499
500 if ((uint)event_id != data->event_id_max) {
501 if ((uint)event_id == data->event_id_min) {
502 if (BcLogVerbose())
503 LogMessage("sguil: processed delayed Confirm: %s", tmpRecvMsg);
504 }
505 else
506 {
507 FatalError("sguil: Expected Confirm %u and got: %s\n", data->event_id_max, tmpRecvMsg);
508 }
509 }
510
511 /* either we are in sync or the confirm we got confirmed
512 * event_id_min. Either way, we can increment it */
513 data->event_id_min++;
514 }
515 }
516
517 mSplitFree(&toks, num_toks);
518 }
519
520 return 0;
521 }
522
523 /*
524 * Function: ParseSguilArgs(char *)
525 *
526 * Purpose: Process the preprocessor arguements from the rules file and
527 * initialize the preprocessor's data struct. This function doesn't
528 * have to exist if it makes sense to parse the args in the init
529 * function.
530 *
531 * Arguments: args => argument list
532 *
533 * Returns: void function
534 *
535 */
ParseSguilArgs(SpoSguilData * ssd_data)536 void ParseSguilArgs(SpoSguilData *ssd_data)
537 {
538 char **toks;
539 int num_toks;
540 int i;
541
542 if(ssd_data->args == NULL)
543 {
544 ErrorMessage("sguil: you must supply arguments for sguil plugin\n");
545 //PrintSguilUsage();
546 FatalError("");
547 }
548
549 /* initialise appropariate values to 0 */
550 ssd_data->agent_port = 0;
551
552 /* parse out your args */
553 toks = mSplit(ssd_data->args, ", ", 31, &num_toks, '\\');
554
555 for(i = 0; i < num_toks; ++i)
556 {
557 char **stoks;
558 int num_stoks;
559 char *index = toks[i];
560 while(isspace((int)*index))
561 ++index;
562
563 stoks = mSplit(index, "=", 2, &num_stoks, 0);
564
565 if ( !strncasecmp(stoks[0], KEYWORD_AGENTPORT, strlen(KEYWORD_AGENTPORT)) )
566 {
567 if(num_stoks > 1)
568 ssd_data->agent_port = atoi(stoks[1]);
569 else
570 LogMessage("sguil: agent_port error\n");
571 }
572 else if ( !strncasecmp(stoks[0], KEYWORD_TAGPATH, strlen(KEYWORD_TAGPATH)) )
573 {
574 if(num_stoks > 1 && ssd_data->tag_path == NULL)
575 ssd_data->tag_path = SnortStrdup(stoks[1]);
576 else
577 LogMessage("sguil: tag_path error\n");
578 }
579 else if ( !strncasecmp(stoks[0], KEYWORD_SENSORNAME, strlen(KEYWORD_SENSORNAME)) )
580 {
581 if(num_stoks > 1 && ssd_data->sensor_name == NULL)
582 ssd_data->sensor_name = SnortStrdup(stoks[1]);
583 else
584 LogMessage("sguil: sensor_name error\n");
585 }
586 else if ( !strncasecmp(stoks[0], KEYWORD_PASSWORD, strlen(KEYWORD_PASSWORD)) )
587 {
588 if(num_stoks > 1 && ssd_data->passwd == NULL)
589 ssd_data->passwd = SnortStrdup(stoks[1]);
590 else
591 LogMessage("sguil: passwd error\n");
592 }
593 else
594 {
595 LogMessage("sguil: unrecognised argument = %s\n", index);
596 }
597
598 /* free your mSplit tokens */
599 mSplitFree(&stoks, num_stoks);
600 }
601
602 /* free your mSplit tokens */
603 mSplitFree(&toks, num_toks);
604
605 /* identify the agent_port */
606 if (ssd_data->agent_port == 0)
607 ssd_data->agent_port = 7735;
608 }
609
610 #ifdef ENABLE_TCL
SguilAppendIPHdrDataEVT(Tcl_DString * list,void * event)611 int SguilAppendIPHdrDataEVT(Tcl_DString *list, void *event)
612 {
613 char buffer[TMP_BUFFER];
614
615 memset(buffer, 0, TMP_BUFFER); /* bzero() deprecated, replaced by memset() */
616
617 SnortSnprintf(buffer, TMP_BUFFER, "%u", ntohl(((Unified2IDSEvent *)event)->ip_source));
618 Tcl_DStringAppendElement(list, buffer);
619 #if defined(WORDS_BIGENDIAN)
620 SnortSnprintf(buffer, TMP_BUFFER, "%u.%u.%u.%u",
621 (((Unified2IDSEvent *)event)->ip_source & 0xff000000) >> 24,
622 (((Unified2IDSEvent *)event)->ip_source & 0x00ff0000) >> 16,
623 (((Unified2IDSEvent *)event)->ip_source & 0x0000ff00) >> 8,
624 (((Unified2IDSEvent *)event)->ip_source & 0x000000ff));
625 #else
626 SnortSnprintf(buffer, TMP_BUFFER, "%u.%u.%u.%u",
627 (((Unified2IDSEvent *)event)->ip_source & 0x000000ff),
628 (((Unified2IDSEvent *)event)->ip_source & 0x0000ff00) >> 8,
629 (((Unified2IDSEvent *)event)->ip_source & 0x00ff0000) >> 16,
630 (((Unified2IDSEvent *)event)->ip_source & 0xff000000) >> 24);
631 #endif
632 Tcl_DStringAppendElement(list, buffer);
633 SnortSnprintf(buffer, TMP_BUFFER, "%u", ntohl(((Unified2IDSEvent *)event)->ip_destination));
634 Tcl_DStringAppendElement(list, buffer);
635 #if defined(WORDS_BIGENDIAN)
636 SnortSnprintf(buffer, TMP_BUFFER, "%u.%u.%u.%u",
637 (((Unified2IDSEvent *)event)->ip_destination & 0xff000000) >> 24,
638 (((Unified2IDSEvent *)event)->ip_destination & 0x00ff0000) >> 16,
639 (((Unified2IDSEvent *)event)->ip_destination & 0x0000ff00) >> 8,
640 (((Unified2IDSEvent *)event)->ip_destination & 0x000000ff));
641 #else
642 SnortSnprintf(buffer, TMP_BUFFER, "%u.%u.%u.%u",
643 (((Unified2IDSEvent *)event)->ip_destination & 0x000000ff),
644 (((Unified2IDSEvent *)event)->ip_destination & 0x0000ff00) >> 8,
645 (((Unified2IDSEvent *)event)->ip_destination & 0x00ff0000) >> 16,
646 (((Unified2IDSEvent *)event)->ip_destination & 0xff000000) >> 24);
647 #endif
648 Tcl_DStringAppendElement(list, buffer);
649 SnortSnprintf(buffer, TMP_BUFFER, "%u", ((Unified2IDSEvent *)event)->protocol);
650 Tcl_DStringAppendElement(list, buffer);
651
652 return 0;
653 }
654 #endif
655
656 #ifdef ENABLE_TCL
SguilAppendIPHdrData(Tcl_DString * list,Packet * p)657 int SguilAppendIPHdrData(Tcl_DString *list, Packet *p)
658 {
659 char buffer[TMP_BUFFER];
660
661 memset(buffer, 0, TMP_BUFFER); /* bzero() deprecated, replaced by memset() */
662
663 SnortSnprintf(buffer, TMP_BUFFER, "%u", ntohl(p->iph->ip_src.s_addr));
664 Tcl_DStringAppendElement(list, buffer);
665 #if defined(WORDS_BIGENDIAN)
666 SnortSnprintf(buffer, TMP_BUFFER, "%u.%u.%u.%u",
667 (p->iph->ip_src.s_addr & 0xff000000) >> 24,
668 (p->iph->ip_src.s_addr & 0x00ff0000) >> 16,
669 (p->iph->ip_src.s_addr & 0x0000ff00) >> 8,
670 (p->iph->ip_src.s_addr & 0x000000ff));
671 #else
672 SnortSnprintf(buffer, TMP_BUFFER, "%u.%u.%u.%u",
673 (p->iph->ip_src.s_addr & 0x000000ff),
674 (p->iph->ip_src.s_addr & 0x0000ff00) >> 8,
675 (p->iph->ip_src.s_addr & 0x00ff0000) >> 16,
676 (p->iph->ip_src.s_addr & 0xff000000) >> 24);
677 #endif
678 Tcl_DStringAppendElement(list, buffer);
679 SnortSnprintf(buffer, TMP_BUFFER, "%u", ntohl(p->iph->ip_dst.s_addr));
680 Tcl_DStringAppendElement(list, buffer);
681 #if defined(WORDS_BIGENDIAN)
682 SnortSnprintf(buffer, TMP_BUFFER, "%u.%u.%u.%u",
683 (p->iph->ip_dst.s_addr & 0xff000000) >> 24,
684 (p->iph->ip_dst.s_addr & 0x00ff0000) >> 16,
685 (p->iph->ip_dst.s_addr & 0x0000ff00) >> 8,
686 (p->iph->ip_dst.s_addr & 0x000000ff));
687 #else
688 SnortSnprintf(buffer, TMP_BUFFER, "%u.%u.%u.%u",
689 (p->iph->ip_dst.s_addr & 0x000000ff),
690 (p->iph->ip_dst.s_addr & 0x0000ff00) >> 8,
691 (p->iph->ip_dst.s_addr & 0x00ff0000) >> 16,
692 (p->iph->ip_dst.s_addr & 0xff000000) >> 24);
693 #endif
694 Tcl_DStringAppendElement(list, buffer);
695 SnortSnprintf(buffer, TMP_BUFFER, "%u", p->iph->ip_proto);
696 Tcl_DStringAppendElement(list, buffer);
697 SnortSnprintf(buffer, TMP_BUFFER, "%u", IP_VER(p->iph));
698 Tcl_DStringAppendElement(list, buffer);
699 SnortSnprintf(buffer, TMP_BUFFER, "%u", IP_HLEN(p->iph));
700 Tcl_DStringAppendElement(list, buffer);
701 SnortSnprintf(buffer, TMP_BUFFER, "%u", p->iph->ip_tos);
702 Tcl_DStringAppendElement(list, buffer);
703 SnortSnprintf(buffer, TMP_BUFFER, "%u", ntohs(p->iph->ip_len));
704 Tcl_DStringAppendElement(list, buffer);
705 SnortSnprintf(buffer, TMP_BUFFER, "%u", ntohs(p->iph->ip_id));
706 Tcl_DStringAppendElement(list, buffer);
707
708 #if defined(WORDS_BIGENDIAN)
709 SnortSnprintf(buffer, TMP_BUFFER, "%u", ((p->iph->ip_off & 0xE000) >> 13));
710 Tcl_DStringAppendElement(list, buffer);
711 SnortSnprintf(buffer, TMP_BUFFER, "%u", htons(p->iph->ip_off & 0x1FFF));
712 Tcl_DStringAppendElement(list, buffer);
713 #else
714 SnortSnprintf(buffer, TMP_BUFFER, "%u", ((p->iph->ip_off & 0x00E0) >> 5));
715 Tcl_DStringAppendElement(list, buffer);
716 SnortSnprintf(buffer, TMP_BUFFER, "%u", htons(p->iph->ip_off & 0xFF1F));
717 Tcl_DStringAppendElement(list, buffer);
718 #endif
719
720 SnortSnprintf(buffer, TMP_BUFFER, "%u", p->iph->ip_ttl);
721 Tcl_DStringAppendElement(list, buffer);
722 SnortSnprintf(buffer, TMP_BUFFER, "%u", htons(p->iph->ip_csum));
723 Tcl_DStringAppendElement(list, buffer);
724
725 return 0;
726 }
727 #endif
728
729 #ifdef ENABLE_TCL
SguilAppendICMPData(Tcl_DString * list,Packet * p)730 int SguilAppendICMPData(Tcl_DString *list, Packet *p)
731 {
732
733 int i;
734 char buffer[TMP_BUFFER];
735
736 memset(buffer, 0, TMP_BUFFER); /* bzero() deprecated, replaced by memset() */
737
738 if (!p->icmph)
739 {
740
741 /* Null out ICMP fields */
742 for(i=0; i < 5; i++)
743 Tcl_DStringAppendElement(list, "");
744
745 }
746 else
747 {
748
749 /* ICMP type */
750 SnortSnprintf(buffer, TMP_BUFFER, "%u", p->icmph->type);
751 Tcl_DStringAppendElement(list, buffer);
752
753 /* ICMP code */
754 SnortSnprintf(buffer, TMP_BUFFER, "%u", p->icmph->code);
755 Tcl_DStringAppendElement(list, buffer);
756
757 /* ICMP CSUM */
758 SnortSnprintf(buffer, TMP_BUFFER, "%u", ntohs(p->icmph->csum));
759 Tcl_DStringAppendElement(list, buffer);
760
761 /* Append other ICMP data if we have it */
762 if (p->icmph->type == ICMP_ECHOREPLY ||
763 p->icmph->type == ICMP_ECHO ||
764 p->icmph->type == ICMP_TIMESTAMP ||
765 p->icmph->type == ICMP_TIMESTAMPREPLY ||
766 p->icmph->type == ICMP_INFO_REQUEST ||
767 p->icmph->type == ICMP_INFO_REPLY)
768 {
769
770 /* ICMP ID */
771 SnortSnprintf(buffer, TMP_BUFFER, "%u", htons(p->icmph->icmp_hun.idseq.id));
772 Tcl_DStringAppendElement(list, buffer);
773
774 /* ICMP Seq */
775 SnortSnprintf(buffer, TMP_BUFFER, "%u", htons(p->icmph->icmp_hun.idseq.seq));
776 Tcl_DStringAppendElement(list, buffer);
777
778 }
779 else
780 {
781
782 /* Add two empty elements */
783 for(i=0; i < 2; i++)
784 Tcl_DStringAppendElement(list, "");
785
786 }
787
788 }
789
790 /* blank out 12 elements */
791 for(i = 0; i < 12; i++)
792 Tcl_DStringAppendElement(list, "");
793
794 return 0;
795
796 }
797 #endif
798
799 #ifdef ENABLE_TCL
SguilAppendTCPData(Tcl_DString * list,Packet * p)800 int SguilAppendTCPData(Tcl_DString *list, Packet *p)
801 {
802 /*
803 ** 33 34 35 36 37 38 39 40
804 ** {tcp seq} {tcp ack} {tcp off} {tcp res} {tcp flags} {tcp win} {tcp csum} {tcp urp}
805 **
806 */
807
808 int i;
809 char buffer[TMP_BUFFER];
810
811 memset(buffer, 0, TMP_BUFFER); /* bzero() deprecated, replaced by memset() */
812
813 /* empty elements for icmp data */
814 for(i=0; i < 5; i++)
815 Tcl_DStringAppendElement(list, "");
816
817 if (!p->tcph)
818 {
819 /* Null out TCP fields */
820 for(i=0; i < 10; i++)
821 Tcl_DStringAppendElement(list, "");
822 }
823 else
824 {
825 SnortSnprintf(buffer, TMP_BUFFER, "%u", p->sp);
826 Tcl_DStringAppendElement(list, buffer);
827
828 SnortSnprintf(buffer, TMP_BUFFER, "%u", p->dp);
829 Tcl_DStringAppendElement(list, buffer);
830
831 SnortSnprintf(buffer, TMP_BUFFER, "%u", ntohl(p->tcph->th_seq));
832 Tcl_DStringAppendElement(list, buffer);
833
834 SnortSnprintf(buffer, TMP_BUFFER, "%u", ntohl(p->tcph->th_ack));
835 Tcl_DStringAppendElement(list, buffer);
836
837 SnortSnprintf(buffer, TMP_BUFFER, "%u", TCP_OFFSET(p->tcph));
838 Tcl_DStringAppendElement(list, buffer);
839
840 SnortSnprintf(buffer, TMP_BUFFER, "%u", TCP_X2(p->tcph));
841 Tcl_DStringAppendElement(list, buffer);
842
843 SnortSnprintf(buffer, TMP_BUFFER, "%u", p->tcph->th_flags);
844 Tcl_DStringAppendElement(list, buffer);
845
846 SnortSnprintf(buffer, TMP_BUFFER, "%u", ntohs(p->tcph->th_win));
847 Tcl_DStringAppendElement(list, buffer);
848
849 SnortSnprintf(buffer, TMP_BUFFER, "%u", ntohs(p->tcph->th_sum));
850 Tcl_DStringAppendElement(list, buffer);
851
852 SnortSnprintf(buffer, TMP_BUFFER, "%u", ntohs(p->tcph->th_urp));
853 Tcl_DStringAppendElement(list, buffer);
854
855 }
856
857 /* empty elements for UDP data */
858 for(i=0; i < 2; i++)
859 Tcl_DStringAppendElement(list, "");
860
861 return 0;
862
863 }
864 #endif
865
866 #ifdef ENABLE_TCL
SguilAppendUDPData(Tcl_DString * list,Packet * p)867 int SguilAppendUDPData(Tcl_DString *list, Packet *p)
868 {
869
870 int i;
871 char buffer[TMP_BUFFER];
872
873 memset(buffer, 0, TMP_BUFFER); /* bzero() deprecated, replaced by memset() */
874
875 /* empty elements for ICMP data */
876 for(i=0; i < 5; i++)
877 Tcl_DStringAppendElement(list, "");
878
879 if (!p->udph)
880 {
881 /* null out port info */
882 for(i=0; i < 2; i++)
883 Tcl_DStringAppendElement(list, "");
884 }
885 else
886 {
887 /* source and dst port */
888 SnortSnprintf(buffer, TMP_BUFFER, "%u", p->sp);
889 Tcl_DStringAppendElement(list, buffer);
890
891 SnortSnprintf(buffer, TMP_BUFFER, "%u", p->dp);
892 Tcl_DStringAppendElement(list, buffer);
893
894 }
895
896 /* empty elements for TCP data */
897 for(i=0; i < 8; i++)
898 Tcl_DStringAppendElement(list, "");
899
900 if (!p->udph)
901 {
902 /* null out UDP info */
903 for(i=0; i < 2; i++)
904 Tcl_DStringAppendElement(list, "");
905 }
906 else
907 {
908 SnortSnprintf(buffer, TMP_BUFFER, "%u", ntohs(p->udph->uh_len));
909 Tcl_DStringAppendElement(list, buffer);
910
911 SnortSnprintf(buffer, TMP_BUFFER, "%u", ntohs(p->udph->uh_chk));
912 Tcl_DStringAppendElement(list, buffer);
913 }
914
915 return 0;
916
917 }
918 #endif
919
920 #ifdef ENABLE_TCL
SguilAppendPayloadData(Tcl_DString * list,Packet * p)921 int SguilAppendPayloadData(Tcl_DString *list, Packet *p)
922 {
923 char *hex_payload;
924
925 if (p->dsize)
926 {
927 hex_payload = fasthex(p->data, p->dsize);
928 Tcl_DStringAppendElement(list, hex_payload);
929 free(hex_payload);
930 } else {
931 Tcl_DStringAppendElement(list, "");
932 }
933
934 return 0;
935 }
936 #endif
937
SguilSensorAgentConnect(SpoSguilData * ssd_data)938 int SguilSensorAgentConnect(SpoSguilData *ssd_data)
939 {
940 int sockfd;
941 struct sockaddr_in my_addr;
942 u_int8_t tries = 4;
943
944 /* loop listening for external signals */
945 while (exit_signal == 0)
946 {
947
948 if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 )
949 {
950 FatalError("sguil: Can't open a local socket.\n");
951 return 1;
952 }
953
954 my_addr.sin_family = AF_INET;
955 my_addr.sin_port = htons(ssd_data->agent_port);
956 my_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
957 memset(&(my_addr.sin_zero), '\0', 8);
958
959 if (connect(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) < 0)
960 {
961 LogMessage("sguil: Can't connect to localhost on TCP port %u.\n",
962 ssd_data->agent_port);
963 close(sockfd);
964
965 /* only perform 4 tries when testing the configuration */
966 if ((BcTestMode()) && (tries-- == 0))
967 {
968 FatalError("sguil: Unable to connect after 4 attempts\n");
969 }
970
971 LogMessage("sguil: Waiting 15 secs to try again.\n");
972
973 /* TODO: test inherent signal handling */
974 if (sleep(15))
975 {
976 // LogMessage("sguil: Received Kill Signal...\n");
977 // CleanExit(0);
978 }
979 }
980 else
981 {
982 ssd_data->agent_sock = sockfd;
983 LogMessage("sguil: Connected to localhost on %u.\n",
984 ssd_data->agent_port);
985 return 0;
986 }
987 }
988
989 return 1;
990 }
991
992 /* Request sensor ID (sid) and next cid from sensor_agent
993 * return 0 on success
994 * return 1 on timeout
995 */
SguilSensorAgentInit(SpoSguilData * ssd_data)996 int SguilSensorAgentInit(SpoSguilData *ssd_data)
997 {
998 char tmpSendMsg[MAX_MSG_LEN];
999 char tmpRecvMsg[MAX_MSG_LEN];
1000
1001 /* Send our Request */
1002 snprintf(tmpSendMsg, MAX_MSG_LEN, "SidCidRequest %s", ssd_data->sensor_name);
1003 SguilSendAgentMsg(ssd_data, tmpSendMsg);
1004
1005 /* Get the Results */
1006 memset(tmpRecvMsg,0x0,MAX_MSG_LEN);
1007
1008 if ( SguilRecvAgentMsg(ssd_data, tmpRecvMsg) == 1 )
1009 {
1010 if (BcLogVerbose())
1011 LogMessage("sguil: Agent registration timed out, retrying\n");
1012
1013 sguil_agent_setup_timeouts++;
1014
1015 /* timeout, resend */
1016 return 1;
1017 }
1018 else
1019 {
1020 char **toks;
1021 int num_toks;
1022
1023 DEBUG_WRAP(DebugMessage(DEBUG_LOG, "sguil: received \"%s\"", tmpRecvMsg););
1024
1025 /* parse the response */
1026 toks = mSplit(tmpRecvMsg, " ", 3, &num_toks, 0);
1027
1028 if ( strcasecmp("SidCidResponse", toks[0]) == 0 )
1029 {
1030 ssd_data->sensor_id = atoi(toks[1]);
1031 ssd_data->event_id_min = ssd_data->event_id_max = atoi(toks[2]);
1032 }
1033 else
1034 {
1035 FatalError("sguil: Expected SidCidResponse and got '%s'\n", tmpRecvMsg);
1036 }
1037
1038 mSplitFree(&toks, num_toks);
1039
1040 if (BcLogVerbose())
1041 LogMessage("sguil: sensor ID = %u\nsguil: last cid = %u\n",
1042 ssd_data->sensor_id, ssd_data->event_id_max);
1043
1044 /* use the next event_id */
1045 ssd_data->event_id_min++;
1046 ssd_data->event_id_max++;
1047 }
1048
1049 return 0;
1050 }
1051
SguilSendAgentMsg(SpoSguilData * data,char * msg)1052 int SguilSendAgentMsg(SpoSguilData *data, char *msg)
1053 {
1054 int schars;
1055 size_t len;
1056 char *tmpMsg;
1057
1058 len = strlen(msg)+2;
1059 tmpMsg = SnortAlloc(len);
1060 snprintf(tmpMsg, len, "%s\n", msg);
1061
1062 if ( (schars = send(data->agent_sock, tmpMsg, sizeof(char)*strlen(tmpMsg), 0)) < 0 )
1063 {
1064 if(BcLogVerbose())
1065 LogMessage("sguil: Lost connection to sensor_agent.\n");
1066
1067 /* resend our message */
1068 SguilSendAgentMsg(data, msg);
1069 }
1070
1071 DEBUG_WRAP(DebugMessage(DEBUG_LOG, "sguil: sending \"%s\"", tmpMsg););
1072
1073 free(tmpMsg);
1074
1075 return 0;
1076 }
1077
1078 /**
1079 * \brief Receive a message from the Sguil server
1080 * \retval 1 on timeout
1081 */
1082
1083 /* I love google. http://pont.net/socket/prog/tcpServer.c */
SguilRecvAgentMsg(SpoSguilData * ssd_data,char * line_to_return)1084 int SguilRecvAgentMsg(SpoSguilData *ssd_data, char *line_to_return)
1085 {
1086 static int rcv_ptr = 0;
1087 static char rcv_msg[MAX_MSG_LEN];
1088 static int n;
1089 struct timeval tv;
1090 fd_set read_fds;
1091 int offset;
1092
1093 offset=0;
1094
1095 /* wait up to 15 secs for our response */
1096 tv.tv_sec = 15;
1097 tv.tv_usec = 0;
1098
1099 FD_ZERO(&read_fds);
1100 FD_SET(ssd_data->agent_sock, &read_fds);
1101
1102 /* loop listening for external signals */
1103 while (exit_signal == 0)
1104 {
1105
1106 /* wait for response from sguild */
1107 select(ssd_data->agent_sock+1, &read_fds, NULL, NULL, &tv);
1108
1109 if ( !(FD_ISSET(ssd_data->agent_sock, &read_fds)) )
1110 {
1111 /* timed out */
1112 if (BcLogVerbose())
1113 LogMessage("sguil: Timed out waiting for response.\n");
1114
1115 return 1;
1116 }
1117 else
1118 {
1119 if (rcv_ptr == 0)
1120 {
1121 memset(rcv_msg,0x0,MAX_MSG_LEN);
1122 n = recv(ssd_data->agent_sock, rcv_msg, MAX_MSG_LEN, 0);
1123 if (n < 0)
1124 {
1125 LogMessage("ERROR: Unable to read data.\n");
1126
1127 /* reconnect to sensor_agent */
1128 SguilSensorAgentConnect(ssd_data);
1129 }
1130 else if (n == 0)
1131 {
1132 LogMessage("ERROR: Connecton closed by client\n");
1133 close(ssd_data->agent_sock);
1134
1135 /* reconnect to sensor_agent */
1136 SguilSensorAgentConnect(ssd_data);
1137 }
1138 }
1139
1140 /* if new data read on socket */
1141 /* OR */
1142 /* if another line is still in buffer */
1143
1144 /* copy line into 'line_to_return' */
1145 while (*(rcv_msg+rcv_ptr) != 0x0A && rcv_ptr < n )
1146 {
1147 memcpy(line_to_return+offset,rcv_msg+rcv_ptr,1);
1148 offset++;
1149 rcv_ptr++;
1150 }
1151
1152 /* end of line + end of buffer => return line */
1153 if (rcv_ptr == (n - 1))
1154 {
1155 /* set last byte to END_LINE */
1156 *(line_to_return + offset) = 0x0A;
1157 rcv_ptr = 0;
1158
1159 return ++offset;
1160 }
1161
1162 /* end of line but still some data in buffer => return line */
1163 if (rcv_ptr < (n - 1))
1164 {
1165 /* set last byte to END_LINE */
1166 *(line_to_return+offset) = 0x0A;
1167 rcv_ptr++;
1168
1169 return ++offset;
1170 }
1171
1172 /* end of buffer but line is not ended => */
1173 /* wait for more data to arrive on socket */
1174 if (rcv_ptr == n)
1175 {
1176 rcv_ptr = 0;
1177 }
1178 }
1179 }
1180
1181 return 0;
1182 }
1183
SguilTimestamp(u_int32_t sec)1184 char *SguilTimestamp(u_int32_t sec)
1185 {
1186 struct tm *lt; /* localtime */
1187 char *buf;
1188 time_t Time = sec;
1189
1190 buf = (char *)SnortAlloc(TMP_BUFFER * sizeof(char));
1191
1192 if (BcOutputUseUtc())
1193 lt = gmtime(&Time);
1194 else
1195 lt = localtime(&Time);
1196
1197 SnortSnprintf(buf, TMP_BUFFER, "%04i-%02i-%02i %02i:%02i:%02i",
1198 1900 + lt->tm_year, lt->tm_mon + 1, lt->tm_mday,
1199 lt->tm_hour, lt->tm_min, lt->tm_sec);
1200 return buf;
1201 }
1202
SguilCleanExitFunc(int signal,void * arg)1203 void SguilCleanExitFunc(int signal, void *arg)
1204 {
1205 SpoSguilData *ssd_data = (SpoSguilData *)arg;
1206
1207 DEBUG_WRAP(DebugMessage(DEBUG_LOG,"SguilCleanExitFunc\n"););
1208
1209 /* free allocated memory from SpoSguilData */
1210 if (ssd_data)
1211 {
1212
1213 if(ssd_data->agent_sock > 0)
1214 {
1215 close(ssd_data->agent_sock);
1216 ssd_data->agent_sock = -1;
1217 }
1218
1219
1220 if (ssd_data->sensor_name)
1221 free(ssd_data->sensor_name);
1222
1223 if (ssd_data->tag_path)
1224 free(ssd_data->tag_path);
1225
1226 if (ssd_data->passwd)
1227 free(ssd_data->passwd);
1228
1229 if (ssd_data->args)
1230 free(ssd_data->args);
1231
1232 free(ssd_data);
1233 }
1234
1235 }
1236
SguilRestartFunc(int signal,void * arg)1237 void SguilRestartFunc(int signal, void *arg)
1238 {
1239 SpoSguilData *ssd_data = (SpoSguilData *)arg;
1240
1241 DEBUG_WRAP(DebugMessage(DEBUG_LOG,"SguilCleanExitFunc\n"););
1242
1243 /* free allocated memory from SpoSguilData */
1244 if (ssd_data)
1245 {
1246
1247 if(ssd_data->agent_sock > 0)
1248 {
1249 close(ssd_data->agent_sock);
1250 ssd_data->agent_sock = -1;
1251 }
1252
1253 if (ssd_data->sensor_name)
1254 free(ssd_data->sensor_name);
1255
1256 if (ssd_data->tag_path)
1257 free(ssd_data->tag_path);
1258
1259 if (ssd_data->passwd)
1260 free(ssd_data->passwd);
1261
1262 if (ssd_data->args)
1263 free(ssd_data->args);
1264
1265 free(ssd_data);
1266 }
1267 }
1268
1269
1270