1 /* $Id$ */
2 /*
3 ** Copyright (C) 2002-2009 Sourcefire, Inc.
4 ** Copyright (C) 2002 Martin Roesch <roesch@sourcefire.com>
5 **
6 ** This program is free software; you can redistribute it and/or modify
7 ** it under the terms of the GNU General Public License Version 2 as
8 ** published by the Free Software Foundation.  You may not use, modify or
9 ** distribute this program under any other version of the GNU General
10 ** Public License.
11 **
12 ** This program is distributed in the hope that it will be useful,
13 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 ** GNU General Public License for more details.
16 **
17 ** You should have received a copy of the GNU General Public License
18 ** along with this program; if not, write to the Free Software
19 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21 
22 
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26 
27 #include <sys/types.h>
28 
29 #ifndef WIN32
30 #include <sys/socket.h>
31 #include <netinet/in.h>
32 #include <arpa/inet.h>
33 #include <sys/wait.h>
34 #include <dirent.h>
35 #include <fnmatch.h>
36 #endif /* !WIN32 */
37 
38 #include <stdarg.h>
39 #include <stdlib.h>
40 #include <syslog.h>
41 #include <errno.h>
42 #include <sys/stat.h>
43 #include <time.h>
44 #include <signal.h>
45 #include <unistd.h>
46 
47 #ifndef WIN32
48 #include <grp.h>
49 #include <pwd.h>
50 #include <netdb.h>
51 #include <limits.h>
52 #endif /* !WIN32 */
53 
54 #include <fcntl.h>
55 
56 #ifdef HAVE_STRING_H
57 #include <string.h>
58 #endif
59 
60 #ifdef HAVE_STRINGS_H
61 #include <strings.h>
62 #endif
63 
64 #include "barnyard2.h"
65 #include "mstring.h"
66 #include "debug.h"
67 #include "util.h"
68 #include "parser.h"
69 #include "plugbase.h"
70 #include "sf_types.h"
71 
72 #ifdef PATH_MAX
73 #define PATH_MAX_UTIL PATH_MAX
74 #else
75 #define PATH_MAX_UTIL 1024
76 #endif /* PATH_MAX */
77 
78 extern Barnyard2Config *barnyard2_conf;
79 extern int exit_signal;
80 
81 /*
82  * you may need to adjust this on the systems which don't have standard
83  * paths defined
84  */
85 #ifndef _PATH_VARRUN
86 static char _PATH_VARRUN[STD_BUF];
87 #endif
88 
89 
90 #ifdef NAME_MAX
91 #define NAME_MAX_UTIL NAME_MAX
92 #else
93 #define NAME_MAX_UTIL 256
94 #endif /* NAME_MAX */
95 
96 #define FILE_MAX_UTIL  (PATH_MAX_UTIL + NAME_MAX_UTIL)
97 
98 
99 
100 /****************************************************************************
101  *
102  * Function: CalcPct(uint64_t, uint64_t)
103  *
104  * Purpose:  Calculate the percentage of a value compared to a total
105  *
106  * Arguments: cnt => the numerator in the equation
107  *            total => the denominator in the calculation
108  *
109  * Returns: pct -> the percentage of cnt to value
110  *
111  ****************************************************************************/
CalcPct(uint64_t cnt,uint64_t total)112 double CalcPct(uint64_t cnt, uint64_t total)
113 {
114     double pct = 0.0;
115 
116     if (total == 0.0)
117     {
118         pct = (double)cnt;
119     }
120     else
121     {
122         pct = (double)cnt / (double)total;
123     }
124 
125     pct *= 100.0;
126 
127     return pct;
128 }
129 
130 
131 /****************************************************************************
132  *
133  * Function: DisplayBanner()
134  *
135  * Purpose:  Show valuable proggie info
136  *
137  * Arguments: None.
138  *
139  * Returns: 0 all the time
140  *
141  ****************************************************************************/
DisplayBanner(void)142 int DisplayBanner(void)
143 {
144     fprintf(stderr, "\n"
145         "  ______   -*> Barnyard2 <*-\n"
146         " / ,,_  \\  Version %s.%s.%s (Build %s)%s%s\n"
147         " |o\"  )~|  By Ian Firns (SecurixLive): http://www.securixlive.com/\n"
148 		" + '''' +  (C) Copyright 2008-2013 Ian Firns <firnsy@securixlive.com>\n"
149         "\n"
150         , VER_MAJOR, VER_MINOR, VER_REVISION, VER_BUILD,
151 #ifdef DEBUG
152 		" DEBUG",
153 #else
154 		"",
155 #endif
156 #ifdef SUP_IP6
157 		" IPv6"
158 #else
159 		""
160 #endif
161 #ifdef ENABLE_TCL
162 		" TCL"
163 #else
164 		""
165 #endif
166 );
167     return 0;
168 }
169 
170 
171 
172 /****************************************************************************
173  *
174  * Function: ts_print(register const struct, char *)
175  *
176  * Purpose: Generate a time stamp and stuff it in a buffer.  This one has
177  *          millisecond precision.  Oh yeah, I ripped this code off from
178  *          TCPdump, props to those guys.
179  *
180  * Arguments: timeval => clock struct coming out of libpcap
181  *            timebuf => buffer to stuff timestamp into
182  *
183  * Returns: void function
184  *
185  ****************************************************************************/
ts_print(register const struct timeval * tvp,char * timebuf)186 void ts_print(register const struct timeval *tvp, char *timebuf)
187 {
188     register int s;
189     int    localzone;
190     time_t Time;
191     struct timeval tv;
192     struct timezone tz;
193     struct tm *lt;    /* place to stick the adjusted clock data */
194 
195     /* if null was passed, we use current time */
196     if(!tvp)
197     {
198         /* manual page (for linux) says tz is never used, so.. */
199 	memset((char *) &tz, 0, sizeof(tz)); /* bzero() deprecated, replaced by memset() */
200         gettimeofday(&tv, &tz);
201         tvp = &tv;
202     }
203 
204     localzone = barnyard2_conf->thiszone;
205 
206     /*
207     **  If we're doing UTC, then make sure that the timezone is correct.
208     */
209     if(BcOutputUseUtc())
210         localzone = 0;
211 
212     s = (tvp->tv_sec + localzone) % 86400;
213     Time = (tvp->tv_sec + localzone) - s;
214 
215     lt = gmtime(&Time);
216 
217     if(BcOutputIncludeYear())
218     {
219         (void) SnortSnprintf(timebuf, TIMEBUF_SIZE,
220                         "%02d/%02d/%02d-%02d:%02d:%02d.%06u ",
221                         lt->tm_mon + 1, lt->tm_mday, lt->tm_year - 100,
222                         s / 3600, (s % 3600) / 60, s % 60,
223                         (u_int) tvp->tv_usec);
224     }
225     else
226     {
227         (void) SnortSnprintf(timebuf, TIMEBUF_SIZE,
228                         "%02d/%02d-%02d:%02d:%02d.%06u ", lt->tm_mon + 1,
229                         lt->tm_mday, s / 3600, (s % 3600) / 60, s % 60,
230                         (u_int) tvp->tv_usec);
231     }
232 }
233 
234 /****************************************************************************
235  *
236  * Function: ts_print2(uint32_t, uint32_t, char *)
237  *
238  * Purpose: Generate a time stamp and stuff it in a buffer.  This one has
239  *          millisecond precision. Oh yeah, I ripped this code off from
240  *          TCPdump, props to those guys.
241  *
242  * Arguments: timeval => clock struct coming out of libpcap
243  *            timebuf => buffer to stuff timestamp into
244  *
245  * Returns: void function
246  *
247  ****************************************************************************/
ts_print2(uint32_t sec,uint32_t usec,char * timebuf)248 void ts_print2(uint32_t sec, uint32_t usec, char *timebuf)
249 {
250     register int s;
251     int    localzone;
252     time_t Time;
253     struct tm *lt;    /* place to stick the adjusted clock data */
254 
255     localzone = barnyard2_conf->thiszone;
256 
257     /*
258     **  If we're doing UTC, then make sure that the timezone is correct.
259     */
260     if(BcOutputUseUtc())
261         localzone = 0;
262 
263     s = (sec + localzone) % 86400;
264     Time = (sec + localzone) - s;
265 
266     lt = gmtime(&Time);
267 
268     if(BcOutputIncludeYear())
269     {
270         (void) SnortSnprintf(timebuf, TIMEBUF_SIZE,
271                         "%02d/%02d/%02d-%02d:%02d:%02d.%06u ",
272                         lt->tm_mon + 1, lt->tm_mday, lt->tm_year - 100,
273                         s / 3600, (s % 3600) / 60, s % 60,
274                         (u_int) usec);
275     }
276     else
277     {
278         (void) SnortSnprintf(timebuf, TIMEBUF_SIZE,
279                         "%02d/%02d-%02d:%02d:%02d.%06u ", lt->tm_mon + 1,
280                         lt->tm_mday, s / 3600, (s % 3600) / 60, s % 60,
281                         (u_int) usec);
282     }
283 }
284 
285 /****************************************************************************
286  *
287  * Function: gmt2local(time_t)
288  *
289  * Purpose: Figures out how to adjust the current clock reading based on the
290  *          timezone you're in.  Ripped off from TCPdump.
291  *
292  * Arguments: time_t => offset from GMT
293  *
294  * Returns: offset seconds from GMT
295  *
296  ****************************************************************************/
gmt2local(time_t t)297 int gmt2local(time_t t)
298 {
299     register int dt, dir;
300     register struct tm *gmt, *loc;
301     struct tm sgmt;
302 
303     if(t == 0)
304         t = time(NULL);
305 
306     gmt = &sgmt;
307     *gmt = *gmtime(&t);
308     loc = localtime(&t);
309 
310     dt = (loc->tm_hour - gmt->tm_hour) * 60 * 60 +
311         (loc->tm_min - gmt->tm_min) * 60;
312 
313     dir = loc->tm_year - gmt->tm_year;
314 
315     if(dir == 0)
316         dir = loc->tm_yday - gmt->tm_yday;
317 
318     dt += dir * 24 * 60 * 60;
319 
320     return(dt);
321 }
322 
323 
324 
325 
326 /****************************************************************************
327  *
328  * Function: copy_argv(u_char **)
329  *
330  * Purpose: Copies a 2D array (like argv) into a flat string.  Stolen from
331  *          TCPDump.
332  *
333  * Arguments: argv => 2D array to flatten
334  *
335  * Returns: Pointer to the flat string
336  *
337  ****************************************************************************/
copy_argv(char ** argv)338 char *copy_argv(char **argv)
339 {
340     char **p;
341     u_int len = 0;
342     char *buf;
343     char *src, *dst;
344     //void ftlerr(char *,...);
345 
346     p = argv;
347     if(*p == 0)
348         return 0;
349 
350     while(*p)
351         len += strlen(*p++) + 1;
352 
353     buf = (char *) calloc(1,len);
354 
355     if(buf == NULL)
356     {
357         FatalError("calloc() failed: %s\n", strerror(errno));
358     }
359     p = argv;
360     dst = buf;
361 
362     while((src = *p++) != NULL)
363     {
364         while((*dst++ = *src++) != '\0');
365         dst[-1] = ' ';
366     }
367 
368     dst[-1] = '\0';
369 
370     /* Check for an empty string */
371     dst = buf;
372     while (isspace((int)*dst))
373         dst++;
374 
375     if (strlen(dst) == 0)
376     {
377         free(buf);
378         buf = NULL;
379     }
380 
381     return buf;
382 }
383 
strtrim(char * str)384 void strtrim(char *str)
385 {
386     char *end;
387 
388      // trim leading space
389      while(isspace(*str)) str++;
390 
391      if(*str == 0)  // All spaces?
392          return;
393 
394      // trim trailing space
395      end = str + strlen(str) - 1;
396      while(end > str && isspace(*end)) end--;
397 
398      // write new null terminator
399      *(end+1) = 0;
400 }
401 
402 /****************************************************************************
403  *
404  * Function: strip(char *)
405  *
406  * Purpose: Strips a data buffer of CR/LF/TABs.  Replaces CR/LF's with
407  *          NULL and TABs with spaces.
408  *
409  * Arguments: data => ptr to the data buf to be stripped
410  *
411  * Returns: void
412  *
413  * 3/7/07 - changed to return void - use strlen to get size of string
414  *
415  * Note that this function will turn all '\n' and '\r' into null chars
416  * so, e.g. 'Hello\nWorld\n' => 'Hello\x00World\x00'
417  * note that the string is now just 'Hello' and the length is shortened
418  * by more than just an ending '\n' or '\r'
419  ****************************************************************************/
strip(char * data)420 void strip(char *data)
421 {
422     int size;
423     char *end;
424     char *idx;
425 
426     idx = data;
427     end = data + strlen(data);
428     size = end - idx;
429 
430     while(idx != end)
431     {
432         if((*idx == '\n') ||
433                 (*idx == '\r'))
434         {
435             *idx = 0;
436             size--;
437         }
438         if(*idx == '\t')
439         {
440             *idx = ' ';
441         }
442         idx++;
443     }
444 }
445 
446 /*
447  * Function: ErrorMessage(const char *, ...)
448  *
449  * Purpose: Print a message to stderr.
450  *
451  * Arguments: format => the formatted error string to print out
452  *            ... => format commands/fillers
453  *
454  * Returns: void function
455  */
ErrorMessage(const char * format,...)456 void ErrorMessage(const char *format,...)
457 {
458     char buf[STD_BUF+1];
459     va_list ap;
460 
461     if (barnyard2_conf == NULL)
462         return;
463 
464     va_start(ap, format);
465 
466     if(BcDaemonMode() || BcLogSyslog())
467     {
468         vsnprintf(buf, STD_BUF, format, ap);
469         buf[STD_BUF] = '\0';
470         syslog(LOG_CONS | LOG_DAEMON | LOG_ERR, "%s", buf);
471     }
472     else
473     {
474         vfprintf(stderr, format, ap);
475     }
476     va_end(ap);
477 }
478 
479 /*
480  * Function: LogMessage(const char *, ...)
481  *
482  * Purpose: Print a message to stdout or with logfacility.
483  *
484  * Arguments: format => the formatted error string to print out
485  *            ... => format commands/fillers
486  *
487  * Returns: void function
488  */
LogMessage(const char * format,...)489 void LogMessage(const char *format,...)
490 {
491     char buf[STD_BUF+1];
492     va_list ap;
493 
494     if (barnyard2_conf == NULL)
495         return;
496 
497     if (BcLogQuiet() && !BcDaemonMode() && !BcLogSyslog())
498         return;
499 
500     va_start(ap, format);
501 
502     if(BcDaemonMode() || BcLogSyslog())
503     {
504         vsnprintf(buf, STD_BUF, format, ap);
505         buf[STD_BUF] = '\0';
506         syslog(LOG_DAEMON | LOG_NOTICE, "%s", buf);
507     }
508     else
509     {
510         vfprintf(stderr, format, ap);
511     }
512 
513     va_end(ap);
514 }
515 
516 
517 /*
518  * Function: CreateApplicationEventLogEntry(const char *)
519  *
520  * Purpose: Add an entry to the Win32 "Application" EventLog
521  *
522  * Arguments: szMessage => the formatted error string to print out
523  *
524  * Returns: void function
525  */
526 #if defined(WIN32) && defined(ENABLE_WIN32_SERVICE)
CreateApplicationEventLogEntry(const char * msg)527 void CreateApplicationEventLogEntry(const char *msg)
528 {
529     HANDLE hEventLog;
530     char*  pEventSourceName = "SnortService";
531 
532     /* prepare to write to Application log on local host
533       * with Event Source of SnortService
534       */
535     AddEventSource(pEventSourceName);
536     hEventLog = RegisterEventSource(NULL, pEventSourceName);
537     if (hEventLog == NULL)
538     {
539         /* Could not register the event source. */
540         return;
541     }
542 
543     if (!ReportEvent(hEventLog,   /* event log handle               */
544             EVENTLOG_ERROR_TYPE,  /* event type                     */
545             0,                    /* category zero                  */
546             EVMSG_SIMPLE,         /* event identifier               */
547             NULL,                 /* no user security identifier    */
548             1,                    /* one substitution string        */
549             0,                    /* no data                        */
550             &msg,                 /* pointer to array of strings    */
551             NULL))                /* pointer to data                */
552     {
553         /* Could not report the event. */
554     }
555 
556     DeregisterEventSource(hEventLog);
557 }
558 #endif  /* WIN32 && ENABLE_WIN32_SERVICE */
559 
560 
561 /*
562  * Function: FatalError(const char *, ...)
563  *
564  * Purpose: When a fatal error occurs, this function prints the error message
565  *          and cleanly shuts down the program
566  *
567  * Arguments: format => the formatted error string to print out
568  *            ... => format commands/fillers
569  *
570  * Returns: void function
571  */
FatalError(const char * format,...)572 NORETURN void FatalError(const char *format,...)
573 {
574     char buf[STD_BUF+1];
575     va_list ap;
576 
577     va_start(ap, format);
578     vsnprintf(buf, STD_BUF, format, ap);
579     va_end(ap);
580 
581     buf[STD_BUF] = '\0';
582 
583     if ((barnyard2_conf != NULL) && (BcDaemonMode() || BcLogSyslog()))
584     {
585         syslog(LOG_CONS | LOG_DAEMON | LOG_ERR, "FATAL ERROR: %s", buf);
586     }
587     else
588     {
589         fprintf(stderr, "ERROR: %s", buf);
590         fprintf(stderr,"Fatal Error, Quitting..\n");
591 #if defined(WIN32) && defined(ENABLE_WIN32_SERVICE)
592         CreateApplicationEventLogEntry(buf);
593 #endif
594     }
595 
596     CleanExit(1);
597 
598 }
599 
600 
601 /****************************************************************************
602  *
603  * Function: CreatePidFile(char *)
604  *
605  * Purpose:  Creates a PID file
606  *
607  * Arguments: Interface opened.
608  *
609  * Returns: void function
610  *
611  ****************************************************************************/
612 static FILE *pid_lockfile = NULL;
613 static FILE *pid_file = NULL;
CreatePidFile(char * intf)614 void CreatePidFile(char *intf)
615 {
616     struct stat pt;
617     int pid = (int) getpid();
618 #ifdef WIN32
619     char dir[STD_BUF + 1];
620 #endif
621 
622     if (1)	// TODO: Read mode flag
623     {
624         if(!BcLogQuiet())
625         {
626             LogMessage("Checking PID path...\n");
627         }
628 
629         if (strlen(barnyard2_conf->pid_path) != 0)
630         {
631             if((stat(barnyard2_conf->pid_path, &pt) == -1) ||
632                 !S_ISDIR(pt.st_mode) || access(barnyard2_conf->pid_path, W_OK) == -1)
633             {
634 #ifndef WIN32
635                 /* Save this just in case it's reset with LogMessage call */
636 				int err = errno;
637 
638 				LogMessage("WARNING: %s is invalid, trying "
639                            "/var/run...\n", barnyard2_conf->pid_path);
640                 if (err)
641                 {
642                     LogMessage("Previous Error, errno=%d, (%s)\n",
643                                err, strerror(err) == NULL ? "Unknown error" : strerror(err));
644                 }
645 #endif
646                 memset(barnyard2_conf->pid_path, '\0', sizeof(barnyard2_conf->pid_path));
647             }
648             else
649             {
650                 LogMessage("PID path stat checked out ok, "
651                            "PID path set to %s\n", barnyard2_conf->pid_path);
652             }
653         }
654 
655         if (strlen(barnyard2_conf->pid_path) == 0)
656         {
657 #ifndef _PATH_VARRUN
658 # ifndef WIN32
659             SnortStrncpy(_PATH_VARRUN, "/var/run/", sizeof(_PATH_VARRUN));
660 # else
661             if (GetCurrentDirectory(sizeof(dir) - 1, dir))
662                 SnortStrncpy(_PATH_VARRUN, dir, sizeof(_PATH_VARRUN));
663 # endif  /* WIN32 */
664 #else
665             LogMessage("PATH_VARRUN is set to %s on this operating "
666                        "system\n", _PATH_VARRUN);
667 #endif  /* _PATH_VARRUN */
668 
669             stat(_PATH_VARRUN, &pt);
670 
671             if(!S_ISDIR(pt.st_mode) || access(_PATH_VARRUN, W_OK) == -1)
672             {
673                 LogMessage("WARNING: _PATH_VARRUN is invalid, trying "
674                            "/var/log...\n");
675                 SnortStrncpy(barnyard2_conf->pid_path, "/var/log/", sizeof(barnyard2_conf->pid_path));
676                 stat(barnyard2_conf->pid_path, &pt);
677 
678                 if(!S_ISDIR(pt.st_mode) || access(barnyard2_conf->pid_path, W_OK) == -1)
679                 {
680                     LogMessage("WARNING: %s is invalid, logging Snort "
681                                "PID path to log directory (%s)\n", barnyard2_conf->pid_path,
682                                barnyard2_conf->log_dir);
683                     CheckLogDir();
684                     SnortSnprintf(barnyard2_conf->pid_path, sizeof(barnyard2_conf->pid_path),
685                                   "%s/", barnyard2_conf->log_dir);
686                 }
687             }
688             else
689             {
690                 LogMessage("PID path stat checked out ok, "
691                            "PID path set to %s\n", _PATH_VARRUN);
692                 SnortStrncpy(barnyard2_conf->pid_path, _PATH_VARRUN, sizeof(barnyard2_conf->pid_path));
693             }
694         }
695     }
696 
697     if(intf == NULL || strlen(barnyard2_conf->pid_path) == 0)
698     {
699         /* barnyard2_conf->pid_path should have some value by now
700          * so let us just be sane.
701          */
702         FatalError("CreatePidFile() failed to lookup interface or pid_path is unknown!\n");
703     }
704 
705     SnortSnprintf(barnyard2_conf->pid_filename, sizeof(barnyard2_conf->pid_filename),
706 				  "%s/barnyard2_%s%s.pid", barnyard2_conf->pid_path, intf, barnyard2_conf->pidfile_suffix);
707 
708 #ifndef WIN32
709     if (!BcNoLockPidFile())
710     {
711         char pid_lockfilename[STD_BUF+1];
712         int lock_fd;
713 
714         /* First, lock the PID file */
715         SnortSnprintf(pid_lockfilename, STD_BUF, "%s.lck", barnyard2_conf->pid_filename);
716         pid_lockfile = fopen(pid_lockfilename, "w");
717 
718         if (pid_lockfile)
719         {
720             struct flock lock;
721             lock_fd = fileno(pid_lockfile);
722 
723             lock.l_type = F_WRLCK;
724             lock.l_whence = SEEK_SET;
725             lock.l_start = 0;
726             lock.l_len = 0;
727 
728             if (fcntl(lock_fd, F_SETLK, &lock) == -1)
729             {
730                 ClosePidFile();
731                 FatalError("Failed to Lock PID File \"%s\" for PID \"%d\"\n", barnyard2_conf->pid_filename, pid);
732             }
733         }
734     }
735 #endif
736 
737     /* Okay, were able to lock PID file, now open and write PID */
738     pid_file = fopen(barnyard2_conf->pid_filename, "w");
739     if(pid_file)
740     {
741         LogMessage("Writing PID \"%d\" to file \"%s\"\n", pid, barnyard2_conf->pid_filename);
742         fprintf(pid_file, "%d\n", pid);
743         fflush(pid_file);
744     }
745     else
746     {
747         ErrorMessage("Failed to create pid file %s", barnyard2_conf->pid_filename);
748         barnyard2_conf->pid_filename[0] = 0;
749     }
750 }
751 
752 /****************************************************************************
753  *
754  * Function: ClosePidFile(char *)
755  *
756  * Purpose:  Releases lock on a PID file
757  *
758  * Arguments: None
759  *
760  * Returns: void function
761  *
762  ****************************************************************************/
ClosePidFile(void)763 void ClosePidFile(void)
764 {
765     if (pid_file)
766     {
767         fclose(pid_file);
768         pid_file = NULL;
769     }
770     if (pid_lockfile)
771     {
772         fclose(pid_lockfile);
773         pid_lockfile = NULL;
774     }
775 }
776 
777 /****************************************************************************
778  *
779  * Function: SetUidGid()
780  *
781  * Purpose:  Sets safe UserID and GroupID if needed
782  *
783  * Arguments: none
784  *
785  * Returns: void function
786  *
787  ****************************************************************************/
SetUidGid(int user_id,int group_id)788 void SetUidGid(int user_id, int group_id)
789 {
790 #ifndef WIN32
791 
792     if ((group_id != -1) && (getgid() != (gid_t)group_id))
793     {
794         if (setgid(group_id) < 0)
795             FatalError("Cannot set gid: %d\n", group_id);
796 
797         DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Set gid to %d\n", group_id););
798     }
799 
800     if ((user_id != -1) && (getuid() != (uid_t)user_id))
801     {
802         struct passwd *pw = getpwuid(user_id);
803 
804         if (pw != NULL)
805         {
806             /* getpwuid and initgroups may use the same static buffers */
807             char *username = SnortStrdup(pw->pw_name);
808 
809             if ((getuid() == 0) && (initgroups(username, group_id) < 0))
810             {
811                 free(username);
812                 FatalError("Can not initgroups(%s,%d)",
813                            username, group_id);
814             }
815 
816             free(username);
817         }
818 
819         /** just to be on a safe side... **/
820         endgrent();
821         endpwent();
822 
823         if (setuid(user_id) < 0)
824             FatalError("Can not set uid: %d\n", user_id);
825 
826         DEBUG_WRAP(DebugMessage(DEBUG_INIT, "Set uid to %d\n", user_id););
827     }
828 #endif  /* WIN32 */
829 }
830 
831 /* exiting should be 0 for if not exiting and 1 if exiting */
DropStats(int exiting)832 void DropStats(int exiting)
833 {
834     uint64_t total = 0;
835 
836     LogMessage("================================================"
837                "===============================\n");
838 
839     LogMessage("Record Totals:\n");
840     LogMessage("   Records:"     FMTu64("12") "\n", pc.total_records);
841     LogMessage("   Events:"      FMTu64("12") " (%.3f%%)\n", pc.total_events,
842                CalcPct(pc.total_events, pc.total_records));
843     LogMessage("   Packets:"     FMTu64("12") " (%.3f%%)\n", pc.total_packets,
844                CalcPct(pc.total_packets, pc.total_records));
845     LogMessage("   Unknown:"     FMTu64("12") " (%.3f%%)\n", pc.total_unknown,
846                CalcPct(pc.total_unknown, pc.total_records));
847     LogMessage("   Suppressed:"  FMTu64("12") " (%.3f%%)\n", pc.total_suppressed,
848                CalcPct(pc.total_suppressed, pc.total_records));
849 
850     total = pc.total_packets;
851 
852     LogMessage("================================================"
853                "===============================\n");
854 
855     LogMessage("Packet breakdown by protocol (includes rebuilt packets):\n");
856 
857     LogMessage("      ETH: " FMTu64("-10") " (%.3f%%)\n",
858                pc.eth, CalcPct(pc.eth, total));
859     LogMessage("  ETHdisc: " FMTu64("-10") " (%.3f%%)\n",
860                pc.ethdisc, CalcPct(pc.ethdisc, total));
861 #ifdef GIDS
862 #ifndef IPFW
863     LogMessage(" IPTables: " FMTu64("-10") " (%.3f%%)\n",
864                pc.iptables, CalcPct(pc.iptables, total));
865 #else
866     LogMessage("     IPFW: " FMTu64("-10") " (%.3f%%)\n",
867                pc.ipfw, CalcPct(pc.ipfw, total));
868 #endif  /* IPFW */
869 #endif  /* GIDS */
870     LogMessage("     VLAN: " FMTu64("-10") " (%.3f%%)\n",
871                pc.vlan, CalcPct(pc.vlan, total));
872 
873     if (pc.nested_vlan != 0)
874     LogMessage("Nested VLAN: " FMTu64("-10") " (%.3f%%)\n",
875                pc.nested_vlan, CalcPct(pc.nested_vlan, total));
876 
877     LogMessage("     IPV6: " FMTu64("-10") " (%.3f%%)\n",
878                pc.ipv6, CalcPct(pc.ipv6, total));
879     LogMessage("  IP6 EXT: " FMTu64("-10") " (%.3f%%)\n",
880                pc.ip6ext, CalcPct(pc.ip6ext, total));
881     LogMessage("  IP6opts: " FMTu64("-10") " (%.3f%%)\n",
882                pc.ipv6opts, CalcPct(pc.ipv6opts, total));
883     LogMessage("  IP6disc: " FMTu64("-10") " (%.3f%%)\n",
884                pc.ipv6disc, CalcPct(pc.ipv6disc, total));
885 
886     LogMessage("      IP4: " FMTu64("-10") " (%.3f%%)\n",
887                pc.ip, CalcPct(pc.ip, total));
888     LogMessage("  IP4disc: " FMTu64("-10") " (%.3f%%)\n",
889                pc.ipdisc, CalcPct(pc.ipdisc, total));
890 
891     LogMessage("    TCP 6: " FMTu64("-10") " (%.3f%%)\n",
892                pc.tcp6, CalcPct(pc.tcp6, total));
893     LogMessage("    UDP 6: " FMTu64("-10") " (%.3f%%)\n",
894                pc.udp6, CalcPct(pc.udp6, total));
895     LogMessage("    ICMP6: " FMTu64("-10") " (%.3f%%)\n",
896                pc.icmp6, CalcPct(pc.icmp6, total));
897     LogMessage("  ICMP-IP: " FMTu64("-10") " (%.3f%%)\n",
898                pc.embdip, CalcPct(pc.embdip, total));
899 
900     LogMessage("      TCP: " FMTu64("-10") " (%.3f%%)\n",
901                pc.tcp, CalcPct(pc.tcp, total));
902     LogMessage("      UDP: " FMTu64("-10") " (%.3f%%)\n",
903                pc.udp, CalcPct(pc.udp, total));
904     LogMessage("     ICMP: " FMTu64("-10") " (%.3f%%)\n",
905                pc.icmp, CalcPct(pc.icmp, total));
906 
907     LogMessage("  TCPdisc: " FMTu64("-10") " (%.3f%%)\n",
908                pc.tdisc, CalcPct(pc.tdisc, total));
909     LogMessage("  UDPdisc: " FMTu64("-10") " (%.3f%%)\n",
910                pc.udisc, CalcPct(pc.udisc, total));
911     LogMessage("  ICMPdis: " FMTu64("-10") " (%.3f%%)\n",
912                pc.icmpdisc, CalcPct(pc.icmpdisc, total));
913 
914     LogMessage("     FRAG: " FMTu64("-10") " (%.3f%%)\n",
915                pc.frags, CalcPct(pc.frags, total));
916     LogMessage("   FRAG 6: " FMTu64("-10") " (%.3f%%)\n",
917                pc.frag6, CalcPct(pc.frag6, total));
918 
919     LogMessage("      ARP: " FMTu64("-10") " (%.3f%%)\n",
920                pc.arp, CalcPct(pc.arp, total));
921 #ifndef NO_NON_ETHER_DECODER
922     LogMessage("    EAPOL: " FMTu64("-10") " (%.3f%%)\n",
923                pc.eapol, CalcPct(pc.eapol, total));
924 #endif
925     LogMessage("  ETHLOOP: " FMTu64("-10") " (%.3f%%)\n",
926                pc.ethloopback, CalcPct(pc.ethloopback, total));
927     LogMessage("      IPX: " FMTu64("-10") " (%.3f%%)\n",
928                pc.ipx, CalcPct(pc.ipx, total));
929 #ifdef GRE
930     LogMessage("IPv4/IPv4: " FMTu64("-10") " (%.3f%%)\n",
931                pc.ip4ip4, CalcPct(pc.ip4ip4, total));
932     LogMessage("IPv4/IPv6: " FMTu64("-10") " (%.3f%%)\n",
933                pc.ip4ip6, CalcPct(pc.ip4ip6, total));
934     LogMessage("IPv6/IPv4: " FMTu64("-10") " (%.3f%%)\n",
935                pc.ip6ip4, CalcPct(pc.ip6ip4, total));
936     LogMessage("IPv6/IPv6: " FMTu64("-10") " (%.3f%%)\n",
937                pc.ip6ip6, CalcPct(pc.ip6ip6, total));
938     LogMessage("      GRE: " FMTu64("-10") " (%.3f%%)\n",
939                pc.gre, CalcPct(pc.gre, total));
940     LogMessage("  GRE ETH: " FMTu64("-10") " (%.3f%%)\n",
941                pc.gre_eth, CalcPct(pc.gre_eth, total));
942     LogMessage(" GRE VLAN: " FMTu64("-10") " (%.3f%%)\n",
943                pc.gre_vlan, CalcPct(pc.gre_vlan, total));
944     LogMessage(" GRE IPv4: " FMTu64("-10") " (%.3f%%)\n",
945                pc.gre_ip, CalcPct(pc.gre_ip, total));
946     LogMessage(" GRE IPv6: " FMTu64("-10") " (%.3f%%)\n",
947                pc.gre_ipv6, CalcPct(pc.gre_ipv6, total));
948     LogMessage("GRE IP6 E: " FMTu64("-10") " (%.3f%%)\n",
949                pc.gre_ipv6ext, CalcPct(pc.gre_ipv6ext, total));
950     LogMessage(" GRE PPTP: " FMTu64("-10") " (%.3f%%)\n",
951                pc.gre_ppp, CalcPct(pc.gre_ppp, total));
952     LogMessage("  GRE ARP: " FMTu64("-10") " (%.3f%%)\n",
953                pc.gre_arp, CalcPct(pc.gre_arp, total));
954     LogMessage("  GRE IPX: " FMTu64("-10") " (%.3f%%)\n",
955                pc.gre_ipx, CalcPct(pc.gre_ipx, total));
956     LogMessage(" GRE LOOP: " FMTu64("-10") " (%.3f%%)\n",
957                pc.gre_loopback, CalcPct(pc.gre_loopback, total));
958 #endif  /* GRE */
959 #ifdef MPLS
960     LogMessage("     MPLS: " FMTu64("-10") " (%.3f%%)\n",
961                    pc.mpls, CalcPct(pc.mpls, total));
962 #endif
963     LogMessage("    OTHER: " FMTu64("-10") " (%.3f%%)\n",
964                pc.other, CalcPct(pc.other, total));
965     LogMessage("  DISCARD: " FMTu64("-10") " (%.3f%%)\n",
966                pc.discards, CalcPct(pc.discards, total));
967     LogMessage("InvChkSum: " FMTu64("-10") " (%.3f%%)\n",
968                pc.invalid_checksums, CalcPct(pc.invalid_checksums, total));
969 
970     LogMessage("   S5 G 1: " FMTu64("-10") " (%.3f%%)\n",
971                pc.s5tcp1, CalcPct(pc.s5tcp1, total));
972     LogMessage("   S5 G 2: " FMTu64("-10") " (%.3f%%)\n",
973                pc.s5tcp2, CalcPct(pc.s5tcp2, total));
974 
975     LogMessage("    Total: " FMTu64("-10") "\n", total);
976 
977 #ifndef NO_NON_ETHER_DECODER
978 #ifdef DLT_IEEE802_11
979     if(datalink == DLT_IEEE802_11)
980     {
981         LogMessage("================================================"
982                    "===============================\n");
983         LogMessage("Wireless Stats:\n");
984         LogMessage("Breakdown by type:\n");
985         LogMessage("    Management Packets: " FMTu64("-10") " (%.3f%%)\n",
986                    pc.wifi_mgmt, CalcPct(pc.wifi_mgmt, total));
987         LogMessage("    Control Packets:    " FMTu64("-10") " (%.3f%%)\n",
988                    pc.wifi_control, CalcPct(pc.wifi_control, total));
989         LogMessage("    Data Packets:       " FMTu64("-10") " (%.3f%%)\n",
990                    pc.wifi_data, CalcPct(pc.wifi_data, total));
991     }
992 #endif  /* DLT_IEEE802_11 */
993 #endif  // NO_NON_ETHER_DECODER
994 
995     LogMessage("=============================================="
996                "=================================\n");
997 
998     return;
999 }
1000 
1001 /****************************************************************************
1002  *
1003  * Function: CleanupProtoNames()
1004  *
1005  * Purpose: Frees the protocol names
1006  *
1007  * Arguments: None.
1008  *
1009  * Returns: void function
1010  *
1011  ****************************************************************************/
CleanupProtoNames(void)1012 void CleanupProtoNames(void)
1013 {
1014     int i;
1015 
1016     for(i = 0; i < 256; i++)
1017     {
1018         if( protocol_names[i] != NULL )
1019         {
1020             free( protocol_names[i] );
1021             protocol_names[i] = NULL;
1022         }
1023     }
1024 
1025     if(protocol_names)
1026     {
1027 	free(protocol_names);
1028 	protocol_names = NULL;
1029     }
1030 
1031 }
1032 
1033  /****************************************************************************
1034   *
1035   * Function: CheckLogDir()
1036   *
1037   * Purpose: CyberPsychotic sez: basically we only check if logdir exist and
1038   *          writable, since it might screw the whole thing in the middle. Any
1039   *          other checks could be performed here as well.
1040   *
1041   * Arguments: None.
1042   *
1043   * Returns: void function
1044   *
1045   ****************************************************************************/
CheckLogDir(void)1046 void CheckLogDir(void)
1047 {
1048     struct stat st;
1049 
1050 	if (barnyard2_conf->log_dir == NULL)
1051 		return;
1052 
1053     if (stat(barnyard2_conf->log_dir, &st) == -1)
1054         FatalError("Stat check on log dir (%s) failed: %s.\n", barnyard2_conf->log_dir, strerror(errno));
1055 
1056     if (!S_ISDIR(st.st_mode) || (access(barnyard2_conf->log_dir, W_OK) == -1))
1057     {
1058         FatalError("Can not get write access to logging directory \"%s\". "
1059                    "(directory doesn't exist or permissions are set incorrectly "
1060                    "or it is not a directory at all)\n",
1061                    barnyard2_conf->log_dir);
1062     }
1063 }
1064 
1065 /* Signal handler for child process signaling the parent
1066  * that is is ready */
1067 static int parent_wait = 1;
SigChildReadyHandler(int signal)1068 static void SigChildReadyHandler(int signal)
1069 {
1070 #ifdef DEBUG
1071     LogMessage("Received Signal from Child\n");
1072 #endif
1073     parent_wait = 0;
1074 }
1075 
1076 /****************************************************************************
1077  *
1078  * Function: GoDaemon()
1079  *
1080  * Purpose: Puts the program into daemon mode, nice and quiet like....
1081  *
1082  * Arguments: None.
1083  *
1084  * Returns: void function
1085  *
1086  ****************************************************************************/
GoDaemon(void)1087 void GoDaemon(void)
1088 {
1089 #ifndef WIN32
1090     int exit_val = 0;
1091     int ret = 0;
1092     pid_t fs;
1093 
1094     LogMessage("Initializing daemon mode\n");
1095 
1096     if (BcDaemonRestart())
1097         return;
1098 
1099     /* Don't daemonize if we've already daemonized and
1100      * received a SIGHUP. */
1101     if(getppid() != 1)
1102     {
1103         /* Register signal handler that parent can trap signal */
1104         signal(SIGNAL_SNORT_CHILD_READY, SigChildReadyHandler);
1105         if (errno != 0) errno=0;
1106 
1107         /* now fork the child */
1108         fs = fork();
1109 
1110         if(fs > 0)
1111         {
1112             /* Parent */
1113 
1114             /* Don't exit quite yet.  Wait for the child
1115              * to signal that is there and created the PID
1116              * file.
1117              */
1118             while (parent_wait)
1119             {
1120                 /* Continue waiting until receiving signal from child */
1121                 int status;
1122                 if (waitpid(fs, &status, WNOHANG) == fs)
1123                 {
1124                     /* If the child is gone, parent should go away, too */
1125                     if (WIFEXITED(status))
1126                     {
1127                         LogMessage("Child exited unexpectedly\n");
1128                         exit_val = -1;
1129                         break;
1130                     }
1131 
1132                     if (WIFSIGNALED(status))
1133                     {
1134                         LogMessage("Child terminated unexpectedly\n");
1135                         exit_val = -2;
1136                         break;
1137                     }
1138                 }
1139 #ifdef DEBUG
1140                 LogMessage("Parent waiting for child...\n");
1141 #endif
1142 
1143                 sleep(1);
1144             }
1145 
1146             LogMessage("Daemon parent exiting\n");
1147 
1148             exit(exit_val);                /* parent */
1149         }
1150 
1151         if(fs < 0)
1152         {
1153             /* Daemonizing failed... */
1154             perror("fork");
1155             exit(1);
1156         }
1157 
1158         /* Child */
1159         setsid();
1160     }
1161 
1162     close(0);
1163     close(1);
1164     close(2);
1165 
1166 #ifdef DEBUG
1167     /* redirect stdin/stdout/stderr to a file */
1168     open("/tmp/barnyard2.debug", O_CREAT | O_RDWR);  /* stdin, fd 0 */
1169 
1170     /* Change ownership to that which we will drop privileges to */
1171     if ((barnyard2_conf->user_id != -1) || (barnyard2_conf->group_id != -1))
1172     {
1173         uid_t user_id = getuid();
1174         gid_t group_id = getgid();
1175 
1176         if (barnyard2_conf->user_id != -1)
1177             user_id = barnyard2_conf->user_id;
1178         if (barnyard2_conf->group_id != -1)
1179             group_id = barnyard2_conf->group_id;
1180 
1181         chown("/tmp/barnyard2.debug", user_id, group_id);
1182     }
1183 #else
1184     /* redirect stdin/stdout/stderr to /dev/null */
1185     (void)open("/dev/null", O_RDWR);  /* stdin, fd 0 */
1186 #endif
1187 
1188     ret = dup(0);  /* stdout, fd 0 => fd 1 */
1189     ret = dup(0);  /* stderr, fd 0 => fd 2 */
1190 
1191     SignalWaitingParent();
1192 #endif /* ! WIN32 */
1193 }
1194 
1195 /* Signal the parent that child is ready */
SignalWaitingParent(void)1196 void SignalWaitingParent(void)
1197 {
1198 #ifndef WIN32
1199     pid_t parentpid = getppid();
1200 #ifdef DEBUG
1201     LogMessage("Signaling parent %d from child %d\n", parentpid, getpid());
1202 #endif
1203 
1204     if (kill(parentpid, SIGNAL_SNORT_CHILD_READY))
1205     {
1206         LogMessage("Daemon initialized, failed to signal parent pid: %d, failure: %d, %s\n", parentpid, errno, strerror(errno));
1207     }
1208     else
1209     {
1210         LogMessage("Daemon initialized, signaled parent pid: %d\n", parentpid);
1211     }
1212 #endif
1213 }
1214 
1215 /* Self preserving memory allocator */
SPAlloc(unsigned long size,struct _SPMemControl * spmc)1216 void *SPAlloc(unsigned long size, struct _SPMemControl *spmc)
1217 {
1218     void *tmp;
1219 
1220     spmc->mem_usage += size;
1221 
1222     if(spmc->mem_usage > spmc->memcap)
1223     {
1224         spmc->sp_func(spmc);
1225     }
1226 
1227     tmp = (void *) calloc(size, sizeof(char));
1228 
1229     if(tmp == NULL)
1230     {
1231         FatalError("Unable to allocate memory!  (%lu requested, %lu in use)\n",
1232                 size, spmc->mem_usage);
1233     }
1234 
1235     return tmp;
1236 }
1237 
1238 /* Guaranteed to be '\0' terminated even if truncation occurs.
1239  *
1240  * returns  SNORT_SNPRINTF_SUCCESS if successful
1241  * returns  SNORT_SNPRINTF_TRUNCATION on truncation
1242  * returns  SNORT_SNPRINTF_ERROR on error
1243  */
SnortSnprintf(char * buf,size_t buf_size,const char * format,...)1244 int SnortSnprintf(char *buf, size_t buf_size, const char *format, ...)
1245 {
1246     va_list ap;
1247     int ret;
1248 
1249     if (buf == NULL || buf_size <= 0 || format == NULL)
1250         return SNORT_SNPRINTF_ERROR;
1251 
1252     /* zero first byte in case an error occurs with
1253      * vsnprintf, so buffer is null terminated with
1254      * zero length */
1255     buf[0] = '\0';
1256     buf[buf_size - 1] = '\0';
1257 
1258     va_start(ap, format);
1259 
1260     ret = vsnprintf(buf, buf_size, format, ap);
1261 
1262     va_end(ap);
1263 
1264     if (ret < 0)
1265         return SNORT_SNPRINTF_ERROR;
1266 
1267     if (buf[buf_size - 1] != '\0' || (size_t)ret >= buf_size)
1268     {
1269         /* result was truncated */
1270         buf[buf_size - 1] = '\0';
1271         return SNORT_SNPRINTF_TRUNCATION;
1272     }
1273 
1274     return SNORT_SNPRINTF_SUCCESS;
1275 }
1276 
1277 /* Appends to a given string
1278  * Guaranteed to be '\0' terminated even if truncation occurs.
1279  *
1280  * returns SNORT_SNPRINTF_SUCCESS if successful
1281  * returns SNORT_SNPRINTF_TRUNCATION on truncation
1282  * returns SNORT_SNPRINTF_ERROR on error
1283  */
SnortSnprintfAppend(char * buf,size_t buf_size,const char * format,...)1284 int SnortSnprintfAppend(char *buf, size_t buf_size, const char *format, ...)
1285 {
1286     int str_len;
1287     int ret;
1288     va_list ap;
1289 
1290     if (buf == NULL || buf_size <= 0 || format == NULL)
1291         return SNORT_SNPRINTF_ERROR;
1292 
1293     str_len = SnortStrnlen(buf, buf_size);
1294 
1295     /* since we've already checked buf and buf_size an error
1296      * indicates no null termination, so just start at
1297      * beginning of buffer */
1298     if (str_len == SNORT_STRNLEN_ERROR)
1299     {
1300         buf[0] = '\0';
1301         str_len = 0;
1302     }
1303 
1304     buf[buf_size - 1] = '\0';
1305 
1306     va_start(ap, format);
1307 
1308     ret = vsnprintf(buf + str_len, buf_size - (size_t)str_len, format, ap);
1309 
1310     va_end(ap);
1311 
1312     if (ret < 0)
1313         return SNORT_SNPRINTF_ERROR;
1314 
1315     if (buf[buf_size - 1] != '\0' || (size_t)ret >= buf_size)
1316     {
1317         /* truncation occured */
1318         buf[buf_size - 1] = '\0';
1319         return SNORT_SNPRINTF_TRUNCATION;
1320     }
1321 
1322     return SNORT_SNPRINTF_SUCCESS;
1323 }
1324 
1325 /* Guaranteed to be '\0' terminated even if truncation occurs.
1326  *
1327  * Arguments:  dst - the string to contain the copy
1328  *             src - the string to copy from
1329  *             dst_size - the size of the destination buffer
1330  *                        including the null byte.
1331  *
1332  * returns SNORT_STRNCPY_SUCCESS if successful
1333  * returns SNORT_STRNCPY_TRUNCATION on truncation
1334  * returns SNORT_STRNCPY_ERROR on error
1335  *
1336  * Note: Do not set dst[0] = '\0' on error since it's possible that
1337  * dst and src are the same pointer - it will at least be null
1338  * terminated in any case
1339  */
SnortStrncpy(char * dst,const char * src,size_t dst_size)1340 int SnortStrncpy(char *dst, const char *src, size_t dst_size)
1341 {
1342     char *ret = NULL;
1343 
1344     if (dst == NULL || src == NULL || dst_size <= 0)
1345         return SNORT_STRNCPY_ERROR;
1346 
1347     dst[dst_size - 1] = '\0';
1348 
1349     ret = strncpy(dst, src, dst_size);
1350 
1351     /* Not sure if this ever happens but might as
1352      * well be on the safe side */
1353     if (ret == NULL)
1354         return SNORT_STRNCPY_ERROR;
1355 
1356     if (dst[dst_size - 1] != '\0')
1357     {
1358         /* result was truncated */
1359         dst[dst_size - 1] = '\0';
1360         return SNORT_STRNCPY_TRUNCATION;
1361     }
1362 
1363     return SNORT_STRNCPY_SUCCESS;
1364 }
1365 
SnortStrndup(const char * src,size_t dst_size)1366 char *SnortStrndup(const char *src, size_t dst_size)
1367 {
1368 	char *ret = SnortAlloc(dst_size + 1);
1369     int ret_val;
1370 
1371 	ret_val = SnortStrncpy(ret, src, dst_size + 1);
1372 
1373     if(ret_val == SNORT_STRNCPY_ERROR)
1374 	{
1375 		free(ret);
1376 		return NULL;
1377 	}
1378 
1379 	return ret;
1380 }
1381 
1382 /* Determines whether a buffer is '\0' terminated and returns the
1383  * string length if so
1384  *
1385  * returns the string length if '\0' terminated
1386  * returns SNORT_STRNLEN_ERROR if not '\0' terminated
1387  */
SnortStrnlen(const char * buf,int buf_size)1388 int SnortStrnlen(const char *buf, int buf_size)
1389 {
1390     int i = 0;
1391 
1392     if (buf == NULL || buf_size <= 0)
1393         return SNORT_STRNLEN_ERROR;
1394 
1395     for (i = 0; i < buf_size; i++)
1396     {
1397         if (buf[i] == '\0')
1398             break;
1399     }
1400 
1401     if (i == buf_size)
1402         return SNORT_STRNLEN_ERROR;
1403 
1404     return i;
1405 }
1406 
SnortStrdup(const char * str)1407 char * SnortStrdup(const char *str)
1408 {
1409     char *copy = NULL;
1410 
1411     if (!str)
1412     {
1413         FatalError("Unable to duplicate string: NULL!\n");
1414     }
1415 
1416     copy = strdup(str);
1417 
1418     if (copy == NULL)
1419     {
1420         FatalError("Unable to duplicate string: %s!\n", str);
1421     }
1422 
1423     return copy;
1424 }
1425 
1426 /*
1427  * Find first occurrence of char of accept in s, limited by slen.
1428  * A 'safe' version of strpbrk that won't read past end of buffer s
1429  * in cases that s is not NULL terminated.
1430  *
1431  * This code assumes 'accept' is a static string.
1432  */
SnortStrnPbrk(const char * s,int slen,const char * accept)1433 const char *SnortStrnPbrk(const char *s, int slen, const char *accept)
1434 {
1435     char ch;
1436     const char *s_end;
1437     if (!s || !*s || !accept || slen == 0)
1438         return NULL;
1439 
1440     s_end = s + slen;
1441     while (s < s_end)
1442     {
1443         ch = *s;
1444         if (strchr(accept, ch))
1445             return s;
1446         s++;
1447     }
1448     return NULL;
1449 }
1450 
1451 /*
1452  * Find first occurrence of searchstr in s, limited by slen.
1453  * A 'safe' version of strstr that won't read past end of buffer s
1454  * in cases that s is not NULL terminated.
1455  */
SnortStrnStr(const char * s,int slen,const char * searchstr)1456 const char *SnortStrnStr(const char *s, int slen, const char *searchstr)
1457 {
1458     char ch, nc;
1459     int len;
1460     if (!s || !*s || !searchstr || slen == 0)
1461         return NULL;
1462 
1463     if ((ch = *searchstr++) != 0)
1464     {
1465         len = strlen(searchstr);
1466         do
1467         {
1468             do
1469             {
1470                 if ((nc = *s++) == 0)
1471                 {
1472                     return NULL;
1473                 }
1474                 slen--;
1475                 if (slen == 0)
1476                     return NULL;
1477             } while (nc != ch);
1478             if (slen - len < 0)
1479                 return NULL;
1480         } while (memcmp(s, searchstr, len) != 0);
1481         s--;
1482         slen++;
1483     }
1484     return s;
1485 }
1486 
1487 /*
1488  * Find first occurrence of substring in s, ignore case.
1489 */
SnortStrcasestr(const char * s,const char * substr)1490 const char *SnortStrcasestr(const char *s, const char *substr)
1491 {
1492     char ch, nc;
1493     int len;
1494 
1495     if (!s || !*s || !substr)
1496         return NULL;
1497 
1498     if ((ch = *substr++) != 0)
1499     {
1500         ch = tolower((char)ch);
1501         len = strlen(substr);
1502         do
1503         {
1504             do
1505             {
1506                 if ((nc = *s++) == 0)
1507                 {
1508                     return NULL;
1509                 }
1510             } while ((char)tolower((uint8_t)nc) != ch);
1511         } while (strncasecmp(s, substr, len) != 0);
1512         s--;
1513     }
1514     return s;
1515 }
1516 
SnortAlloc(unsigned long size)1517 void *SnortAlloc(unsigned long size)
1518 {
1519     void *tmp;
1520 
1521     tmp = (void *) calloc(size, sizeof(char));
1522 
1523     if(tmp == NULL)
1524     {
1525         FatalError("Unable to allocate memory!  (%lu requested)\n", size);
1526     }
1527 
1528     return tmp;
1529 }
1530 
SnortAlloc2(size_t size,const char * format,...)1531 void * SnortAlloc2(size_t size, const char *format, ...)
1532 {
1533     void *tmp;
1534 
1535     tmp = (void *)calloc(size, sizeof(char));
1536 
1537     if(tmp == NULL)
1538     {
1539         va_list ap;
1540         char buf[STD_BUF];
1541 
1542         buf[STD_BUF - 1] = '\0';
1543 
1544         va_start(ap, format);
1545 
1546         vsnprintf(buf, STD_BUF - 1, format, ap);
1547 
1548         va_end(ap);
1549 
1550         FatalError("%s", buf);
1551     }
1552 
1553     return tmp;
1554 }
1555 
1556 /**
1557  * Chroot and adjust the barnyard2_conf->log_dir reference
1558  *
1559  * @param directory directory to chroot to
1560  * @param logstore ptr to barnyard2_conf->log_dir which must be dynamically allocated
1561  */
SetChroot(char * directory,char ** logstore)1562 void SetChroot(char *directory, char **logstore)
1563 {
1564 #ifdef WIN32
1565     FatalError("SetChroot() should not be called under Win32!\n");
1566 #else
1567     char *absdir;
1568     size_t abslen;
1569     char *logdir;
1570 
1571     if(!directory || !logstore)
1572     {
1573         FatalError("Null parameter passed\n");
1574     }
1575 
1576     logdir = *logstore;
1577 
1578     if(logdir == NULL || *logdir == '\0')
1579     {
1580         FatalError("Null log directory\n");
1581     }
1582 
1583     DEBUG_WRAP(DebugMessage(DEBUG_INIT,"SetChroot: %s\n",
1584                                        CurrentWorkingDir()););
1585 
1586     logdir = GetAbsolutePath(logdir);
1587 
1588     DEBUG_WRAP(DebugMessage(DEBUG_INIT, "SetChroot: %s\n",
1589                                        CurrentWorkingDir()));
1590 
1591     logdir = SnortStrdup(logdir);
1592 
1593     /* We're going to reset logstore, so free it now */
1594     free(*logstore);
1595     *logstore = NULL;
1596 
1597     /* change to the directory */
1598     if(chdir(directory) != 0)
1599     {
1600         FatalError("SetChroot: Can not chdir to \"%s\": %s\n", directory,
1601                    strerror(errno));
1602     }
1603 
1604     /* always returns an absolute pathname */
1605     absdir = CurrentWorkingDir();
1606 
1607     if(absdir == NULL)
1608     {
1609         FatalError("NULL Chroot found\n");
1610     }
1611 
1612     abslen = strlen(absdir);
1613 
1614     DEBUG_WRAP(DebugMessage(DEBUG_INIT, "ABS: %s %d\n", absdir, abslen););
1615 
1616     /* make the chroot call */
1617     if(chroot(absdir) < 0)
1618     {
1619         FatalError("Can not chroot to \"%s\": absolute: %s: %s\n",
1620                    directory, absdir, strerror(errno));
1621     }
1622 
1623     DEBUG_WRAP(DebugMessage(DEBUG_INIT,"chroot success (%s ->", absdir););
1624     DEBUG_WRAP(DebugMessage(DEBUG_INIT,"%s)\n ", CurrentWorkingDir()););
1625 
1626     /* change to "/" in the new directory */
1627     if(chdir("/") < 0)
1628     {
1629         FatalError("Can not chdir to \"/\" after chroot: %s\n",
1630                    strerror(errno));
1631     }
1632 
1633     DEBUG_WRAP(DebugMessage(DEBUG_INIT,"chdir success (%s)\n",
1634                             CurrentWorkingDir()););
1635 
1636 
1637     if(strncmp(absdir, logdir, strlen(absdir)))
1638     {
1639         FatalError("Absdir is not a subset of the logdir");
1640     }
1641 
1642     if(abslen >= strlen(logdir))
1643     {
1644         *logstore = SnortStrdup("/");
1645     }
1646     else
1647     {
1648         *logstore = SnortStrdup(logdir + abslen);
1649     }
1650 
1651     DEBUG_WRAP(DebugMessage(DEBUG_INIT,"new logdir from %s to %s\n",
1652                             logdir, *logstore));
1653 
1654     LogMessage("Chroot directory = %s\n", directory);
1655 
1656 #if 0
1657     /* XXX XXX */
1658     /* install the I can't do this signal handler */
1659     signal(SIGHUP, SigCantHupHandler);
1660 #endif
1661 #endif /* !WIN32 */
1662 }
1663 
1664 
1665 /**
1666  * Return a ptr to the absolute pathname of snort.  This memory must
1667  * be copied to another region if you wish to save it for later use.
1668  */
CurrentWorkingDir(void)1669 char *CurrentWorkingDir(void)
1670 {
1671     static char buf[PATH_MAX_UTIL + 1];
1672 
1673     if(getcwd((char *) buf, PATH_MAX_UTIL) == NULL)
1674     {
1675         return NULL;
1676     }
1677 
1678     buf[PATH_MAX_UTIL] = '\0';
1679 
1680     return (char *) buf;
1681 }
1682 
1683 /**
1684  * Given a directory name, return a ptr to a static
1685  */
GetAbsolutePath(char * dir)1686 char *GetAbsolutePath(char *dir)
1687 {
1688     char *savedir, *dirp;
1689     static char buf[PATH_MAX_UTIL + 1];
1690 
1691     if(dir == NULL)
1692     {
1693         return NULL;
1694     }
1695 
1696     savedir = strdup(CurrentWorkingDir());
1697 
1698     if(savedir == NULL)
1699     {
1700         return NULL;
1701     }
1702 
1703     if(chdir(dir) < 0)
1704     {
1705         LogMessage("Can't change to directory: %s\n", dir);
1706         free(savedir);
1707         return NULL;
1708     }
1709 
1710     dirp = CurrentWorkingDir();
1711 
1712     if(dirp == NULL)
1713     {
1714         LogMessage("Unable to access current directory\n");
1715         free(savedir);
1716         return NULL;
1717     }
1718     else
1719     {
1720         strncpy(buf, dirp, PATH_MAX_UTIL);
1721         buf[PATH_MAX_UTIL] = '\0';
1722     }
1723 
1724     if(chdir(savedir) < 0)
1725     {
1726         LogMessage("Can't change back to directory: %s\n", dir);
1727         free(savedir);
1728         return NULL;
1729     }
1730 
1731     free(savedir);
1732     return (char *) buf;
1733 }
1734 
String2Long(char * string,long * result)1735 int String2Long(char *string, long *result)
1736 {
1737     long value;
1738     char *endptr;
1739     if(!string)
1740         return -1;
1741 
1742     value = strtol(string, &endptr, 10);
1743 
1744     while(isspace(*endptr))
1745         endptr++;
1746 
1747     if(*endptr != '\0')
1748         return -1;
1749 
1750     if(result)
1751         *result = value;
1752 
1753     return 0;
1754 }
1755 
String2ULong(char * string,unsigned long * result)1756 int String2ULong(char *string, unsigned long *result)
1757 {
1758     unsigned long value;
1759     char *endptr;
1760 
1761     if(!string)
1762         return -1;
1763 
1764     value = strtoul(string, &endptr, 10);
1765 
1766     while(isspace(*endptr))
1767         endptr++;
1768 
1769     if(*endptr != '\0')
1770         return -1;
1771 
1772     if(result)
1773         *result = value;
1774 
1775     return 0;
1776 }
1777 
Move(const char * source,const char * dest)1778 int Move(const char *source, const char *dest)
1779 {
1780     if(link(source, dest) != 0)
1781     {
1782         if(errno == EXDEV || errno == EPERM)
1783         {
1784             /* can't hardlink, do it the hard way */
1785             char *command;
1786             size_t command_len;
1787             command_len = strlen("mv") + 1 + strlen(source) + 1 + strlen(dest);
1788             command = (char *)SnortAlloc(command_len + 1);
1789             snprintf(command, command_len + 1, "mv %s %s", source, dest);
1790             if(system(command) != 0)
1791             {
1792                 LogMessage("Failed to archive file \"%s\" to \"%s\": %s",
1793                         source, dest, strerror(errno));
1794             }
1795             free(command);
1796         }
1797         LogMessage("Failed to archive file \"%s\" to \"%s\": %s",
1798                 source, dest, strerror(errno));
1799     }
1800     else
1801     {
1802         if (unlink(source) != 0) { /* oops, unlink/remove has failed */
1803 		LogMessage("Failed to unlink \"%s\": %s",
1804 			source, strerror(errno));
1805 	}
1806     }
1807     return 0;
1808 }
1809 
ArchiveFile(const char * filepath,const char * archive_dir)1810 int ArchiveFile(const char *filepath, const char *archive_dir)
1811 {
1812     char *dest;
1813     size_t dest_len;
1814     if(!filepath || !archive_dir)
1815         return -1;  /* Invalid argument */
1816 
1817     /* Archive the file */
1818     dest_len = strlen(archive_dir) + 1 + strlen(strrchr(filepath, '/') + 1);
1819     dest = (char *)SnortAlloc(dest_len + 1);
1820     snprintf(dest, dest_len + 1, "%s/%s", archive_dir,
1821             strrchr(filepath, '/') + 1);
1822 
1823     Move(filepath, dest);
1824     free(dest);
1825     return 0;
1826 }
1827 
1828 /****************************************************************************
1829  *
1830  * Function: GetUniqueName(char * iface)
1831  *
1832  * Purpose: To return a string that has a high probability of being unique
1833  *          for a given sensor.
1834  *
1835  * Arguments: char * iface - The network interface you are sniffing
1836  *
1837  * Returns: A char * -- its a static char * so you should not free it
1838  *
1839  ***************************************************************************/
GetUniqueName(char * iface)1840 char *GetUniqueName(char * iface)
1841 {
1842     char * rptr;
1843     static char uniq_name[256];
1844 
1845     if (iface == NULL) LogMessage("Interface is NULL. Name may not be unique for the host\n");
1846 	if (iface != NULL)
1847 	{
1848 		SnortSnprintf(uniq_name, 255, "%s:%s\n",GetHostname(), iface);
1849 	}
1850 	else
1851 	{
1852 	    SnortSnprintf(uniq_name, 255, "%s\n", GetHostname());
1853     }
1854 
1855     rptr = uniq_name;
1856 
1857     if (BcLogVerbose()) LogMessage("Node unique name is: %s\n", rptr);
1858     return rptr;
1859 }
1860 
1861 /****************************************************************************
1862  *
1863  * Function: GetHostname()
1864  *
1865  * Purpose: To return a string representing the hostname
1866  *
1867  * Arguments: None
1868  *
1869  * Returns: A static char * representing the hostname.
1870  *
1871  ***************************************************************************/
GetHostname()1872 char *GetHostname()
1873 {
1874 #ifdef WIN32
1875     DWORD bufflen = 256;
1876     static char buff[256];
1877     GetComputerName(buff, &bufflen);
1878     return buff;
1879 #else
1880     char				*error = "unknown";
1881 	static char			hostname[255];
1882 
1883 	if (barnyard2_conf->hostname)
1884 		return barnyard2_conf->hostname;
1885 	else if (gethostname(hostname, 255) == 0)
1886 		return hostname;
1887     else if(getenv("HOSTNAME"))
1888 		return getenv("HOSTNAME");
1889     else if(getenv("HOST"))
1890 		return getenv("HOST");
1891     else
1892 		return error;
1893 #endif
1894 }
1895 
1896 /****************************************************************************
1897  *
1898  * Function: GetTimestamp(register const struct timeval *tvp, int tz)
1899  *
1900  * Purpose: Get an ISO-8601 formatted timestamp for tvp within the tz
1901  *          timezone.
1902  *
1903  * Arguments: sec is time in seconds.
1904  *            usec is microsecond component.
1905  *            tz is a timezone.
1906  *
1907  * Returns: char * -- You must free this char * when you are done with it.
1908  *
1909  ***************************************************************************/
GetTimestampByComponent(uint32_t sec,uint32_t usec,int tz)1910 char *GetTimestampByComponent(uint32_t sec, uint32_t usec, int tz)
1911 {
1912     struct tm			*lt;  /* localtime */
1913     char				*buf;
1914     time_t				Time;
1915     int					msec;
1916 
1917     buf = (char *)SnortAlloc(SMALLBUFFER * sizeof(char));
1918 
1919     Time = sec;
1920     msec = usec / 1000;
1921 
1922     if (BcOutputUseUtc())
1923     {
1924 	lt = gmtime(&Time);
1925         SnortSnprintf(buf, SMALLBUFFER,
1926 		      "%04i-%02i-%02i %02i:%02i:%02i.%03i",
1927 		      1900 + lt->tm_year, lt->tm_mon + 1, lt->tm_mday,
1928 		      lt->tm_hour, lt->tm_min, lt->tm_sec, msec);
1929     }
1930     else
1931     {
1932 	lt = localtime(&Time);
1933         SnortSnprintf(buf, SMALLBUFFER,
1934 		      "%04i-%02i-%02i %02i:%02i:%02i.%03i+%03i",
1935 		      1900 + lt->tm_year, lt->tm_mon + 1, lt->tm_mday,
1936 		      lt->tm_hour, lt->tm_min, lt->tm_sec, msec, tz);
1937     }
1938 
1939     return buf;
1940 }
1941 
1942 /* Same a above using a static buffer */
GetTimestampByComponent_STATIC(uint32_t sec,uint32_t usec,int tz,char * buf)1943 u_int32_t GetTimestampByComponent_STATIC(uint32_t sec, uint32_t usec, int tz,char *buf)
1944 {
1945     struct tm                   *lt;  /* localtime */
1946     time_t                              Time;
1947     int                                 msec;
1948 
1949     if(buf == NULL)
1950     {
1951 	/* XXX */
1952 	return 1;
1953     }
1954 
1955     Time = sec;
1956     msec = usec / 1000;
1957 
1958     if (BcOutputUseUtc())
1959     {
1960         lt = gmtime(&Time);
1961         SnortSnprintf(buf, SMALLBUFFER,
1962                       "%04i-%02i-%02i %02i:%02i:%02i.%03i",
1963                       1900 + lt->tm_year, lt->tm_mon + 1, lt->tm_mday,
1964                       lt->tm_hour, lt->tm_min, lt->tm_sec, msec);
1965     }
1966     else
1967     {
1968         lt = localtime(&Time);
1969         SnortSnprintf(buf, SMALLBUFFER,
1970                       "%04i-%02i-%02i %02i:%02i:%02i.%03i+%03i",
1971                       1900 + lt->tm_year, lt->tm_mon + 1, lt->tm_mday,
1972                       lt->tm_hour, lt->tm_min, lt->tm_sec, msec, tz);
1973     }
1974 
1975     return 0;
1976 }
1977 
1978 
1979 /****************************************************************************
1980  *
1981  * Function: GetTimestampByStruct(register const struct timeval *tvp, int tz)
1982  *
1983  * Purpose: Get an ISO-8601 formatted timestamp for tvp within the tz
1984  *          timezone.
1985  *
1986  * Arguments: tvp is a timeval pointer. tz is a timezone.
1987  *
1988  * Returns: char * -- You must free this char * when you are done with it.
1989  *
1990  ***************************************************************************/
GetTimestampByStruct(register const struct timeval * tvp,int tz)1991 char *GetTimestampByStruct(register const struct timeval *tvp, int tz)
1992 {
1993     struct tm *lt;  /* localtime */
1994     char * buf;
1995     int msec;
1996 
1997     buf = (char *)SnortAlloc(SMALLBUFFER * sizeof(char));
1998 
1999     msec = tvp->tv_usec / 1000;
2000 
2001     if (BcOutputUseUtc())
2002     {
2003         lt = gmtime((time_t *)&tvp->tv_sec);
2004         SnortSnprintf(buf, SMALLBUFFER, "%04i-%02i-%02i %02i:%02i:%02i.%03i",
2005                 1900 + lt->tm_year, lt->tm_mon + 1, lt->tm_mday,
2006                 lt->tm_hour, lt->tm_min, lt->tm_sec, msec);
2007     }
2008     else
2009     {
2010         lt = localtime((time_t *)&tvp->tv_sec);
2011         SnortSnprintf(buf, SMALLBUFFER,
2012                 "%04i-%02i-%02i %02i:%02i:%02i.%03i+%03i",
2013                 1900 + lt->tm_year, lt->tm_mon + 1, lt->tm_mday,
2014                 lt->tm_hour, lt->tm_min, lt->tm_sec, msec, tz);
2015     }
2016 
2017     return buf;
2018 }
2019 
2020 
2021 /* Same as above using static buffer */
GetTimestampByStruct_STATIC(register const struct timeval * tvp,int tz,char * buf)2022 u_int32_t GetTimestampByStruct_STATIC(register const struct timeval *tvp, int tz,char *buf)
2023 {
2024     struct tm *lt;  /* localtime */
2025     int msec;
2026 
2027     if(buf == NULL)
2028     {
2029 	/* XXX */
2030 	return 1;
2031     }
2032 
2033     msec = tvp->tv_usec / 1000;
2034 
2035     if (BcOutputUseUtc())
2036     {
2037         lt = gmtime((time_t *)&tvp->tv_sec);
2038         SnortSnprintf(buf, SMALLBUFFER, "%04i-%02i-%02i %02i:%02i:%02i.%03i",
2039 		      1900 + lt->tm_year, lt->tm_mon + 1, lt->tm_mday,
2040 		      lt->tm_hour, lt->tm_min, lt->tm_sec, msec);
2041     }
2042     else
2043     {
2044         lt = localtime((time_t *)&tvp->tv_sec);
2045         SnortSnprintf(buf, SMALLBUFFER,
2046 		      "%04i-%02i-%02i %02i:%02i:%02i.%03i+%03i",
2047 		      1900 + lt->tm_year, lt->tm_mon + 1, lt->tm_mday,
2048 		      lt->tm_hour, lt->tm_min, lt->tm_sec, msec, tz);
2049     }
2050 
2051     return 0;
2052 }
2053 
2054 
2055 /****************************************************************************
2056  *
2057  * Function: GetLocalTimezone()
2058  *
2059  * Purpose: Find the offset from GMT for current host
2060  *
2061  * Arguments: none
2062  *
2063  * Returns: int representing the offset from GMT
2064  *
2065  ***************************************************************************/
GetLocalTimezone()2066 int GetLocalTimezone()
2067 {
2068     time_t      ut;
2069     struct tm * ltm;
2070     long        seconds_away_from_utc;
2071 
2072     time(&ut);
2073     ltm = localtime(&ut);
2074 
2075 #if defined(WIN32) || defined(SOLARIS) || defined(AIX) || defined(HPUX) ||\
2076     defined(__CYGWIN__) || defined( __CYGWIN64__) || defined(__CYGWIN__)
2077     /* localtime() sets the global timezone variable,
2078        which is defined in <time.h> */
2079     seconds_away_from_utc = timezone;
2080 #else
2081     seconds_away_from_utc = ltm->tm_gmtoff;
2082 #endif
2083 
2084     return  seconds_away_from_utc/3600;
2085 }
2086 
2087 /****************************************************************************
2088  *
2089  * Function: GetCurrentTimestamp()
2090  *
2091  * Purpose: Generate an ISO-8601 formatted timestamp for the current time.
2092  *
2093  * Arguments: none
2094  *
2095  * Returns: char * -- You must free this char * when you are done with it.
2096  *
2097  ***************************************************************************/
GetCurrentTimestamp(void)2098 char *GetCurrentTimestamp(void)
2099 {
2100     struct tm *lt;
2101     struct timezone tz;
2102     struct timeval tv;
2103     struct timeval *tvp;
2104     char * buf;
2105     int tzone;
2106     int msec;
2107 
2108     buf = (char *)SnortAlloc(SMALLBUFFER * sizeof(char));
2109 
2110     memset((char *)&tz, 0, sizeof(tz)); /* bzero() deprecated, replaced by memset() */
2111     gettimeofday(&tv,&tz);
2112     tvp = &tv;
2113 
2114     msec = tvp->tv_usec/1000;
2115 
2116     if (BcOutputUseUtc())
2117     {
2118         lt = gmtime((time_t *)&tvp->tv_sec);
2119         SnortSnprintf(buf, SMALLBUFFER, "%04i-%02i-%02i %02i:%02i:%02i.%03i",
2120                 1900 + lt->tm_year, lt->tm_mon + 1, lt->tm_mday,
2121                 lt->tm_hour, lt->tm_min, lt->tm_sec, msec);
2122     }
2123     else
2124     {
2125         lt = localtime((time_t *)&tvp->tv_sec);
2126 
2127         tzone = GetLocalTimezone();
2128 
2129         SnortSnprintf(buf, SMALLBUFFER,
2130                 "%04i-%02i-%02i %02i:%02i:%02i.%03i+%03i",
2131                 1900 + lt->tm_year, lt->tm_mon + 1, lt->tm_mday,
2132                 lt->tm_hour, lt->tm_min, lt->tm_sec, msec, tzone);
2133     }
2134 
2135     return buf;
2136 }
2137 
2138 /* Same as above using static */
GetCurrentTimestamp_STATIC(char * buf)2139 u_int32_t GetCurrentTimestamp_STATIC(char *buf)
2140 {
2141     struct tm *lt;
2142     struct timezone tz;
2143     struct timeval tv;
2144     struct timeval *tvp;
2145     int tzone;
2146     int msec;
2147 
2148     if(buf == NULL)
2149     {
2150 	/* XXX */
2151 	return 1;
2152     }
2153 
2154 
2155     bzero((char *)&tz,sizeof(tz));
2156     gettimeofday(&tv,&tz);
2157     tvp = &tv;
2158 
2159     msec = tvp->tv_usec/1000;
2160 
2161     if (BcOutputUseUtc())
2162     {
2163         lt = gmtime((time_t *)&tvp->tv_sec);
2164         SnortSnprintf(buf, SMALLBUFFER, "%04i-%02i-%02i %02i:%02i:%02i.%03i",
2165 		      1900 + lt->tm_year, lt->tm_mon + 1, lt->tm_mday,
2166 		      lt->tm_hour, lt->tm_min, lt->tm_sec, msec);
2167     }
2168     else
2169     {
2170         lt = localtime((time_t *)&tvp->tv_sec);
2171 
2172         tzone = GetLocalTimezone();
2173 
2174         SnortSnprintf(buf, SMALLBUFFER,
2175 		      "%04i-%02i-%02i %02i:%02i:%02i.%03i+%03i",
2176 		      1900 + lt->tm_year, lt->tm_mon + 1, lt->tm_mday,
2177 		      lt->tm_hour, lt->tm_min, lt->tm_sec, msec, tzone);
2178     }
2179 
2180     return 0;
2181 }
2182 
2183 
2184 
2185 
2186 /****************************************************************************
2187  * Function: base64(char * xdata, int length)
2188  *
2189  * Purpose: Insert data into the database
2190  *
2191  * Arguments: xdata  => pointer to data to base64 encode
2192  *            length => how much data to encode
2193  *
2194  * Make sure you allocate memory for the output before you pass
2195  * the output pointer into this function. You should allocate
2196  * (1.5 * length) bytes to be safe.
2197  *
2198  * Returns: data base64 encoded as a char *
2199  *
2200  ***************************************************************************/
base64(const u_char * xdata,int length)2201 char * base64(const u_char * xdata, int length)
2202 {
2203     int count, cols, bits, c, char_count;
2204     unsigned char alpha[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";  /* 64 bytes */
2205     char * payloadptr;
2206     char * output;
2207     char_count = 0;
2208     bits = 0;
2209     cols = 0;
2210 
2211     output = (char *)SnortAlloc( ((unsigned int) (length * 1.5 + 4)) * sizeof(char) );
2212 
2213     payloadptr = output;
2214 
2215     for(count = 0; count < length; count++)
2216     {
2217         c = xdata[count];
2218 
2219         if(c > 255)
2220         {
2221             ErrorMessage("plugbase.c->base64(): encountered char > 255 (decimal %d)\n If you see this error message a char is more than one byte on your machine\n This means your base64 results can not be trusted", c);
2222         }
2223 
2224         bits += c;
2225         char_count++;
2226 
2227         if(char_count == 3)
2228         {
2229             *output = alpha[bits >> 18]; output++;
2230             *output = alpha[(bits >> 12) & 0x3f]; output++;
2231             *output = alpha[(bits >> 6) & 0x3f]; output++;
2232             *output = alpha[bits & 0x3f]; output++;
2233             cols += 4;
2234             if(cols == 72)
2235             {
2236                 *output = '\n'; output++;
2237                 cols = 0;
2238             }
2239             bits = 0;
2240             char_count = 0;
2241         }
2242         else
2243         {
2244             bits <<= 8;
2245         }
2246     }
2247 
2248     if(char_count != 0)
2249     {
2250         bits <<= 16 - (8 * char_count);
2251         *output = alpha[bits >> 18]; output++;
2252         *output = alpha[(bits >> 12) & 0x3f]; output++;
2253         if(char_count == 1)
2254         {
2255             *output = '='; output++;
2256             *output = '='; output++;
2257         }
2258         else
2259         {
2260             *output = alpha[(bits >> 6) & 0x3f];
2261             output++; *output = '=';
2262             output++;
2263         }
2264     }
2265     *output = '\0';
2266     return payloadptr;
2267 }
2268 
2269 /* Same as above but uses a static buffer provided as a 3rd argument to function.. */
base64_STATIC(const u_char * xdata,int length,char * output)2270 u_int32_t base64_STATIC(const u_char * xdata, int length,char *output)
2271 {
2272     int count, cols, bits, c, char_count;
2273     unsigned char alpha[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";  /* 64 bytes */
2274 
2275 
2276     char_count = 0;
2277     bits = 0;
2278     cols = 0;
2279 
2280     if( ((length * 1.5) + 4 ) > MAX_QUERY_LENGTH)
2281     {
2282 	/* XXX */
2283 	return 1;
2284     }
2285 
2286     memset(output,'\0',MAX_QUERY_LENGTH);
2287 
2288 
2289     for(count = 0; count < length; count++)
2290     {
2291         c = xdata[count];
2292 
2293         if(c > 255)
2294         {
2295             ErrorMessage("plugbase.c->base64(): encountered char > 255 (decimal %d)\n If you see this error message a char is more than one byte on your machine\n This means your base64 results can not be trusted", c);
2296         }
2297 
2298         bits += c;
2299         char_count++;
2300 
2301         if(char_count == 3)
2302         {
2303             *output = alpha[bits >> 18]; output++;
2304             *output = alpha[(bits >> 12) & 0x3f]; output++;
2305             *output = alpha[(bits >> 6) & 0x3f]; output++;
2306             *output = alpha[bits & 0x3f]; output++;
2307             cols += 4;
2308             if(cols == 72)
2309             {
2310                 *output = '\n'; output++;
2311                 cols = 0;
2312             }
2313             bits = 0;
2314             char_count = 0;
2315         }
2316         else
2317         {
2318             bits <<= 8;
2319         }
2320     }
2321 
2322     if(char_count != 0)
2323     {
2324         bits <<= 16 - (8 * char_count);
2325         *output = alpha[bits >> 18]; output++;
2326         *output = alpha[(bits >> 12) & 0x3f]; output++;
2327         if(char_count == 1)
2328         {
2329             *output = '='; output++;
2330             *output = '='; output++;
2331         }
2332         else
2333         {
2334             *output = alpha[(bits >> 6) & 0x3f];
2335             output++; *output = '=';
2336             output++;
2337         }
2338     }
2339     *output = '\0';
2340 
2341 
2342     return 0;
2343 }
2344 
2345 
2346 
2347 /****************************************************************************
2348  *
2349  * Function: ascii(u_char *xdata, int length)
2350  *
2351  * Purpose: This function takes takes a buffer "xdata" and its length then
2352  *          returns a string of only the printable ASCII characters.
2353  *
2354  * Arguments: xdata is the buffer, length is the length of the buffer in
2355  *            bytes
2356  *
2357  * Returns: char * -- You must free this char * when you are done with it.
2358  *
2359  ***************************************************************************/
ascii(const u_char * xdata,int length)2360 char *ascii(const u_char *xdata, int length)
2361 {
2362      char *d_ptr, *ret_val;
2363      int i,count = 0;
2364      int size;
2365 
2366      if(xdata == NULL)
2367      {
2368          return NULL;
2369      }
2370 
2371      for(i=0;i<length;i++)
2372      {
2373          if(xdata[i] == '<')
2374              count+=4;              /* &lt; */
2375          else if(xdata[i] == '&')
2376              count+=5;              /* &amp; */
2377          else if(xdata[i] == '>')   /* &gt;  */
2378              count += 4;
2379      }
2380 
2381      size = length + count + 1;
2382      ret_val = (char *) calloc(1,size);
2383 
2384      if(ret_val == NULL)
2385      {
2386          LogMessage("plugbase.c: ascii(): Out of memory, can't log anything!\n");
2387          return NULL;
2388      }
2389 
2390      d_ptr = ret_val;
2391 
2392      for(i=0;i<length;i++)
2393      {
2394          if((xdata[i] > 0x1F) && (xdata[i] < 0x7F))
2395          {
2396              if(xdata[i] == '<')
2397              {
2398                  SnortStrncpy(d_ptr, "&lt;", size - (d_ptr - ret_val));
2399                  d_ptr+=4;
2400              }
2401              else if(xdata[i] == '&')
2402              {
2403                  SnortStrncpy(d_ptr, "&amp;", size - (d_ptr - ret_val));
2404                  d_ptr += 5;
2405              }
2406              else if(xdata[i] == '>')
2407              {
2408                  SnortStrncpy(d_ptr, "&gt;", size - (d_ptr - ret_val));
2409                  d_ptr += 4;
2410              }
2411              else
2412              {
2413                  *d_ptr++ = xdata[i];
2414              }
2415          }
2416          else
2417          {
2418              *d_ptr++ = '.';
2419          }
2420      }
2421 
2422      *d_ptr++ = '\0';
2423 
2424      return ret_val;
2425 }
2426 
2427 /* Same as above but working with a static buffer .. */
ascii_STATIC(const u_char * xdata,int length,char * ret_val)2428 u_int32_t ascii_STATIC(const u_char *xdata, int length,char *ret_val)
2429 {
2430     char *d_ptr;
2431     int i,count = 0;
2432     int size;
2433 
2434     if( (xdata == NULL) ||
2435 	(ret_val == NULL))
2436     {
2437 	return 1;
2438     }
2439 
2440     for(i=0;i<length;i++)
2441     {
2442 	if(xdata[i] == '<')
2443 	    count+=4;              /* &lt; */
2444 	else if(xdata[i] == '&')
2445 	    count+=5;              /* &amp; */
2446 	else if(xdata[i] == '>')   /* &gt;  */
2447 	    count += 4;
2448     }
2449 
2450     size = length + count + 1;
2451 
2452     if(size > MAX_QUERY_LENGTH)
2453     {
2454 	return 1;
2455     }
2456 
2457     memset(ret_val,'\0',MAX_QUERY_LENGTH);
2458 
2459     d_ptr = ret_val;
2460 
2461     for(i=0;i<length;i++)
2462     {
2463 	if((xdata[i] > 0x1F) && (xdata[i] < 0x7F))
2464 	{
2465 	    if(xdata[i] == '<')
2466 	    {
2467 		SnortStrncpy(d_ptr, "&lt;", size - (d_ptr - ret_val));
2468 		d_ptr+=4;
2469 	    }
2470 	    else if(xdata[i] == '&')
2471 	    {
2472 		SnortStrncpy(d_ptr, "&amp;", size - (d_ptr - ret_val));
2473 		d_ptr += 5;
2474 	    }
2475 	    else if(xdata[i] == '>')
2476 	    {
2477 		SnortStrncpy(d_ptr, "&gt;", size - (d_ptr - ret_val));
2478 		d_ptr += 4;
2479 	    }
2480 	    else
2481 	    {
2482 		*d_ptr++ = xdata[i];
2483 	    }
2484 	}
2485 	else
2486 	{
2487 	    *d_ptr++ = '.';
2488 	}
2489     }
2490 
2491     *d_ptr++ = '\0';
2492 
2493     return 0;
2494 
2495 }
2496 
2497 
2498 /****************************************************************************
2499  *
2500  * Function: hex(u_char *xdata, int length)
2501  *
2502  * Purpose: This function takes takes a buffer "xdata" and its length then
2503  *          returns a string of hex with no spaces
2504  *
2505  * Arguments: xdata is the buffer, length is the length of the buffer in
2506  *            bytes
2507  *
2508  * Returns: char * -- You must free this char * when you are done with it.
2509  *
2510  ***************************************************************************/
hex(const u_char * xdata,int length)2511 char *hex(const u_char *xdata, int length)
2512 {
2513     int x;
2514     char *rval = NULL;
2515     char *buf = NULL;
2516 
2517     if (xdata == NULL)
2518         return NULL;
2519 
2520     buf = (char *)calloc((length * 2) + 1, sizeof(char));
2521 
2522     if (buf != NULL)
2523     {
2524         rval = buf;
2525 
2526         for (x = 0; x < length; x++)
2527         {
2528             SnortSnprintf(buf, 3, "%02X", xdata[x]);
2529             buf += 2;
2530         }
2531 
2532         rval[length * 2] = '\0';
2533     }
2534 
2535     return rval;
2536 }
2537 
2538 
2539 
2540 
2541 
fasthex(const u_char * xdata,int length)2542 char *fasthex(const u_char *xdata, int length)
2543 {
2544     char conv[] = "0123456789ABCDEF";
2545     char *retbuf = NULL;
2546     const u_char *index;
2547     const u_char *end;
2548     char *ridx;
2549 
2550     index = xdata;
2551     end = xdata + length;
2552     retbuf = (char *)SnortAlloc(((length * 2) + 1) * sizeof(char));
2553     ridx = retbuf;
2554 
2555     while(index < end)
2556     {
2557         *ridx++ = conv[((*index & 0xFF)>>4)];
2558         *ridx++ = conv[((*index & 0xFF)&0x0F)];
2559         index++;
2560     }
2561 
2562     return retbuf;
2563 }
2564 
2565 /* same as above but working with a static buffer */
fasthex_STATIC(const u_char * xdata,int length,char * retbuf)2566 u_int32_t fasthex_STATIC(const u_char *xdata, int length,char *retbuf)
2567 {
2568     char conv[] = "0123456789ABCDEF";
2569     const u_char *index;
2570     const u_char *end;
2571     char *ridx;
2572 
2573     if( (xdata == NULL) ||
2574 	(retbuf == NULL) ||
2575 	(((length *2) + 1) > MAX_QUERY_LENGTH))
2576     {
2577 	/* XXX */
2578 	return 1;
2579     }
2580 
2581     index = xdata;
2582     end = xdata + length;
2583 
2584     memset(retbuf,'\0',MAX_QUERY_LENGTH);
2585 
2586     ridx = retbuf;
2587 
2588     while(index < end)
2589     {
2590         *ridx++ = conv[((*index & 0xFF)>>4)];
2591         *ridx++ = conv[((*index & 0xFF)&0x0F)];
2592         index++;
2593     }
2594 
2595     return 0;
2596 }
2597 
2598 
2599 /*
2600  *   Fatal Integer Parser
2601  *   Ascii to Integer conversion with fatal error support
2602  */
xatol(const char * s,const char * etext)2603 long int xatol(const char *s , const char *etext)
2604 {
2605     long int val;
2606     char *endptr;
2607     char *default_error = "xatol() error\n";
2608 
2609     if (etext == NULL)
2610         etext = default_error;
2611 
2612     if (s == NULL)
2613         FatalError("%s: String is NULL\n", etext);
2614 
2615     while (isspace((int)*s))
2616         s++;
2617 
2618     if (strlen(s) == 0)
2619         FatalError("%s: String is empty\n", etext);
2620 
2621     errno = 0;
2622 
2623     /*
2624      *  strtoul - errors on win32 : ERANGE (VS 6.0)
2625      *            errors on linux : ERANGE, EINVAL
2626      *               (for EINVAL, unsupported base which won't happen here)
2627      */
2628     val = strtol(s, &endptr, 0);
2629 
2630     if ((errno == ERANGE) || (*endptr != '\0'))
2631         FatalError("%s: Invalid integer input: %s\n", etext, s);
2632 
2633     return val;
2634 }
2635 
2636 /*
2637  *   Fatal Integer Parser
2638  *   Ascii to Integer conversion with fatal error support
2639  */
xatou(const char * s,const char * etext)2640 unsigned long int xatou(const char *s , const char *etext)
2641 {
2642     unsigned long int val;
2643     char *endptr;
2644     char *default_error = "xatou() error\n";
2645 
2646     if (etext == NULL)
2647         etext = default_error;
2648 
2649     if (s == NULL)
2650         FatalError("%s: String is NULL\n", etext);
2651 
2652     while (isspace((int)*s))
2653         s++;
2654 
2655     if (strlen(s) == 0)
2656         FatalError("%s: String is empty\n", etext);
2657 
2658     if (*s == '-')
2659     {
2660         FatalError("%s: Invalid unsigned integer - negative sign found, "
2661                    "input: %s\n", etext, s);
2662     }
2663 
2664     errno = 0;
2665 
2666     /*
2667      *  strtoul - errors on win32 : ERANGE (VS 6.0)
2668      *            errors on linux : ERANGE, EINVAL
2669      */
2670     val = strtoul(s, &endptr, 0);
2671 
2672     if ((errno == ERANGE) || (*endptr != '\0'))
2673         FatalError("%s: Invalid integer input: %s\n", etext, s);
2674 
2675     return val;
2676 }
2677 
xatoup(const char * s,const char * etext)2678 unsigned long int xatoup(const char *s , const char *etext)
2679 {
2680     unsigned long int val = xatou(s, etext);
2681     if ( !val )
2682         FatalError("%s: must be > 0\n", etext);
2683     return val;
2684 }
2685 
2686 
2687 
2688 /*
2689    Tough to be a solution for a issue where it was not needed
2690    but kept if its ever needed.
2691 */
string_sanitize_character(char * input,char ichar)2692 u_int32_t string_sanitize_character(char *input,char ichar)
2693 {
2694     char *cindex = NULL;
2695 
2696     u_int32_t orig_len = 0;
2697     u_int32_t end_len = 0;
2698 
2699     if( (input == NULL) ||
2700 	(ichar == 0x00))
2701     {
2702 	/* XXX */
2703 	return 1;
2704     }
2705 
2706     orig_len = strlen(input) + 1;
2707 
2708     while( (cindex = index(input,ichar)) != NULL)
2709     {
2710 
2711 	if( (end_len = strlen(cindex)) > orig_len)
2712         {
2713 	    /* Could be far fetched ...but who know's...*/
2714 	    /* XXX */
2715 	    return 1;
2716         }
2717 
2718 	memcpy(cindex,cindex+1,strlen((cindex)));
2719 	cindex[end_len] = '\0';
2720 	cindex = NULL;
2721     }
2722 
2723     return 0;
2724 }
2725 
2726 
BY2Strtoul(char * inStr,unsigned long * ul_ptr)2727 int BY2Strtoul(char *inStr,unsigned long *ul_ptr)
2728 {
2729     char *endptr = NULL;
2730 
2731     if( (inStr == NULL) ||
2732         (ul_ptr == NULL))
2733     {
2734         return 1;
2735     }
2736 
2737     *ul_ptr = strtoul(inStr,&endptr,10);
2738 
2739     if ((errno == ERANGE && ( *ul_ptr == LONG_MAX || *ul_ptr == LONG_MIN)) ||
2740         (errno != 0 && *ul_ptr == 0))
2741     {
2742         FatalError("[%s()], strtoul error : [%s] for [%s]\n",
2743                    __FUNCTION__,
2744                    strerror(errno),
2745                    inStr);
2746     }
2747 
2748     if( *endptr != '\0' || (endptr == inStr))
2749     {
2750         LogMessage("[%s()], is not a digit [%s] \n",
2751                    __FUNCTION__,
2752                    inStr);
2753         return 1;
2754     }
2755 
2756     return 0;
2757 }
2758