1 /* $Id$ */
2 /*
3 ** Copyright (C) 2002-2009 Sourcefire, Inc.
4 ** Copyright (C) 1998-2002 Martin Roesch <roesch@sourcefire.com>
5 ** Copyright (C) 2000,2001 Andrew R. Baker <andrewb@uab.edu>
6 **
7 ** This program is free software; you can redistribute it and/or modify
8 ** it under the terms of the GNU General Public License Version 2 as
9 ** published by the Free Software Foundation.  You may not use, modify or
10 ** distribute this program under any other version of the GNU General
11 ** Public License.
12 **
13 ** This program is distributed in the hope that it will be useful,
14 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 ** GNU General Public License for more details.
17 **
18 ** You should have received a copy of the GNU General Public License
19 ** along with this program; if not, write to the Free Software
20 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 */
22 
23 #ifdef HAVE_CONFIG_H
24 # include "config.h"
25 #endif
26 
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <assert.h>
32 #include <errno.h>
33 #include <ctype.h>
34 #include <unistd.h>
35 #include <stdarg.h>
36 
37 #ifdef HAVE_STRINGS_H
38 # include <strings.h>
39 #endif
40 
41 #ifndef WIN32
42 # include <netdb.h>
43 # include <sys/socket.h>
44 # include <netinet/in.h>
45 # include <arpa/inet.h>
46 # include <grp.h>
47 # include <pwd.h>
48 # include <fnmatch.h>
49 #endif /* !WIN32 */
50 
51 #include "bounds.h"
52 #include "rules.h"
53 #include "parser.h"
54 #include "plugbase.h"
55 #include "debug.h"
56 #include "util.h"
57 #include "mstring.h"
58 #include "log.h"
59 #include "generators.h"
60 #include "strlcatu.h"
61 #include "strlcpyu.h"
62 #include "barnyard2.h"
63 #include "sf_vartable.h"
64 #include "ipv6_port.h"
65 #include "sfutil/sf_ip.h"
66 
67 #ifdef TARGET_BASED
68 # include "sftarget_reader.h"
69 #endif
70 
71 #ifdef PORTLISTS
72 # include "sfutil/sfrim.h"
73 # include "sfutil/sfportobject.h"
74 #endif
75 
76 /* MPLS payload types */
77 #ifdef MPLS
78 # define MPLS_PAYLOAD_OPT__IPV4      "ipv4"
79 # define MPLS_PAYLOAD_OPT__IPV6      "ipv6"
80 # define MPLS_PAYLOAD_OPT__ETHERNET  "ethernet"
81 #endif
82 
83 /* Macros *********************************************************************/
84 #define MAX_RULE_OPTIONS     256
85 #define MAX_LINE_LENGTH    32768
86 #define MAX_IPLIST_ENTRIES  4096
87 #define DEFAULT_LARGE_RULE_GROUP 9
88 #define SF_IPPROTO_UNKNOWN -1
89 #define MAX_RULE_COUNT (65535 * 2)
90 
91 /* For user defined rule type */
92 #define RULE_TYPE_OPT__TYPE    "type"
93 
94 #define ERR_PAIR_COUNT \
95     "%s has incorrect argument count; should be %d pairs.", ERR_KEY
96 #define ERR_NOT_PAIRED \
97     "%s is missing an option or argument to go with: %s.", ERR_KEY, pairs[0]
98 #define ERR_EXTRA_OPTION \
99     "%s has extra option of type: %s.", ERR_KEY, pairs[0]
100 #define ERR_BAD_OPTION \
101     "%s has unknown option: %s.", ERR_KEY, pairs[0]
102 #define ERR_BAD_VALUE \
103     "%s has unknown %s: %s.", ERR_KEY, pairs[0], pairs[1]
104 #define ERR_BAD_ARG_COUNT \
105     "%s has incorrect argument count.", ERR_KEY
106 #define ERR_CREATE \
107     "%s could not be created.", ERR_KEY
108 #define ERR_CREATE_EX \
109     "%s could not be created: %s.", ERR_KEY
110 
111 // arbitrary conf file name used to allow initialization w/o conf
112 // (required for packet logging mode)
113 #define NULL_CONF "null"
114 
115 /* Data types *****************************************************************/
116 typedef void (*ParseFunc)(Barnyard2Config *, char *);
117 typedef void (*ParseConfigFunc)(Barnyard2Config *, char *);
118 
119 /* Used to determine whether or not to parse the keyword line based on
120  * whether or not we're parsing rules */
121 typedef enum _KeywordType
122 {
123     KEYWORD_TYPE__MAIN,
124     KEYWORD_TYPE__RULE,
125     KEYWORD_TYPE__ALL
126 
127 } KeywordType;
128 
129 typedef enum _VarType
130 {
131     VAR_TYPE__DEFAULT,
132     VAR_TYPE__PORTVAR,
133     VAR_TYPE__IPVAR
134 
135 } VarType;
136 
137 typedef struct _KeywordFunc
138 {
139     char *name;
140     KeywordType type;
141     int expand_vars;
142     ParseFunc parse_func;
143 
144 } KeywordFunc;
145 
146 typedef struct _ConfigFunc
147 {
148     char *name;
149     int args_required;
150     int only_once;
151     ParseConfigFunc parse_func;
152 
153 } ConfigFunc;
154 
155 /* Externs ********************************************************************/
156 extern VarNode *cmd_line_var_list;
157 extern char *barnyard2_conf_file;
158 extern char *barnyard2_conf_dir;
159 
160 /* Globals ********************************************************************/
161 
162 /* Set to the current barnyard2 config we're parsing.  Mostly used for the
163  * plugins (input and output) since the callbacks don't pass a barnyard2
164  * configuration */
165 Barnyard2Config *barnyard2_conf_for_parsing = NULL;
166 
167 char *file_name = NULL;   /* current config file being processed */
168 int file_line = 0;        /* current line being processed in the file */
169 
170 /* Main parsing function uses this to indicate whether or not
171  * rules are to be parsed. */
172 static int parse_rules = 0;
173 
174 static void ParseConfig(Barnyard2Config *, char *);
175 static void ParseIpVar(Barnyard2Config *, char *);
176 static void ParseVar(Barnyard2Config *, char *);
177 static void AddVarToTable(Barnyard2Config *, char *, char *);
178 
179 static const KeywordFunc barnyard2_conf_keywords[] =
180 {
181     /* Non-rule keywords */
182     { BARNYARD2_CONF_KEYWORD__VAR,               KEYWORD_TYPE__MAIN, 0, ParseVar },
183     { BARNYARD2_CONF_KEYWORD__CONFIG,            KEYWORD_TYPE__MAIN, 1, ParseConfig },
184     { BARNYARD2_CONF_KEYWORD__IPVAR,             KEYWORD_TYPE__MAIN, 0, ParseIpVar },
185     { BARNYARD2_CONF_KEYWORD__INPUT,             KEYWORD_TYPE__MAIN, 1, ParseInput },
186     { BARNYARD2_CONF_KEYWORD__OUTPUT,            KEYWORD_TYPE__MAIN, 1, ParseOutput },
187     { NULL, 0, 0, NULL }   /* Marks end of array */
188 };
189 
190 static const ConfigFunc config_opts[] =
191 {
192     { CONFIG_OPT__DISABLE_ALERT_ON_EACH_PACKET_IN_STREAM, 0, 1, ConfigDisableAlertOnEachPacketInStream },
193     { CONFIG_OPT__EVENT_CACHE_SIZE, 0, 1, ConfigSetEventCacheSize },
194     { CONFIG_OPT__ALERT_ON_EACH_PACKET_IN_STREAM, 0, 1, ConfigAlertOnEachPacketInStream },
195     { CONFIG_OPT__ALERT_WITH_IFACE_NAME, 0, 1, ConfigAlertWithInterfaceName },
196     { CONFIG_OPT__ARCHIVE_DIR, 1, 1, ConfigArchiveDir },
197     { CONFIG_OPT__CHROOT_DIR, 1, 1, ConfigChrootDir },
198     { CONFIG_OPT__CLASSIFICATION, 1, 0, ConfigClassification },
199     { CONFIG_OPT__CLASSIFICATION_FILE, 1, 0, ConfigClassificationFile },
200     { CONFIG_OPT__DAEMON, 0, 1, ConfigDaemon },
201     { CONFIG_OPT__DECODE_DATA_LINK, 0, 1, ConfigDecodeDataLink },
202     { CONFIG_OPT__DUMP_CHARS_ONLY, 0, 1, ConfigDumpCharsOnly },
203     { CONFIG_OPT__DUMP_PAYLOAD, 0, 1, ConfigDumpPayload },
204     { CONFIG_OPT__DUMP_PAYLOAD_VERBOSE, 0, 1, ConfigDumpPayloadVerbose },
205     { CONFIG_OPT__GEN_FILE, 1, 0, ConfigGenFile },
206     { CONFIG_OPT__HOSTNAME, 1, 0, ConfigHostname },
207     { CONFIG_OPT__INTERFACE, 1, 1, ConfigInterface },
208     { CONFIG_OPT__LOG_DIR, 1, 1, ConfigLogDir },
209     { CONFIG_OPT__OBFUSCATE, 0, 1, ConfigObfuscate },
210     { CONFIG_OPT__SIGSUPPRESS,0,0,ConfigSigSuppress},
211     /* XXX We can configure this on the command line - why not in config file ??? */
212 #ifdef NOT_UNTIL_WE_DAEMONIZE_AFTER_READING_CONFFILE
213     { CONFIG_OPT__PID_PATH, 1, 1, ConfigPidPath },
214 #endif
215     { CONFIG_OPT__PROCESS_NEW_RECORDS_ONLY, 0, 1, ConfigProcessNewRecordsOnly },
216     { CONFIG_OPT__QUIET, 0, 1, ConfigQuiet },
217     { CONFIG_OPT__REFERENCE, 1, 0, ConfigReference },
218     { CONFIG_OPT__REFERENCE_FILE, 1, 0, ConfigReferenceFile },
219     { CONFIG_OPT__REFERENCE_NET, 1, 1, ConfigReferenceNet },
220     { CONFIG_OPT__SET_GID, 1, 1, ConfigSetGid },
221     { CONFIG_OPT__SET_UID, 1, 1, ConfigSetUid },
222     { CONFIG_OPT__SID_FILE, 1, 0, ConfigSidFile },
223     { CONFIG_OPT__SHOW_YEAR, 0, 1, ConfigShowYear },
224     { CONFIG_OPT__UMASK, 1, 1, ConfigUmask },
225     { CONFIG_OPT__UTC, 0, 1, ConfigUtc },
226     { CONFIG_OPT__VERBOSE, 0, 1, ConfigVerbose },
227     { CONFIG_OPT__WALDO_FILE, 1, 0, ConfigWaldoFile },
228 #ifdef MPLS
229     { CONFIG_OPT__MAX_MPLS_LABELCHAIN_LEN, 0, 1, ConfigMaxMplsLabelChain },
230     { CONFIG_OPT__MPLS_PAYLOAD_TYPE, 0, 1, ConfigMplsPayloadType },
231 #endif
232     { NULL, 0, 0, NULL }   /* Marks end of array */
233 };
234 
235 /* Used to determine if a config option has already been configured
236  * Gets zeroed when initially parsing a configuration file, then each
237  * index gets set to 1 as an option is configured.  Maps to config_opts */
238 static uint8_t config_opt_configured[sizeof(config_opts) / sizeof(ConfigFunc)];
239 
240 
241 /* Private function prototypes ************************************************/
242 static void InitVarTables(Barnyard2Config *);
243 static void InitParser(void);
244 #ifdef SUP_IP6
245 static int VarIsIpAddr(vartable_t *, char *);
246 #endif
247 static void ParseConfigFile(Barnyard2Config *, char *);
248 static int ContinuationCheck(char *);
249 static VarEntry * VarDefine(Barnyard2Config *, char *, char *);
250 static char * VarSearch(Barnyard2Config *, char *);
251 static char * ExpandVars(Barnyard2Config *, char *);
252 static VarEntry * VarAlloc(void);
253 static void DeleteVars(VarEntry *);
254 static void TransferOutputConfigs(OutputConfig *, OutputConfig **);
255 static OutputConfig * DupOutputConfig(OutputConfig *);
256 static void RemoveOutputConfigs(OutputConfig **, int);
257 
258 static void DisallowCrossTableDuplicateVars(Barnyard2Config *, char *, VarType);
259 
260 /****************************************************************************
261  * Function: ParseSnortConf()
262  *
263  * Read the rules file a line at a time and send each rule to the rule parser
264  * This is the first pass of the configuration file.  It parses everything
265  * except the rules.
266  *
267  * Arguments: None
268  *
269  * Returns:
270  *  Barnyard2Config *
271  *      An initialized and configured snort configuration struct.
272  *      This struct should be passed on the second pass of the
273  *      configuration file to parse the rules.
274  *
275  ***************************************************************************/
ParseBarnyard2Conf(void)276 Barnyard2Config * ParseBarnyard2Conf(void)
277 {
278     Barnyard2Config *bc = Barnyard2ConfNew();
279     VarNode *tmp = cmd_line_var_list;
280 
281     file_line = 0;
282     file_name = barnyard2_conf_file ? barnyard2_conf_file : NULL_CONF;
283 
284     /* Need to set this for plugin configurations since they're using
285      * lists of callbacks */
286     barnyard2_conf_for_parsing = bc;
287 
288     InitParser();
289 
290     /* We're not going to parse rules on the first pass */
291     parse_rules = 0;
292 
293     InitVarTables(bc);
294 
295     /* Add command line defined variables - duplicates will already
296      * have been resolved */
297     while (tmp != NULL)
298     {
299         AddVarToTable(bc, tmp->name, tmp->value);
300         tmp = tmp->next;
301     }
302 
303     if ( strcmp(file_name, NULL_CONF) )
304         ParseConfigFile(bc, file_name);
305 
306     /* Add command line defined variables - duplicates will already
307      * have been resolved */
308     tmp = cmd_line_var_list;
309     while (tmp != NULL)
310     {
311         AddVarToTable(bc, tmp->name, tmp->value);
312         tmp = tmp->next;
313     }
314 
315     /* Make sure this gets set back to NULL when we're done parsing */
316     barnyard2_conf_for_parsing = NULL;
317 
318     /* Reset these.  The only issue in not reseting would be if we were
319      * parsing a command line again, but do it anyway */
320     file_name = NULL;
321     file_line = 0;
322 
323     return bc;
324 }
325 
ParseInput(Barnyard2Config * bc,char * args)326 void ParseInput(Barnyard2Config *bc, char *args)
327 {
328     char **toks;
329     int num_toks;
330     char *opts = NULL;
331     InputConfig *config;
332 
333     toks = mSplit(args, ":", 2, &num_toks, '\\');
334 
335     if (num_toks > 1)
336         opts = toks[1];
337 
338     config = (InputConfig *)SnortAlloc(sizeof(InputConfig));
339 
340     if (bc->input_configs == NULL)
341     {
342         bc->input_configs = config;
343     }
344     else
345     {
346         InputConfig *tmp = bc->input_configs;
347 
348         while (tmp->next != NULL)
349             tmp = tmp->next;
350 
351         tmp->next = config;
352     }
353 
354     config->keyword = SnortStrdup(toks[0]);
355     if (opts != NULL)
356         config->opts = SnortStrdup(opts);
357 
358     /* This could come from parsing the command line */
359     if (file_name != NULL)
360     {
361         config->file_name = SnortStrdup(file_name);
362         config->file_line = file_line;
363     }
364 
365     mSplitFree(&toks, num_toks);
366 }
367 
ConfigureInputPlugins(Barnyard2Config * bc)368 void ConfigureInputPlugins(Barnyard2Config *bc)
369 {
370     InputConfig *config;
371     char *stored_file_name = file_name;
372     int stored_file_line = file_line;
373 
374     barnyard2_conf_for_parsing = bc;
375 
376     DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Input Plugin\n"););
377 
378     for (config = bc->input_configs; config != NULL; config = config->next)
379     {
380         InputConfigFunc func;
381 
382         file_name = config->file_name;
383         file_line = config->file_line;
384 
385         func = GetInputConfigFunc(config->keyword);
386         if (func == NULL)
387             ParseError("Unknown input plugin: \"%s\"", config->keyword);
388 
389         func(config->opts);
390     }
391 
392     /* Reset these since we're done with configuring dynamic preprocessors */
393     file_name = stored_file_name;
394     file_line = stored_file_line;
395 
396     barnyard2_conf_for_parsing = NULL;
397 }
398 
ParseOutput(Barnyard2Config * bc,char * args)399 void ParseOutput(Barnyard2Config *bc, char *args)
400 {
401     char **toks;
402     int num_toks;
403     char *opts = NULL;
404     OutputConfig *config;
405 
406     toks = mSplit(args, ":", 2, &num_toks, '\\');
407 
408     if (num_toks > 1)
409         opts = toks[1];
410 
411     config = (OutputConfig *)SnortAlloc(sizeof(OutputConfig));
412 
413     if (bc->output_configs == NULL)
414     {
415         bc->output_configs = config;
416     }
417     else
418     {
419         OutputConfig *tmp = bc->output_configs;
420 
421         while (tmp->next != NULL)
422             tmp = tmp->next;
423 
424         tmp->next = config;
425     }
426 
427     config->keyword = SnortStrdup(toks[0]);
428     if (opts != NULL)
429         config->opts = SnortStrdup(opts);
430 
431     /* This could come from parsing the command line */
432     if (file_name != NULL)
433     {
434         config->file_name = SnortStrdup(file_name);
435         config->file_line = file_line;
436     }
437 
438     mSplitFree(&toks, num_toks);
439 }
440 
TransferOutputConfigs(OutputConfig * from_list,OutputConfig ** to_list)441 static void TransferOutputConfigs(OutputConfig *from_list, OutputConfig **to_list)
442 {
443     if ((from_list == NULL) || (to_list == NULL))
444         return;
445 
446     for (; from_list != NULL; from_list = from_list->next)
447     {
448         if (*to_list == NULL)
449         {
450             *to_list = DupOutputConfig(from_list);
451         }
452         else
453         {
454             OutputConfig *tmp = DupOutputConfig(from_list);
455 
456             if (tmp != NULL)
457             {
458                 tmp->next = *to_list;
459                 *to_list = tmp;
460             }
461         }
462     }
463 }
464 
DupOutputConfig(OutputConfig * dupme)465 static OutputConfig * DupOutputConfig(OutputConfig *dupme)
466 {
467     OutputConfig *medup;
468 
469     if (dupme == NULL)
470         return NULL;
471 
472     medup = (OutputConfig *)SnortAlloc(sizeof(OutputConfig));
473 
474     if (dupme->keyword != NULL)
475         medup->keyword = SnortStrdup(dupme->keyword);
476 
477     if (dupme->opts != NULL)
478         medup->opts = SnortStrdup(dupme->opts);
479 
480     if (dupme->file_name != NULL)
481         medup->file_name = SnortStrdup(dupme->file_name);
482 
483     medup->file_line = dupme->file_line;
484 
485     return medup;
486 }
487 
RemoveOutputConfigs(OutputConfig ** head,int remove_flags)488 static void RemoveOutputConfigs(OutputConfig **head, int remove_flags)
489 {
490     OutputConfig *config;
491     OutputConfig *last = NULL;
492 
493     if (head == NULL)
494         return;
495 
496     config = *head;
497 
498     while (config != NULL)
499     {
500         int type_flags = GetOutputTypeFlags(config->keyword);
501 
502         if (type_flags & remove_flags)
503         {
504             OutputConfig *tmp = config;
505 
506             config = config->next;
507 
508             if (last == NULL)
509                 *head = config;
510             else
511                 last->next = config;
512 
513             free(tmp->keyword);
514 
515             if (tmp->opts != NULL)
516                 free(tmp->opts);
517 
518             if (tmp->file_name != NULL)
519                 free(tmp->file_name);
520 
521             free(tmp);
522         }
523         else
524         {
525             last = config;
526             config = config->next;
527         }
528     }
529 }
530 
ResolveOutputPlugins(Barnyard2Config * cmd_line,Barnyard2Config * config_file)531 void ResolveOutputPlugins(Barnyard2Config *cmd_line, Barnyard2Config *config_file)
532 {
533     int cmd_line_type_flags = 0;
534 
535     if (cmd_line == NULL)
536         return;
537 
538     /* Command line overrides configuration file output */
539     if (cmd_line->output_configs != NULL)
540     {
541         OutputConfig *config = cmd_line->output_configs;
542 
543         for (; config != NULL; config = config->next)
544         {
545             int type_flags = GetOutputTypeFlags(config->keyword);
546 
547             cmd_line_type_flags |= type_flags;
548 
549             if (config_file != NULL)
550             {
551                 RemoveOutputConfigs(&config_file->output_configs, type_flags);
552             }
553         }
554 
555         /* Put what's in the command line output into the config file output */
556         if (config_file != NULL)
557             TransferOutputConfigs(cmd_line->output_configs, &config_file->output_configs);
558     }
559 
560     /* Don't try to configure defaults if running in test mode */
561     if (!BcTestMode())
562     {
563         if (config_file == NULL)
564         {
565             if (!(cmd_line_type_flags & OUTPUT_TYPE__LOG))
566                 ParseOutput(cmd_line, "log_tcpdump");
567 
568             if (!(cmd_line_type_flags & OUTPUT_TYPE__ALERT))
569                 ParseOutput(cmd_line, "alert_full");
570         }
571         else
572         {
573             int config_file_type_flags = 0;
574             OutputConfig *config = config_file->output_configs;
575 
576             for (; config != NULL; config = config->next)
577                 config_file_type_flags |= GetOutputTypeFlags(config->keyword);
578 
579 //            if (!(config_file_type_flags & OUTPUT_TYPE__LOG))
580 //                ParseOutput(config_file, "log_tcpdump");
581 
582 //            if (!(config_file_type_flags & OUTPUT_TYPE__ALERT))
583 //                ParseOutput(config_file, "alert_full");
584         }
585     }
586 }
587 
ConfigureOutputPlugins(Barnyard2Config * bc)588 void ConfigureOutputPlugins(Barnyard2Config *bc)
589 {
590     OutputConfig *config;
591     char *stored_file_name = file_name;
592     int stored_file_line = file_line;
593 
594     barnyard2_conf_for_parsing = bc;
595 
596     DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Output Plugin\n"););
597 
598     for (config = bc->output_configs; config != NULL; config = config->next)
599     {
600         OutputConfigFunc func;
601 
602         file_name = config->file_name;
603         file_line = config->file_line;
604 
605         func = GetOutputConfigFunc(config->keyword);
606         if (func == NULL)
607             ParseError("Unknown output plugin: \"%s\"", config->keyword);
608 
609         func(config->opts);
610     }
611 
612     /* Reset these since we're done with configuring dynamic preprocessors */
613     file_name = stored_file_name;
614     file_line = stored_file_line;
615 
616     barnyard2_conf_for_parsing = NULL;
617 }
618 
619 /****************************************************************************
620  *
621  * Function: VarAlloc()
622  *
623  * Purpose: allocates memory for a variable
624  *
625  * Arguments: none
626  *
627  * Returns: pointer to new VarEntry
628  *
629  ***************************************************************************/
VarAlloc()630 VarEntry *VarAlloc()
631 {
632     VarEntry *new;
633 
634     new = (VarEntry *)SnortAlloc(sizeof(VarEntry));
635 
636     return(new);
637 }
638 
639 #ifdef SUP_IP6
640 /****************************************************************************
641  *
642  * Function: VarIsIpAddr(char *, char *)
643  *
644  * Purpose: Checks if a var is an IP address. Necessary since moving forward
645  *          we want all IP addresses handled by the IP variable table.
646  *          If a list is given, this checks each value.
647  *
648  * Arguments: value => the string to check
649  *
650  * Returns: 1 if IP address, 0 otherwise
651  *
652  ***************************************************************************/
VarIsIpAddr(vartable_t * ip_vartable,char * value)653 static int VarIsIpAddr(vartable_t *ip_vartable, char *value)
654 {
655     char *tmp;
656 
657     /* empty list, consider this an IP address */
658     if ((*value == '[') && (*(value+1) == ']'))
659         return 1;
660 
661     while(*value == '!' || *value == '[') value++;
662 
663     /* Check for dotted-quad */
664     if( isdigit((int)*value) &&
665          ((tmp = strchr(value, (int)'.')) != NULL) &&
666          ((tmp = strchr(tmp+1, (int)'.')) != NULL) &&
667          (strchr(tmp+1, (int)'.') != NULL))
668         return 1;
669 
670     /* IPv4 with a mask, and fewer than 4 fields */
671     else if( isdigit((int)*value) &&
672          (strchr(value+1, (int)':') == NULL) &&
673          ((tmp = strchr(value+1, (int)'/')) != NULL) &&
674          isdigit((int)(*(tmp+1))) )
675         return 1;
676 
677     /* IPv6 */
678     else if((tmp = strchr(value, (int)':')) != NULL)
679     {
680         char *tmp2;
681 
682         if((tmp2 = strchr(tmp+1, (int)':')) == NULL)
683             return 0;
684 
685         for(tmp++; tmp < tmp2; tmp++)
686             if(!isxdigit((int)*tmp))
687                 return 0;
688 
689         return 1;
690     }
691 
692     /* Check if it's a variable containing an IP */
693     else if(sfvt_lookup_var(ip_vartable, value+1) || sfvt_lookup_var(ip_vartable, value))
694         return 1;
695 
696     return 0;
697 }
698 
699 /****************************************************************************
700  *
701  * Function: CheckBrackets(char *)
702  *
703  * Purpose: Check that the brackets match up in a string that
704  *          represents a list.
705  *
706  * Arguments: value => the string to check
707  *
708  * Returns: 1 if the brackets match correctly, 0 otherwise
709  *
710  ***************************************************************************/
CheckBrackets(char * value)711 static int CheckBrackets(char *value)
712 {
713     int num_brackets = 0;
714 
715     while (*value == '!')
716         value++;
717 
718     if ((value[0] != '[') || value[strlen(value)-1] != ']')
719     {
720         /* List does not begin or end with a bracket. */
721         return 0;
722     }
723 
724     while ((*value != '\0') && (num_brackets >= 0))
725     {
726         if (*value == '[')
727             num_brackets++;
728         else if (*value == ']')
729             num_brackets--;
730         value++;
731     }
732     if (num_brackets != 0)
733     {
734         /* Mismatched brackets */
735         return 0;
736     }
737 
738     return 1;
739 }
740 
741 /****************************************************************************
742  *
743  * Function: VarIsIpList(vartable_t *, char*)
744  *
745  * Purpose: Checks if a var is a list of IP addresses.
746  *
747  * Arguments: value => the string to check
748  *
749  * Returns: 1 if each item is an IP address, 0 otherwise
750  *
751  ***************************************************************************/
VarIsIpList(vartable_t * ip_vartable,char * value)752 static int VarIsIpList(vartable_t *ip_vartable, char *value)
753 {
754     char *copy, *item;
755     int item_is_ip = 1;
756 
757     copy = SnortStrdup((const char*)value);
758 
759     /* Ensure that the brackets are correct. */
760     if (strchr((const char*)copy, ','))
761     {
762         /* This is a list! */
763         if (CheckBrackets(copy) == 0)
764         {
765             free(copy);
766             return 0;
767         }
768     }
769 
770     /* There's no need to worry about the list structure here.
771      * We just strip out the IP delimiters and process each one. */
772     item = strtok(copy, "[],!");
773     while ((item != NULL) && item_is_ip)
774     {
775         item_is_ip = VarIsIpAddr(ip_vartable, item);
776         item = strtok(NULL, "[],!");
777     }
778 
779     free(copy);
780     return item_is_ip;
781 }
782 #endif
783 
784 /****************************************************************************
785  *
786  * Function: DisallowCrossTableDuplicateVars(char *, int)
787  *
788  * Purpose: FatalErrors if the a variable name is redefined across variable
789  *          types.  Enforcing this mutual exclusion prevents the
790  *          catatrophe where the variable lookup fall-through (see VarSearch)
791  *          finds an unintended variable from the wrong table.  Note:  VarSearch
792  *          is only necessary for ExpandVars.
793  *
794  * Arguments: name => The name of the variable
795  *            var_type => The type of the variable that is about to be defined.
796  *                        The corresponding variable table will not be searched.
797  *
798  * Returns: void function
799  *
800  ***************************************************************************/
DisallowCrossTableDuplicateVars(Barnyard2Config * bc,char * name,VarType var_type)801 static void DisallowCrossTableDuplicateVars(Barnyard2Config *bc, char *name, VarType var_type)
802 {
803 #ifdef SUP_IP6
804     VarEntry            *var_table = bc->var_table;
805     vartable_t          *ip_vartable = bc->ip_vartable;
806     VarEntry            *p = var_table;
807 #endif
808 
809 
810     switch (var_type)
811     {
812         case VAR_TYPE__DEFAULT:
813             if(
814 #ifdef SUP_IP6
815                sfvt_lookup_var(ip_vartable, name) ||
816 #endif
817             /* This 0 is for the case that neither IPv6
818              * support or Portlists is compiled in. Quiets a warning. */
819             0)
820             {
821                 ParseError("Can not redefine variable name %s to be of type "
822                            "'var'. Use a different name.", name);
823             }
824             break;
825 
826 #ifdef SUP_IP6
827         case VAR_TYPE__IPVAR:
828             if (var_table != NULL)
829             {
830                 do
831                 {
832                     if(strcasecmp(p->name, name) == 0)
833                     {
834                         ParseError("Can not redefine variable name %s to be of "
835                                    "type 'ipvar'. Use a different name.", name);
836                     }
837 
838                     p = p->next;
839                 } while(p != var_table);
840             }
841 #endif /* SUP_IP6 */
842 
843         default:
844             /* Invalid function usage */
845             break;
846     }
847 }
848 
849 /****************************************************************************
850  *
851  * Function: VarDefine(char *, char *)
852  *
853  * Purpose: define the contents of a variable
854  *
855  * Arguments: name => the name of the variable
856  *            value => the contents of the variable
857  *
858  * Returns: void function
859  *
860  ***************************************************************************/
VarDefine(Barnyard2Config * bc,char * name,char * value)861 VarEntry * VarDefine(Barnyard2Config *bc, char *name, char *value)
862 {
863     VarEntry *var_table = bc->var_table;
864 #ifdef SUP_IP6
865     vartable_t *ip_vartable = bc->ip_vartable;
866 #endif
867     VarEntry *p;
868     //int    vlen,n;
869     //char  *s;
870 
871     if(value == NULL)
872     {
873         ParseError("Bad value in variable definition!  Make sure you don't "
874                    "have a \"$\" in the var name.");
875     }
876 
877 #ifdef SUP_IP6
878     if(VarIsIpList(ip_vartable, value))
879     {
880         SFIP_RET ret;
881 
882         if (ip_vartable == NULL)
883             return NULL;
884 
885         /* Verify a variable by this name is not already used as either a
886          * portvar or regular var.  Enforcing this mutual exclusion prevents the
887          * catatrophe where the variable lookup fall-through (see VarSearch)
888          * finds an unintended variable from the wrong table.  Note:  VarSearch
889          * is only necessary for ExpandVars. */
890         DisallowCrossTableDuplicateVars(bc, name, VAR_TYPE__IPVAR);
891 
892         if((ret = sfvt_define(ip_vartable, name, value)) != SFIP_SUCCESS)
893         {
894             switch(ret) {
895                 case SFIP_ARG_ERR:
896                     ParseError("The following is not allowed: %s.", value);
897                     break;
898 
899                 case SFIP_DUPLICATE:
900                     ParseMessage("Var '%s' redefined.", name);
901                     break;
902 
903                 case SFIP_CONFLICT:
904                     ParseError("Negated IP ranges that are more general than "
905                                "non-negated ranges are not allowed. Consider "
906                                "inverting the logic in %s.", name);
907                     break;
908 
909                 case SFIP_NOT_ANY:
910                     ParseError("!any is not allowed in %s.", name);
911                     break;
912 
913                 default:
914                     ParseError("Failed to parse the IP address: %s.", value);
915             }
916         }
917         return NULL;
918     }
919     /* Check if this is a variable that stores an IP */
920     else if(*value == '$')
921     {
922         sfip_var_t *var;
923         if((var = sfvt_lookup_var(ip_vartable, value)) != NULL)
924         {
925             sfvt_define(ip_vartable, name, value);
926             return NULL;
927         }
928     }
929 
930 #endif
931 
932     DisallowCrossTableDuplicateVars(bc, name, VAR_TYPE__DEFAULT);
933 
934     if (var_table == NULL)
935     {
936         p = VarAlloc();
937         p->name  = SnortStrdup(name);
938         p->value = SnortStrdup(value);
939 
940         p->prev = p;
941         p->next = p;
942 
943         bc->var_table = p;
944 
945         return p;
946     }
947 
948     /* See if an existing variable is being redefined */
949     p = var_table;
950 
951     do
952     {
953         if (strcasecmp(p->name, name) == 0)
954         {
955             if (p->value != NULL)
956                 free(p->value);
957 
958             p->value = SnortStrdup(value);
959             LogMessage("Var '%s' redefined\n", p->name);
960             return p;
961         }
962 
963         p = p->next;
964 
965     } while (p != var_table);   /* List is circular */
966 
967     p = VarAlloc();
968     p->name  = SnortStrdup(name);
969     p->value = SnortStrdup(value);
970     p->prev = var_table;
971     p->next = var_table->next;
972     p->next->prev = p;
973     var_table->next = p;
974 
975     return p;
976 }
977 
DeleteVars(VarEntry * var_table)978 static void DeleteVars(VarEntry *var_table)
979 {
980     VarEntry *q, *p = var_table;
981 
982     while (p)
983     {
984         q = p->next;
985         if (p->name)
986             free(p->name);
987         if (p->value)
988             free(p->value);
989         free(p);
990         p = q;
991         if (p == var_table)
992             break;  /* Grumble, it's a friggin circular list */
993     }
994 }
995 
996 /****************************************************************************
997  *
998  * Function: VarGet(char *)
999  *
1000  * Purpose: get the contents of a variable
1001  *
1002  * Arguments: name => the name of the variable
1003  *
1004  * Returns: char * to contents of variable or FatalErrors on an
1005  *          undefined variable name
1006  *
1007  ***************************************************************************/
VarGet(char * name)1008 char *VarGet(char *name)
1009 {
1010     Barnyard2Config *bc = barnyard2_conf_for_parsing;
1011     VarEntry *var_table;
1012 #ifdef SUP_IP6
1013     vartable_t *ip_vartable;
1014     sfip_var_t *var;
1015 #else
1016     VarEntry *p = NULL;
1017     char *ret = NULL;
1018 #endif
1019 
1020     if (bc == NULL)
1021         return NULL;
1022 
1023     var_table = bc->var_table;
1024 
1025 #ifdef SUP_IP6
1026 // XXX-IPv6 This function should never be used if IP6 support is enabled!
1027 // Infact it won't presently even work for IP variables since the raw ASCII
1028 // value is never stored, and is never meant to be used.
1029     ip_vartable = bc->ip_vartable;
1030 
1031     if((var = sfvt_lookup_var(ip_vartable, name)) == NULL) {
1032         /* Do the old style lookup since it wasn't found in
1033          * the variable table */
1034         if(var_table != NULL)
1035         {
1036             VarEntry *p = var_table;
1037             do
1038             {
1039                 if(strcasecmp(p->name, name) == 0)
1040                     return p->value;
1041                 p = p->next;
1042             } while(p != var_table);
1043         }
1044 
1045         ParseError("Undefined variable name: %s.", name);
1046     }
1047 
1048     return name;
1049 
1050 #else
1051 
1052     if (var_table != NULL)
1053     {
1054         p = var_table;
1055 
1056         do
1057         {
1058             if (strcasecmp(p->name, name) == 0)
1059             {
1060                 ret = p->value;
1061                 break;
1062             }
1063 
1064             p = p->next;
1065 
1066         } while (p != var_table);
1067     }
1068 
1069     if (ret == NULL)
1070         ParseError("Undefined variable name: %s.", name);
1071 
1072     return ret;
1073 #endif
1074 }
1075 
1076 /****************************************************************************
1077  *
1078  * Function: ExpandVars()
1079  *
1080  * Purpose: expand all variables in a string
1081  *
1082  * Arguments:
1083  *  Barnyard2Config *
1084  *      The snort config that has the vartables.
1085  *  char *
1086  *      The name of the variable.
1087  *
1088  * Returns:
1089  *  char *
1090  *      The expanded string.  Note that the string is returned in a
1091  *      static variable and most likely needs to be string dup'ed.
1092  *
1093  ***************************************************************************/
ExpandVars(Barnyard2Config * bc,char * string)1094 static char * ExpandVars(Barnyard2Config *bc, char *string)
1095 {
1096     static char estring[ PARSERULE_SIZE ];
1097 
1098     char rawvarname[128], varname[128], varaux[128], varbuffer[128];
1099     char varmodifier, *varcontents;
1100     int varname_completed, c, i, j, iv, jv, l_string, name_only;
1101     int quote_toggle = 0;
1102 
1103     if(!string || !*string || !strchr(string, '$'))
1104         return(string);
1105 
1106     memset((char *) estring, 0, PARSERULE_SIZE); /* bzero() deprecated, replaced by memset() */
1107 
1108     i = j = 0;
1109     l_string = strlen(string);
1110     DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES, "ExpandVars, Before: %s\n", string););
1111 
1112     while(i < l_string && j < (int)sizeof(estring) - 1)
1113     {
1114         c = string[i++];
1115 
1116         if(c == '"')
1117         {
1118             /* added checks to make sure that we are inside a quoted string
1119              */
1120             quote_toggle ^= 1;
1121         }
1122 
1123         if(c == '$' && !quote_toggle)
1124         {
1125 	    memset((char *) rawvarname, 0, sizeof(rawvarname)); /* bzero() deprecated, replaced by memset() */
1126             varname_completed = 0;
1127             name_only = 1;
1128             iv = i;
1129             jv = 0;
1130 
1131             if(string[i] == '(')
1132             {
1133                 name_only = 0;
1134                 iv = i + 1;
1135             }
1136 
1137             while(!varname_completed
1138                   && iv < l_string
1139                   && jv < (int)sizeof(rawvarname) - 1)
1140             {
1141                 c = string[iv++];
1142 
1143                 if((name_only && !(isalnum(c) || c == '_'))
1144                    || (!name_only && c == ')'))
1145                 {
1146                     varname_completed = 1;
1147 
1148                     if(name_only)
1149                         iv--;
1150                 }
1151                 else
1152                 {
1153                     rawvarname[jv++] = (char)c;
1154                 }
1155             }
1156 
1157             if(varname_completed || iv == l_string)
1158             {
1159                 char *p;
1160 
1161                 i = iv;
1162 
1163                 varcontents = NULL;
1164 
1165 		memset((char *) varname, 0, sizeof(varname)); /* bzero() deprecated, replaced by memset() */
1166 		memset((char *) varaux, 0, sizeof(varaux)); /* bzero() deprecated, replaced by memset() */
1167                 varmodifier = ' ';
1168 
1169                 p = strchr(rawvarname, ':');
1170                 if (p)
1171                 {
1172                     SnortStrncpy(varname, rawvarname, p - rawvarname);
1173 
1174                     if(strlen(p) >= 2)
1175                     {
1176                         varmodifier = *(p + 1);
1177                         SnortStrncpy(varaux, p + 2, sizeof(varaux));
1178                     }
1179                 }
1180                 else
1181                     SnortStrncpy(varname, rawvarname, sizeof(varname));
1182 
1183 		memset((char *) varbuffer, 0, sizeof(varbuffer)); /* bzero() deprecated, replaced by memset() */
1184 
1185                 varcontents = VarSearch(bc, varname);
1186 
1187                 switch(varmodifier)
1188                 {
1189                     case '-':
1190                         if(!varcontents || !strlen(varcontents))
1191                             varcontents = varaux;
1192                         break;
1193 
1194                     case '?':
1195                         if(!varcontents || !strlen(varcontents))
1196                         {
1197                             ErrorMessage("%s(%d): ", file_name, file_line);
1198 
1199                             if(strlen(varaux))
1200                                 ParseError("%s", varaux);
1201                             else
1202                                 ParseError("Undefined variable \"%s\".", varname);
1203                         }
1204                         break;
1205                 }
1206 
1207                 /* If variable not defined now, we're toast */
1208                 if(!varcontents || !strlen(varcontents))
1209                     ParseError("Undefined variable name: %s.", varname);
1210 
1211                 if(varcontents)
1212                 {
1213                     int l_varcontents = strlen(varcontents);
1214 
1215                     iv = 0;
1216 
1217                     while(iv < l_varcontents && j < (int)sizeof(estring) - 1)
1218                         estring[j++] = varcontents[iv++];
1219                 }
1220             }
1221             else
1222             {
1223                 estring[j++] = '$';
1224             }
1225         }
1226         else
1227         {
1228             estring[j++] = (char)c;
1229         }
1230     }
1231 
1232     DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES, "ExpandVars, After: %s\n", estring););
1233 
1234     return estring;
1235 }
1236 
ProcessFileOption(Barnyard2Config * bc,const char * filespec)1237 char * ProcessFileOption(Barnyard2Config *bc, const char *filespec)
1238 {
1239     char *filename = NULL;
1240     char buffer[STD_BUF];
1241 
1242     if (bc == NULL)
1243         bc = barnyard2_conf;
1244 
1245     if(filespec == NULL)
1246     {
1247         FatalError("no arguement in this file option, remove extra ':' at the end of the alert option\n");
1248     }
1249 
1250     /* look for ".." in the string and complain and exit if it is found */
1251     if(strstr(filespec, "..") != NULL)
1252     {
1253         FatalError("file definition contains \"..\".  Do not do that!\n");
1254     }
1255 
1256     if(filespec[0] == '/')
1257     {
1258         /* absolute filespecs are saved as is */
1259         filename = SnortStrdup(filespec);
1260     }
1261     else
1262     {
1263         /* relative filespec is considered relative to the log directory */
1264         /* or /var/log if the log directory has not been set */
1265         /* Make sure this function isn't called before log dir is set */
1266         if ((bc != NULL) && (bc->log_dir != NULL))
1267         {
1268             strlcpy(buffer, barnyard2_conf->log_dir, STD_BUF);
1269         }
1270         else
1271         {
1272             strlcpy(buffer, "/var/log/barnyard2", STD_BUF);
1273         }
1274 
1275         strlcat(buffer, "/", STD_BUF - strlen(buffer));
1276         strlcat(buffer, filespec, STD_BUF - strlen(buffer));
1277         buffer[sizeof(buffer) - 1] = '\0';
1278         filename = SnortStrdup(buffer);
1279     }
1280 
1281     DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"ProcessFileOption: %s\n", filename););
1282 
1283     return filename;
1284 }
1285 
ParseConfig(Barnyard2Config * bc,char * args)1286 static void ParseConfig(Barnyard2Config *bc, char *args)
1287 {
1288     char **toks;
1289     int num_toks;
1290     char *opts = NULL;
1291     int i;
1292 
1293     DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Rule file config\n"););
1294 
1295     toks = mSplit(args, ":", 2, &num_toks, 0);
1296 
1297     DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Opt: %s\n", toks[0]););
1298 
1299     if (num_toks > 1)
1300     {
1301 
1302         opts = SnortStrdup(toks[1]);
1303         DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Args: %s\n", opts););
1304     }
1305 
1306     for (i = 0; config_opts[i].name != NULL; i++)
1307     {
1308         if (strcasecmp(toks[0], config_opts[i].name) == 0)
1309         {
1310             if (config_opts[i].only_once && config_opt_configured[i])
1311             {
1312                 /* Configured already and set to only configure once
1313                  * This array is reset for each policy read in so this is
1314                  * on a per policy basis */
1315                 ParseError("Config option \"%s\" can only be "
1316                            "configured once.", toks[0]);
1317             }
1318 
1319             if (config_opts[i].args_required && (opts == NULL))
1320             {
1321                 /* Need arguments and there are none */
1322                  ParseError("Config option \"%s\" requires arguments.", toks[0]);
1323             }
1324 
1325             config_opts[i].parse_func(bc, opts);
1326             config_opt_configured[i] = 1;
1327             break;
1328         }
1329     }
1330 
1331     if (config_opts[i].name == NULL)
1332     {
1333         /* Didn't find a matching config option */
1334         ParseError("Unknown config directive: %s.", toks[0]);
1335     }
1336 
1337     mSplitFree(&toks, num_toks);
1338 
1339     if(opts)
1340     {
1341 	free(opts);
1342     }
1343 
1344 }
1345 
1346 /*
1347  * Same as VarGet - but this does not Fatal out if a var is not found
1348  */
VarSearch(Barnyard2Config * bc,char * name)1349 static char * VarSearch(Barnyard2Config *bc, char *name)
1350 {
1351     VarEntry *var_table = bc->var_table;
1352 #ifdef SUP_IP6
1353     vartable_t *ip_vartable = bc->ip_vartable;
1354 #endif
1355 
1356 #ifdef SUP_IP6
1357     if(!sfvt_lookup_var(ip_vartable, name))
1358     {
1359 #endif
1360 
1361         if(var_table != NULL)
1362         {
1363             VarEntry *p = var_table;
1364             do
1365             {
1366                 if(strcasecmp(p->name, name) == 0)
1367                     return p->value;
1368                 p = p->next;
1369             } while(p != var_table);
1370         }
1371 
1372         return NULL;
1373 
1374 #ifdef SUP_IP6
1375     }
1376 #endif
1377 
1378     return name;
1379 }
1380 
ParserCleanup(void)1381 void ParserCleanup(void)
1382 {
1383 }
1384 
InitVarTables(Barnyard2Config * bc)1385 static void InitVarTables(Barnyard2Config *bc)
1386 {
1387     if (bc == NULL)
1388         return;
1389 
1390     if (bc->var_table != NULL)
1391         DeleteVars(bc->var_table);
1392 
1393 #ifdef SUP_IP6
1394     if (bc->ip_vartable != NULL)
1395         sfvt_free_table(bc->ip_vartable);
1396     bc->ip_vartable = sfvt_alloc_table();
1397 #endif
1398 }
1399 
InitParser(void)1400 static void InitParser(void)
1401 {
1402     /* This is for determining if a config option has already been
1403      * configured.  Most can only be configured once */
1404     memset(config_opt_configured, 0, sizeof(config_opt_configured));
1405 }
1406 
ParseConfigFile(Barnyard2Config * bc,char * fname)1407 static void ParseConfigFile(Barnyard2Config *bc, char *fname)
1408 {
1409     /* Used for line continuation */
1410     int continuation = 0;
1411     char *saved_line = NULL;
1412     char *new_line = NULL;
1413     char *buf = (char *)SnortAlloc(MAX_LINE_LENGTH + 1);
1414     FILE *fp = fopen(fname, "r");
1415 
1416     /* open the rules file */
1417     if (fp == NULL)
1418     {
1419         FatalError("Unable to open config file \"%s\": %s.\n",
1420                    fname, strerror(errno));
1421     }
1422 
1423     /* loop thru each file line and send it to the rule parser */
1424     while ((fgets(buf, MAX_LINE_LENGTH, fp)) != NULL)
1425     {
1426         /* buffer indexing pointer */
1427         char *index = buf;
1428 
1429         /* Increment the line counter so the error messages know which
1430          * line to bitch about */
1431         file_line++;
1432 
1433         /* fgets always appends a null, so doing a strlen should be safe */
1434         if ((strlen(buf) + 1) == MAX_LINE_LENGTH)
1435         {
1436             ParseError("Line greater than or equal to %u characters which is "
1437                        "more than the parser is willing to handle.  Try "
1438                        "splitting it up on multiple lines if possible.",
1439                        MAX_LINE_LENGTH);
1440         }
1441 
1442         DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES, "Got line %s (%d): %s\n",
1443                                 fname, file_line, buf););
1444 
1445         /* advance through any whitespace at the beginning of the line */
1446         while (isspace((int)*index))
1447             index++;
1448 
1449         /* If it's an empty line or starts with a comment character */
1450         if ((strlen(index) == 0) || (*index == '#') || (*index == ';'))
1451             continue;
1452 
1453         if (continuation)
1454         {
1455             int new_line_len = strlen(saved_line) + strlen(index) + 1;
1456 
1457             if (new_line_len >= PARSERULE_SIZE)
1458             {
1459                 ParseError("Rule greater than or equal to %u characters which "
1460                            "is more than the parser is willing to handle.  "
1461                            "Submit a bug to bugs@snort.org if you legitimately "
1462                            "feel like your rule or keyword configuration needs "
1463                            "more than this amount of space.", PARSERULE_SIZE);
1464             }
1465 
1466             new_line = (char *)SnortAlloc(new_line_len);
1467             snprintf(new_line, new_line_len, "%s%s", saved_line, index);
1468 
1469             free(saved_line);
1470             saved_line = NULL;
1471             index = new_line;
1472 
1473             DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"concat rule: %s\n",
1474                                     new_line););
1475         }
1476 
1477         /* check for a '\' continuation character at the end of the line
1478          * if it's there we need to get the next line in the file */
1479         if (ContinuationCheck(index) == 0)
1480         {
1481             char **toks;
1482             int num_toks;
1483             char *keyword;
1484             char *args;
1485             int i;
1486 
1487             DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,
1488                                     "[*] Processing keyword: %s\n", index););
1489 
1490             /* Get the keyword and args */
1491             toks = mSplit(index, " \t", 2, &num_toks, 0);
1492             if (num_toks != 2)
1493                 ParseError("Invalid configuration line: %s", index);
1494 
1495             keyword = SnortStrdup(ExpandVars(bc, toks[0]));
1496             args = toks[1];
1497 
1498             for (i = 0; barnyard2_conf_keywords[i].name != NULL; i++)
1499             {
1500                 if (strcasecmp(keyword, barnyard2_conf_keywords[i].name) == 0)
1501                 {
1502                     if (barnyard2_conf_keywords[i].expand_vars)
1503                         args = SnortStrdup(ExpandVars(bc, toks[1]));
1504 
1505                     barnyard2_conf_keywords[i].parse_func(bc, args);
1506 
1507                     break;
1508                 }
1509             }
1510 
1511             if (args != toks[1])
1512                 free(args);
1513 
1514             free(keyword);
1515             mSplitFree(&toks, num_toks);
1516 
1517             if(new_line != NULL)
1518             {
1519                 free(new_line);
1520                 new_line = NULL;
1521                 continuation = 0;
1522             }
1523         }
1524         else
1525         {
1526             /* save the current line */
1527             saved_line = SnortStrdup(index);
1528 
1529             /* current line was a continuation itself... */
1530             if (new_line != NULL)
1531             {
1532                 free(new_line);
1533                 new_line = NULL;
1534             }
1535 
1536             /* set the flag to let us know the next line is
1537              * a continuation line */
1538             continuation = 1;
1539         }
1540     }
1541 
1542     fclose(fp);
1543     free(buf);
1544 }
1545 
ContinuationCheck(char * rule)1546 static int ContinuationCheck(char *rule)
1547 {
1548     char *idx;  /* indexing var for moving around on the string */
1549 
1550     idx = rule + strlen(rule) - 1;
1551 
1552     DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"initial idx set to \'%c\'\n",
1553                 *idx););
1554 
1555     while(isspace((int)*idx))
1556     {
1557         idx--;
1558     }
1559 
1560     if(*idx == '\\')
1561     {
1562         DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Got continuation char, "
1563                     "clearing char and returning 1\n"););
1564 
1565         /* clear the '\' so there isn't a problem on the appended string */
1566         *idx = '\x0';
1567         return 1;
1568     }
1569 
1570     return 0;
1571 }
1572 
1573 
ConfigAlertOnEachPacketInStream(Barnyard2Config * bc,char * args)1574 void ConfigAlertOnEachPacketInStream(Barnyard2Config *bc, char *args)
1575 {
1576     if (bc == NULL)
1577         return;
1578 
1579     LogMessage("INFO: Alerting on each packet associated with an event: is now enabled by default. \n"
1580                " use: command line argument --disable-alert-on-each-packet-in-stream or \n"
1581                " configure file argument disable-alert-on-each-packet-in-stream to disable the feature \n");
1582 
1583     return;
1584 }
1585 
1586 
ConfigSetEventCacheSize(Barnyard2Config * bc,char * args)1587 void ConfigSetEventCacheSize(Barnyard2Config *bc, char *args)
1588 {
1589     if( (bc == NULL) ||
1590         (args == NULL))
1591     {
1592         return;
1593     }
1594 
1595     bc->event_cache_size = strtoul(args,NULL,10);
1596     return;
1597 }
1598 
ConfigDisableAlertOnEachPacketInStream(Barnyard2Config * bc,char * args)1599 void ConfigDisableAlertOnEachPacketInStream(Barnyard2Config *bc, char *args)
1600 {
1601     if (bc == NULL)
1602         return;
1603 
1604     bc->alert_on_each_packet_in_stream_flag = 0;
1605 }
1606 
ConfigArchiveDir(Barnyard2Config * bc,char * args)1607 void ConfigArchiveDir(Barnyard2Config *bc, char *args)
1608 {
1609     if ((args == NULL) || (bc == NULL) || (bc->archive_dir != NULL))
1610         return;
1611 
1612     bc->archive_dir = SnortStrdup(args);
1613 }
1614 
ConfigAlertWithInterfaceName(Barnyard2Config * bc,char * args)1615 void ConfigAlertWithInterfaceName(Barnyard2Config *bc, char *args)
1616 {
1617     if (bc == NULL)
1618         return;
1619 
1620     bc->output_flags |= OUTPUT_FLAG__ALERT_IFACE;
1621 }
1622 
ConfigChrootDir(Barnyard2Config * bc,char * args)1623 void ConfigChrootDir(Barnyard2Config *bc, char *args)
1624 {
1625 #ifdef WIN32
1626     ParseError("Setting the chroot directory is not supported in "
1627                "the WIN32 port of snort!");
1628 #else
1629     if ((args == NULL) || (bc == NULL) || (bc->chroot_dir != NULL))
1630         return;
1631 
1632     bc->chroot_dir = SnortStrdup(args);
1633 #endif
1634 }
1635 
ConfigClassification(Barnyard2Config * bc,char * args)1636 void ConfigClassification(Barnyard2Config *bc, char *args)
1637 {
1638     char **toks;
1639     int num_toks;
1640     char *endptr;
1641     ClassType *new_node, *current;
1642     int max_id = 0;
1643 
1644     if ((args == NULL) || (bc == NULL))
1645         return;
1646 
1647     toks = mSplit(args, ",", 0, &num_toks, '\\');
1648     if (num_toks != 3)
1649         ParseError("Invalid classification config: %s.", args);
1650 
1651     /* create the new node */
1652     new_node = (ClassType *)SnortAlloc(sizeof(ClassType));
1653 
1654     new_node->type = SnortStrdup(toks[0]);
1655     new_node->name = SnortStrdup(toks[1]);
1656 
1657     new_node->priority = strtol(toks[2], &endptr, 0);
1658     if ((errno == ERANGE) || (*endptr != '\0') || (new_node->priority <= 0))
1659     {
1660         ParseError("Invalid argument for classification priority "
1661                    "configuration: %s.  Must be a positive integer.", toks[2]);
1662     }
1663 
1664     current = bc->classifications;
1665     while (current != NULL)
1666     {
1667         /* dup check */
1668         if (strcasecmp(current->type, new_node->type) == 0)
1669         {
1670             LogMessage("%s(%d): Duplicate classification \"%s\""
1671                          "found, ignoring this line\n", file_name, file_line,
1672                          new_node->type);
1673             break;
1674         }
1675 
1676         if (current->id > max_id)
1677             max_id = current->id;
1678 
1679         current = current->next;
1680     }
1681 
1682     /* Got a dup */
1683     if (current != NULL)
1684     {
1685         free(new_node->name);
1686         free(new_node->type);
1687         free(new_node);
1688         mSplitFree(&toks, num_toks);
1689         return;
1690     }
1691 
1692     /* insert node */
1693     new_node->id = max_id + 1;
1694     new_node->next = bc->classifications;
1695     bc->classifications = new_node;
1696 
1697     mSplitFree(&toks, num_toks);
1698 }
1699 
ConfigClassificationFile(Barnyard2Config * bc,char * args)1700 void ConfigClassificationFile(Barnyard2Config *bc, char *args)
1701 {
1702     if ((args == NULL) || (bc == NULL) )
1703         return;
1704 
1705     bc->class_file = strndup(args,strlen(args));
1706 
1707     ReadClassificationFile(bc);
1708 }
1709 
ConfigCreatePidFile(Barnyard2Config * bc,char * args)1710 void ConfigCreatePidFile(Barnyard2Config *bc, char *args)
1711 {
1712     if (bc == NULL)
1713         return;
1714 
1715     bc->run_flags |= RUN_FLAG__CREATE_PID_FILE;
1716 }
1717 
ConfigDaemon(Barnyard2Config * bc,char * args)1718 void ConfigDaemon(Barnyard2Config *bc, char *args)
1719 {
1720 #ifdef WIN32
1721     ParseError("Setting the Daemon mode is not supported in the "
1722                "WIN32 port of barnyard2!  Use 'barnyard2 /SERVICE ...' instead.");
1723 #else
1724     if (bc == NULL)
1725         return;
1726 
1727     DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Daemon mode flag set\n"););
1728     bc->run_flags |= RUN_FLAG__DAEMON;
1729     bc->logging_flags |= LOGGING_FLAG__QUIET;
1730 #endif
1731 }
1732 
ConfigDecodeDataLink(Barnyard2Config * bc,char * args)1733 void ConfigDecodeDataLink(Barnyard2Config *bc, char *args)
1734 {
1735     if (bc == NULL)
1736         return;
1737 
1738     DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Decode DLL set\n"););
1739     bc->output_flags |= OUTPUT_FLAG__SHOW_DATA_LINK;
1740 }
1741 
ConfigDumpCharsOnly(Barnyard2Config * bc,char * args)1742 void ConfigDumpCharsOnly(Barnyard2Config *bc, char *args)
1743 {
1744     if (bc == NULL)
1745         return;
1746 
1747     /* dump the application layer as text only */
1748     DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Character payload dump set\n"););
1749     bc->output_flags |= OUTPUT_FLAG__CHAR_DATA;
1750 }
1751 
ConfigDumpPayload(Barnyard2Config * bc,char * args)1752 void ConfigDumpPayload(Barnyard2Config *bc, char *args)
1753 {
1754     if (bc == NULL)
1755         return;
1756 
1757     /* dump the application layer */
1758     DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Payload dump set\n"););
1759     bc->output_flags |= OUTPUT_FLAG__APP_DATA;
1760 }
1761 
ConfigDumpPayloadVerbose(Barnyard2Config * bc,char * args)1762 void ConfigDumpPayloadVerbose(Barnyard2Config *bc, char *args)
1763 {
1764     if (bc == NULL)
1765         return;
1766 
1767     DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Verbose packet bytecode dumps enabled\n"););
1768     bc->output_flags |= OUTPUT_FLAG__VERBOSE_DUMP;
1769 }
1770 
ConfigGenFile(Barnyard2Config * bc,char * args)1771 void ConfigGenFile(Barnyard2Config *bc, char *args)
1772 {
1773     if ((args == NULL) || (bc == NULL) )
1774         return;
1775 
1776     bc->gen_msg_file = strndup(args,PATH_MAX);
1777     return;
1778 }
1779 
ConfigHostname(Barnyard2Config * bc,char * args)1780 void ConfigHostname(Barnyard2Config *bc, char *args)
1781 {
1782     if ((args == NULL) || (bc == NULL) || (bc->hostname != NULL))
1783         return;
1784 
1785     /* this code handles the case in which the user specifies
1786      * the entire name of the host and it is compiled regardless
1787      * of which OS you have */
1788     bc->hostname = SnortStrdup(args);
1789 }
1790 
ConfigInterface(Barnyard2Config * bc,char * args)1791 void ConfigInterface(Barnyard2Config *bc, char *args)
1792 {
1793     if ((args == NULL) || (bc == NULL) || (bc->interface != NULL))
1794         return;
1795 
1796     /* this code handles the case in which the user specifies
1797      * the entire name of the interface and it is compiled
1798      * regardless of which OS you have */
1799     bc->interface = SnortStrdup(args);
1800 }
1801 
ConfigLogDir(Barnyard2Config * bc,char * args)1802 void ConfigLogDir(Barnyard2Config *bc, char *args)
1803 {
1804     if ((args == NULL) || (bc == NULL) || (bc->log_dir != NULL))
1805         return;
1806 
1807     bc->log_dir = SnortStrdup(args);
1808 }
1809 
ConfigNoLoggingTimestamps(Barnyard2Config * bc,char * args)1810 void ConfigNoLoggingTimestamps(Barnyard2Config *bc, char *args)
1811 {
1812     if (bc == NULL)
1813         return;
1814 
1815     bc->output_flags |= OUTPUT_FLAG__NO_TIMESTAMP;
1816 }
1817 
ConfigObfuscate(Barnyard2Config * bc,char * args)1818 void ConfigObfuscate(Barnyard2Config *bc, char *args)
1819 {
1820     if (bc == NULL)
1821         return;
1822 
1823     bc->output_flags |= OUTPUT_FLAG__OBFUSCATE;
1824 }
1825 
ConfigObfuscationMask(Barnyard2Config * bc,char * args)1826 void ConfigObfuscationMask(Barnyard2Config *bc, char *args)
1827 {
1828 #ifndef SUP_IP6
1829     struct in_addr net;       /* place to stick the local network data */
1830     char **toks;              /* dbl ptr to store mSplit return data in */
1831     int num_toks;             /* number of tokens mSplit returns */
1832     int nmask;                /* temporary netmask storage */
1833 # ifdef DEBUG
1834     struct in_addr sin;
1835 # endif
1836 #endif
1837 
1838     if ((bc == NULL) || (args == NULL))
1839         return;
1840 
1841     DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Got obfus data: %s\n", args););
1842 
1843 #ifdef SUP_IP6
1844     sfip_pton(args, &bc->obfuscation_net);
1845     bc->output_flags |= OUTPUT_FLAG__OBFUSCATE;
1846 #else
1847     /* break out the CIDR notation from the IP address */
1848     toks = mSplit(args, "/", 2, &num_toks, 0);
1849 
1850     if(num_toks > 1)
1851     {
1852         /* convert the CIDR notation into a real live netmask */
1853         nmask = atoi(toks[1]);
1854 
1855         if((nmask > 0) && (nmask < 33))
1856         {
1857             bc->obfuscation_mask = htonl(netmasks[nmask]);
1858         }
1859         else
1860         {
1861             ParseError("Bad CIDR block (%s) in obfuscation mask %s. "
1862                        "1 to 32 please!", toks[1], args);
1863         }
1864     }
1865     else
1866     {
1867         ParseError("No netmask specified for obsucation mask!");
1868     }
1869 
1870     DEBUG_WRAP(DebugMessage(DEBUG_INIT, "obfuscation netmask = %#8lX\n",
1871                             bc->obfuscation_mask););
1872 
1873     /* convert the IP addr into its 32-bit value */
1874     if((net.s_addr = inet_addr(toks[0])) == INADDR_NONE)
1875         ParseError("Obfuscation mask (%s) didn't translate.", toks[0]);
1876 
1877     DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Obfuscation Net = %s (%X)\n",
1878                             inet_ntoa(net), net.s_addr););
1879 
1880     /* set the final homenet address up */
1881     bc->obfuscation_net = net.s_addr & bc->obfuscation_mask;
1882 
1883 #ifdef DEBUG
1884     sin.s_addr = bc->obfuscation_net;
1885     DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Obfuscation Net = %s (%X)\n",
1886                             inet_ntoa(sin), sin.s_addr););
1887 #endif
1888 
1889     bc->obfuscation_mask = ~bc->obfuscation_mask;
1890     bc->output_flags |= OUTPUT_FLAG__OBFUSCATE;
1891 
1892     mSplitFree(&toks, num_toks);
1893 #endif
1894 }
1895 
ConfigPidPath(Barnyard2Config * bc,char * args)1896 void ConfigPidPath(Barnyard2Config *bc, char *args)
1897 {
1898     if ((args == NULL) || (bc == NULL))
1899         return;
1900 
1901     LogMessage("Found pid path directive (%s)\n", args);
1902 
1903     bc->run_flags |= RUN_FLAG__CREATE_PID_FILE;
1904     if (SnortStrncpy(bc->pid_path, args, sizeof(bc->pid_path)) != SNORT_STRNCPY_SUCCESS)
1905         ParseError("Pid path too long.");
1906 
1907     DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Pid Path directory = %s\n",
1908                             bc->pid_path););
1909 }
1910 
ConfigQuiet(Barnyard2Config * bc,char * args)1911 void ConfigQuiet(Barnyard2Config *bc, char *args)
1912 {
1913     if (bc == NULL)
1914         return;
1915 
1916     bc->logging_flags |= LOGGING_FLAG__QUIET;
1917 }
1918 
ConfigReference(Barnyard2Config * bc,char * args)1919 void ConfigReference(Barnyard2Config *bc, char *args)
1920 {
1921     char **toks;
1922     int num_toks;
1923     char *url = NULL;
1924 
1925     if ((bc == NULL) || (args == NULL))
1926         return;
1927 
1928     /* 2 tokens: name <url> */
1929     toks = mSplit(args, " \t", 0, &num_toks, 0);
1930 
1931     if (num_toks > 2)
1932     {
1933         ParseError("Reference config requires at most two arguments: "
1934                    "\"name [<url>]\".");
1935     }
1936 
1937     if (num_toks == 2)
1938         url = toks[1];
1939 
1940     ReferenceSystemAdd(&bc->references, toks[0], url);
1941 
1942     mSplitFree(&toks, num_toks);
1943 }
1944 
ConfigReferenceFile(Barnyard2Config * bc,char * args)1945 void ConfigReferenceFile(Barnyard2Config *bc, char *args)
1946 {
1947     if ((args == NULL) || (bc == NULL) )
1948         return;
1949 
1950     ReadReferenceFile(bc, args);
1951 }
1952 
1953 /*
1954  * Function: ConfigReferenceNet
1955  *
1956  * Purpose: Translate the command line character string into its equivalent
1957  *          32-bit network byte ordered value (with netmask)
1958  *
1959  * Arguments: args => The address/CIDR block
1960  *
1961  * Returns: void function
1962  */
ConfigReferenceNet(Barnyard2Config * bc,char * args)1963 void ConfigReferenceNet(Barnyard2Config *bc, char *args)
1964 {
1965 #ifndef SUP_IP6
1966     struct in_addr net;    /* place to stick the local network data */
1967     char **toks;           /* dbl ptr to store mSplit return data in */
1968     int num_toks;          /* number of tokens mSplit returns */
1969     int nmask;             /* temporary netmask storage */
1970 # ifdef DEBUG
1971     struct in_addr sin;
1972 # endif
1973 #endif
1974 
1975     if ((bc == NULL) || (args == NULL))
1976         return;
1977 
1978 #ifdef SUP_IP6
1979     sfip_pton(args, &bc->homenet);
1980 #else
1981 
1982     /* break out the CIDR notation from the IP address */
1983     toks = mSplit(args, "/", 2, &num_toks, 0);
1984 
1985     if(num_toks > 1)
1986     {
1987         /* convert the CIDR notation into a real live netmask */
1988         nmask = atoi(toks[1]);
1989 
1990         if((nmask > 0) && (nmask < 33))
1991         {
1992             bc->netmask = htonl(netmasks[nmask]);
1993         }
1994         else
1995         {
1996             ParseError("Bad CIDR block (%s) in obfuscation mask %s. "
1997                        "1 to 32 please!", toks[1], args);
1998         }
1999     }
2000     else
2001     {
2002         ParseError("No netmask specified for home network!");
2003     }
2004 
2005     DEBUG_WRAP(DebugMessage(DEBUG_INIT, "homenet netmask = %#8lX\n",
2006                             bc->netmask););
2007 
2008     /* convert the IP addr into its 32-bit value */
2009     if((net.s_addr = inet_addr(toks[0])) == INADDR_NONE)
2010         ParseError("Homenet (%s) didn't translate", toks[0]);
2011 
2012     DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Net = %s (%X)\n",
2013                             inet_ntoa(net), net.s_addr););
2014 
2015     /* set the final homenet address up */
2016     bc->homenet = net.s_addr & bc->netmask;
2017 
2018 # ifdef DEBUG
2019     sin.s_addr = bc->homenet;
2020     DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Homenet = %s (%X)\n",
2021                             inet_ntoa(sin), sin.s_addr););
2022 # endif
2023 
2024     mSplitFree(&toks, num_toks);
2025 #endif
2026 }
2027 
ConfigSetGid(Barnyard2Config * bc,char * args)2028 void ConfigSetGid(Barnyard2Config *bc, char *args)
2029 {
2030 #ifdef WIN32
2031     ParseError("Setting the group id is not supported in the "
2032                "WIN32 port of barnyard2!");
2033 #else
2034     size_t i;
2035     char *endptr;
2036 
2037     if ((bc == NULL) || (args == NULL))
2038         return;
2039 
2040     for (i = 0; i < strlen(args); i++)
2041     {
2042         /* If we get something other than a digit, assume it's
2043          * a group name */
2044         if (!isdigit((int)args[i]))
2045         {
2046             struct group *gr = getgrnam(args);
2047 
2048             if (gr == NULL)
2049                 ParseError("Group \"%s\" unknown.", args);
2050 
2051             bc->group_id = gr->gr_gid;
2052             break;
2053         }
2054     }
2055 
2056     /* It's all digits.  Assume it's a group id */
2057     if (i == strlen(args))
2058     {
2059         bc->group_id = strtol(args, &endptr, 10);
2060         if ((errno == ERANGE) || (*endptr != '\0') ||
2061             (bc->group_id < 0))
2062         {
2063             ParseError("Group id \"%s\" out of range.", args);
2064         }
2065     }
2066 #endif
2067 }
2068 
ConfigSetUid(Barnyard2Config * bc,char * args)2069 void ConfigSetUid(Barnyard2Config *bc, char *args)
2070 {
2071 #ifdef WIN32
2072     ParseError("Setting the user id is not supported in the "
2073                "WIN32 port of barnyard2!");
2074 #else
2075     size_t i;
2076     char *endptr;
2077 
2078     if ((bc == NULL) || (args == NULL))
2079         return;
2080 
2081     for (i = 0; i < strlen(args); i++)
2082     {
2083         /* If we get something other than a digit, assume it's
2084          * a user name */
2085         if (!isdigit((int)args[i]))
2086         {
2087             struct passwd *pw = getpwnam(args);
2088 
2089             if (pw == NULL)
2090                 ParseError("User \"%s\" unknown.", args);
2091 
2092             bc->user_id = (int)pw->pw_uid;
2093 
2094             /* Why would someone want to run as another user
2095              * but still as root group? */
2096             if (bc->group_id == -1)
2097                 bc->group_id = (int)pw->pw_gid;
2098 
2099             break;
2100         }
2101     }
2102 
2103     /* It's all digits.  Assume it's a user id */
2104     if (i == strlen(args))
2105     {
2106         bc->user_id = strtol(args, &endptr, 10);
2107         if ((errno == ERANGE) || (*endptr != '\0'))
2108             ParseError("User id \"%s\" out of range.", args);
2109 
2110         /* Set group id to user's default group if not
2111          * already set */
2112         if (bc->group_id == -1)
2113         {
2114             struct passwd *pw = getpwuid((uid_t)bc->user_id);
2115 
2116             if (pw == NULL)
2117                 ParseError("User \"%s\" unknown.", args);
2118 
2119             bc->group_id = (int)pw->pw_gid;
2120         }
2121     }
2122 
2123     DEBUG_WRAP(DebugMessage(DEBUG_INIT, "UserID: %d GroupID: %d.\n",
2124                             bc->user_id, bc->group_id););
2125 #endif  /* !WIN32 */
2126 }
2127 
ConfigShowYear(Barnyard2Config * bc,char * args)2128 void ConfigShowYear(Barnyard2Config *bc, char *args)
2129 {
2130     if (bc == NULL)
2131         return;
2132 
2133     bc->output_flags |= OUTPUT_FLAG__INCLUDE_YEAR;
2134     DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Enabled year in timestamp\n"););
2135 }
2136 
ConfigSidFile(Barnyard2Config * bc,char * args)2137 void ConfigSidFile(Barnyard2Config *bc, char *args)
2138 {
2139     if ((args == NULL) || (bc == NULL) )
2140         return;
2141 
2142     bc->sid_msg_file = strndup(args,PATH_MAX);
2143 }
2144 
ConfigUmask(Barnyard2Config * bc,char * args)2145 void ConfigUmask(Barnyard2Config *bc, char *args)
2146 {
2147 #ifdef WIN32
2148     ParseError("Setting the umask is not supported in the "
2149                "WIN32 port of snort!");
2150 #else
2151     char *endptr;
2152     long mask;
2153 
2154     if ((bc == NULL) || (args == NULL))
2155         return;
2156 
2157     mask = strtol(args, &endptr, 0);
2158 
2159     if ((errno == ERANGE) || (*endptr != '\0') ||
2160         (mask < 0) || (mask & ~FILEACCESSBITS))
2161     {
2162         ParseError("Bad umask: %s", args);
2163     }
2164     bc->file_mask = (mode_t)mask;
2165 #endif
2166 }
2167 
ConfigUtc(Barnyard2Config * bc,char * args)2168 void ConfigUtc(Barnyard2Config *bc, char *args)
2169 {
2170     if (bc == NULL)
2171         return;
2172 
2173     bc->output_flags |= OUTPUT_FLAG__USE_UTC;
2174 }
2175 
ConfigVerbose(Barnyard2Config * bc,char * args)2176 void ConfigVerbose(Barnyard2Config *bc, char *args)
2177 {
2178     if (bc == NULL)
2179         return;
2180 
2181     bc->logging_flags |= LOGGING_FLAG__VERBOSE;
2182     DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Verbose Flag active\n"););
2183 }
2184 
ConfigProcessNewRecordsOnly(Barnyard2Config * bc,char * args)2185 void ConfigProcessNewRecordsOnly(Barnyard2Config *bc, char *args)
2186 {
2187     if (bc == NULL)
2188         return;
2189 
2190     bc->process_new_records_only_flag = 1;
2191 }
2192 
ConfigSpoolFilebase(Barnyard2Config * bc,char * args)2193 void ConfigSpoolFilebase(Barnyard2Config *bc, char *args)
2194 {
2195     if ((args == NULL) || (bc == NULL) )
2196         return;
2197 
2198     if ( SnortSnprintf(bc->waldo.data.spool_filebase, STD_BUF, "%s", args) != SNORT_SNPRINTF_SUCCESS )
2199         FatalError("barnyard2: spool filebase too long\n");
2200 }
2201 
ConfigSpoolDirectory(Barnyard2Config * bc,char * args)2202 void ConfigSpoolDirectory(Barnyard2Config *bc, char *args)
2203 {
2204     if ((args == NULL) || (bc == NULL) )
2205         return;
2206 
2207     if ( SnortSnprintf(bc->waldo.data.spool_dir, STD_BUF, "%s", args) != SNORT_SNPRINTF_SUCCESS )
2208         FatalError("barnyard2: spool directory too long\n");
2209 }
2210 
ConfigWaldoFile(Barnyard2Config * bc,char * args)2211 void ConfigWaldoFile(Barnyard2Config *bc, char *args)
2212 {
2213     if ((args == NULL) || (bc == NULL) )
2214         return;
2215 
2216     if ( SnortSnprintf(bc->waldo.filepath, STD_BUF, "%s", args) != SNORT_SNPRINTF_SUCCESS )
2217         FatalError("barnyard2: waldo filepath too long\n");
2218 
2219     bc->waldo.state |= WALDO_STATE_ENABLED;
2220 }
2221 
2222 
DisplaySigSuppress(SigSuppress_list ** sHead)2223 void DisplaySigSuppress(SigSuppress_list **sHead)
2224 {
2225     if(sHead == NULL)
2226     {
2227 	return;
2228     }
2229     SigSuppress_list *cNode = *sHead;
2230 
2231     LogMessage("\n\n+[ Signature Suppress list ]+\n"
2232 	            "----------------------------\n");
2233 
2234     if(cNode)
2235     {
2236 	while(cNode)
2237 	{
2238 	    LogMessage("-- Element type:[%s] gid:[%d] sid min:[%d] sid max:[%d] \n",
2239 		       (cNode->ss_type & SS_SINGLE) ? "SINGLE" : "RANGE ",
2240 		       cNode->gid,
2241 		       cNode->ss_min,
2242 		       cNode->ss_max);
2243 
2244 	    cNode = cNode->next;
2245 	}
2246     }
2247     else
2248     {
2249 	LogMessage("+[No entry in Signature Suppress List]+\n");
2250     }
2251     LogMessage("----------------------------\n"
2252 	       "+[ Signature Suppress list ]+\n\n");
2253     return;
2254 }
2255 
SigSuppressUnlinkNode(SigSuppress_list ** sHead,SigSuppress_list ** cNode,SigSuppress_list ** pNode)2256 int SigSuppressUnlinkNode(SigSuppress_list **sHead,SigSuppress_list **cNode,SigSuppress_list **pNode)
2257 {
2258     SigSuppress_list *nNode = NULL;
2259 
2260     if( ((sHead == NULL) || (*sHead == NULL)) ||
2261 	((cNode == NULL) || (*cNode == NULL)) ||
2262 	((pNode == NULL) || (*pNode == NULL)))
2263     {
2264 	return 1;
2265     }
2266 
2267     nNode =(SigSuppress_list *)(*cNode)->next;
2268 
2269     if( *cNode == *sHead)
2270     {
2271 	*sHead = nNode;
2272 	free(*cNode);
2273 	*cNode = nNode;
2274 	*pNode = *cNode;
2275     }
2276     else
2277     {
2278 	(*(SigSuppress_list **)(pNode))->next = nNode;
2279 	free(*cNode);
2280 	*cNode = nNode;
2281     }
2282 
2283     return 0;
2284 }
2285 
SigSuppressAddElement(SigSuppress_list ** sHead,SigSuppress_list * sElement)2286 int SigSuppressAddElement(SigSuppress_list **sHead,SigSuppress_list *sElement)
2287 {
2288     SigSuppress_list *cNode = NULL;
2289     SigSuppress_list *pNode = NULL;
2290     SigSuppress_list *newNode = NULL;
2291 
2292     u_int8_t comp_set[4] = {0};
2293 
2294     int has_flag = 0;
2295     int no_add = 0;
2296 
2297     if( (sHead == NULL) ||
2298 	(sElement == NULL))
2299     {
2300 	return 1;
2301     }
2302 
2303     if(*sHead == NULL)
2304     {
2305 	if( (newNode = calloc(1,sizeof(SigSuppress_list))) == NULL)
2306 	{
2307 	    return 1;
2308 	}
2309 
2310 	memcpy(newNode,sElement,sizeof(SigSuppress_list));
2311 	*sHead = newNode;
2312     }
2313     else
2314     {
2315 	cNode = *sHead;
2316 	pNode = cNode;
2317 
2318 	has_flag = 0;
2319 	no_add = 0;
2320 
2321 	while(cNode != NULL)
2322 	{
2323 	    memset(&comp_set,'\0',(sizeof(u_int8_t)*4));
2324 
2325 	    if (cNode->gid == sElement->gid)
2326 	    {
2327 		switch(sElement->ss_type)
2328 		{
2329 		case SS_SINGLE:
2330 		    switch(cNode->ss_type)
2331 		    {
2332 		    case SS_SINGLE:
2333 			if( ((cNode->ss_min == sElement->ss_min)  &&
2334 			     (cNode->ss_max == sElement->ss_max)))
2335 			{
2336 			    DEBUG_WRAP(DebugMessage(DEBUG_SID_SUPPRESS,"[%s()], Signature Suppress configuration entry type:[SINGLE] gid:[%d] sid:[%d] was not added because it is already in present.\n",
2337 						    __FUNCTION__,
2338 						    sElement->gid,
2339 						    sElement->ss_min););
2340 			    return 0;
2341 			}
2342 			break;
2343 
2344 		    case SS_RANGE:
2345 			if( ((cNode->ss_min <= sElement->ss_min) &&
2346                              (cNode->ss_max >= sElement->ss_max)))
2347                         {
2348 			    DEBUG_WRAP(DebugMessage(DEBUG_SID_SUPPRESS,
2349 						    "[%s()], Signature Suppress configuration entry gid:[%d] sid[%d] already covered by\n"
2350 						    "Signature Suppress configuration list element type:[RANGE] gid:[%d] sid min:[%d] sid max:[%d].\n",
2351 						    __FUNCTION__,
2352 						    sElement->gid,
2353 						    sElement->ss_min,
2354 						    cNode->gid,
2355 						    cNode->ss_min,
2356 						    cNode->ss_max););
2357 			    return 0;
2358 			}
2359 			break;
2360 
2361 		    default:
2362 			/* XXX */
2363 			return 1;
2364 			break;
2365 		    }
2366 		    break;
2367 
2368 		case SS_RANGE:
2369 		    switch(cNode->ss_type)
2370                     {
2371 		    case SS_SINGLE:
2372 			if( ((sElement->ss_min <= cNode->ss_min) &&
2373 			     (sElement->ss_max >= cNode->ss_max)))
2374 			{
2375 			    DEBUG_WRAP(DebugMessage(DEBUG_SID_SUPPRESS,
2376 						    "[%s()], Signature Suppress configuration gid:[%d] sid:[%d] flagged for deletion from list,\n"
2377 						    "Element is intersecting with Signature Suppress list  range gid[%d] sid min:[%d] sid max:[%d]\n\n",
2378 						    __FUNCTION__,
2379 						    cNode->gid,
2380 						    cNode->ss_min,
2381 						    sElement->gid,
2382 						    sElement->ss_min,
2383 						    sElement->ss_max););
2384 			    cNode->flag = 1;
2385 			    has_flag = 1;
2386 			}
2387 			break;
2388 
2389 		    case SS_RANGE:
2390 			if(sElement->ss_min <= cNode->ss_min)
2391 			    comp_set[0] = 1;
2392 
2393 			if(sElement->ss_min >= cNode->ss_max)
2394 			    comp_set[1] = 1;
2395 
2396 			if(sElement->ss_max >= cNode->ss_min)
2397 			    comp_set[2] = 1;
2398 
2399 			if(sElement->ss_max <= cNode->ss_max)
2400 			    comp_set[3] = 1;
2401 
2402 			DEBUG_WRAP(DebugMessage(DEBUG_SID_SUPPRESS,
2403 						"[%s()]: Comparing Signature intersection comp0:[%d] comp1:[%d] comp2:[%d] comp3:[%d]\n"
2404 						"Signature Suppress configuration entry: gid:[%d] sid min:[%d] sid max:[%d]\n"
2405                                                 "Signature Suppress list entry:          gid:[%d] sid min:[%d] sid max:[%d]\n\n",
2406 						__FUNCTION__,
2407 						comp_set[0],comp_set[1],comp_set[2],comp_set[3],
2408 						sElement->gid,sElement->ss_min,sElement->ss_max,
2409 						cNode->gid,cNode->ss_min,cNode->ss_max););
2410 
2411 			if( (comp_set[0] && !comp_set[1] && comp_set[2] && comp_set[3]) ||
2412 			    (!comp_set[0] && !comp_set[1] && comp_set[2] && comp_set[3]))
2413 			{
2414 			    DEBUG_WRAP(DebugMessage(DEBUG_SID_SUPPRESS,
2415 						    "[%s()]: Signature Suppress configuration entry  gid:[%d] sid min:[%d] sid max:[%d] is INCLUDED in \n"
2416 						    "Signature Suppress list entry gid:[%d] sid min:[%d] sid max:[%d]\n\n",
2417 						    __FUNCTION__,
2418 						    sElement->gid,sElement->ss_min,sElement->ss_max,
2419 						    cNode->gid,cNode->ss_min,cNode->ss_max););
2420 
2421 			    no_add = 1;
2422 			}
2423 			else if( (comp_set[0] && comp_set[1] && !comp_set[2] && comp_set[3]) ||
2424 				 (!comp_set[0] && !comp_set[1] && comp_set[2] && !comp_set[3]))
2425 			{
2426 
2427 			    DEBUG_WRAP(DebugMessage(DEBUG_SID_SUPPRESS,
2428 						    "[%s()]: Signature Suppress list entry  gid:[%d] sid min:[%d] sid max:[%d] and\n"
2429 						    "Signature Suppress configuration entry  gid:[%d] sid min:[%d] sid max:[%d] share some intesection, altering list entry. \n\n",
2430 						    __FUNCTION__,
2431 						    cNode->gid,cNode->ss_min,cNode->ss_max,
2432 						    sElement->gid,sElement->ss_min,sElement->ss_max););
2433 
2434 			    if(sElement->ss_min <= cNode->ss_min)
2435 			    {
2436 				cNode->ss_min = sElement->ss_min;
2437 			    }
2438 
2439 			    if(sElement->ss_max >= cNode->ss_max)
2440 			    {
2441 				cNode->ss_max = sElement->ss_max;
2442 			    }
2443 
2444 			    DEBUG_WRAP(DebugMessage(DEBUG_SID_SUPPRESS,
2445 						    "[%s()]: Modified Signature Suppress list entry gid:[%d] sid min:[%d] sid max:[%d] \n",
2446 						    __FUNCTION__,
2447 						    cNode->gid,cNode->ss_min,cNode->ss_max););
2448 
2449 			    no_add = 1;
2450 			}
2451 			break;
2452 
2453 		    default:
2454 			FatalError("[%s()]: Unknown type[%d] for Signature Suppress configuration entry gid:[%d] sid min:[%d] max sid:[%d] \n",
2455 				   __FUNCTION__,
2456 				   cNode->ss_type,
2457 				   cNode->gid,
2458 				   cNode->ss_min,
2459 				   cNode->ss_max);
2460 			return 1;
2461 			break;
2462 
2463 		    }
2464 		    break;
2465 
2466 		default:
2467 		    FatalError("[%s()]: Unknown type[%d] for Signature Suppress configuration entry gid:[%d] sid min:[%d] max sid:[%d] \n",
2468 			       __FUNCTION__,
2469 			       sElement->ss_type,
2470 			       sElement->gid,
2471 			       sElement->ss_min,
2472 			       sElement->ss_max);
2473 		    return 1;
2474 		    break;
2475 		}
2476 	    }
2477 
2478 	    pNode = cNode;
2479 	    cNode = cNode->next;
2480 	}
2481 
2482 	/* We could keep an index, but rolling is way faster isin't ;) */
2483 	if(has_flag)
2484 	{
2485 	    cNode = *sHead;
2486 	    pNode = cNode;
2487 
2488 	    while(cNode)
2489 	    {
2490 		if(cNode->flag)
2491 		{
2492 		    DEBUG_WRAP(DebugMessage(DEBUG_SID_SUPPRESS,
2493 					    "[%s(), unlinking Signature Suppress list entry type:[%d] gid:[%d] sid_min:[%d] sid_max:[%d] \n",
2494 					    __FUNCTION__,
2495 					    cNode->ss_type,
2496 					    cNode->gid,
2497 					    cNode->ss_min,
2498 					    cNode->ss_max););
2499 
2500 		    if( SigSuppressUnlinkNode(sHead,&cNode,&pNode))
2501 		    {
2502 			return 1;
2503 		    }
2504 		}
2505 
2506 		if(cNode)
2507 		{
2508 		    pNode = cNode;
2509 		    cNode = cNode->next;
2510 		}
2511 	    }
2512 	}
2513 
2514 	if(!no_add)
2515 	{
2516 	    if( (newNode = calloc(1,sizeof(SigSuppress_list))) == NULL)
2517 	    {
2518 		return 1;
2519 	    }
2520 
2521 	    memcpy(newNode,sElement,sizeof(SigSuppress_list));
2522 
2523 	    pNode->next = newNode;
2524 
2525 	    DEBUG_WRAP(DebugMessage(DEBUG_SID_SUPPRESS,
2526 				    "[%s()], Signature Suppress configuration entry type:[%s] gid:[%d] sid min:[%d] sid max:[%d] added to Signature Suppress list.\n",
2527 				    __FUNCTION__,
2528 				    (newNode->ss_type & SS_SINGLE) ? "SINGLE" : "RANGE",
2529 				    newNode->gid,
2530 				    newNode->ss_min,
2531 				    newNode->ss_max););
2532 	}
2533     }
2534 
2535 
2536     return 0;
2537 }
2538 
ConfigSigSuppress(Barnyard2Config * bc,char * args)2539 void ConfigSigSuppress(Barnyard2Config *bc, char *args)
2540 {
2541     char **toks = NULL;
2542     int num_toks = 0;
2543     int ptoks = 0;
2544 
2545     char gid_string[256] = {0};
2546 
2547     char **range_toks = NULL;
2548     int range_num_toks = 0;
2549 
2550     char **gid_toks = NULL;
2551     char *gid_sup_toks = NULL;
2552     int gid_num_toks = 0;
2553 
2554     SigSuppress_list t_supp_elem = {0};
2555 
2556     if( (bc == NULL) || (args == NULL))
2557     {
2558 	return;
2559     }
2560 
2561     toks = mSplit(args, ",", 0, &num_toks, 0);
2562 
2563     while(ptoks < num_toks)
2564     {
2565 	memset(gid_string,'\0',256);
2566 
2567 	gid_toks = mSplit(toks[ptoks], ":", 2, &gid_num_toks, 0);
2568 
2569 	if(gid_num_toks == 1)
2570 	{
2571 	    DEBUG_WRAP(DebugMessage(DEBUG_SID_SUPPRESS_PARSE,"Defaulting gid 1 for toks [%s]\n",
2572 				    toks[ptoks]););
2573 	    t_supp_elem.gid = 1;
2574 	    gid_sup_toks = toks[ptoks];
2575 	}
2576 	else if(gid_num_toks == 2)
2577 	{
2578 	    memcpy(gid_string,gid_toks[0],strlen(gid_toks[0]));
2579 
2580 	    if( BY2Strtoul(gid_string,&t_supp_elem.gid))
2581 	    {
2582 		FatalError("[%s] \n",__FUNCTION__);
2583 	    }
2584 
2585 	    DEBUG_WRAP(DebugMessage(DEBUG_SID_SUPPRESS_PARSE,"Using gid [%d] for toks [%s]\n",
2586 				    t_supp_elem.gid,
2587 				    toks[ptoks]););
2588 
2589 	    gid_sup_toks = gid_toks[1];
2590 	}
2591 	else
2592 	{
2593 	    FatalError("[%s()]: Invalid gid split value for [%s]\n",
2594 		       __FUNCTION__,
2595 		       toks[ptoks]);
2596 	}
2597 
2598 	range_toks = mSplit(gid_sup_toks, "-", 0, &range_num_toks, 0);
2599 
2600 	if(range_num_toks == 1)
2601 	{
2602 	    t_supp_elem.ss_type = SS_SINGLE;
2603 
2604 	    if( BY2Strtoul(gid_sup_toks,&t_supp_elem.ss_min))
2605             {
2606                 FatalError("[%s] \n",__FUNCTION__);
2607             }
2608 
2609 	    t_supp_elem.ss_max = t_supp_elem.ss_min;
2610 
2611 	    DEBUG_WRAP(DebugMessage(DEBUG_SID_SUPPRESS_PARSE,"Single element gid[%d] sid[%d] \n",
2612 				    t_supp_elem.gid,
2613 				    t_supp_elem.ss_min););
2614 	}
2615 	else if(range_num_toks == 2)
2616 	{
2617 	    DEBUG_WRAP(DebugMessage(DEBUG_SID_SUPPRESS_PARSE,"Got range [%s] : [%s] [%s] \n",
2618 				    gid_sup_toks,
2619 				    range_toks[0],
2620 				    range_toks[1]););
2621 
2622 	    t_supp_elem.ss_type = SS_RANGE;
2623 
2624 	    if( BY2Strtoul(range_toks[0],&t_supp_elem.ss_min))
2625             {
2626                 FatalError("[%s] \n",__FUNCTION__);
2627             }
2628 
2629 	    if( BY2Strtoul(range_toks[1],&t_supp_elem.ss_max))
2630             {
2631                 FatalError("[%s] \n",__FUNCTION__);
2632             }
2633 
2634 	    if(t_supp_elem.ss_min > t_supp_elem.ss_max)
2635 	    {
2636 		FatalError("[%s()], Min greater than max, invalid range [%s] \n",
2637 			   __FUNCTION__,
2638 			   gid_sup_toks);
2639 	    }
2640 
2641 	    if(t_supp_elem.ss_min == t_supp_elem.ss_max)
2642 	    {
2643 		FatalError("[%s()], Min equal than max, invalid range [%s] \n",
2644 			   __FUNCTION__,
2645 			   gid_sup_toks);
2646 	    }
2647 	}
2648 	else
2649 	{
2650 	    FatalError("element[%s] is an invalid range \n",gid_sup_toks);
2651 	}
2652 
2653        	mSplitFree(&range_toks, range_num_toks);
2654 	mSplitFree(&gid_toks, gid_num_toks);
2655 
2656 	if(SigSuppressAddElement(BCGetSigSuppressHead(),&t_supp_elem))
2657 	{
2658 	    FatalError("[%s()], unrecoverable call to SigSuppressAddElement() \n",
2659 		       __FUNCTION__);
2660 	}
2661 
2662 	ptoks++;
2663     }
2664 
2665     mSplitFree(&toks, num_toks);
2666     return;
2667 }
2668 
2669 
2670 
2671 
2672 #ifdef MPLS
ConfigMaxMplsLabelChain(Barnyard2Config * bc,char * args)2673 void ConfigMaxMplsLabelChain(Barnyard2Config *bc, char *args)
2674 {
2675     char *endp;
2676     long val = 0;
2677 
2678     if (bc == NULL)
2679         return;
2680 
2681     if (args != NULL)
2682     {
2683         val = strtol(args, &endp, 0);
2684         if ((args == endp) || *endp || (val < -1))
2685             val = DEFAULT_LABELCHAIN_LENGTH;
2686     }
2687     else
2688     {
2689         val = DEFAULT_LABELCHAIN_LENGTH;
2690     }
2691 
2692     bc->mpls_stack_depth = val;
2693 }
2694 
ConfigMplsPayloadType(Barnyard2Config * bc,char * args)2695 void ConfigMplsPayloadType(Barnyard2Config *bc, char *args)
2696 {
2697     if (bc == NULL)
2698         return;
2699 
2700     if (args != NULL)
2701     {
2702         if (strcasecmp(args, MPLS_PAYLOAD_OPT__IPV4) == 0)
2703         {
2704             bc->mpls_payload_type = MPLS_PAYLOADTYPE_IPV4;
2705         }
2706         else if (strcasecmp(args, MPLS_PAYLOAD_OPT__IPV6) == 0)
2707         {
2708             bc->mpls_payload_type = MPLS_PAYLOADTYPE_IPV6;
2709         }
2710         else if (strcasecmp(args, MPLS_PAYLOAD_OPT__ETHERNET) == 0)
2711         {
2712             bc->mpls_payload_type = MPLS_PAYLOADTYPE_ETHERNET;
2713         }
2714         else
2715         {
2716             ParseError("Non supported mpls payload type: %s.", args);
2717         }
2718     }
2719     else
2720     {
2721         bc->mpls_payload_type = DEFAULT_MPLS_PAYLOADTYPE;
2722     }
2723 }
2724 #endif
2725 
2726 #ifdef SUP_IP6
ParseIpVar(Barnyard2Config * bc,char * args)2727 static void ParseIpVar(Barnyard2Config *bc, char *args)
2728 {
2729     char **toks;
2730     int num_toks;
2731 
2732     DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES, "IpVar\n"););
2733 
2734     toks = mSplit(args, " \t", 0, &num_toks, 0);
2735     if (num_toks != 2)
2736     {
2737         ParseError("Missing argument to %s", toks[0]);
2738     }
2739 
2740     /* Check command line variables to see if this has already
2741      * been defined */
2742     if (cmd_line_var_list != NULL)
2743     {
2744         VarNode *tmp = cmd_line_var_list;
2745 
2746         while (tmp != NULL)
2747         {
2748             /* Already defined this via command line */
2749             if (strcasecmp(toks[0], tmp->name) == 0)
2750             {
2751                 mSplitFree(&toks, num_toks);
2752                 return;
2753             }
2754 
2755             tmp = tmp->next;
2756         }
2757     }
2758 
2759     DisallowCrossTableDuplicateVars(bc, toks[0], VAR_TYPE__IPVAR);
2760     sfvt_define(bc->ip_vartable, toks[0], toks[1]);
2761 
2762     mSplitFree(&toks, num_toks);
2763 }
2764 #else
ParseIpVar(Barnyard2Config * bc,char * args)2765 static void ParseIpVar(Barnyard2Config *bc, char *args)
2766 {
2767     ParseError("Unknown rule type: %s.", "ipvar");
2768 }
2769 #endif
2770 
ParseVar(Barnyard2Config * bc,char * args)2771 static void ParseVar(Barnyard2Config *bc, char *args)
2772 {
2773     char **toks;
2774     int num_toks;
2775 
2776     DEBUG_WRAP(DebugMessage(DEBUG_CONFIGRULES,"Variable\n"););
2777 
2778     toks = mSplit(args, " \t", 0, &num_toks, 0);
2779     if (num_toks != 2)
2780     {
2781         ParseError("Missing argument to %s", toks[0]);
2782     }
2783 
2784     /* Check command line variables to see if this has already
2785      * been defined */
2786     if (cmd_line_var_list != NULL)
2787     {
2788         VarNode *tmp = cmd_line_var_list;
2789 
2790         while (tmp != NULL)
2791         {
2792            // Already defined this via command line
2793             if (strcasecmp(toks[0], tmp->name) == 0)
2794             {
2795                 mSplitFree(&toks, num_toks);
2796                 return;
2797             }
2798 
2799             tmp = tmp->next;
2800         }
2801     }
2802 
2803     AddVarToTable(bc, toks[0], toks[1]);
2804     mSplitFree(&toks, num_toks);
2805 }
2806 
AddVarToTable(Barnyard2Config * bc,char * name,char * value)2807 static void AddVarToTable(Barnyard2Config *bc, char *name, char *value)
2808 {
2809     VarDefine(bc, name, value);
2810 }
2811 
VarTablesFree(Barnyard2Config * bc)2812 void VarTablesFree(Barnyard2Config *bc)
2813 {
2814     if (bc == NULL)
2815         return;
2816 
2817     if (bc->var_table != NULL)
2818     {
2819         DeleteVars(bc->var_table);
2820         bc->var_table = NULL;
2821     }
2822 
2823 #ifdef SUP_IP6
2824     if (bc->ip_vartable != NULL)
2825     {
2826         sfvt_free_table(bc->ip_vartable);
2827         bc->ip_vartable = NULL;
2828     }
2829 #endif
2830 }
2831 
ParseError(const char * format,...)2832 NORETURN void ParseError(const char *format, ...)
2833 {
2834     char buf[STD_BUF+1];
2835     va_list ap;
2836 
2837     va_start(ap, format);
2838     vsnprintf(buf, STD_BUF, format, ap);
2839     va_end(ap);
2840 
2841     buf[STD_BUF] = '\0';
2842 
2843     if (file_name != NULL)
2844         FatalError("%s(%d) %s\n", file_name, file_line, buf);
2845     else
2846         FatalError("%s\n", buf);
2847 }
2848 
ParseMessage(const char * format,...)2849 void ParseMessage(const char *format, ...)
2850 {
2851     char buf[STD_BUF+1];
2852     va_list ap;
2853 
2854     va_start(ap, format);
2855     vsnprintf(buf, STD_BUF, format, ap);
2856     va_end(ap);
2857 
2858     buf[STD_BUF] = '\0';
2859 
2860     if (file_name != NULL)
2861         LogMessage("%s(%d) %s\n", file_name, file_line, buf);
2862     else
2863         LogMessage("%s\n", buf);
2864 }
2865 
2866 // the presence of ip lists exceeds mSplit's one-level parsing
2867 // so we transform rule string into something that mSplit can
2868 // handle by changing ',' to c outside ip lists.
2869 // we also strip the leading keyword.
FixSeparators(char * rule,char c,const char * err)2870 char* FixSeparators (char* rule, char c, const char* err)
2871 {
2872     int list = 0;
2873     char* p = strchr(rule, c);
2874 
2875     if ( p && err )
2876     {
2877         FatalError("%s(%d) => %s: '%c' not allowed in argument\n",
2878             file_name, file_line, err, c);
2879     }
2880     while ( isspace((int)*rule) ) rule++;
2881 
2882     p = rule;
2883 
2884     while ( *p ) {
2885         if ( *p == '[' ) list++;
2886         else if ( *p == ']' ) list--;
2887         else if ( *p == ',' && !list ) *p = c;
2888         p++;
2889     }
2890     return rule;
2891 }
2892 
GetNameValue(char * arg,char ** nam,char ** val,const char * err)2893 void GetNameValue (char* arg, char** nam, char** val, const char* err)
2894 {
2895     while ( isspace((int)*arg) ) arg++;
2896     *nam = arg;
2897 
2898     while ( *arg && !isspace((int)*arg) ) arg++;
2899     if ( *arg ) *arg++ = '\0';
2900     *val = arg;
2901 
2902     if ( err && !**val )
2903     {
2904         FatalError("%s(%d) => %s: name value pair expected: %s\n",
2905             file_name, file_line, err, *nam);
2906     }
2907 }
2908 
2909