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