1 /*
2 **
3 ** Copyright (C) 2008-2013 Ian Firns (SecurixLive) <dev@securixlive.com>
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 ** Description:
23 **   In memory linked list structures of sid-msg.map, gen-msg.map and
24 ** classification.config
25 **
26 ** Author(s):
27 **   firnsy <firnsy@securixlive.com>
28 **   SecurixLive.com Team <dev@securixlive.com>
29 **
30 ** Comments:
31 **   Ideas stolen liberally from:
32 **     1. the orginal barnyard (A. Baker, M. Roesch)
33 **
34 **
35 **
36 **
37 ** TODO:
38 **   -ERROR CHECKING..........!@#$%@
39 **   1. Convert existing linked lists to adaptive splayed trees.
40 */
41 
42 #ifdef HAVE_CONFIG_H
43 #include "config.h"
44 #endif
45 
46 #include <stdio.h>
47 #include <errno.h>
48 #include <sys/types.h>
49 #ifdef SOLARIS
50     #include <strings.h>
51 #endif
52 
53 #include "debug.h"
54 #include "map.h"
55 #include "util.h"
56 #include "mstring.h"
57 #include "strlcatu.h"
58 
59 #include "barnyard2.h"
60 #include "parser.h"
61 
62 #include <string.h>
63 #include <stdlib.h>
64 
65 
66 /********************* Reference Implementation *******************************/
67 
AddReference(Barnyard2Config * bc,ReferenceNode ** head,char * system,char * id)68 ReferenceNode * AddReference(Barnyard2Config *bc, ReferenceNode **head, char *system, char *id)
69 {
70     ReferenceNode *node;
71 
72     if ((system == NULL) || (id == NULL) ||
73         (bc == NULL) || (head == NULL))
74     {
75         return NULL;
76     }
77 
78     /* create the new node */
79     node = (ReferenceNode *)SnortAlloc(sizeof(ReferenceNode));
80 
81     /* lookup the reference system */
82     node->system = ReferenceSystemLookup(bc->references, system);
83     if (node->system == NULL)
84         node->system = ReferenceSystemAdd(&bc->references, system, NULL);
85 
86     node->id = SnortStrdup(id);
87 
88     /* Add the node to the front of the list */
89     node->next = *head;
90     *head = node;
91 
92     return node;
93 }
94 
95 /* print a reference node */
FPrintReference(FILE * fp,ReferenceNode * ref_node)96 void FPrintReference(FILE *fp, ReferenceNode *ref_node)
97 {
98     if ((fp == NULL) || (ref_node == NULL))
99         return;
100 
101     if (ref_node->system != NULL)
102     {
103         if(ref_node->system->url)
104         {
105             fprintf(fp, "[Xref => %s%s]", ref_node->system->url,
106                     ref_node->id);
107         }
108         else
109         {
110             fprintf(fp, "[Xref => %s %s]", ref_node->system->name,
111                     ref_node->id);
112         }
113     }
114     else
115     {
116         fprintf(fp, "[Xref => %s]", ref_node->id);
117     }
118 }
119 
ParseReference(Barnyard2Config * bc,char * args,SigNode * sn)120 void ParseReference(Barnyard2Config *bc, char *args, SigNode *sn)
121 {
122     char **toks, *system, *id;
123     int num_toks;
124 
125     DEBUG_WRAP(DebugMessage(DEBUG_MAPS_DEEP, "map: parsing reference %s\n", args););
126 
127     /* 2 tokens: system, id */
128     toks = mSplit(args, ",", 2, &num_toks, 0);
129     if(num_toks != 2)
130     {
131         LogMessage("WARNING: invalid Reference spec '%s'. Ignored\n", args);
132     }
133     else
134     {
135         system = toks[0];
136         while ( isspace((int) *system) )
137             system++;
138 
139         id = toks[1];
140         while ( isspace((int) *id) )
141             id++;
142 
143         sn->refs = AddReference(bc, &sn->refs, system, id);
144     }
145 
146     mSplitFree(&toks, num_toks);
147 
148     return;
149 }
150 
151 
152 /********************* End of Reference Implementation ************************/
153 
154 /********************** Reference System Implementation ***********************/
155 
ReferenceSystemAdd(ReferenceSystemNode ** head,char * name,char * url)156 ReferenceSystemNode * ReferenceSystemAdd(ReferenceSystemNode **head, char *name, char *url)
157 {
158     ReferenceSystemNode *node;
159 
160     if (name == NULL)
161     {
162         ErrorMessage("NULL reference system name\n");
163         return NULL;
164     }
165 
166     if (head == NULL)
167         return NULL;
168 
169     /* create the new node */
170     node = (ReferenceSystemNode *)SnortAlloc(sizeof(ReferenceSystemNode));
171 
172     node->name = SnortStrdup(name);
173     if (url != NULL)
174         node->url = SnortStrdup(url);
175 
176     /* Add to the front of the list */
177     node->next = *head;
178     *head = node;
179 
180     return node;
181 }
182 
ReferenceSystemLookup(ReferenceSystemNode * head,char * name)183 ReferenceSystemNode * ReferenceSystemLookup(ReferenceSystemNode *head, char *name)
184 {
185     if (name == NULL)
186         return NULL;
187 
188     while (head != NULL)
189     {
190         if (strcasecmp(name, head->name) == 0)
191             break;
192 
193         head = head->next;
194     }
195 
196     return head;
197 }
198 
DeleteReferenceSystems(Barnyard2Config * bc)199 void DeleteReferenceSystems(Barnyard2Config *bc)
200 {
201     ReferenceSystemNode *current, *tmpReference;
202 
203     current = bc->references;
204     while (current!= NULL)
205     {
206         tmpReference = current->next;
207         if (current->url)
208             free(current->url);
209         if (current->name)
210             free(current->name);
211         free(current);
212         current = tmpReference;
213     }
214 
215     bc->references = NULL;
216 }
217 
ParseReferenceSystemConfig(Barnyard2Config * bc,char * args)218 void ParseReferenceSystemConfig(Barnyard2Config *bc, char *args)
219 {
220     char **toks;
221     char *name = NULL;
222     char *url = NULL;
223     int num_toks;
224 
225     /* 2 tokens: name <url> */
226     toks = mSplit(args, " ", 2, &num_toks, 0);
227     name = toks[0];
228     if(num_toks == 2)
229     {
230         url = toks[1];
231         while(isspace((int)*url))
232             url++;
233         if(url[0] == '\0')
234             url = NULL;
235     }
236     ReferenceSystemAdd(&bc->references, name, url);
237 
238     mSplitFree(&toks, num_toks);
239     return;
240 }
241 
ReadReferenceFile(Barnyard2Config * bc,const char * file)242 int ReadReferenceFile(Barnyard2Config *bc, const char *file)
243 {
244     FILE        *fd;
245     char        buf[BUFFER_SIZE];
246     char        *index;
247     char        **toks;
248     int         num_toks;
249   int         count = 0;
250 
251     DEBUG_WRAP(DebugMessage(DEBUG_MAPS, "map: opening file %s\n", file););
252 
253     if((fd = fopen(file, "r")) == NULL)
254     {
255         LogMessage("ERROR: Unable to open Reference file '%s' (%s)\n",
256                 file, strerror(errno));
257 
258         return -1;
259     }
260 
261     memset(buf, 0, BUFFER_SIZE); /* bzero() deprecated, replaced with memset() */
262 
263     while ( fgets(buf, BUFFER_SIZE, fd) != NULL )
264     {
265         index = buf;
266 
267         /* advance through any whitespace at the beginning of the line */
268         while (*index == ' ' || *index == '\t')
269             index++;
270 
271         /* if it's not a comment or a <CR>, send it to the parser */
272         if ( (*index != '#') && (*index != 0x0a) && (index != NULL) )
273         {
274             toks = mSplit(index, ":", 2, &num_toks, 0);
275 
276             if(num_toks > 1)
277             {
278                 ParseReferenceSystemConfig(bc, toks[1]);
279 		count++;
280             }
281 
282             mSplitFree(&toks, num_toks);
283         }
284     }
285 
286   if(fd != NULL)
287     fclose(fd);
288 
289   return 0;
290 }
291 
292 /****************** End of Reference System Implementation ********************/
293 
294 
295 /************************ Class/Priority Implementation ***********************/
296 
297 /* NOTE:  This lookup can only be done during parse time */
298 /* Wut ...*/
ClassTypeLookupByType(Barnyard2Config * bc,char * type)299 ClassType * ClassTypeLookupByType(Barnyard2Config *bc, char *type)
300 {
301     ClassType *node;
302 
303     if (bc == NULL)
304         FatalError("Barnyard2 config is NULL.\n");
305 
306     if (type == NULL)
307         return NULL;
308 
309     node = bc->classifications;
310 
311     while (node != NULL)
312     {
313         if (strcasecmp(type, node->type) == 0)
314             break;
315 
316         node = node->next;
317     }
318 
319     return node;
320 }
321 
ClassTypeLookupByTypePure(ClassType * node,char * type)322 ClassType * ClassTypeLookupByTypePure(ClassType *node, char *type)
323 {
324 
325     if( (node == NULL) ||
326 	(type == NULL))
327     {
328         return NULL;
329     }
330 
331 
332     while (node != NULL)
333     {
334         if (strcasecmp(type, node->type) == 0)
335 	    return node;
336 
337         node = node->next;
338     }
339 
340     return NULL;
341 }
342 
343 
344 /* NOTE:  This lookup can only be done during parse time */
345 /* Wut ...*/
ClassTypeLookupById(Barnyard2Config * bc,int id)346 ClassType * ClassTypeLookupById(Barnyard2Config *bc, int id)
347 {
348     ClassType *node;
349 
350     if (bc == NULL)
351         FatalError("Barnyard2 config is NULL.\n");
352 
353     node = bc->classifications;
354 
355     while (node != NULL)
356     {
357         if (id == node->id)
358             break;
359 
360         node = node->next;
361     }
362 
363     return node;
364 }
365 
AddClassificationConfig(Barnyard2Config * bc,ClassType * newNode)366 int AddClassificationConfig(Barnyard2Config *bc, ClassType *newNode)
367 {
368     int max_id = 0;
369     ClassType *current = bc->classifications;
370 
371     while(current != NULL)
372     {
373         /* dup check */
374         if(strcasecmp(current->type, newNode->type) == 0)
375             return -1;
376 
377         if(current->id > max_id)
378             max_id = current->id;
379 
380         current = current->next;
381     }
382 
383     /* insert node */
384     newNode->id = max_id + 1;
385     newNode->next = bc->classifications;
386     bc->classifications = newNode;
387 
388     return newNode->id;
389 }
390 
ParseClassificationConfig(Barnyard2Config * bc,char * args)391 void ParseClassificationConfig(Barnyard2Config *bc, char *args)
392 {
393     char **toks;
394     int num_toks;
395     char *data;
396     ClassType *newNode;
397 
398     toks = mSplit(args, ",", 3, &num_toks, '\\');
399 
400     if(num_toks != 3)
401     {
402         ErrorMessage(": Invalid classification config: %s\n", args);
403     }
404     else
405     {
406         /* create the new node */
407         newNode = (ClassType *)SnortAlloc(sizeof(ClassType));
408 
409         data = toks[0];
410         while(isspace((int)*data))
411             data++;
412         newNode->type = SnortStrdup(data);   /* XXX: oom check */
413 
414         data = toks[1];
415         while(isspace((int)*data))
416             data++;
417         newNode->name = SnortStrdup(data);   /* XXX: oom check */
418 
419         data = toks[2];
420         while(isspace((int)*data))
421             data++;
422         /* XXX: error checking needed */
423         newNode->priority = atoi(data); /* XXX: oom check */
424 
425         if(AddClassificationConfig(bc, newNode) == -1)
426         {
427             ErrorMessage(": Duplicate classification \"%s\""
428                     "found, ignoring this line\n", newNode->type);
429 
430             if(newNode)
431             {
432                 if(newNode->name)
433                     free(newNode->name);
434                 if(newNode->type)
435                     free(newNode->type);
436                 free(newNode);
437             }
438         }
439     }
440 
441     mSplitFree(&toks, num_toks);
442     return;
443 }
444 
DeleteClassifications(Barnyard2Config * bc)445 void DeleteClassifications(Barnyard2Config *bc)
446 {
447     ClassType           *current = bc->classifications;
448     ClassType           *tmpClass;
449 
450     while (current != NULL)
451     {
452         tmpClass = current->next;
453         if (current->type)
454             free(current->type);
455         if (current->name)
456             free(current->name);
457         free(current);
458         current = tmpClass;
459     }
460 
461     bc->classifications = NULL;
462 }
463 
ReadClassificationFile(Barnyard2Config * bc)464 int ReadClassificationFile(Barnyard2Config *bc)
465 {
466     FILE        *fd;
467     char        buf[BUFFER_SIZE];
468     char        *index;
469     char        **toks;
470     int         num_toks;
471     int         count = 0;
472 
473     if( (bc == NULL) ||
474 	(bc->class_file == NULL))
475     {
476 	/* XXX */
477 	return 1;
478     }
479 
480     DEBUG_WRAP(DebugMessage(DEBUG_MAPS, "map: opening file %s\n", file););
481 
482     if((fd = fopen(bc->class_file, "r")) == NULL)
483     {
484         LogMessage("ERROR: Unable to open Classification file '%s' (%s)\n",
485 		   bc->class_file, strerror(errno));
486 
487         return -1;
488     }
489 
490     memset(buf, 0, BUFFER_SIZE); /* bzero() deprecated, replaced with memset() */
491 
492     while ( fgets(buf, BUFFER_SIZE, fd) != NULL )
493     {
494         index = buf;
495 
496         /* advance through any whitespace at the beginning of the line */
497         while (*index == ' ' || *index == '\t')
498             index++;
499 
500         /* if it's not a comment or a <CR>, send it to the parser */
501         if ( (*index != '#') && (*index != 0x0a) && (index != NULL) )
502         {
503             toks = mSplit(index, ":", 2, &num_toks, 0);
504 
505             if(num_toks > 1)
506             {
507                 ParseClassificationConfig(bc, toks[1]);
508 		count++;
509             }
510 
511             mSplitFree(&toks, num_toks);
512         }
513     }
514 
515   if(fd != NULL)
516     fclose(fd);
517 
518 
519   return 0;
520 }
521 
522 /***************** End of Class/Priority Implementation ***********************/
523 
524 /************************* Sid/Gid Map Implementation *************************/
525 
526 
527 
528 /*
529    Classification parsing should happen before signature parsing,
530    so classification resolution should be done at signature initialization.
531 
532    But at the moment this function was written classification could be parsed before
533    signature or signature before classification, thus leading to possible unresolvability.
534 
535    hence.
536 */
SignatureResolveClassification(ClassType * class,SigNode * sig,char * sid_msg_file,char * classification_file)537 int SignatureResolveClassification(ClassType *class,SigNode *sig,char *sid_msg_file,char *classification_file)
538 {
539 
540     ClassType *found = NULL;
541 
542     if( (class == NULL) ||
543         (sig == NULL) ||
544 	(sid_msg_file == NULL) ||
545 	(classification_file == NULL))
546     {
547 	DEBUG_WRAP(DebugMessage(DEBUG_MAPS,"ERROR [%s()]: Failed class ptr [0x%x], sig ptr [0x%x], "
548 				"sig_literal ptr [0x%x], sig_map_file ptr [0x%x], classification_file ptr [0x%x] \n",
549 				__FUNCTION__,
550 				class,
551 				sig,
552 				sig->classLiteral,
553 				sid_msg_file,
554 				classification_file););
555 	return 1;
556     }
557 
558     while(sig != NULL)
559     {
560 	found = NULL;
561 
562 	if(sig->classLiteral)
563 	{
564 	    if(strncasecmp(sig->classLiteral,"NOCLASS",strlen("NOCLASS")) == 0)
565 	    {
566 		DEBUG_WRAP(DebugMessage(DEBUG_MAPS,
567 					"\nINFO: [%s()],In File [%s] \n"
568 					"Signature [gid: %d] [sid : %d] [revision: %d] message [%s] has no classification [%s] defined, signature priority is [%d]\n\n",
569 					__FUNCTION__,
570 					BcGetSourceFile(sig->source_file),
571 					sig->generator,
572 					sig->id,
573 					sig->rev,
574 					sig->msg,
575 					sig->classLiteral,
576 					sig->priority););
577 
578 	    }
579 	    else if( (found = ClassTypeLookupByTypePure(class,sig->classLiteral)) == NULL)
580 	    {
581 		sig->class_id = 0;
582 	    }
583 	    else
584 	    {
585 		sig->class_id = found->id;
586 	    }
587 	}
588 	else
589 	{
590 	    if(sig->class_id == 0)
591 	    {
592 
593 		DEBUG_WRAP(DebugMessage(DEBUG_MAPS,
594 					"\nINFO: [%s()],In file [%s]\n"
595 					"Signature [gid: %d] [sid : %d] [revision: %d] message [%s] has no classification literal defined, signature priority is [%d]\n\n",
596 					__FUNCTION__,
597 					BcGetSourceFile(sig->source_file),
598 					sig->generator,
599 					sig->id,
600 					sig->rev,
601 					sig->msg,
602 					sig->priority););
603 	    }
604 	}
605 
606 	if(sig->priority == 0)
607 	{
608 	    if(found)
609 		sig->priority = found->priority;
610 	}
611 	else
612 	{
613 	    if( (found) &&
614 		(found->priority != sig->priority))
615 	    {
616 		DEBUG_WRAP(DebugMessage(DEBUG_MAPS,
617 					"\nINFO: [%s()],In file [%s]\n"
618 					"Signature [gid: %d] [sid : %d] [revision: %d] message [%s] has classification [%s] priority [%d]\n"
619 					"The priority define by the rule will overwride classification [%s] priority [%d] defined in [%s] using [%d] as priority \n\n",
620 					__FUNCTION__,
621 					BcGetSourceFile(sig->source_file),
622 					sig->generator,
623 					sig->id,
624 					sig->rev,
625 					sig->msg,
626 					sig->classLiteral,
627 					sig->priority,
628 					found->type,
629 					found->priority,
630 					classification_file,
631 					sig->priority););
632 	    }
633 	}
634 
635 	if(sig->classLiteral)
636 	{
637 	    free(sig->classLiteral);
638 	    sig->classLiteral = NULL;
639 	}
640 
641 	sig = sig->next;
642     }
643 
644     return 0;
645 }
646 
SigLookup(SigNode * head,u_int32_t gid,u_int32_t sid,u_int8_t source_file,SigNode ** r_node)647 u_int32_t SigLookup(SigNode *head,u_int32_t gid,u_int32_t sid,u_int8_t source_file,SigNode **r_node)
648 {
649     if( (head == NULL) ||
650 	(r_node == NULL))
651     {
652 	return 0;
653     }
654 
655     while(head != NULL)
656     {
657 
658 	if(head->source_file == source_file)
659 	{
660 	    if( (head->generator == gid) &&
661 		(head->id == sid))
662 	    {
663 		*r_node = head;
664 		return 1;
665 	    }
666 	}
667 
668 	head = head->next;
669     }
670 
671 
672     *r_node = NULL;
673     return 0;
674 
675 }
676 
677 
678 
ReadSidFile(Barnyard2Config * bc)679 int ReadSidFile(Barnyard2Config *bc)
680 {
681     FILE *fd;
682     char buf[BUFFER_SIZE];
683     char *index;
684     int count = 0;
685 
686     if(bc == NULL)
687     {
688 	return 1;
689     }
690 
691     if(bc->sid_msg_file == NULL)
692     {
693 	return 0;
694     }
695 
696     DEBUG_WRAP(DebugMessage(DEBUG_MAPS, "[%s()] map: opening file %s\n",
697 			    __FUNCTION__,
698 			    bc->sid_msg_file););
699 
700     if( (fd = fopen(bc->sid_msg_file, "r")) == NULL )
701     {
702         LogMessage("ERROR: Unable to open SID file '%s' (%s)\n",
703 		   bc->sid_msg_file,
704 		   strerror(errno));
705 	return 1;
706     }
707 
708     memset(buf, 0, BUFFER_SIZE); /* bzero() deprecated, replaced by memset() */
709 
710     while(fgets(buf, BUFFER_SIZE, fd) != NULL)
711     {
712         index = buf;
713 
714         /* advance through any whitespace at the beginning of the line */
715         while(*index == ' ' || *index == '\t')
716             index++;
717 
718 	/* Check if we are dealing with a sidv2 file */
719 	if( (count == 0) &&
720 	    (bc->sidmap_version == 0))
721 	{
722 	    if(*index == '#')
723 	    {
724 		index++;
725 		if( strncasecmp(index,SIDMAPV2STRING,strlen(SIDMAPV2STRING)) == 0)
726 		{
727 		    bc->sidmap_version=SIDMAPV2;
728 		}
729 	    }
730 	    else
731 	    {
732 		bc->sidmap_version=SIDMAPV1;
733 	    }
734 
735 	    continue;
736 	}
737 
738 	/* if it's not a comment or a <CR>, send it to the parser */
739 	if((*index != '#') && (*index != 0x0a) && (index != NULL))
740 	{
741 	    ParseSidMapLine(bc, index);
742 	    count++;
743 	}
744     }
745 
746     //LogMessage("Read [%u] signature \n",count);
747 
748   if(fd != NULL)
749     fclose(fd);
750 
751   return 0;
752 }
753 
754 
755 
ParseSidMapLine(Barnyard2Config * bc,char * data)756 void ParseSidMapLine(Barnyard2Config *bc, char *data)
757 {
758 
759     SigNode *sn = NULL;
760     SigNode t_sn = {0};
761 
762     char **toks = NULL;
763     char *idx = NULL;
764 
765     int num_toks = 0;
766     int min_toks = 0;
767     int i = 0;
768 
769     toks = mSplitSpecial(data, "||", 32, &num_toks, '\0');
770 
771     switch(bc->sidmap_version)
772     {
773     case SIDMAPV1:
774 	min_toks = 2;
775 	break;
776 
777     case SIDMAPV2:
778 	min_toks = 6;
779 	break;
780 
781     default:
782 	FatalError("[%s()]: Unknown sidmap file version [%d] \n",
783 		   __FUNCTION__,
784 		   bc->sidmap_version);
785     }
786 
787     if(num_toks < min_toks)
788     {
789         LogMessage("WARNING: Ignoring bad line in SID file: '%s'\n", data);
790     }
791     else
792     {
793         DEBUG_WRAP(DebugMessage(DEBUG_MAPS_DEEP, "map: creating new node\n"););
794 
795 
796         for(i = 0; i<num_toks; i++)
797         {
798             strtrim(toks[i]);
799             strip(toks[i]);
800             idx = toks[i];
801             while(*idx == ' ') idx++;
802 
803 	    if( (idx == NULL) ||
804 		(strlen(idx) == 0))
805 	    {
806 		LogMessage("\n");
807 		FatalError("[%s()], File [%s],\nError in map definition [%s] for value [%s] \n\n",
808 			   __FUNCTION__,
809 			   bc->sid_msg_file,
810 			   data,
811 			   idx);
812 	    }
813 
814 	    switch(bc->sidmap_version)
815 	    {
816 	    case SIDMAPV1:
817 		switch(i)
818 		{
819                 case 0: /* sid */
820                     t_sn.generator = 1;
821 		    if( ((unsigned long)(t_sn.id = strtoul(idx, NULL, 10))) == ULONG_MAX)
822 		    {
823 			FatalError("[%s()], error converting integer [%s] for line [%s] \n",
824 				   __FUNCTION__,
825 				   strerror(errno),
826 				   data);
827 		    }
828 		    break;
829 
830                 case 1: /* msg */
831                     if( (t_sn.msg = SnortStrdup(idx)) == NULL)
832 		    {
833 			FatalError("[%s()], error converting string for line [%s] \n",
834 				   __FUNCTION__,
835 				   data);
836 		    }
837                     break;
838 
839                 default: /* reference data */
840                     ParseReference(bc, idx, &t_sn);
841                     break;
842 		}
843 		break;
844 
845 	    case SIDMAPV2:
846 
847 		switch(i)
848 		{
849 
850 		case 0: /*gid */
851 		    if( ((unsigned long)(t_sn.generator = strtoul(idx,NULL,10))) == ULONG_MAX)
852 		    {
853                         FatalError("[%s()], error converting integer [%s] for line [%s] \n",
854                                    __FUNCTION__,
855                                    strerror(errno),
856                                    data);
857                     }
858 
859 		    break;
860 
861 		case 1: /* sid */
862 		    if( ((unsigned long)(t_sn.id = strtoul(idx, NULL, 10))) == ULONG_MAX)
863 		    {
864                         FatalError("[%s()], error converting integer [%s] for line [%s] \n",
865                                    __FUNCTION__,
866                                    strerror(errno),
867                                    data);
868                     }
869 		    break;
870 
871 		case 2: /* revision */
872 		    if( ((unsigned long)(t_sn.rev = strtoul(idx, NULL, 10))) == ULONG_MAX)
873 		    {
874                         FatalError("[%s()], error converting integer [%s] for line [%s] \n",
875                                    __FUNCTION__,
876                                    strerror(errno),
877                                    data);
878                     }
879 		    break;
880 
881 		case 3: /* classification */
882 		    if( (t_sn.classLiteral = SnortStrdup(idx)) == NULL)
883 		    {
884 			FatalError("[%s()], error converting string for line [%s] \n",
885 				   __FUNCTION__,
886 				   data);
887 		    }
888 		    break;
889 
890 		case 4: /* priority */
891 
892 		    if( (unsigned long)(t_sn.priority = strtoul(idx, NULL, 10)) == ULONG_MAX)
893 		    {
894                         FatalError("[%s()], error converting integer [%s] for line [%s] \n",
895                                    __FUNCTION__,
896                                    strerror(errno),
897                                    data);
898                     }
899 		    break;
900 
901 		case 5: /* msg */
902 		    if( (t_sn.msg = SnortStrdup(idx)) == NULL)
903 		    {
904 			FatalError("[%s()], error converting string for line [%s] \n",
905 				   __FUNCTION__,
906 				   data);
907 		    }
908 		    break;
909 
910 		default: /* reference data */
911 		    ParseReference(bc, idx, &t_sn);
912 		    break;
913 		}
914 		break;
915 	    }
916 	}
917     }
918 
919     sn = (SigNode *)*BcGetSigNodeHead();
920 
921     /* Look if we have a brother inserted from sid map file */
922     sig_lookup_continue:
923     if(SigLookup(sn,t_sn.generator,t_sn.id,SOURCE_SID_MSG,&sn))
924     {
925 	if(t_sn.rev == sn->rev)
926 	{
927 	    DEBUG_WRAP(DebugMessage(DEBUG_MAPS,
928 				    "[%s()],Item not inserted [ gid:[%d] sid:[%d] rev:[%d] msg:[%s] class:[%d] prio:[%d] ] in signature list \n"
929  				    "\t Item already present  [ gid:[%d] sid:[%d] rev:[%d] msg:[%s] class:[%d] prio:[%d] ] \n",
930 				    __FUNCTION__,
931 				    t_sn.generator,t_sn.id,t_sn.rev,t_sn.msg,t_sn.class_id,t_sn.priority, /* revision,class_id and priority are hardcoded for generator */
932 				    sn->generator,sn->id,sn->rev,sn->msg,sn->class_id,sn->priority););
933 	}
934 	else
935 	{
936 	    /* Continue to traverse the list to be sure */
937 	    sn = sn->next;
938 	    goto sig_lookup_continue;
939 	}
940     }
941     else
942     {
943         if( (sn = CreateSigNode(BcGetSigNodeHead(),SOURCE_SID_MSG)) == NULL)
944         {
945             FatalError("[%s()], CreateSigNode() returned a NULL node, bailing \n",
946                        __FUNCTION__);
947         }
948 
949         memcpy(sn,&t_sn,sizeof(SigNode));
950 
951 	sn->source_file = SOURCE_SID_MSG;
952     }
953 
954     mSplitFree(&toks, num_toks);
955 
956     return;
957 }
958 
GetSigByGidSid(u_int32_t gid,u_int32_t sid,u_int32_t revision)959 SigNode *GetSigByGidSid(u_int32_t gid, u_int32_t sid,u_int32_t revision)
960 {
961     /* set temp node pointer to the Sid map list head */
962     SigNode **sh = BcGetSigNodeHead();
963     SigNode *sn = *sh;
964 
965     switch(BcSidMapVersion())
966     {
967     case SIDMAPV1:
968 	/* The comment below is not true anymore with  sidmapv2 files generated by pulled pork */
969 
970 	/* a snort general rule (gid=1) and a snort dynamic rule (gid=3) use the  */
971 	/* the same sids and thus can be considered one in the same. */
972 	if (gid == 3)
973 	{
974 	    gid = 1;
975 	}
976 
977 	/* find any existing Snort ID's that match */
978 	while (sn != NULL)
979 	{
980 	    if (sn->generator == gid && sn->id == sid)
981 	    {
982 		return sn;
983 	    }
984 
985 	    sn = sn->next;
986 	}
987 	break;
988 
989     case SIDMAPV2:
990 	while (sn != NULL)
991         {
992             if ( (sn->generator == gid) &&
993 		 (sn->id == sid) &&
994 		 (sn->rev == revision))
995             {
996                 return sn;
997             }
998 
999             sn = sn->next;
1000         }
1001 	break;
1002     }
1003 
1004     /* create a default message since we didn't find any match */
1005     sn = CreateSigNode(BcGetSigNodeHead(),SOURCE_GEN_RUNTIME);
1006     sn->generator = gid;
1007     sn->id = sid;
1008     sn->rev = revision;
1009     sn->msg = (char *)SnortAlloc(42);
1010     snprintf(sn->msg, 42, "Snort Alert [%u:%u:%u]", gid, sid, revision);
1011 
1012     return sn;
1013 }
1014 
1015 
1016 
CreateSigNode(SigNode ** head,const u_int8_t source_file)1017 SigNode *CreateSigNode(SigNode **head,const u_int8_t source_file)
1018 {
1019     SigNode       *sn = NULL;
1020 
1021     if (*head == NULL)
1022     {
1023         *head = (SigNode *) SnortAlloc(sizeof(SigNode));
1024 	sn = *head;
1025 	sn->source_file = source_file;
1026         return *head;
1027     }
1028     else
1029     {
1030         sn = *head;
1031 
1032         while (sn->next != NULL)
1033 	    sn = sn->next;
1034 
1035         sn->next = (SigNode *) SnortAlloc(sizeof(SigNode));
1036 	sn->next->source_file = source_file;
1037         return sn->next;
1038     }
1039 
1040     /* XXX */
1041     return NULL;
1042 }
1043 
ReadGenFile(Barnyard2Config * bc)1044 int ReadGenFile(Barnyard2Config *bc)
1045 {
1046     FILE        *fd;
1047     char        buf[BUFFER_SIZE];
1048     char        *index;
1049     int         count = 0;
1050 
1051     if(bc->gen_msg_file == NULL)
1052     {
1053 	return 0;
1054     }
1055 
1056     DEBUG_WRAP(DebugMessage(DEBUG_MAPS, "[%s()] map: opening file %s\n",
1057 			    __FUNCTION__,
1058 			    bc->gen_msg_file););
1059 
1060     if ( (fd = fopen(bc->gen_msg_file, "r")) == NULL )
1061     {
1062 	LogMessage("ERROR: Unable to open Generator file \"%s\": %s\n",
1063 		   bc->gen_msg_file,
1064 		   strerror(errno));
1065 
1066 	return 1;
1067     }
1068 
1069     memset(buf, 0, BUFFER_SIZE); /* bzero() deprecated, replaced by memset() */
1070 
1071     while( fgets(buf, BUFFER_SIZE, fd) != NULL )
1072     {
1073         index = buf;
1074 
1075         /* advance through any whitespace at the beginning of the line */
1076         while (*index == ' ' || *index == '\t')
1077             index++;
1078 
1079         /* if it's not a comment or a <CR>, send it to the parser */
1080         if( (*index != '#') && (*index != 0x0a) && (index != NULL) )
1081         {
1082             ParseGenMapLine(index);
1083 	    count++;
1084         }
1085     }
1086 
1087     //LogMessage("Read [%u] gen \n",count);
1088 
1089     if(fd != NULL)
1090 	fclose(fd);
1091 
1092     return 0;
1093 }
1094 
1095 
ParseGenMapLine(char * data)1096 void ParseGenMapLine(char *data)
1097 {
1098     char **toks = NULL;
1099     char *idx = NULL;
1100 
1101     SigNode *sn = NULL;
1102     SigNode t_sn = {0};  /* used for temp storage before lookup */
1103 
1104     int num_toks = 0;
1105     int i = 0;
1106 
1107     toks = mSplitSpecial(data, "||", 32, &num_toks, '\0');
1108 
1109     if(num_toks < 2)
1110     {
1111         LogMessage("WARNING: Ignoring bad line in SID file: \"%s\"\n", data);
1112 	return;
1113     }
1114 
1115     for(i=0; i<num_toks; i++)
1116     {
1117         strip(toks[i]);
1118         idx = toks[i];
1119         while(*idx == ' ') idx++;
1120 
1121         switch(i)
1122         {
1123 	case 0: /* gen */
1124 	    if( (unsigned long)(t_sn.generator = strtoul(idx, NULL, 10)) == ULONG_MAX)
1125 	    {
1126 		FatalError("[%s()], error converting integer [%s] for line [%s] \n",
1127 			   __FUNCTION__,
1128 			   strerror(errno),
1129 			   data);
1130 	    }
1131 	    break;
1132 
1133 	case 1: /* sid */
1134 	    if( (unsigned long)(t_sn.id = strtoul(idx, NULL, 10)) == ULONG_MAX)
1135 	    {
1136 		FatalError("[%s()], error converting integer [%s] for line [%s] \n",
1137 			   __FUNCTION__,
1138 			   strerror(errno),
1139 			   data);
1140 	    }
1141 	    break;
1142 
1143 	case 2: /* msg */
1144 	    if( (t_sn.msg = SnortStrdup(idx)) == NULL)
1145 	    {
1146 		FatalError("[%s()], error converting string for line [%s] \n",
1147 			   __FUNCTION__,
1148 			   data);
1149 	    }
1150 	    break;
1151 
1152 	default:
1153 	    break;
1154         }
1155     }
1156 
1157     switch(BcSidMapVersion())
1158     {
1159         case SIDMAPV1:
1160            t_sn.rev = 1;
1161            t_sn.priority = 0;
1162            t_sn.classLiteral = strdup("NOCLASS"); /* default */
1163            t_sn.class_id = 0;
1164            break;
1165 
1166         case SIDMAPV2:
1167            /*
1168               Generators have pre-defined revision,classification and priority
1169            */
1170            t_sn.rev = 1;
1171            t_sn.classLiteral = strdup("NOCLASS"); /* default */
1172            t_sn.class_id = 0;
1173            t_sn.priority = 3;
1174            break;
1175     }
1176 
1177     /* Look if we have a brother inserted from sid map file */
1178     if(SigLookup((SigNode *)*BcGetSigNodeHead(),t_sn.generator,t_sn.id,SOURCE_SID_MSG,&sn))
1179     {
1180 
1181 	DEBUG_WRAP(DebugMessage(DEBUG_MAPS,
1182 				"[%s()],Item not inserted [ gid:[%d] sid:[%d] rev:[%d] msg:[%s] class:[%d] prio:[%d] ] in signature list \n"
1183 				"\t Item already present  [ gid:[%d] sid:[%d] rev:[%d] msg:[%s] class:[%d] prio:[%d] ] \n",
1184 				__FUNCTION__,
1185 				t_sn.generator,t_sn.id,t_sn.rev,t_sn.msg,t_sn.class_id,t_sn.priority, /* revision,class_id and priority are hardcoded for generator */
1186 				sn->generator,sn->id,sn->rev,sn->msg,sn->class_id,sn->priority););
1187 
1188 	/*
1189 	   This is a quick hack for now to put sweet gid-msg.map messages up there
1190 	*/
1191 	if(t_sn.msg)
1192 	{
1193 	    DEBUG_WRAP(DebugMessage(DEBUG_MAPS,"[%s()], swapping message [%s] for [%s] \n",
1194 				    __FUNCTION__,
1195 				    sn->msg,
1196 				    t_sn.msg););
1197 	    free(sn->msg);
1198 	    sn->msg = NULL;
1199 	    sn->msg = t_sn.msg;
1200 	    t_sn.msg = NULL;
1201 	}
1202 
1203 	if(t_sn.classLiteral)
1204 	{
1205 	    free(t_sn.classLiteral);
1206 	    t_sn.classLiteral = NULL;
1207 	}
1208 
1209 	DEBUG_WRAP(DebugMessage(DEBUG_MAPS,"\n"););
1210 
1211     }
1212     else
1213     {
1214 	if(SigLookup((SigNode *)*BcGetSigNodeHead(),t_sn.generator,t_sn.id,SOURCE_GEN_MSG,&sn) == 0)
1215 	{
1216 	    if( (sn = CreateSigNode(BcGetSigNodeHead(),SOURCE_GEN_MSG)) == NULL)
1217 	    {
1218 		FatalError("[%s()], CreateSigNode() returned a NULL node, bailing \n",
1219 			   __FUNCTION__);
1220 	    }
1221 
1222 	    memcpy(sn,&t_sn,sizeof(SigNode));
1223 
1224 	    sn->source_file = SOURCE_GEN_MSG;
1225 	}
1226 	else
1227 	{
1228 
1229 	    DEBUG_WRAP(DebugMessage(DEBUG_MAPS,
1230 				    "[%s()],Item not inserted [ gid:[%d] sid:[%d] rev:[%d] msg:[%s] class:[%d] prio:[%d] ] in signature list \n"
1231 				    "\t Item already present  [ gid:[%d] sid:[%d] rev:[%d] msg:[%s] class:[%d] prio:[%d] ] \n\n",
1232 				    __FUNCTION__,
1233 				    t_sn.generator,t_sn.id,t_sn.rev,t_sn.msg,t_sn.class_id,t_sn.priority, /* revision,class_id and priority are hardcoded for generator */
1234 				    sn->generator,sn->id,sn->rev,sn->msg,sn->class_id,sn->priority););
1235 
1236 	    if(t_sn.msg)
1237 	    {
1238 		free(t_sn.msg);
1239 		t_sn.msg = NULL;
1240 	    }
1241 
1242 	    if(t_sn.classLiteral)
1243 	    {
1244 		free(t_sn.classLiteral);
1245 		t_sn.classLiteral = NULL;
1246 	    }
1247 
1248 	}
1249     }
1250 
1251     mSplitFree(&toks, num_toks);
1252 
1253     return;
1254 }
1255 
1256 /*
1257  * Some destructors
1258  *
1259  *
1260  */
1261 
FreeSigNodes(SigNode ** sigHead)1262 void FreeSigNodes(SigNode **sigHead)
1263 {
1264     SigNode *sn = NULL, *snn = NULL;
1265     ReferenceNode *rn = NULL, *rnn = NULL;
1266     sn = *sigHead;
1267 
1268     while(sn != NULL)
1269     {
1270         snn = sn->next;
1271 
1272         /* free the message */
1273         if(sn->msg)
1274 	{
1275             free(sn->msg);
1276 	    sn->msg = NULL;
1277 	}
1278 
1279 	if(sn->classLiteral)
1280 	{
1281 	    free(sn->classLiteral);
1282 	    sn->classLiteral = NULL;
1283 	}
1284 
1285         /* free the references (NOT the reference systems) */
1286         if(sn->refs)
1287         {
1288             rn = sn->refs;
1289             while(rn != NULL)
1290             {
1291                 rnn = rn->next;
1292 
1293                 /* free the id */
1294                 if(rn->id)
1295                     free(rn->id);
1296 
1297                 /* free the reference node */
1298                 free(rn);
1299 
1300                 rn = rnn;
1301             }
1302         }
1303 
1304         /* free the signature node */
1305 	free(sn);
1306 	sn = NULL;
1307         sn = snn;
1308     }
1309 
1310     *sigHead = NULL;
1311 
1312     return;
1313 }
1314 
FreeClassifications(ClassType ** i_head)1315 void FreeClassifications(ClassType **i_head)
1316 {
1317     ClassType *head = *i_head;
1318 
1319     while (head != NULL)
1320     {
1321         ClassType *tmp = head;
1322 
1323         head = head->next;
1324 
1325         if (tmp->name != NULL)
1326             free(tmp->name);
1327 
1328         if (tmp->type != NULL)
1329             free(tmp->type);
1330 
1331         free(tmp);
1332     }
1333 
1334     *i_head = NULL;
1335 }
1336 
1337 
FreeReferences(ReferenceSystemNode ** i_head)1338 void FreeReferences(ReferenceSystemNode **i_head)
1339 {
1340     ReferenceSystemNode *head = *i_head;
1341 
1342     while (head != NULL)
1343     {
1344         ReferenceSystemNode *tmp = head;
1345 
1346         head = head->next;
1347 
1348         if (tmp->name != NULL)
1349             free(tmp->name);
1350 
1351         if (tmp->url != NULL)
1352             free(tmp->url);
1353 
1354         free(tmp);
1355     }
1356 
1357     *i_head = NULL;
1358 }
1359 
FreeSigSuppression(SigSuppress_list ** i_head)1360 void FreeSigSuppression(SigSuppress_list **i_head)
1361 {
1362     SigSuppress_list *head = *i_head;
1363 
1364     while(head != NULL)
1365     {
1366 	SigSuppress_list *next = head->next;
1367 
1368 	free(head);
1369 	head = next;
1370     }
1371 
1372     *i_head = NULL;
1373 }
1374