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; /* < */
2375 else if(xdata[i] == '&')
2376 count+=5; /* & */
2377 else if(xdata[i] == '>') /* > */
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, "<", size - (d_ptr - ret_val));
2399 d_ptr+=4;
2400 }
2401 else if(xdata[i] == '&')
2402 {
2403 SnortStrncpy(d_ptr, "&", size - (d_ptr - ret_val));
2404 d_ptr += 5;
2405 }
2406 else if(xdata[i] == '>')
2407 {
2408 SnortStrncpy(d_ptr, ">", 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; /* < */
2444 else if(xdata[i] == '&')
2445 count+=5; /* & */
2446 else if(xdata[i] == '>') /* > */
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, "<", size - (d_ptr - ret_val));
2468 d_ptr+=4;
2469 }
2470 else if(xdata[i] == '&')
2471 {
2472 SnortStrncpy(d_ptr, "&", size - (d_ptr - ret_val));
2473 d_ptr += 5;
2474 }
2475 else if(xdata[i] == '>')
2476 {
2477 SnortStrncpy(d_ptr, ">", 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