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