summaryrefslogtreecommitdiffstats
path: root/src/#sh_unix.c#
diff options
context:
space:
mode:
Diffstat (limited to 'src/#sh_unix.c#')
-rw-r--r--src/#sh_unix.c#5710
1 files changed, 0 insertions, 5710 deletions
diff --git a/src/#sh_unix.c# b/src/#sh_unix.c#
deleted file mode 100644
index 695d46f..0000000
--- a/src/#sh_unix.c#
+++ /dev/null
@@ -1,5710 +0,0 @@
-/* SAMHAIN file system integrity testing */
-/* Copyright (C) 1999 Rainer Wichmann */
-/* */
-/* This program is free software; you can redistribute it */
-/* and/or modify */
-/* it under the terms of the GNU General Public License as */
-/* published by */
-/* the Free Software Foundation; either version 2 of the License, or */
-/* (at your option) any later version. */
-/* */
-/* This program is distributed in the hope that it will be useful, */
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
-/* GNU General Public License for more details. */
-/* */
-/* You should have received a copy of the GNU General Public License */
-/* along with this program; if not, write to the Free Software */
-/* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-#include "config_xor.h"
-
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#ifdef HAVE_LINUX_FS_H
-#include <linux/fs.h>
-#endif
-
-#ifdef HAVE_MEMORY_H
-#include <memory.h>
-#endif
-
-#ifdef HAVE_UNISTD_H
-#include <errno.h>
-#include <signal.h>
-#include <pwd.h>
-#include <grp.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/resource.h>
-#include <fcntl.h>
-#include <unistd.h>
-/* need to undef these, since the #define's may be picked up from
- * linux/wait.h, and will clash with a typedef in sys/wait.h
- */
-#undef P_ALL
-#undef P_PID
-#undef P_PGID
-#include <sys/wait.h>
-
-/*********************
-#ifdef HAVE_SYS_VFS_H
-#include <sys/vfs.h>
-#endif
-**********************/
-#endif
-
-#if TIME_WITH_SYS_TIME
-#include <sys/time.h>
-#include <time.h>
-#else
-#if HAVE_SYS_TIME_H
-#include <sys/time.h>
-#else
-#include <time.h>
-#endif
-#endif
-
-#ifdef HAVE_SYS_SELECT_H
-#include <sys/select.h>
-#endif
-
-#ifndef FD_SET
-#define NFDBITS 32
-#define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
-#define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
-#define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
-#endif /* !FD_SET */
-#ifndef FD_SETSIZE
-#define FD_SETSIZE 32
-#endif
-#ifndef FD_ZERO
-#define FD_ZERO(p) memset((char *)(p), '\0', sizeof(*(p)))
-#endif
-
-
-#if defined(HAVE_MLOCK) && !defined(HAVE_BROKEN_MLOCK)
-#include <sys/mman.h>
-#endif
-
-#include "samhain.h"
-#include "sh_error.h"
-#include "sh_unix.h"
-#include "sh_utils.h"
-#include "sh_mem.h"
-#include "sh_hash.h"
-#include "sh_tools.h"
-#include "sh_restrict.h"
-#include "sh_ipvx.h"
-#include "sh_tiger.h"
-#include "sh_prelink.h"
-#include "sh_pthread.h"
-#include "sh_sem.h"
-
-/* moved here from far below
- */
-#include <netdb.h>
-
-#define SH_NEED_PWD_GRP
-#define SH_NEED_GETHOSTBYXXX
-#include "sh_static.h"
-
-#ifndef HAVE_LSTAT
-#define lstat stat
-#endif
-
-#if defined(S_IFLNK) && !defined(S_ISLNK)
-#define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
-#else
-#if !defined(S_ISLNK)
-#define S_ISLNK(mode) (0)
-#endif
-#endif
-
-#if defined(S_IFSOCK) && !defined(S_ISSOCK)
-#define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
-#else
-#if !defined(S_ISSOCK)
-#define S_ISSOCK(mode) (0)
-#endif
-#endif
-
-#if defined(S_IFDOOR) && !defined(S_ISDOOR)
-#define S_ISDOOR(mode) (((mode) & S_IFMT) == S_IFDOOR)
-#else
-#if !defined(S_ISDOOR)
-#define S_ISDOOR(mode) (0)
-#endif
-#endif
-
-#if defined(S_IFPORT) && !defined(S_ISPORT)
-#define S_ISPORT(mode) (((mode) & S_IFMT) == S_IFPORT)
-#else
-#if !defined(S_ISPORT)
-#define S_ISPORT(mode) (0)
-#endif
-#endif
-
-#define SH_KEY_NULL _("000000000000000000000000000000000000000000000000")
-
-#undef FIL__
-#define FIL__ _("sh_unix.c")
-
-unsigned long mask_PRELINK = MASK_PRELINK_;
-unsigned long mask_USER0 = MASK_USER_;
-unsigned long mask_USER1 = MASK_USER_;
-unsigned long mask_USER2 = MASK_USER_;
-unsigned long mask_USER3 = MASK_USER_;
-unsigned long mask_USER4 = MASK_USER_;
-unsigned long mask_ALLIGNORE = MASK_ALLIGNORE_;
-unsigned long mask_ATTRIBUTES = MASK_ATTRIBUTES_;
-unsigned long mask_LOGFILES = MASK_LOGFILES_;
-unsigned long mask_LOGGROW = MASK_LOGGROW_;
-unsigned long mask_READONLY = MASK_READONLY_;
-unsigned long mask_NOIGNORE = MASK_NOIGNORE_;
-
-
-extern char **environ;
-
-int sh_unix_maskreset()
-{
- mask_PRELINK = MASK_PRELINK_;
- mask_USER0 = MASK_USER_;
- mask_USER1 = MASK_USER_;
- mask_USER2 = MASK_USER_;
- mask_USER3 = MASK_USER_;
- mask_USER4 = MASK_USER_;
- mask_ALLIGNORE = MASK_ALLIGNORE_;
- mask_ATTRIBUTES = MASK_ATTRIBUTES_;
- mask_LOGFILES = MASK_LOGFILES_;
- mask_LOGGROW = MASK_LOGGROW_;
- mask_READONLY = MASK_READONLY_;
- mask_NOIGNORE = MASK_NOIGNORE_;
- return 0;
-}
-
-
-#ifdef SYS_SIGLIST_DECLARED
-/* extern const char * const sys_siglist[]; */
-#else
-char * sh_unix_siglist (int signum)
-{
- switch (signum)
- {
-#ifdef SIGHUP
- case SIGHUP:
- return _("Hangup");
-#endif
-#ifdef SIGINT
- case SIGINT:
- return _("Interrupt");
-#endif
-#ifdef SIGQUIT
- case SIGQUIT:
- return _("Quit");
-#endif
-#ifdef SIGILL
- case SIGILL:
- return _("Illegal instruction");
-#endif
-#ifdef SIGTRAP
- case SIGTRAP:
- return _("Trace/breakpoint trap");
-#endif
-#ifdef SIGABRT
- case SIGABRT:
- return _("IOT trap/Abort");
-#endif
-#ifdef SIGBUS
- case SIGBUS:
- return _("Bus error");
-#endif
-#ifdef SIGFPE
- case SIGFPE:
- return _("Floating point exception");
-#endif
-#ifdef SIGUSR1
- case SIGUSR1:
- return _("User defined signal 1");
-#endif
-#ifdef SIGSEGV
- case SIGSEGV:
- return _("Segmentation fault");
-#endif
-#ifdef SIGUSR2
- case SIGUSR2:
- return _("User defined signal 2");
-#endif
-#ifdef SIGPIPE
- case SIGPIPE:
- return _("Broken pipe");
-#endif
-#ifdef SIGALRM
- case SIGALRM:
- return _("Alarm clock");
-#endif
-#ifdef SIGTERM
- case SIGTERM:
- return _("Terminated");
-#endif
-#ifdef SIGSTKFLT
- case SIGSTKFLT:
- return _("Stack fault");
-#endif
-#ifdef SIGCHLD
- case SIGCHLD:
- return _("Child exited");
-#endif
-#ifdef SIGCONT
- case SIGCONT:
- return _("Continued");
-#endif
-#ifdef SIGSTOP
- case SIGSTOP:
- return _("Stopped");
-#endif
-#ifdef SIGTSTP
- case SIGTSTP:
- return _("Stop typed at tty");
-#endif
-#ifdef SIGTTIN
- case SIGTTIN:
- return _("Stopped (tty input)");
-#endif
-#ifdef SIGTTOU
- case SIGTTOU:
- return _("Stopped (tty output)");
-#endif
-#ifdef SIGURG
- case SIGURG:
- return _("Urgent condition");
-#endif
-#ifdef SIGXCPU
- case SIGXCPU:
- return _("CPU time limit exceeded");
-#endif
-#ifdef SIGXFSZ
- case SIGXFSZ:
- return _("File size limit exceeded");
-#endif
-#ifdef SIGVTALRM
- case SIGVTALRM:
- return _("Virtual time alarm");
-#endif
-#ifdef SIGPROF
- case SIGPROF:
- return _("Profile signal");
-#endif
-#ifdef SIGWINCH
- case SIGWINCH:
- return _("Window size changed");
-#endif
-#ifdef SIGIO
- case SIGIO:
- return _("Possible I/O");
-#endif
-#ifdef SIGPWR
- case SIGPWR:
- return _("Power failure");
-#endif
-#ifdef SIGUNUSED
- case SIGUNUSED:
- return _("Unused signal");
-#endif
- }
- return _("Unknown");
-}
-#endif
-
-
-/* Log from within a signal handler without using any
- * functions that are not async signal safe.
- *
- * This is the safe_itoa helper function.
- */
-char * safe_itoa(int i, char * str, int size)
-{
- unsigned int u;
- int iisneg = 0;
- char *p = &str[size-1];
-
- *p = '\0';
- if (i < 0) {
- iisneg = 1;
- u = ((unsigned int)(-(1+i))) + 1;
- } else {
- u = i;
- }
- do {
- --p;
- *p = '0' + (u % 10);
- u /= 10;
- } while (u && (p != str));
- if ((iisneg == 1) && (p != str)) {
- --p;
- *p = '-';
- }
- return p;
-}
-
-/* Log from within a signal handler without using any
- * functions that are not async signal safe.
- *
- * This is the safe_logger function.
- * Arguments: signal (signal number), method (0=logger, 1=stderr), thepid (pid)
- */
-extern int OnlyStderr;
-
-int safe_logger (int thesignal, int method, char * details)
-{
- unsigned int i = 0;
- int status = -1;
- struct stat buf;
- pid_t newpid;
- char str[128];
- char * p;
-
- char l0[64], l1[64], l2[64], l3[64];
- char a0[32];
- char e0[128];
- char msg[128];
-
- char * locations[] = { NULL, NULL, NULL, NULL, NULL };
- char * envp[] = { NULL, NULL };
- char * argp[] = { NULL, NULL, NULL };
-
- pid_t thepid = getpid();
-
- if ((sh.flag.isdaemon == S_FALSE) || (OnlyStderr == S_TRUE))
- method = 1;
-
- /* seems that solaris cc needs this way of initializing ...
- */
- locations[0] = l0;
- locations[1] = l1;
- locations[2] = l2;
- locations[3] = l3;
-
- envp[0] = e0;
- argp[0] = a0;
-
- sl_strlcpy(msg, _("samhain["), 128);
- p = safe_itoa((int) thepid, str, 128);
- if (p && *p)
- sl_strlcat(msg, p, 128);
- if (thesignal == 0)
- {
- if (details == NULL) {
- sl_strlcat(msg, _("]: out of memory"), 128);
- } else {
- sl_strlcat(msg, _("]: "), 128);
- sl_strlcat(msg, details, 128);
- }
- }
- else
- {
- sl_strlcat(msg, _("]: exit on signal "), 128);
- p = safe_itoa(thesignal, str, 128);
- if (p && *p)
- sl_strlcat(msg, p, 128);
- }
-
- if (method == 1) {
-#ifndef STDERR_FILENO
-#define STDERR_FILENO 2
-#endif
- int retval = 0;
- do {
- retval = write(STDERR_FILENO, msg, strlen(msg));
- } while (retval < 0 && errno == EINTR);
- do {
- retval = write(STDERR_FILENO, "\n", 1);
- } while (retval < 0 && errno == EINTR);
- return 0;
- }
-
- sl_strlcpy (l0, _("/usr/bin/logger"), 64);
- sl_strlcpy (l1, _("/usr/sbin/logger"), 64);
- sl_strlcpy (l2, _("/usr/ucb/logger"), 64);
- sl_strlcpy (l3, _("/bin/logger"), 64);
-
- sl_strlcpy (a0, _("logger"), 32);
- sl_strlcpy (e0,
- _("PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/ucb:/usr/local/bin"),
- 128);
-
- while (locations[i] != NULL) {
- status = stat(locations[i], &buf);
- if (status == 0)
- break;
- ++i;
- }
-
- if (locations[i] != NULL) {
- argp[1] = msg;
- newpid = fork();
- if (newpid == 0) {
- execve(locations[i], argp, envp);
- _exit(1);
- }
- else if (newpid > 0) {
- waitpid(newpid, &status, WUNTRACED);
- }
- }
- return 0;
-}
-
-void safe_fatal (const char * details,
- const char * file, int line)
-{
- char msg[128];
- char str[128];
- char * p;
- int thesignal = 0;
- int method = 0;
-
- p = safe_itoa((int) line, str, 128);
- sl_strlcpy(msg, _("FATAL: "), 128);
- sl_strlcat(msg, file, 128);
- sl_strlcat(msg, ": ", 128);
- if (p && (*p)) {
- sl_strlcat(msg, p , 128);
- sl_strlcat(msg, ": ", 128);
- }
- sl_strlcat(msg, details, 128);
- (void) safe_logger (thesignal, method, msg);
-
- close_ipc ();
- raise(SIGKILL);
-}
-
-extern char sh_sig_msg[64];
-
-volatile int immediate_exit_normal = 0;
-
-#if defined(SA_SIGACTION_WORKS)
-static
-void sh_unix_sigexit (int mysignal, siginfo_t * signal_info, void * signal_add)
-#else
-static
-void sh_unix_sigexit (int mysignal)
-#endif
-{
-
-#if defined(SA_SIGACTION_WORKS)
- if (signal_info != NULL && signal_info->si_code == SI_USER &&
- mysignal != SIGTERM && mysignal != SIGINT)
- {
- return;
- }
-
- /* avoid compiler warning (unused var)
- */
- (void) signal_add;
-#endif
-
- /*
- * Block re-entry
- */
- if (immediate_exit_normal > 0)
- {
- ++immediate_exit_normal;
- if ((skey != NULL) && (immediate_exit_normal == 2))
- memset (skey, '\0', sizeof(sh_key_t));
- if (immediate_exit_normal == 2)
- {
- int val_return;
-
- do {
- val_return = chdir ("/");
- } while (val_return < 0 && errno == EINTR);
-
- close_ipc ();
- safe_logger (mysignal, 0, NULL);
- }
- raise(SIGKILL);
- }
- else
- {
- immediate_exit_normal = 1;
- }
-
-#ifdef SYS_SIGLIST_DECLARED
- strncpy (sh_sig_msg, sys_siglist[mysignal], 40);
-#else
- strncpy (sh_sig_msg, sh_unix_siglist(mysignal), 40);
-#endif
- sh_sig_msg[63] = '\0';
-
- ++sig_raised;
- ++sig_urgent;
- sig_termfast = 1;
- return;
-}
-
-volatile int immediate_exit_fast = 0;
-
-#if defined(SA_SIGACTION_WORKS)
-static
-void sh_unix_sigexit_fast (int mysignal, siginfo_t * signal_info,
- void * signal_add)
-#else
-static
-void sh_unix_sigexit_fast (int mysignal)
-#endif
-{
-#if defined(SL_DEBUG) && (defined(USE_SYSTEM_MALLOC) || !defined(USE_MALLOC_LOCK))
- int retval;
-#endif
-
-#if defined(SA_SIGACTION_WORKS)
- if (signal_info != NULL && signal_info->si_code == SI_USER)
- {
- return;
- }
-#endif
-
- /* avoid compiler warning (unused var)
- */
-#if defined(SA_SIGACTION_WORKS)
- (void) signal_add;
-#endif
-
- /* Check whether the heap is ok; otherwise _exit
- */
-#if !defined(SL_DEBUG) || (!defined(USE_SYSTEM_MALLOC) && defined(USE_MALLOC_LOCK))
- ++immediate_exit_fast;
- if (skey != NULL && immediate_exit_fast < 2)
- memset (skey, '\0', sizeof(sh_key_t));
- if (immediate_exit_fast < 2)
- safe_logger (mysignal, 0, NULL);
- raise(SIGKILL);
-#else
-
- /* debug code
- */
- if (immediate_exit_fast == 1)
- {
- ++immediate_exit_fast;
- if (skey != NULL)
- memset (skey, '\0', sizeof(sh_key_t));
- close_ipc ();
- safe_logger (mysignal, 0, NULL);
- do {
- retval = chdir ("/");
- } while (retval < 0 && errno == EINTR);
- raise(SIGFPE);
- }
- else if (immediate_exit_fast == 2)
- {
- do {
- retval = chdir ("/");
- } while (retval < 0 && errno == EINTR);
- raise(SIGFPE);
- }
- else if (immediate_exit_fast != 0)
- {
- raise(SIGKILL);
- }
-
- ++immediate_exit_fast;
-
- /* The FPE|BUS|SEGV|ILL signals leave the system in an undefined
- * state, thus it is best to exit immediately.
- */
-#ifdef SYS_SIGLIST_DECLARED
- strncpy (sh_sig_msg, sys_siglist[mysignal], 40);
-#else
- strncpy (sh_sig_msg, sh_unix_siglist(mysignal), 40);
-#endif
- sh_sig_msg[63] = '\0';
-
- sl_stack_print();
-
- /* Try to push out an error message.
- */
- sh_error_handle ((-1), FIL__, __LINE__, mysignal, MSG_EXIT_NORMAL,
- sh.prg_name, sh_sig_msg);
-
- if (skey != NULL)
- memset (skey, '\0', sizeof(sh_key_t));
- close_ipc ();
-
- do {
- retval = chdir ("/");
- } while (retval < 0 && errno == EINTR);
-
- raise(SIGFPE);
-#endif
-}
-
-
-static
-void sh_unix_sigaction (int mysignal)
-{
- ++sig_raised;
-#ifdef SIGUSR1
- if (mysignal == SIGUSR1)
- sig_debug_switch = 1;
-#endif
-#ifdef SIGUSR2
- if (mysignal == SIGUSR2)
- {
- ++sig_suspend_switch;
- ++sig_urgent;
- }
-#endif
-#ifdef SIGHUP
- if (mysignal == SIGHUP)
- sig_config_read_again = 1;
-#endif
-#ifdef SIGTTOU
- if (mysignal == SIGTTOU) {
- sig_force_check = 1; sh_sem_trylock(); }
-#endif
-#ifdef SIGTSTP
- if (mysignal == SIGTSTP) {
- sig_force_check = 1; sig_force_silent = 1; sh_sem_trylock(); }
-#endif
-#ifdef SIGTTIN
- if (mysignal == SIGTTIN)
- sig_fresh_trail = 1;
-#endif
-#ifdef SIGABRT
- if (mysignal == SIGABRT)
- sig_fresh_trail = 1;
-#endif
-#ifdef SIGQUIT
- if (mysignal == SIGQUIT)
- sig_terminate = 1;
-#endif
-#ifdef SIGTERM
- if (mysignal == SIGTERM)
- {
- strncpy (sh_sig_msg, _("Terminated"), 40);
- sig_termfast = 1;
- ++sig_urgent;
- }
-#endif
-
- return;
-}
-
-void sh_unix_ign_sigpipe()
-{
- struct sigaction ignact;
-
- ignact.sa_handler = SIG_IGN; /* signal action */
- sigemptyset( &ignact.sa_mask ); /* set an empty mask */
- ignact.sa_flags = 0; /* init sa_flags */
-
-#ifdef SIGPIPE
- retry_sigaction(FIL__, __LINE__, SIGPIPE, &ignact, NULL);
-#endif
-
- return;
-}
-static
-void sh_unix_siginstall (int goDaemon)
-{
- struct sigaction act, act_fast, act2, oldact, ignact;
-#if defined (SH_WITH_SERVER)
- (void) goDaemon;
-#endif
-
- SL_ENTER(_("sh_unix_siginstall"));
-
- ignact.sa_handler = SIG_IGN; /* signal action */
- sigemptyset( &ignact.sa_mask ); /* set an empty mask */
- ignact.sa_flags = 0; /* init sa_flags */
-
-#if defined(SA_SIGACTION_WORKS)
- act.sa_sigaction = &sh_unix_sigexit; /* signal action */
-#else
- act.sa_handler = &sh_unix_sigexit; /* signal action */
-#endif
-
- sigfillset ( &act.sa_mask ); /* set a full mask */
-
-
- /* Block all but deadly signals.
- */
-#ifdef SIGILL
- sigdelset ( &act.sa_mask, SIGILL );
-#endif
-#ifndef SL_DEBUG
-#ifdef SIGFPE
- sigdelset ( &act.sa_mask, SIGFPE );
-#endif
-#endif
-#ifdef SIGSEGV
- sigdelset ( &act.sa_mask, SIGSEGV );
-#endif
-#ifdef SIGBUS
- sigdelset ( &act.sa_mask, SIGBUS );
-#endif
-
-#if defined(SA_SIGACTION_WORKS)
- act_fast.sa_sigaction = &sh_unix_sigexit_fast; /* signal action */
-#else
- act_fast.sa_handler = &sh_unix_sigexit_fast; /* signal action */
-#endif
-
- sigfillset ( &act_fast.sa_mask ); /* set a full mask */
-
-#ifdef SIGILL
- sigdelset ( &act_fast.sa_mask, SIGILL );
-#endif
-#ifndef SL_DEBUG
-#ifdef SIGFPE
- sigdelset ( &act_fast.sa_mask, SIGFPE );
-#endif
-#endif
-#ifdef SIGSEGV
- sigdelset ( &act_fast.sa_mask, SIGSEGV );
-#endif
-#ifdef SIGBUS
- sigdelset ( &act_fast.sa_mask, SIGBUS );
-#endif
-
-
- /* Use siginfo to verify origin of signal, if possible.
- */
-#if defined(SA_SIGACTION_WORKS)
- act.sa_flags = SA_SIGINFO;
- act_fast.sa_flags = SA_SIGINFO;
-#else
- act.sa_flags = 0;
- act_fast.sa_flags = 0;
-#endif
-
- /* Do not block the signal from being received in its handler ...
- * (is this a good or a bad idea ??).
- */
-#if defined(SA_NOMASK)
- act_fast.sa_flags |= SA_NOMASK;
-#elif defined(SA_NODEFER)
- act_fast.sa_flags |= SA_NODEFER;
-#endif
-
-
- act2.sa_handler = &sh_unix_sigaction; /* signal action */
- sigemptyset( &act2.sa_mask ); /* set an empty mask */
- act2.sa_flags = 0; /* init sa_flags */
-
- /* signals to control the daemon */
-
-#ifdef SIGHUP
- retry_sigaction(FIL__, __LINE__, SIGHUP, &act2, &oldact);
-#endif
-#ifdef SIGABRT
- retry_sigaction(FIL__, __LINE__, SIGABRT, &act2, &oldact);
-#endif
-#ifdef SIGUSR1
- retry_sigaction(FIL__, __LINE__, SIGUSR1, &act2, &oldact);
-#endif
-#ifdef SIGUSR2
- retry_sigaction(FIL__, __LINE__, SIGUSR2, &act2, &oldact);
-#endif
-#ifdef SIGQUIT
- retry_sigaction(FIL__, __LINE__, SIGQUIT, &act2, &oldact);
-#endif
-#ifdef SIGTERM
- retry_sigaction(FIL__, __LINE__, SIGTERM, &act, &oldact);
-#endif
-
- /* fatal signals that may cause termination */
-
-#ifdef SIGILL
- retry_sigaction(FIL__, __LINE__, SIGILL, &act_fast, &oldact);
-#endif
-#ifndef SL_DEBUG
-#ifdef SIGFPE
- retry_sigaction(FIL__, __LINE__, SIGFPE, &act_fast, &oldact);
-#endif
-#endif
-#ifdef SIGSEGV
- retry_sigaction(FIL__, __LINE__, SIGSEGV, &act_fast, &oldact);
-#endif
-#ifdef SIGBUS
- retry_sigaction(FIL__, __LINE__, SIGBUS, &act_fast, &oldact);
-#endif
-
- /* other signals */
-
-#ifdef SIGINT
- retry_sigaction(FIL__, __LINE__, SIGINT, &act, &oldact);
-#endif
-#ifdef SIGPIPE
- retry_sigaction(FIL__, __LINE__, SIGPIPE, &ignact, &oldact);
-#endif
-#ifdef SIGALRM
- retry_sigaction(FIL__, __LINE__, SIGALRM, &ignact, &oldact);
-#endif
-
-#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
-#ifdef SIGTTOU
- if (goDaemon == 1)
- retry_sigaction(FIL__, __LINE__, SIGTTOU, &act2, &oldact);
- else
- retry_sigaction(FIL__, __LINE__, SIGTTOU, &ignact, &oldact);
-#endif
-#ifdef SIGTSTP
- if (goDaemon == 1)
- retry_sigaction(FIL__, __LINE__, SIGTSTP, &act2, &oldact);
- else
- retry_sigaction(FIL__, __LINE__, SIGTSTP, &ignact, &oldact);
-#endif
-#ifdef SIGTTIN
- if (goDaemon == 1)
- retry_sigaction(FIL__, __LINE__, SIGTTIN, &act2, &oldact);
- else
- retry_sigaction(FIL__, __LINE__, SIGTTIN, &ignact, &oldact);
-#endif
-#else
-#ifdef SIGTSTP
- retry_sigaction(FIL__, __LINE__, SIGTSTP, &ignact, &oldact);
-#endif
-#ifdef SIGTTOU
- retry_sigaction(FIL__, __LINE__, SIGTTOU, &ignact, &oldact);
-#endif
-#ifdef SIGTTIN
- retry_sigaction(FIL__, __LINE__, SIGTTIN, &ignact, &oldact);
-#endif
-#endif
-
-#ifdef SIGTRAP
-#if !defined(SCREW_IT_UP)
- retry_sigaction(FIL__, __LINE__, SIGTRAP, &act, &oldact);
-#endif
-#endif
-
-#ifdef SIGPOLL
- retry_sigaction(FIL__, __LINE__, SIGPOLL, &ignact, &oldact);
-#endif
-#if defined(SIGPROF) && !defined(SH_PROFILE)
- retry_sigaction(FIL__, __LINE__, SIGPROF, &ignact, &oldact);
-#endif
-#ifdef SIGSYS
- retry_sigaction(FIL__, __LINE__, SIGSYS, &act, &oldact);
-#endif
-#ifdef SIGURG
- retry_sigaction(FIL__, __LINE__, SIGURG, &ignact, &oldact);
-#endif
-#if defined(SIGVTALRM) && !defined(SH_PROFILE)
- retry_sigaction(FIL__, __LINE__, SIGVTALRM, &ignact, &oldact);
-#endif
-#ifdef SIGXCPU
- retry_sigaction(FIL__, __LINE__, SIGXCPU, &act, &oldact);
-#endif
-#ifdef SIGXFSZ
- retry_sigaction(FIL__, __LINE__, SIGXFSZ, &act, &oldact);
-#endif
-
-#ifdef SIGEMT
- retry_sigaction(FIL__, __LINE__, SIGEMT, &ignact, &oldact);
-#endif
-#ifdef SIGSTKFLT
- retry_sigaction(FIL__, __LINE__, SIGSTKFLT, &act, &oldact);
-#endif
-#ifdef SIGIO
- retry_sigaction(FIL__, __LINE__, SIGIO, &ignact, &oldact);
-#endif
-#ifdef SIGPWR
- retry_sigaction(FIL__, __LINE__, SIGPWR, &act, &oldact);
-#endif
-
-#ifdef SIGLOST
- retry_sigaction(FIL__, __LINE__, SIGLOST, &ignact, &oldact);
-#endif
-#ifdef SIGUNUSED
- retry_sigaction(FIL__, __LINE__, SIGUNUSED, &ignact, &oldact);
-#endif
-
- SL_RET0(_("sh_unix_siginstall"));
-}
-
-/* ---------------------------------------------------------------- */
-
-/* checksum the own binary
- */
-int sh_unix_self_hash (const char * c)
-{
- char message[512];
- char hashbuf[KEYBUF_SIZE];
-
- SL_ENTER(_("sh_unix_self_hash"));
-
- if (c == NULL)
- {
- sh.exec.path[0] = '\0';
- SL_RETURN((0), _("sh_unix_self_hash"));
- }
- sl_strlcpy(sh.exec.path, c, SH_PATHBUF);
-
- sl_strlcpy(sh.exec.hash,
- sh_tiger_hash (c, TIGER_FILE, TIGER_NOLIM, hashbuf, sizeof(hashbuf)),
- KEY_LEN+1);
- sl_snprintf(message, 512, _("%s has checksum: %s"),
- sh.exec.path, sh.exec.hash);
- message[511] = '\0';
- sh_error_handle(SH_ERR_INFO, FIL__, __LINE__, 0, MSG_E_SUBGEN,
- message, _("sh_unix_self_hash"));
- if (0 == sl_strcmp(sh.exec.hash, SH_KEY_NULL ))
- {
- dlog(1, FIL__, __LINE__,
- _("Could not checksum my own executable because of the\nfollowing error: %s: %s\n\nPossible reasons include:\n Wrong path in configure file option SamhainPath=/path/to/executable\n No read permission for the effective UID: %d\n"),
- sh.exec.path, sl_get_errmsg(), (int) sl_ret_euid());
- sh_error_handle ((-1), FIL__, __LINE__, EACCES, MSG_NOACCESS,
- (long) sh.real.uid, c);
- aud_exit (FIL__, __LINE__, EXIT_FAILURE);
- }
- SL_RETURN((0), _("sh_unix_self_hash"));
-}
-
-int sh_unix_self_check ()
-{
- char newhash[KEY_LEN+1];
- char message[512];
- char hashbuf[KEYBUF_SIZE];
-
- SL_ENTER(_("sh_unix_self_check"));
- if (sh.exec.path[0] == '\0')
- SL_RETURN((0), _("sh_unix_self_check"));
-
- sl_strlcpy(newhash,
- sh_tiger_hash (sh.exec.path, TIGER_FILE, TIGER_NOLIM, hashbuf, sizeof(hashbuf)),
- KEY_LEN+1);
-
- if (0 == sl_strncmp(sh.exec.hash, newhash, KEY_LEN))
- {
- sh_error_handle(SH_ERR_INFO, FIL__, __LINE__, 0, MSG_E_SUBGEN,
- _("Checksum ok"), _("sh_unix_self_check"));
- SL_RETURN((0), _("sh_unix_self_check"));
- }
-
- if (0 == sl_strncmp(SH_KEY_NULL, newhash, KEY_LEN))
- {
- sh_error_handle(SH_ERR_WARN, FIL__, __LINE__, 0, MSG_E_SUBGEN,
- _("Could not read samhain executable"), _("sh_unix_self_check"));
- SL_RETURN((0), _("sh_unix_self_check"));
- }
-
- dlog(1, FIL__, __LINE__,
- _("The checksum of the executable: %s has changed since startup (%s -> %s).\n"),
- sh.exec.path, sh.exec.hash, newhash);
-
- sl_snprintf(message, 512,
- _("The checksum of %s has changed since startup (%s -> %s)"),
- sh.exec.path, sh.exec.hash, newhash);
- message[511] = '\0';
-
- sh_error_handle(SH_ERR_INFO, FIL__, __LINE__, 0, MSG_E_SUBGEN,
- message, _("sh_unix_self_check"));
- sh_error_handle ((-1), FIL__, __LINE__, EACCES, MSG_E_AUTH,
- sh.exec.path);
- SL_RETURN((-1), _("sh_unix_self_check"));
-}
-
-
-/* ---------------------------------------------------------------- */
-
-long sh_group_to_gid (const char * g, int * fail)
-{
- struct group * w;
- gid_t gid = 0;
- int status = 0;
-
-#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
- struct group grp;
- char * buffer;
- static size_t gbufsize = SH_GRBUF_SIZE;
-#endif
-
- *fail = -1;
-
- if (g)
- {
- size_t i;
- size_t len = strlen(g);
-
- *fail = 0;
-
- for (i = 0; i < len; ++i)
- {
- char c = g[i];
-
- if (!isdigit((int) c))
- goto is_a_name;
- }
- return atol(g);
-
- is_a_name:
-
-#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
-
- buffer = SH_ALLOC(gbufsize);
- status = sh_getgrnam_r(g, &grp, buffer, gbufsize, &w);
-
- if ((status == ERANGE) && (w == NULL))
- {
- if (S_TRUE == sl_ok_adds( gbufsize, SH_GRBUF_SIZE ))
- {
- SH_FREE(buffer);
- gbufsize += SH_GRBUF_SIZE;
- goto is_a_name;
- }
- }
-
-#else
-
- errno = 0;
- w = sh_getgrnam(g);
- status = errno;
-
-#endif
-
- if ((status == ERANGE) && (w == NULL))
- {
- static int seen = 0;
-
- if (seen == 0)
- {
- char errbuf[SH_ERRBUF_SIZE];
-
- sh_error_handle (SH_ERR_ERR, FIL__, __LINE__, EINVAL, MSG_E_GRNULL,
- sh_error_message(status, errbuf, sizeof(errbuf)),
- _("sh_group_to_gid"), (long) -1, _("line too long in group entry"));
- ++seen;
- }
- *fail = -1;
- }
- else if (w == NULL)
- {
- char * tmp = sh_util_strdup(g);
- sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS,
- _("sh_group_to_gid"), tmp);
- SH_FREE(tmp);
- *fail = -1;
- }
- else
- {
- gid = w->gr_gid;
- }
-#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
- SH_FREE(buffer);
-#endif
- }
-
- return gid;
-}
-
-/* ---------------------------------------------------------------- */
-
-
-/* added Tue Feb 22 10:36:44 NFT 2000 Rainer Wichmann */
-static int tf_add_trusted_user_int(const char * c)
-{
- struct passwd * w;
- int count;
- uid_t pwid = (uid_t)-1;
-
-#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
- struct passwd pwd;
- char * buffer;
-#endif
-
- SL_ENTER(_("tf_add_trusted_user_int"));
-
- /* First check for a user name.
- */
-#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
- buffer = SH_ALLOC(SH_PWBUF_SIZE);
- sh_getpwnam_r(c, &pwd, buffer, SH_PWBUF_SIZE, &w);
-#else
- w = sh_getpwnam(c);
-#endif
-
- if ((w != NULL) && ((pwid = w->pw_uid) > 0))
- goto succe;
-
- /* Failed, so check for a numerical value.
- */
- pwid = strtol(c, (char **)NULL, 10);
- if (pwid > 0 && pwid < 65535)
- goto succe;
-
- sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS,
- _("add trusted user"), c);
-#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
- SH_FREE(buffer);
-#endif
- SL_RETURN((-1), _("tf_add_trusted_user_int"));
-
- succe:
- count = sl_trust_add_user(pwid);
-#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
- SH_FREE(buffer);
-#endif
- SL_RETURN((count), _("tf_add_trusted_user_int"));
-}
-
-int tf_add_trusted_user(const char * c)
-{
- int i;
- char * q;
- char * p = sh_util_strdup (c);
-#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
- char * saveptr;
-#endif
-
- SL_ENTER(_("tf_add_trusted_user"));
-
-#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
- q = strtok_r(p, ", \t", &saveptr);
-#else
- q = strtok(p, ", \t");
-#endif
- if (!q)
- {
- SH_FREE(p);
- SL_RETURN((-1), _("tf_add_trusted_user"));
- }
- while (q)
- {
- i = tf_add_trusted_user_int(q);
- if (SL_ISERROR(i))
- {
- SH_FREE(p);
- SL_RETURN((i), _("tf_add_trusted_user"));
- }
-#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
- q = strtok_r(NULL, ", \t", &saveptr);
-#else
- q = strtok(NULL, ", \t");
-#endif
- }
- SH_FREE(p);
- SL_RETURN((0), _("tf_add_trusted_user"));
-}
-
-extern uid_t sl_trust_baduid(void);
-extern gid_t sl_trust_badgid(void);
-
-#if defined(HOST_IS_CYGWIN) || defined(__cygwin__) || defined(__CYGWIN32__) || defined(__CYGWIN__)
-int tf_trust_check (const char * file, int mode)
-{
- (void) file;
- (void) mode;
- return 0;
-}
-#else
-int tf_trust_check (const char * file, int mode)
-{
- char * tmp;
- char * tmp2;
- char * p;
- int status;
- int level;
- uid_t ff_euid = (uid_t) -1;
-
- SL_ENTER(_("tf_trust_check"));
-
- if (mode == SL_YESPRIV)
- sl_get_euid(&ff_euid);
- else
- sl_get_ruid(&ff_euid);
-
-#if defined(SH_WITH_SERVER)
- if (0 == sl_ret_euid()) /* privileges not dropped yet */
- {
-#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
- struct passwd pwd;
- char * buffer = SH_ALLOC(SH_PWBUF_SIZE);
- struct passwd * tempres;
- sh_getpwnam_r(DEFAULT_IDENT, &pwd, buffer, SH_PWBUF_SIZE, &tempres);
-#else
- struct passwd * tempres = sh_getpwnam(DEFAULT_IDENT);
-#endif
-
- if (!tempres)
- {
- dlog(1, FIL__, __LINE__,
- _("User %s does not exist. Please add the user to your system.\n"),
- DEFAULT_IDENT);
- aud_exit (FIL__, __LINE__, EXIT_FAILURE);
- }
- else
- {
- ff_euid = tempres->pw_uid;
- }
-#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
- SH_FREE(buffer);
-#endif
- }
-#endif
-
- status = sl_trustfile_euid(file, ff_euid);
-
- if ( SL_ENONE != status)
- {
- if (status == SL_ESTAT)
- level = SH_ERR_ALL;
- else
- level = SH_ERR_ERR;
-
- tmp = sh_util_safe_name (file);
- p = sl_trust_errfile();
- if (p && *p != '\0')
- {
- tmp2 = sh_util_safe_name (sl_trust_errfile());
- sh_error_handle(level, FIL__, __LINE__, status, MSG_E_TRUST2,
- sl_error_string(status), tmp, tmp2);
- SH_FREE(tmp2);
- }
- else
- {
- sh_error_handle(level, FIL__, __LINE__, status, MSG_E_TRUST1,
- sl_error_string(status), tmp);
- }
- SH_FREE(tmp);
-
- if (status == SL_EBADUID || status == SL_EBADGID ||
- status == SL_EBADOTH || status == SL_ETRUNC ||
- status == SL_EINTERNAL )
- {
- switch (status) {
- case SL_EINTERNAL:
- dlog(1, FIL__, __LINE__,
- _("An internal error occured in the trustfile function.\n"));
- break;
- case SL_ETRUNC:
- tmp = sh_util_safe_name (file);
- dlog(1, FIL__, __LINE__,
- _("A filename truncation occured in the trustfile function.\nProbably the normalized filename for %s\nis too long. This may be due e.g. to deep or circular softlinks.\n"),
- tmp);
- SH_FREE(tmp);
- break;
- case SL_EBADOTH:
- tmp = sh_util_safe_name (file);
- p = sl_trust_errfile();
- dlog(1, FIL__, __LINE__,
- _("The path element: %s\nin the filename: %s is world writeable.\n"),
- p, tmp);
- SH_FREE(tmp);
- break;
- case SL_EBADUID:
- tmp = sh_util_safe_name (file);
- p = sl_trust_errfile();
- dlog(1, FIL__, __LINE__,
- _("The owner (UID = %ld) of the path element: %s\nin the filename: %s\nis not in the list of trusted users.\nTo fix the problem, you can:\n - run ./configure again with the option --with-trusted=0,...,UID\n where UID is the UID of the untrusted user, or\n - use the option TrustedUser=UID in the configuration file.\n"),
- (UID_CAST)sl_trust_baduid(), p, tmp);
- SH_FREE(tmp);
- break;
- case SL_EBADGID:
- tmp = sh_util_safe_name (file);
- p = sl_trust_errfile();
- dlog(1, FIL__, __LINE__,
- _("The path element: %s\nin the filename: %s\nis group writeable (GID = %ld), and at least one of the group\nmembers (UID = %ld) is not in the list of trusted users.\nTo fix the problem, you can:\n - run ./configure again with the option --with-trusted=0,...,UID\n where UID is the UID of the untrusted user, or\n - use the option TrustedUser=UID in the configuration file.\n"),
- p, tmp, (UID_CAST)sl_trust_badgid(),
- (UID_CAST)sl_trust_baduid());
- SH_FREE(tmp);
- break;
- default:
- break;
- }
-
- SL_RETURN((-1), _("tf_trust_check"));
- }
- }
-
- SL_RETURN((0), _("tf_trust_check"));
-}
-#endif
-
-#ifdef HAVE_INITGROUPS
-#ifdef HOST_IS_OSF
-int sh_unix_initgroups ( char * in_user, gid_t in_gid)
-#else
-int sh_unix_initgroups (const char * in_user, gid_t in_gid)
-#endif
-{
- int status = -1;
- status = sh_initgroups (in_user, in_gid);
- if (status < 0)
- {
- if (errno == EPERM)
- return 0;
- if (errno == EINVAL)
- return 0;
- return -1;
- }
- return 0;
-}
-#else
-int sh_unix_initgroups (const char * in_user, gid_t in_gid)
-{
- (void) in_user;
- (void) in_gid;
- return 0;
-}
-#endif
-
-#ifdef HAVE_INITGROUPS
-char * sh_unix_getUIDname (int level, uid_t uid, char * out, size_t len);
-int sh_unix_initgroups2 (uid_t in_pid, gid_t in_gid)
-{
- int status = -1;
- char user[SH_MINIBUF];
-
- SL_ENTER(_("sh_unix_initgroups2"));
-
- if (NULL == sh_unix_getUIDname (SH_ERR_ERR, in_pid, user, sizeof(user)))
- SL_RETURN((-1), _("sh_unix_initgroups2"));
- status = sh_initgroups (user, in_gid);
- if (status < 0)
- {
- if (errno == EPERM)
- status = 0;
- if (errno == EINVAL)
- status = 0;
- }
- SL_RETURN((status), _("sh_unix_initgroups2"));
-}
-#else
-int sh_unix_initgroups2 (uid_t in_pid, gid_t in_gid)
-{
- (void) in_pid;
- (void) in_gid;
- return 0;
-}
-#endif
-
-void sh_unix_closeall (int fd, int except, int inchild)
-{
- int fdx = fd;
-#ifdef _SC_OPEN_MAX
- int fdlimit = sysconf (_SC_OPEN_MAX);
-#else
-#ifdef OPEN_MAX
- int fdlimit = OPEN_MAX;
-#else
- int fdlimit = _POSIX_OPEN_MAX;
-#endif
-#endif
-
- SL_ENTER(_("sh_unix_closeall"));
-
- /* can't happen - so fix it :-(
- */
- if (fdlimit < 0)
- fdlimit = 20; /* POSIX lower limit */
-
- if (fdlimit > 65536)
- fdlimit = 65536;
-
- if (!inchild)
- sl_dropall (fdx, except);
- else
- sl_dropall_dirty (fdx, except);
-
- /* Close everything from fd (inclusive) up to fdlimit (exclusive).
- */
- while (fd < fdlimit)
- {
- if (fd == except)
- fd++;
- else if (slib_do_trace != 0 && fd == slib_trace_fd)
- fd++;
- else
- sl_close_fd(FIL__, __LINE__, fd++);
- }
-
- SL_RET0(_("sh_unix_closeall"));
-}
-
-static void sh_unix_setlimits(void)
-{
- struct rlimit limits;
-
- SL_ENTER(_("sh_unix_setlimits"));
-
- limits.rlim_cur = RLIM_INFINITY;
- limits.rlim_max = RLIM_INFINITY;
-
-#ifdef RLIMIT_CPU
- setrlimit (RLIMIT_CPU, &limits);
-#endif
-#ifdef RLIMIT_FSIZE
- setrlimit (RLIMIT_FSIZE, &limits);
-#endif
-#ifdef RLIMIT_DATA
- setrlimit (RLIMIT_DATA, &limits);
-#endif
-#ifdef RLIMIT_STACK
- setrlimit (RLIMIT_STACK, &limits);
-#endif
-#ifdef RLIMIT_RSS
- setrlimit (RLIMIT_RSS, &limits);
-#endif
-#ifdef RLIMIT_NPROC
- setrlimit (RLIMIT_NPROC, &limits);
-#endif
-#ifdef RLIMIT_MEMLOCK
- setrlimit (RLIMIT_MEMLOCK, &limits);
-#endif
-
-#if !defined(SL_DEBUG)
- /* no core dumps
- */
- limits.rlim_cur = 0;
- limits.rlim_max = 0;
-#ifdef RLIMIT_CORE
- setrlimit (RLIMIT_CORE, &limits);
-#endif
-#else
-#ifdef RLIMIT_CORE
- setrlimit (RLIMIT_CORE, &limits);
-#endif
-#endif
-
- limits.rlim_cur = 1024;
- limits.rlim_max = 1024;
-
-#if defined(RLIMIT_NOFILE)
- setrlimit (RLIMIT_NOFILE, &limits);
-#elif defined(RLIMIT_OFILE)
- setrlimit (RLIMIT_OFILE, &limits);
-#endif
-
- SL_RET0(_("sh_unix_setlimits"));
-}
-
-static void sh_unix_copyenv(void)
-{
- char ** env0 = environ;
- char ** env1;
- int envlen = 0;
- size_t len;
-
- SL_ENTER(_("sh_unix_copyenv"));
-
- while (env0 != NULL && env0[envlen] != NULL) {
- /* printf("%2d: %s\n", envlen, env0[envlen]); */
- ++envlen;
- }
- ++envlen;
-
- /* printf("-> %2d: slots allocated\n", envlen); */
- env1 = calloc(1,sizeof(char *) * envlen); /* only once */
- if (env1 == NULL)
- {
- fprintf(stderr, _("%s: %d: Out of memory\n"), FIL__, __LINE__);
- SL_RET0(_("sh_unix_copyenv"));
- }
- env0 = environ;
- envlen = 0;
-
- while (env0 != NULL && env0[envlen] != NULL) {
- len = strlen(env0[envlen]) + 1;
- env1[envlen] = calloc(1,len); /* only once */
- if (env1[envlen] == NULL)
- {
- int i;
- fprintf(stderr, _("%s: %d: Out of memory\n"), FIL__, __LINE__);
- for (i = 0; i < envlen; ++i) free(env1[len]);
- free(env1);
- SL_RET0(_("sh_unix_copyenv"));
- }
- sl_strlcpy(env1[envlen], env0[envlen], len);
- ++envlen;
- }
- env1[envlen] = NULL;
-
- environ = env1;
- SL_RET0(_("sh_unix_copyenv"));
-}
-
-/* delete all environment variables
- */
-static void sh_unix_zeroenv(void)
-{
- char * c;
- char ** env;
-
- SL_ENTER(_("sh_unix_zeroenv"));
-
- sh_unix_copyenv();
- env = environ;
-
- while (env != NULL && *env != NULL) {
- c = strchr ((*env), '=');
-#ifdef WITH_MYSQL
- /*
- * Skip the MYSQL_UNIX_PORT environment variable; MySQL may need it.
- */
- if (0 == sl_strncmp((*env), _("MYSQL_UNIX_PORT="), 16))
- {
- ++(env);
- continue;
- }
- if (0 == sl_strncmp((*env), _("MYSQL_TCP_PORT="), 15))
- {
- ++(env);
- continue;
- }
- if (0 == sl_strncmp((*env), _("MYSQL_HOME="), 11))
- {
- ++(env);
- continue;
- }
-#endif
-#ifdef WITH_ORACLE
- /*
- * Skip the ORACLE_HOME and TNS_ADMIN environment variables;
- * Oracle may need them.
- */
- if (0 == sl_strncmp((*env), _("ORACLE_HOME="), 12))
- {
- ++(env);
- continue;
- }
- if (0 == sl_strncmp((*env), _("TNS_ADMIN="), 10))
- {
- ++(env);
- continue;
- }
-#endif
- /*
- * Skip the TZ environment variable.
- */
- if (0 == sl_strncmp((*env), _("TZ="), 3))
- {
- ++(env);
- continue;
- }
- ++(env);
- if (c != NULL)
- {
- ++c;
- while ((*c) != '\0') {
- (*c) = '\0';
- ++c;
- }
- }
- }
-
-#ifdef HAVE_TZSET
- tzset();
-#endif
-
- SL_RET0(_("sh_unix_zeroenv"));
-}
-
-
-static void sh_unix_resettimer(void)
-{
- struct itimerval this_timer;
-
- SL_ENTER(_("sh_unix_resettimer"));
-
- this_timer.it_value.tv_sec = 0;
- this_timer.it_value.tv_usec = 0;
-
- this_timer.it_interval.tv_sec = 0;
- this_timer.it_interval.tv_usec = 0;
-
- setitimer(ITIMER_REAL, &this_timer, NULL);
-#if !defined(SH_PROFILE)
- setitimer(ITIMER_VIRTUAL, &this_timer, NULL);
- setitimer(ITIMER_PROF, &this_timer, NULL);
-#endif
-
- SL_RET0(_("sh_unix_resettimer"));
-}
-
-static void sh_unix_resetsignals(void)
-{
- int sig_num;
-#ifdef NSIG
- int max_sig = NSIG;
-#else
- int max_sig = 255;
-#endif
- int test;
- int status;
- struct sigaction act;
-#if !defined(SH_PROFILE)
- struct sigaction oldact;
-#endif
-
- sigset_t set_proc;
-
- SL_ENTER(_("sh_unix_resetsignals"));
- /*
- * Reset the current signal mask (inherited from parent process).
- */
-
- sigfillset(&set_proc);
-
- do {
- errno = 0;
- test = SH_SETSIGMASK(SIG_UNBLOCK, &set_proc, NULL);
- } while (test < 0 && errno == EINTR);
-
- /*
- * Reset signal handling.
- */
-
- act.sa_handler = SIG_DFL; /* signal action */
- sigemptyset( &act.sa_mask ); /* set an empty mask */
- act.sa_flags = 0; /* init sa_flags */
-
- for (sig_num = 1; sig_num <= max_sig; ++sig_num)
- {
-#if !defined(SH_PROFILE)
- test = retry_sigaction(FIL__, __LINE__, sig_num, &act, &oldact);
-#else
- test = 0;
-#endif
- if ((test == -1) && (errno != EINVAL))
- {
- char errbuf[SH_ERRBUF_SIZE];
- status = errno;
- sh_error_handle ((-1), FIL__, __LINE__, status, MSG_W_SIG,
- sh_error_message (status, errbuf, sizeof(errbuf)), sig_num);
- }
- }
-
- SL_RET0(_("sh_unix_resetsignals"));
-}
-
-/* Get the local hostname (FQDN)
- */
-static char * sh_tolower (char * s)
-{
- char * ret = s;
- if (s)
- {
- for (; *s; ++s)
- {
- *s = tolower((unsigned char) *s);
- }
- }
- return ret;
-}
-
-
-#include <sys/socket.h>
-
-/* Required for BSD
- */
-#ifdef HAVE_NETINET_IN_H
-#include <netinet/in.h>
-#endif
-
-#include <arpa/inet.h>
-
-const char * sh_unix_h_name (struct hostent * host_entry)
-{
- char ** p;
- if (strchr(host_entry->h_name, '.')) {
- return host_entry->h_name;
- } else {
- for (p = host_entry->h_aliases; *p; ++p) {
- if (strchr(*p, '.'))
- return *p;
- }
- }
- return host_entry->h_name;
-}
-
-/* uname() on FreeBSD is broken, because the 'nodename' buf is too small
- * to hold a valid (leftmost) domain label.
- */
-#if defined(HAVE_UNAME) && !defined(HOST_IS_FREEBSD)
-#include <sys/utsname.h>
-void sh_unix_localhost()
-{
- struct utsname buf;
- int i;
- unsigned int ddot;
- int len;
- char * p;
- char hostname[256];
- char numeric[SH_IP_BUF];
- char * canonical;
-
-
- SL_ENTER(_("sh_unix_localhost"));
-
- (void) uname (&buf);
- /* flawfinder: ignore */ /* ff bug, ff sees system() */
- sl_strlcpy (sh.host.system, buf.sysname, SH_MINIBUF);
- sl_strlcpy (sh.host.release, buf.release, SH_MINIBUF);
- sl_strlcpy (sh.host.machine, buf.machine, SH_MINIBUF);
-
- /* Workaround for cases where nodename could be
- * a truncated FQDN.
- */
- if (strlen(buf.nodename) == (sizeof(buf.nodename)-1))
- {
- p = strchr(buf.nodename, '.');
- if (NULL != p) {
- *p = '\0';
- sl_strlcpy(hostname, buf.nodename, 256);
- } else {
-#ifdef HAVE_GETHOSTNAME
- if (0 != gethostname(hostname, 256))
- {
- sh_error_handle(SH_ERR_WARN, FIL__, __LINE__, 0, MSG_E_SUBGEN,
- _("nodename returned by uname may be truncated"),
- _("sh_unix_localhost"));
- sl_strlcpy (hostname, buf.nodename, 256);
- }
- else
- {
- hostname[255] = '\0';
- }
-#else
- sh_error_handle(SH_ERR_WARN, FIL__, __LINE__, 0, MSG_E_SUBGEN,
- _("nodename returned by uname may be truncated"),
- _("sh_unix_localhost"));
- sl_strlcpy(hostname, buf.nodename, 256);
-#endif
- }
- }
- else
- {
- sl_strlcpy(hostname, buf.nodename, 256);
- }
-
- canonical = sh_ipvx_canonical(hostname, numeric, sizeof(numeric));
-
- if (canonical == NULL)
- {
- sl_strlcpy (sh.host.name, hostname, SH_PATHBUF);
- sh_tolower (sh.host.name);
- }
- else
- {
- sl_strlcpy (sh.host.name, canonical, SH_PATHBUF);
- SH_FREE(canonical);
- }
-
- /* check whether it looks like a FQDN
- */
- len = sl_strlen(sh.host.name);
- ddot = 0;
- for (i = 0; i < len; ++i)
- if (sh.host.name[i] == '.') ++ddot;
-
- if (ddot == 0)
- {
- dlog(1, FIL__, __LINE__,
- _("According to uname, your nodename is %s, but your resolver\nlibrary cannot resolve this nodename to a FQDN.\nRather, it resolves this to %s.\nFor more information, see the entry about self-resolving under\n'Most frequently' in the FAQ that you will find in the docs/ subdirectory.\n"),
- hostname, sh.host.name);
- sl_strlcpy (sh.host.name, numeric, SH_PATHBUF);
- SL_RET0(_("sh_unix_localhost"));
- }
-
- if (sh_ipvx_is_numeric(sh.host.name))
- {
- dlog(1, FIL__, __LINE__,
- _("According to uname, your nodename is %s, but your resolver\nlibrary cannot resolve this nodename to a FQDN.\nRather, it resolves this to %s.\nFor more information, see the entry about self-resolving under\n'Most frequently' in the FAQ that you will find in the docs/ subdirectory.\n"),
- hostname, sh.host.name);
- }
-
- SL_RET0(_("sh_unix_localhost"));
-}
-
-#else
-
-/*
- * --FreeBSD code
- */
-#if defined(HAVE_UNAME)
-#include <sys/utsname.h>
-#endif
-void sh_unix_localhost()
-{
-#if defined(HAVE_UNAME)
- struct utsname buf;
-#endif
- int i;
- int ddot;
- int len;
- char hostname[1024];
- char numeric[SH_IP_BUF];
- char * canonical;
-
- SL_ENTER(_("sh_unix_localhost"));
-
-#if defined(HAVE_UNAME)
- (void) uname (&buf);
- /* flawfinder: ignore */ /* ff bug, ff sees system() */
- sl_strlcpy (sh.host.system, buf.sysname, SH_MINIBUF);
- sl_strlcpy (sh.host.release, buf.release, SH_MINIBUF);
- sl_strlcpy (sh.host.machine, buf.machine, SH_MINIBUF);
-#endif
-
- (void) gethostname (hostname, 1024);
- hostname[1023] = '\0';
-
- canonical = sh_ipvx_canonical(hostname, numeric, sizeof(numeric));
-
- if (canonical == NULL)
- {
- sl_strlcpy (sh.host.name, hostname, SH_PATHBUF);
- sh_tolower (sh.host.name);
- }
- else
- {
- sl_strlcpy (sh.host.name, canonical, SH_PATHBUF);
- SH_FREE(canonical);
- }
-
- /* check whether it looks like a FQDN
- */
- len = sl_strlen(sh.host.name);
- ddot = 0;
- for (i = 0; i < len; ++i)
- if (sh.host.name[i] == '.') ++ddot;
- if (ddot == 0)
- {
- dlog(1, FIL__, __LINE__,
- _("According to uname, your nodename is %s, but your resolver\nlibrary cannot resolve this nodename to a FQDN.\nRather, it resolves this to %s.\nFor more information, see the entry about self-resolving under\n'Most frequently' in the FAQ that you will find in the docs/ subdirectory.\n"),
- hostname, sh.host.name);
- sl_strlcpy (sh.host.name, numeric, SH_PATHBUF);
- SL_RET0(_("sh_unix_localhost"));
- }
-
- if (sh_ipvx_is_numeric(sh.host.name))
- {
- dlog(1, FIL__, __LINE__,
- _("According to uname, your nodename is %s, but your resolver\nlibrary cannot resolve this nodename to a FQDN.\nRather, it resolves this to %s.\nFor more information, see the entry about self-resolving under\n'Most frequently' in the FAQ that you will find in the docs/ subdirectory.\n"),
- hostname, sh.host.name);
- }
-
- SL_RET0(_("sh_unix_localhost"));
-}
-#endif
-
-
-void sh_unix_memlock()
-{
- SL_ENTER(_("sh_unix_memlock"));
-
- /* do this before dropping privileges
- */
-#if defined(HAVE_MLOCK) && !defined(HAVE_BROKEN_MLOCK)
- if (skey->mlock_failed == S_FALSE)
- {
- if ( (-1) == sh_unix_mlock( FIL__, __LINE__,
- (char *) skey, sizeof (sh_key_t)) )
- {
- SH_MUTEX_LOCK_UNSAFE(mutex_skey);
- skey->mlock_failed = S_TRUE;
- SH_MUTEX_UNLOCK_UNSAFE(mutex_skey);
- }
- }
-#else
- if (skey->mlock_failed == S_FALSE)
- {
- SH_MUTEX_LOCK_UNSAFE(mutex_skey);
- skey->mlock_failed = S_TRUE;
- SH_MUTEX_UNLOCK_UNSAFE(mutex_skey);
- }
-#endif
-
- SL_RET0(_("sh_unix_memlock"));
-}
-
-#ifdef SH_WITH_SERVER
-char * chroot_dir = NULL;
-
-int sh_unix_set_chroot(const char * str)
-{
- size_t len;
- static int block = 0;
-
- if (block == 1)
- return 0;
-
- if (str && *str == '/')
- {
- len = strlen(str) + 1;
- chroot_dir = calloc(1,strlen(str) + 1); /* only once */
- if (!chroot_dir)
- {
- fprintf(stderr, _("%s: %d: Out of memory\n"), FIL__, __LINE__);
- return 1;
- }
- sl_strlcpy(chroot_dir, str, len);
- block = 1;
- return 0;
- }
- return 1;
-}
-
-int sh_unix_chroot(void)
-{
- int status;
-
- if (chroot_dir != NULL)
- {
- status = retry_aud_chdir(FIL__, __LINE__, chroot_dir);
- if ( (-1) == status )
- {
- char errbuf[SH_ERRBUF_SIZE];
- status = errno;
- sh_error_handle ((-1), FIL__, __LINE__, status, MSG_W_CHDIR,
- sh_error_message (status, errbuf, sizeof(errbuf)), chroot_dir);
- aud_exit(FIL__, __LINE__, EXIT_FAILURE);
- }
- /* flawfinder: ignore */
- return (chroot(chroot_dir));
- }
- return 0;
-}
-/* #ifdef SH_WITH_SERVER */
-#else
-int sh_unix_chroot(void) { return 0; }
-#endif
-
-/* daemon mode
- */
-static int block_setdeamon = 0;
-
-int sh_unix_setdeamon(const char * dummy)
-{
- int res = 0;
-
- SL_ENTER(_("sh_unix_setdeamon"));
-
- if (block_setdeamon != 0)
- SL_RETURN((0),_("sh_unix_setdeamon"));
-
- if (dummy == NULL)
- sh.flag.isdaemon = S_TRUE;
- else
- res = sh_util_flagval (dummy, &sh.flag.isdaemon);
-
- if (sh.flag.opts == S_TRUE)
- block_setdeamon = 1;
-
- SL_RETURN(res, _("sh_unix_setdeamon"));
-}
-#if defined(HAVE_LIBPRELUDE)
-#include "sh_prelude.h"
-#endif
-
-int sh_unix_setnodeamon(const char * dummy)
-{
- int res = 0;
-
- SL_ENTER(_("sh_unix_setnodeamon"));
-
- if (block_setdeamon != 0)
- SL_RETURN((0),_("sh_unix_setmodeamon"));
-
- if (dummy == NULL)
- sh.flag.isdaemon = S_FALSE;
- else
- res = sh_util_flagval (dummy, &sh.flag.isdaemon);
-
- if (sh.flag.opts == S_TRUE)
- block_setdeamon = 1;
-
- SL_RETURN(res, _("sh_unix_setnodeamon"));
-}
-
-int sh_unix_init(int goDaemon)
-{
- int status;
- uid_t uid;
- pid_t oldpid = getpid();
-#if defined(SH_WITH_SERVER)
- extern int sh_socket_open_int (void);
-#endif
- char errbuf[SH_ERRBUF_SIZE];
-
- extern void sh_kill_sub();
-
- SL_ENTER(_("sh_unix_init"));
-
- /* fork twice, exit the parent process
- */
- if (goDaemon == 1) {
-
- switch (aud_fork(FIL__, __LINE__)) {
- case 0: break; /* child process continues */
- case -1: SL_RETURN((-1),_("sh_unix_init")); /* error */
- default: /* parent process exits */
- sh_kill_sub();
- aud__exit(FIL__, __LINE__, 0);
- }
-
- /* Child processes do not inherit page locks across a fork.
- * Error in next fork would return in this (?) thread of execution.
- */
- sh_unix_memlock();
-
- setsid(); /* should not fail */
- sh.pid = (UINT64) getpid();
-
- switch (aud_fork(FIL__, __LINE__)) {
- case 0: break; /* child process continues */
- case -1: SL_RETURN((-1),_("sh_unix_init")); /* error */
- default: /* parent process exits */
- sh_kill_sub();
- aud__exit(FIL__, __LINE__, 0);
- }
-
- /* Child processes do not inherit page locks across a fork.
- */
- sh_unix_memlock();
- sh.pid = (UINT64) getpid();
-
- } else {
- setsid(); /* should not fail */
- }
-
- /* set working directory
- */
-#ifdef SH_PROFILE
- status = 0;
-#else
- status = retry_aud_chdir(FIL__, __LINE__, "/");
-#endif
- if ( (-1) == status )
- {
- status = errno;
- sh_error_handle ((-1), FIL__, __LINE__, status, MSG_W_CHDIR,
- sh_error_message (status, errbuf, sizeof(errbuf)), "/");
- aud_exit(FIL__, __LINE__, EXIT_FAILURE);
- }
-
- /* reset timers
- */
- sh_unix_resettimer();
-
- /* signal handlers
- */
- sh_unix_resetsignals();
-#if defined(SCREW_IT_UP)
- sh_sigtrap_prepare();
-#endif
- sh_unix_siginstall (goDaemon);
-
- /* set file creation mask
- */
- (void) umask (0); /* should not fail */
-
- /* set resource limits to maximum, and
- * core dump size to zero
- */
- sh_unix_setlimits();
-
- /* zero out the environment (like PATH='\0')
- */
- sh_unix_zeroenv();
-
- if (goDaemon == 1)
- {
- /* Close first tree file descriptors
- */
- sl_close_fd (FIL__, __LINE__, 0); /* if running as daemon */
- sl_close_fd (FIL__, __LINE__, 1); /* if running as daemon */
- sl_close_fd (FIL__, __LINE__, 2); /* if running as daemon */
-
- /* Enable full error logging
- */
- sh_error_only_stderr (S_FALSE);
-
- /* open first three streams to /dev/null
- */
- status = aud_open(FIL__, __LINE__, SL_NOPRIV, _("/dev/null"), O_RDWR, 0);
- if (status < 0)
- {
- status = errno;
- sh_error_handle((-1), FIL__, __LINE__, status, MSG_E_SUBGEN,
- sh_error_message(status, errbuf, sizeof(errbuf)), _("open"));
- aud_exit(FIL__, __LINE__, EXIT_FAILURE);
- }
-
- status = retry_aud_dup(FIL__, __LINE__, 0);
- if (status >= 0)
- retry_aud_dup(FIL__, __LINE__, 0);
-
- if (status < 0)
- {
- status = errno;
- sh_error_handle((-1), FIL__, __LINE__, status, MSG_E_SUBGEN,
- sh_error_message(status, errbuf, sizeof(errbuf)), _("dup"));
- aud_exit(FIL__, __LINE__, EXIT_FAILURE);
- }
-
- sh_error_enable_unsafe (S_TRUE);
-#if defined(HAVE_LIBPRELUDE)
- sh_prelude_reset ();
-#endif
-
- /* --- wait until parent has exited ---
- */
- while (1 == 1)
- {
- errno = 0;
- if (0 > aud_kill (FIL__, __LINE__, oldpid, 0) && errno == ESRCH)
- {
- break;
- }
- retry_msleep(0, 1);
- }
-
- /* write PID file
- */
- status = sh_unix_write_pid_file();
- if (status < 0)
- {
- sl_get_euid(&uid);
- sh_error_handle ((-1), FIL__, __LINE__, status, MSG_PIDFILE,
- (long) uid, sh.srvlog.alt);
- aud_exit(FIL__, __LINE__, EXIT_FAILURE);
- }
-#if defined(SH_WITH_SERVER)
- sh_socket_open_int ();
-#endif
- }
- else
- {
- sh_error_enable_unsafe (S_TRUE);
-#if defined(HAVE_LIBPRELUDE)
- sh_prelude_reset ();
-#endif
-#if defined(SH_WITH_SERVER)
- sh_socket_open_int ();
-#endif
- }
-
- /* chroot (this is a no-op if no chroot dir is specified
- */
- status = sh_unix_chroot();
- if (status < 0)
- {
- status = errno;
- sh_error_handle((-1), FIL__, __LINE__, status, MSG_E_SUBGEN,
- sh_error_message(status, errbuf, sizeof(errbuf)), _("chroot"));
- aud_exit(FIL__, __LINE__, EXIT_FAILURE);
- }
-
- /* drop capabilities
- */
- sl_drop_cap();
-
- SL_RETURN((0),_("sh_unix_init"));
-}
-
-/* --- run a command, securely --- */
-
-int sh_unix_run_command (const char * str)
-{
- pid_t pid;
- char * arg[4];
- char * env[5];
- char * path = sh_util_strdup(_("/bin/sh"));
-
- int status = -1;
-
- arg[0] = sh_util_strdup(_("/bin/sh"));
- arg[1] = sh_util_strdup(_("-c"));
- arg[2] = sh_util_strdup(str);
- arg[3] = NULL;
-
- env[0] = sh_util_strdup(_("PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/ucb"));
- env[1] = sh_util_strdup(_("SHELL=/bin/sh"));
- env[2] = sh_util_strdup(_("IFS= \t\n"));
- if (getenv("TZ")) { /* flawfinder: ignore */
- char * tz = sh_util_strdup(getenv("TZ")); /* flawfinder: ignore */
- size_t tzlen = strlen(tz);
- if (S_TRUE == sl_ok_adds (4, tzlen)) {
- env[3] = SH_ALLOC(4+tzlen);
- sl_strlcpy(env[3], "TZ=", 4);
- sl_strlcat(env[3], tz , 4+tzlen);
- } else {
- env[3] = NULL;
- }
- } else {
- env[3] = NULL;
- }
- env[4] = NULL;
-
- pid = fork();
-
- if (pid == (pid_t)(-1))
- {
- return -1;
- }
-
- else if (pid == 0) /* child */
- {
- memset(skey, 0, sizeof(sh_key_t));
- (void) umask(S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH);
- sh_unix_closeall (3, -1, S_TRUE); /* in child process */
- execve(path, arg, env);
- _exit(EXIT_FAILURE);
- }
-
- else /* parent */
- {
- int r;
-
- while((r = waitpid(pid, &status, WUNTRACED)) != pid && r != -1) ;
-
-#if !defined(USE_UNO)
- if (r == -1 || !WIFEXITED(status))
- {
- status = -1;
- }
- else
- {
- status = WEXITSTATUS(status);
- }
-#endif
- }
-
- return status;
-}
-
-/********************************************************
- *
- * TIME
- *
- ********************************************************/
-
-/* Figure out the time offset of the current timezone
- * in a portable way.
- */
-char * t_zone(const time_t * xx)
-{
- struct tm aa;
- struct tm bb;
-
- struct tm * aptr;
- struct tm * bptr;
-
- int sign = 0;
- int diff = 0;
- int hh, mm;
- static char tz[64];
-
- SL_ENTER(_("t_zone"));
-
-#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GMTIME_R)
- aptr = gmtime_r (xx, &aa);
-#else
- aptr = gmtime(xx);
- if (aptr)
- memcpy (&aa, aptr, sizeof(struct tm));
-#endif
-
-#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_LOCALTIME_R)
- bptr = localtime_r (xx, &bb);
-#else
- bptr = localtime(xx);
- if (bptr)
- memcpy (&bb, bptr, sizeof(struct tm));
-#endif
-
- if (bptr && aptr)
- {
- /* Check for datum wrap-around.
- */
- if ((aa.tm_mday == 1) && (aa.tm_mday < bb.tm_mday) && (aa.tm_hour < bb.tm_hour))
- sign = ( 1);
- else if (aa.tm_year < bb.tm_year)
- sign = (-1);
- else if (aa.tm_mon < bb.tm_mon)
- sign = (-1);
- else if (aa.tm_mday < bb.tm_mday)
- sign = (-1);
- else if (bb.tm_year < aa.tm_year)
- sign = ( 1);
- else if (bb.tm_mon < aa.tm_mon)
- sign = ( 1);
- else if (bb.tm_mday < aa.tm_mday)
- sign = ( 1);
-
- diff = aa.tm_hour * 60 + aa.tm_min;
- diff = (bb.tm_hour * 60 + bb.tm_min) - diff;
- diff = diff - (sign * 24 * 60); /* datum wrap-around correction */
- hh = diff / 60;
- mm = diff - (hh * 60);
- sprintf (tz, _("%+03d%02d"), hh, mm); /* known to fit */
- }
- else
- {
- sprintf (tz, _("%+03d%02d"), 0, 0);
- }
- SL_RETURN(tz, _("t_zone"));
-}
-
-unsigned long sh_unix_longtime ()
-{
- return ((unsigned long)time(NULL));
-}
-
-#ifdef HAVE_GETTIMEOFDAY
-unsigned long sh_unix_notime ()
-{
- struct timeval tv;
-
- gettimeofday (&tv, NULL);
-
- return ((unsigned long)(tv.tv_sec + tv.tv_usec * 10835 + getpid() + getppid()));
-
-}
-#endif
-
-static int count_dev_time = 0;
-
-void reset_count_dev_time(void)
-{
- count_dev_time = 0;
- return;
-}
-
-int sh_unix_settimeserver (const char * address)
-{
-
- SL_ENTER(_("sh_unix_settimeserver"));
-
- if (address != NULL && count_dev_time < 2
- && sl_strlen(address) < SH_PATHBUF)
- {
- if (count_dev_time == 0)
- sl_strlcpy (sh.srvtime.name, address, SH_PATHBUF);
- else
- sl_strlcpy (sh.srvtime.alt, address, SH_PATHBUF);
-
- ++count_dev_time;
- SL_RETURN((0), _("sh_unix_settimeserver"));
- }
- SL_RETURN((-1), _("sh_unix_settimeserver"));
-}
-
-
-#ifdef HAVE_NTIME
-#define UNIXEPOCH 2208988800UL /* difference between Unix time and net time
- * The UNIX EPOCH starts in 1970.
- */
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <ctype.h>
-#endif
-
-/* Timeserver service. */
-/* define is missing on HP-UX 10.20 */
-#ifndef IPPORT_TIMESERVER
-#define IPPORT_TIMESERVER 37
-#endif
-
-char * sh_unix_time (time_t thetime, char * buffer, size_t len)
-{
-
- int status;
- char AsciiTime[81]; /* local time */
- time_t time_now;
- struct tm * time_ptr;
-#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_LOCALTIME_R)
- struct tm time_tm;
-#endif
-#ifdef SH_USE_XML
- static char deftime[] = N_("0000-00-00T00:00:00"); /* default time */
-#else
- static char deftime[] = N_("[0000-00-00T00:00:00]"); /* default time */
-#endif
-
-#ifdef HAVE_NTIME
- int fd; /* network file descriptor */
- u_char net_time[4]; /* remote time in network format */
- static int failerr = 0; /* no net time */
- int fail = 0; /* no net time */
- int errflag;
- char errmsg[256];
- char error_call[SH_MINIBUF];
- int error_num;
-#endif
-
- SL_ENTER(_("sh_unix_time"));
-
-#ifdef HAVE_NTIME
- if (thetime == 0)
- {
- if (sh.srvtime.name[0] == '\0')
- {
- fail = 1;
- (void) time (&time_now);
- }
- else /* have a timeserver address */
- {
- /* don't call timeserver more than once per second */
- static time_t time_old = 0;
- time_t time_new;
- static time_t time_saved = 0;
- (void) time (&time_new);
- if ((time_new == time_old) && (time_saved != 0))
- {
- time_now = time_saved;
- goto end;
- }
- time_old = time_new;
-
-
- fd = connect_port_2 (sh.srvtime.name, sh.srvtime.alt,
- IPPORT_TIMESERVER,
- error_call, &error_num, errmsg, sizeof(errmsg));
- if (fd >= 0)
- {
- if (4 != read_port (fd, (char *) net_time, 4, &errflag, 2))
- {
- fail = 1;
- sh_error_handle ((-1), FIL__, __LINE__, errflag,
- MSG_E_NLOST,
- _("time"), sh.srvtime.name);
- }
- sl_close_fd(FIL__, __LINE__, fd);
- }
- else
- {
- sh_error_handle ((-1), FIL__, __LINE__, error_num,
- MSG_E_NET, errmsg, error_call,
- _("time"), sh.srvtime.name);
- fail = 1;
- }
-
- if (fail == 0)
- {
- unsigned long ltmp;
- UINT32 ttmp;
- memcpy(&ttmp, net_time, sizeof(UINT32)); ltmp = ttmp;
- time_now = ntohl(ltmp) - UNIXEPOCH;
- time_saved = time_now;
-
- if (failerr == 1) {
- failerr = 0;
- sh_error_handle ((-1), FIL__, __LINE__, 0,
- MSG_E_NEST,
- _("time"), sh.srvtime.name);
- }
- }
- else
- {
- (void) time (&time_now);
- time_saved = 0;
-
- if (failerr == 0)
- {
- failerr = 1;
- sh_error_handle ((-1), FIL__, __LINE__, errflag,
- MSG_SRV_FAIL,
- _("time"), sh.srvtime.name);
- }
- }
- end:
- ; /* 'label at end of compound statement' */
- }
- }
- else
- {
- time_now = thetime;
- }
-
- /* #ifdef HAVE_NTIME */
-#else
-
- if (thetime == 0)
- {
- (void) time (&time_now);
- }
- else
- {
- time_now = thetime;
- }
-
- /* #ifdef HAVE_NTIME */
-#endif
-
- if (time_now == (-1) )
- {
- sl_strlcpy(buffer, _(deftime), len);
- SL_RETURN(buffer, _("sh_unix_time"));
- }
- else
- {
-#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_LOCALTIME_R)
- time_ptr = localtime_r (&time_now, &time_tm);
-#else
- time_ptr = localtime (&time_now);
-#endif
- }
- if (time_ptr != NULL)
- {
- status = strftime (AsciiTime, sizeof(AsciiTime),
-#ifdef SH_USE_XML
- _("%Y-%m-%dT%H:%M:%S%%s"),
-#else
- _("[%Y-%m-%dT%H:%M:%S%%s]"),
-#endif
- time_ptr);
-
- sl_snprintf(buffer, len, AsciiTime, t_zone(&time_now));
-
- if ( (status == 0) || (status == sizeof(AsciiTime)) )
- {
- sl_strlcpy(buffer, _(deftime), len);
- SL_RETURN( buffer, _("sh_unix_time"));
- }
- else
- {
- SL_RETURN(buffer, _("sh_unix_time"));
- }
- }
-
- /* last resort
- */
- sl_strlcpy(buffer, _(deftime), len);
- SL_RETURN( buffer, _("sh_unix_time"));
-}
-
-static int sh_unix_use_localtime = S_FALSE;
-
-/* whether to use localtime for file timestamps in logs
- */
-int sh_unix_uselocaltime (const char * c)
-{
- int i;
- SL_ENTER(_("sh_unix_uselocaltime"));
- i = sh_util_flagval(c, &(sh_unix_use_localtime));
-
- SL_RETURN(i, _("sh_unix_uselocaltime"));
-}
-
-char * sh_unix_gmttime (time_t thetime, char * buffer, size_t len)
-{
-
- int status;
-
- struct tm * time_ptr;
-#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS)
- struct tm time_tm;
-#endif
- char AsciiTime[81]; /* GMT time */
-#ifdef SH_USE_XML
- static char deftime[] = N_("0000-00-00T00:00:00"); /* default time */
-#else
- static char deftime[] = N_("[0000-00-00T00:00:00]"); /* default time */
-#endif
-
- SL_ENTER(_("sh_unix_gmttime"));
-
- if (sh_unix_use_localtime == S_FALSE)
- {
-#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GMTIME_R)
- time_ptr = gmtime_r (&thetime, &time_tm);
-#else
- time_ptr = gmtime (&thetime);
-#endif
- }
- else
- {
-#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_LOCALTIME_R)
- time_ptr = localtime_r (&thetime, &time_tm);
-#else
- time_ptr = localtime (&thetime);
-#endif
- }
- if (time_ptr != NULL)
- {
- status = strftime (AsciiTime, 80,
-#ifdef SH_USE_XML
- _("%Y-%m-%dT%H:%M:%S"),
-#else
- _("[%Y-%m-%dT%H:%M:%S]"),
-#endif
- time_ptr);
-
- if ( (status == 0) || (status == 80) )
- sl_strlcpy(buffer, _(deftime), len);
- else
- sl_strlcpy(buffer, AsciiTime, len);
- SL_RETURN( buffer, _("sh_unix_gmttime"));
- }
-
- /* last resort
- */
- sl_strlcpy(buffer, _(deftime), len);
- SL_RETURN( buffer, _("sh_unix_gmttime"));
-}
-
-
-char * sh_unix_getUIDdir (int level, uid_t uid, char * out, size_t len)
-{
- struct passwd * tempres;
- int status = 0;
-
-#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWUID_R)
- struct passwd pwd;
- char * buffer;
-#endif
- char errbuf[SH_ERRBUF_SIZE];
-
- SL_ENTER(_("sh_unix_getUIDdir"));
-
-#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWUID_R)
- buffer = SH_ALLOC(SH_PWBUF_SIZE);
- sh_getpwuid_r(uid, &pwd, buffer, SH_PWBUF_SIZE, &tempres);
-#else
- errno = 0;
- tempres = sh_getpwuid(uid);
- status = errno;
-#endif
-
- if (tempres == NULL) {
- sh_error_handle (level, FIL__, __LINE__, EINVAL, MSG_E_PWNULL,
- sh_error_message(status, errbuf, sizeof(errbuf)),
- _("getpwuid"), (long) uid, _("completely missing"));
-#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R)
- SH_FREE(buffer);
-#endif
- SL_RETURN( NULL, _("sh_unix_getUIDdir"));
- }
-
- if (tempres->pw_dir != NULL) {
- sl_strlcpy(out, tempres->pw_dir, len);
-#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R)
- SH_FREE(buffer);
-#endif
- SL_RETURN( out, _("sh_unix_getUIDdir"));
- } else {
- sh_error_handle (level, FIL__, __LINE__, EINVAL, MSG_E_PWNULL,
- sh_error_message(status, errbuf, sizeof(errbuf)),
- _("getpwuid"), (long) uid, _("pw_dir"));
-#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R)
- SH_FREE(buffer);
-#endif
- SL_RETURN( NULL, _("sh_unix_getUIDdir"));
- }
-}
-
-/* ------------------- Caching ----------------*/
-#include "zAVLTree.h"
-
-#define CACHE_GID 0
-#define CACHE_UID 1
-
-struct user_id {
- char * name;
- uid_t id;
- struct user_id * next;
-};
-
-static struct user_id * uid_list = NULL;
-static struct user_id * gid_list = NULL;
-
-SH_MUTEX_STATIC(mutex_cache, PTHREAD_MUTEX_INITIALIZER);
-
-static void sh_userid_free(struct user_id * item)
-{
- while (item)
- {
- struct user_id * user = item;
- item = item->next;
-
- SH_FREE(user->name);
- SH_FREE(user);
- }
- return;
-}
-
-void sh_userid_destroy ()
-{
- struct user_id * tmp_uid;
- struct user_id * tmp_gid;
-
- SH_MUTEX_LOCK_UNSAFE(mutex_cache);
- tmp_gid = gid_list;
- gid_list = NULL;
- tmp_uid = uid_list;
- uid_list = NULL;
- SH_MUTEX_UNLOCK_UNSAFE(mutex_cache);
-
- sh_userid_free(tmp_uid);
- sh_userid_free(tmp_gid);
- return;
-}
-
-static void sh_userid_additem(struct user_id * list, struct user_id * item)
-{
- if (list)
- {
- while (list && list->next)
- list = list->next;
- list->next = item;
- }
- return;
-}
-
-static void sh_userid_add(uid_t id, char * username, int which)
-{
- size_t len;
- struct user_id * user = SH_ALLOC(sizeof(struct user_id));
-
- if (username)
- len = strlen(username) + 1;
- else
- len = 1;
-
- user->name = SH_ALLOC(len);
- user->id = id;
- if (username)
- sl_strlcpy(user->name, username, len);
- else
- user->name[0] = '\0';
- user->next = NULL;
-
- SH_MUTEX_LOCK(mutex_cache);
- if (which == CACHE_UID)
- {
- if (!uid_list)
- uid_list = user;
- else
- sh_userid_additem(uid_list, user);
- }
- else
- {
- if (!gid_list)
- gid_list = user;
- else
- sh_userid_additem(gid_list, user);
- }
- SH_MUTEX_UNLOCK(mutex_cache);
-
- return;
-}
-
-static char * sh_userid_search(struct user_id * list, uid_t id)
-{
- while (list)
- {
- if (list->id == id)
- return list->name;
- list = list->next;
- }
- return NULL;
-}
-
-static char * sh_userid_get (uid_t id, int which, char * out, size_t len)
-{
- char * user = NULL;
-
- SH_MUTEX_LOCK_UNSAFE(mutex_cache);
- if (which == CACHE_UID)
- user = sh_userid_search(uid_list, id);
- else
- user = sh_userid_search(gid_list, id);
- if (user)
- {
- sl_strlcpy(out, user, len);
- user = out;
- }
- SH_MUTEX_UNLOCK_UNSAFE(mutex_cache);
-
- return user;
-}
-
-/* --------- end caching code --------- */
-
-char * sh_unix_getUIDname (int level, uid_t uid, char * out, size_t len)
-{
- struct passwd * tempres;
-#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWUID_R)
- struct passwd pwd;
- char * buffer;
-#endif
- int status = 0;
- char errbuf[SH_ERRBUF_SIZE];
- char * tmp;
-
- SL_ENTER(_("sh_unix_getUIDname"));
-
- tmp = sh_userid_get(uid, CACHE_UID, out, len);
-
- if (tmp)
- {
- if (tmp[0] != '\0')
- {
- SL_RETURN( out, _("sh_unix_getUIDname"));
- }
- else
- {
- SL_RETURN( NULL, _("sh_unix_getUIDname"));
- }
- }
-
-#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWUID_R)
- buffer = SH_ALLOC(SH_PWBUF_SIZE);
- sh_getpwuid_r(uid, &pwd, buffer, SH_PWBUF_SIZE, &tempres);
-#else
- errno = 0;
- tempres = sh_getpwuid(uid);
- status = errno;
-#endif
-
- if (tempres == NULL)
- {
- sh_error_handle (level, FIL__, __LINE__, EINVAL, MSG_E_PWNULL,
- sh_error_message(status, errbuf, sizeof(errbuf)),
- _("getpwuid"), (long) uid, _("completely missing"));
-#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R)
- SH_FREE(buffer);
-#endif
- sh_userid_add(uid, NULL, CACHE_UID);
- SL_RETURN( NULL, _("sh_unix_getUIDname"));
- }
-
-
- if (tempres->pw_name != NULL)
- {
-
- sl_strlcpy(out, tempres->pw_name, len);
- sh_userid_add(uid, out, CACHE_UID);
-
-#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R)
- SH_FREE(buffer);
-#endif
-
- SL_RETURN( out, _("sh_unix_getUIDname"));
- }
- else
- {
- sh_error_handle (level, FIL__, __LINE__, EINVAL, MSG_E_PWNULL,
- sh_error_message(status, errbuf, sizeof(errbuf)),
- _("getpwuid"), (long) uid, _("pw_user"));
-#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R)
- SH_FREE(buffer);
-#endif
- SL_RETURN( NULL, _("sh_unix_getUIDname"));
- }
- /* notreached */
-}
-
-char * sh_unix_getGIDname (int level, gid_t gid, char * out, size_t len)
-{
- struct group * tempres;
- int status = 0;
-
-#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R)
- struct group grp;
- char * buffer;
-#endif
- char errbuf[SH_ERRBUF_SIZE];
- char * tmp;
-
- SL_ENTER(_("sh_unix_getGIDname"));
-
- tmp = sh_userid_get((uid_t)gid, CACHE_GID, out, len);
-
- if (tmp)
- {
- if (tmp[0] != '\0')
- {
- SL_RETURN( out, _("sh_unix_getGIDname"));
- }
- else
- {
- SL_RETURN( NULL, _("sh_unix_getGIDname"));
- }
- }
-
-#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R)
- buffer = SH_ALLOC(SH_GRBUF_SIZE);
- status = sh_getgrgid_r(gid, &grp, buffer, SH_GRBUF_SIZE, &tempres);
-#else
- errno = 0;
- tempres = sh_getgrgid(gid);
- status = errno;
-#endif
-
- if (status == ERANGE)
- {
- static int seen = 0;
-
- if (seen == 0)
- {
- sh_error_handle (SH_ERR_ERR, FIL__, __LINE__, EINVAL, MSG_E_GRNULL,
- sh_error_message(status, errbuf, sizeof(errbuf)),
- _("getgrgid"), (long) gid, _("line too long in group entry"));
- ++seen;
- }
-
-#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R)
- SH_FREE(buffer);
-#endif
-
- sh_userid_add(gid, NULL, CACHE_GID);
- SL_RETURN( NULL, _("sh_unix_getGIDname"));
- }
-
- if (tempres == NULL)
- {
- sh_error_handle (level, FIL__, __LINE__, EINVAL, MSG_E_GRNULL,
- sh_error_message(status, errbuf, sizeof(errbuf)),
- _("getgrgid"), (long) gid, _("completely missing"));
-
-#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R)
- SH_FREE(buffer);
-#endif
-
- sh_userid_add(gid, NULL, CACHE_GID);
- SL_RETURN( NULL, _("sh_unix_getGIDname"));
- }
-
- if (tempres->gr_name != NULL)
- {
-
- sl_strlcpy(out, tempres->gr_name, len);
- sh_userid_add((uid_t)gid, out, CACHE_GID);
-
-#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R)
- SH_FREE(buffer);
-#endif
-
- SL_RETURN( out, _("sh_unix_getGIDname"));
- }
- else
- {
- sh_error_handle (level, FIL__, __LINE__, EINVAL, MSG_E_GRNULL,
- sh_error_message(status, errbuf, sizeof(errbuf)),
- _("getgrgid"), (long) gid, _("gr_name"));
-
-#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R)
- SH_FREE(buffer);
-#endif
-
- SL_RETURN( NULL, _("sh_unix_getGIDname"));
- }
- /* notreached */
-}
-
-int sh_unix_getUser ()
-{
- char * p;
- uid_t seuid, sruid;
- char user[USER_MAX];
- char dir[SH_PATHBUF];
-
- SL_ENTER(_("sh_unix_getUser"));
-
- seuid = geteuid();
-
- sh.effective.uid = seuid;
-
- p = sh_unix_getUIDdir (SH_ERR_ERR, seuid, dir, sizeof(dir));
-
- if (p == NULL)
- SL_RETURN((-1), _("sh_unix_getUser"));
- else
- {
- if (sl_strlen(p) >= SH_PATHBUF) {
- sh_error_handle (SH_ERR_ERR, FIL__, __LINE__, EINVAL, MSG_E_PWLONG,
- _("getpwuid"), (long) seuid, _("pw_home"));
- SL_RETURN((-1), _("sh_unix_getUser"));
- } else {
- sl_strlcpy ( sh.effective.home, p, SH_PATHBUF);
- }
- }
-
- sruid = getuid();
-
- sh.real.uid = sruid;
-
- p = sh_unix_getUIDname (SH_ERR_ERR, sruid, user, sizeof(user));
- if (p == NULL)
- SL_RETURN((-1), _("sh_unix_getUser"));
- else
- {
- if (sl_strlen(p) >= USER_MAX) {
- sh_error_handle (SH_ERR_ERR, FIL__, __LINE__, EINVAL, MSG_E_PWLONG,
- _("getpwuid"), (long) sruid, _("pw_user"));
- SL_RETURN((-1), _("sh_unix_getUser"));
- } else {
- sl_strlcpy ( sh.real.user, p, USER_MAX);
- }
- }
-
- p = sh_unix_getUIDdir (SH_ERR_ERR, sruid, dir, sizeof(dir));
-
- if (p == NULL)
- SL_RETURN((-1), _("sh_unix_getUser"));
- else
- {
- if (sl_strlen(p) >= SH_PATHBUF) {
- sh_error_handle (SH_ERR_ERR, FIL__, __LINE__, EINVAL, MSG_E_PWLONG,
- _("getpwuid"), (long) sruid, _("pw_home"));
- SL_RETURN((-1), _("sh_unix_getUser"));
- } else {
- sl_strlcpy ( sh.real.home, p, SH_PATHBUF);
- }
- }
-
- SL_RETURN((0), _("sh_unix_getUser"));
-
- /* notreached */
-}
-
-
-int sh_unix_getline (SL_TICKET fd, char * line, int sizeofline)
-{
- register int count;
- register int n = 0;
- char c;
-
- SL_ENTER(_("sh_unix_getline"));
-
- if (sizeofline < 2) {
- line[0] = '\0';
- SL_RETURN((0), _("sh_unix_getline"));
- }
-
- --sizeofline;
-
- while (n < sizeofline) {
-
- count = sl_read (fd, &c, 1);
-
- /* end of file
- */
- if (count < 1) {
- line[n] = '\0';
- n = -1;
- break;
- }
-
- if (/* c != '\0' && */ c != '\n') {
- line[n] = c;
- ++n;
- } else if (c == '\n') {
- if (n > 0) {
- line[n] = '\0';
- break;
- } else {
- line[n] = '\n'; /* get newline only if only char on line */
- ++n;
- line[n] = '\0';
- break;
- }
- } else {
- line[n] = '\0';
- break;
- }
-
- }
-
-
- line[sizeofline] = '\0'; /* make sure line is terminated */
- SL_RETURN((n), _("sh_unix_getline"));
-}
-
-
-#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
-
-/**************************************************************
- *
- * --- FILE INFO ---
- *
- **************************************************************/
-
-#if (defined(__linux__) && (defined(HAVE_LINUX_EXT2_FS_H) || defined(HAVE_EXT2FS_EXT2_FS_H))) || defined(HAVE_STAT_FLAGS)
-
-#if defined(__linux__)
-
-/* --- Determine ext2fs file attributes. ---
- */
-#include <sys/ioctl.h>
-#if defined(HAVE_EXT2FS_EXT2_FS_H)
-#include <ext2fs/ext2_fs.h>
-#else
-#include <linux/ext2_fs.h>
-#endif
-
-/* __linux__ includes */
-#endif
-
-static
-int sh_unix_getinfo_attr (char * name,
- unsigned long * flags,
- char * c_attr,
- int fd, struct stat * buf)
-{
-
-/* TAKEN FROM:
- *
- * lsattr.c - List file attributes on an ext2 file system
- *
- * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
- * Laboratoire MASI, Institut Blaise Pascal
- * Universite Pierre et Marie Curie (Paris VI)
- *
- * This file can be redistributed under the terms of the GNU General
- * Public License
- */
-
-#ifdef HAVE_STAT_FLAGS
-
- SL_ENTER(_("sh_unix_getinfo_attr"));
-
- *flags = 0;
-
- /* cast to void to avoid compiler warning about unused parameters */
- (void) fd;
- (void) name;
-
-#ifdef UF_NODUMP
- if (buf->st_flags & UF_NODUMP) {
- *flags |= UF_NODUMP;
- c_attr[0] = 'd';
- }
-#endif
-#ifdef UF_IMMUTABLE
- if (buf->st_flags & UF_IMMUTABLE) {
- *flags |= UF_IMMUTABLE;
- c_attr[1] = 'i';
- }
-#endif
-#ifdef UF_APPEND
- if (buf->st_flags & UF_APPEND) {
- *flags |= UF_APPEND;
- c_attr[2] = 'a';
- }
-#endif
-#ifdef UF_NOUNLINK
- if (buf->st_flags & UF_NOUNLINK) {
- *flags |= UF_NOUNLINK;
- c_attr[3] = 'u';
- }
-#endif
-#ifdef UF_OPAQUE
- if (buf->st_flags & UF_OPAQUE) {
- *flags |= UF_OPAQUE;
- c_attr[4] = 'o';
- }
-#endif
-#ifdef SF_ARCHIVED
- if (buf->st_flags & SF_ARCHIVED) {
- *flags |= SF_ARCHIVED;
- c_attr[5] = 'R';
- }
-
-#endif
-#ifdef SF_IMMUTABLE
- if (buf->st_flags & SF_IMMUTABLE) {
- *flags |= SF_IMMUTABLE;
- c_attr[6] = 'I';
- }
-#endif
-#ifdef SF_APPEND
- if (buf->st_flags & SF_APPEND) {
- *flags |= SF_APPEND;
- c_attr[7] = 'A';
- }
-#endif
-#ifdef SF_NOUNLINK
- if (buf->st_flags & SF_NOUNLINK) {
- *flags |= SF_NOUNLINK;
- c_attr[8] = 'U';
- }
-#endif
-
- /* ! HAVE_STAT_FLAGS */
-#else
-
-#ifdef HAVE_EXT2_IOCTLS
- int /* fd, */ r, f;
-
- SL_ENTER(_("sh_unix_getinfo_attr"));
-
- *flags = 0;
- (void) buf;
-
- /* open() -> aud_open() R.Wichmann
- fd = aud_open (FIL__, __LINE__, SL_YESPRIV, name, O_RDONLY|O_NONBLOCK, 0);
- */
-
- if (fd == -1 || name == NULL)
- SL_RETURN(-1, _("sh_unix_getinfo_attr"));
-
-
- r = ioctl (fd, EXT2_IOC_GETFLAGS, &f);
- /* sl_close_fd (FIL__, __LINE__, fd); */
-
- if (r == -1)
- SL_RETURN(-1, _("sh_unix_getinfo_attr"));
-
- if (f == 0)
- SL_RETURN(0, _("sh_unix_getinfo_attr"));
-
- *flags = f;
-
-/* ! HAVE_EXT2_IOCTLS */
-#else
-
- SL_ENTER(_("sh_unix_getinfo_attr"));
-
- *flags = 0; /* modified by R.Wichmann */
-
-/* ! HAVE_EXT2_IOCTLS */
-#endif
-/*
- * END
- *
- * lsattr.c - List file attributes on an ext2 file system
- */
-
- if (*flags == 0)
- goto theend;
-
-#ifdef EXT2_SECRM_FL
- if ( (*flags & EXT2_SECRM_FL) != 0 ) c_attr[0] = 's';
-#endif
-#ifdef EXT2_UNRM_FL
- if ( (*flags & EXT2_UNRM_FL) != 0 ) c_attr[1] = 'u';
-#endif
-#ifdef EXT2_SYNC_FL
- if ( (*flags & EXT2_SYNC_FL) != 0 ) c_attr[2] = 'S';
-#endif
-#ifdef EXT2_IMMUTABLE_FL
- if ( (*flags & EXT2_IMMUTABLE_FL) != 0) c_attr[3] = 'i';
-#endif
-#ifdef EXT2_APPEND_FL
- if ( (*flags & EXT2_APPEND_FL) != 0 ) c_attr[4] = 'a';
-#endif
-#ifdef EXT2_NODUMP_FL
- if ( (*flags & EXT2_NODUMP_FL) != 0 ) c_attr[5] = 'd';
-#endif
-#ifdef EXT2_NOATIME_FL
- if ( (*flags & EXT2_NOATIME_FL) != 0) c_attr[6] = 'A';
-#endif
-#ifdef EXT2_COMPR_FL
- if ( (*flags & EXT2_COMPR_FL) != 0 ) c_attr[7] = 'c';
-#endif
-
-#ifdef EXT2_TOPDIR_FL
- if ( (*flags & EXT2_TOPDIR_FL) != 0 ) c_attr[8] = 'T';
-#endif
-#ifdef EXT2_DIRSYNC_FL
- if ( (*flags & EXT2_DIRSYNC_FL) != 0 ) c_attr[9] = 'D';
-#endif
-#ifdef EXT2_NOTAIL_FL
- if ( (*flags & EXT2_NOTAIL_FL) != 0 ) c_attr[10] = 't';
-#endif
-#ifdef EXT2_JOURNAL_DATA_FL
- if ( (*flags & EXT2_JOURNAL_DATA_FL) != 0) c_attr[11] = 'j';
-#endif
-
- theend:
- /* ext2 */
-#endif
-
- c_attr[12] = '\0';
-
- SL_RETURN(0, _("sh_unix_getinfo_attr"));
-}
-
-/* defined(__linux__) || defined(HAVE_STAT_FLAGS) */
-#endif
-
-/* determine file type
- */
-static
-int sh_unix_getinfo_type (struct stat * buf,
- ShFileType * type,
- char * c_mode)
-{
- SL_ENTER(_("sh_unix_getinfo_type"));
-
- if ( S_ISREG(buf->st_mode) ) {
- (*type) = SH_FILE_REGULAR;
- c_mode[0] = '-';
- }
- else if ( S_ISLNK(buf->st_mode) ) {
- (*type) = SH_FILE_SYMLINK;
- c_mode[0] = 'l';
- }
- else if ( S_ISDIR(buf->st_mode) ) {
- (*type) = SH_FILE_DIRECTORY;
- c_mode[0] = 'd';
- }
- else if ( S_ISCHR(buf->st_mode) ) {
- (*type) = SH_FILE_CDEV;
- c_mode[0] = 'c';
- }
- else if ( S_ISBLK(buf->st_mode) ) {
- (*type) = SH_FILE_BDEV;
- c_mode[0] = 'b';
- }
- else if ( S_ISFIFO(buf->st_mode) ) {
- (*type) = SH_FILE_FIFO;
- c_mode[0] = '|';
- }
- else if ( S_ISSOCK(buf->st_mode) ) {
- (*type) = SH_FILE_SOCKET;
- c_mode[0] = 's';
- }
- else if ( S_ISDOOR(buf->st_mode) ) {
- (*type) = SH_FILE_DOOR;
- c_mode[0] = 'D';
- }
- else if ( S_ISPORT(buf->st_mode) ) {
- (*type) = SH_FILE_PORT;
- c_mode[0] = 'P';
- }
- else {
- (*type) = SH_FILE_UNKNOWN;
- c_mode[0] = '?';
- }
-
- SL_RETURN(0, _("sh_unix_getinfo_type"));
-}
-
-int sh_unix_get_ftype(char * fullpath)
-{
- char c_mode[CMODE_SIZE];
- struct stat buf;
- ShFileType type;
- int res;
-
- SL_ENTER(_("sh_unix_get_ftype"));
-
- res = retry_lstat(FIL__, __LINE__, fullpath, &buf);
-
- if (res < 0)
- SL_RETURN(SH_FILE_UNKNOWN, _("sh_unix_getinfo_type"));
-
- sh_unix_getinfo_type (&buf, &type, c_mode);
-
- SL_RETURN(type, _("sh_unix_get_ftype"));
-}
-
-
-static
-int sh_unix_getinfo_mode (struct stat *buf,
- unsigned int * mode,
- char * c_mode)
-{
-
- SL_ENTER(_("sh_unix_getinfo_mode"));
-
- (*mode) = buf->st_mode;
-
- /* make 'ls'-like string */
-
- if ( (buf->st_mode & S_IRUSR) != 0 ) c_mode[1] = 'r';
- if ( (buf->st_mode & S_IWUSR) != 0 ) c_mode[2] = 'w';
- if ( (buf->st_mode & S_IXUSR) != 0 ) {
- if ((buf->st_mode & S_ISUID) != 0 ) c_mode[3] = 's';
- else c_mode[3] = 'x';
- } else {
- if ((buf->st_mode & S_ISUID) != 0 ) c_mode[3] = 'S';
- }
-
- if ( (buf->st_mode & S_IRGRP) != 0 ) c_mode[4] = 'r';
- if ( (buf->st_mode & S_IWGRP) != 0 ) c_mode[5] = 'w';
- if ( (buf->st_mode & S_IXGRP) != 0 ) {
- if ((buf->st_mode & S_ISGID) != 0 ) c_mode[6] = 's';
- else c_mode[6] = 'x';
- } else {
- if ((buf->st_mode & S_ISGID) != 0 ) c_mode[6] = 'S';
- }
-
- if ( (buf->st_mode & S_IROTH) != 0 ) c_mode[7] = 'r';
- if ( (buf->st_mode & S_IWOTH) != 0 ) c_mode[8] = 'w';
-#ifdef S_ISVTX /* not POSIX */
- if ( (buf->st_mode & S_IXOTH) != 0 ) {
- if ((buf->st_mode & S_ISVTX) != 0 ) c_mode[9] = 't';
- else c_mode[9] = 'x';
- } else {
- if ((buf->st_mode & S_ISVTX) != 0 ) c_mode[9] = 'T';
- }
-#else
- if ( (buf->st_mode & S_IXOTH) != 0 ) c_mode[9] = 'x';
-#endif
-
- SL_RETURN(0, _("sh_unix_getinfo_mode"));
-}
-
-
-long IO_Limit = 0;
-
-void sh_unix_io_pause ()
-{
- long runtime;
- float someval;
- unsigned long sometime;
-
- if (IO_Limit == 0)
- {
- return;
- }
- else
- {
- runtime = (long) (time(NULL) - sh.statistics.time_start);
-
- if (runtime > 0 && (long)(sh.statistics.bytes_hashed/runtime) > IO_Limit)
- {
- someval = sh.statistics.bytes_hashed - (IO_Limit * runtime);
- someval /= (float) IO_Limit;
- if (someval < 1.0)
- {
- someval *= 1000; /* milliseconds in a second */
- sometime = (unsigned long) someval;
- retry_msleep(0, sometime);
- }
- else
- {
- sometime = (unsigned long) someval;
- retry_msleep (sometime, 0);
- }
- }
- }
- return;
-}
-
-int sh_unix_set_io_limit (const char * c)
-{
- long val;
-
- SL_ENTER(_("sh_unix_set_io_limit"));
-
- val = strtol (c, (char **)NULL, 10);
- if (val < 0)
- sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS,
- _("set I/O limit"), c);
-
- val = (val < 0 ? 0 : val);
-
- IO_Limit = val * 1024;
- SL_RETURN( 0, _("sh_unix_set_io_limit"));
-}
-
-/* obtain file info
- */
-extern int flag_err_debug;
-
-#include "sh_ignore.h"
-
-int sh_unix_checksum_size (char * filename, off_t size, int is_max_size,
- char * fileHash, int alert_timeout, SL_TICKET fd, unsigned long mask)
-{
- file_type * tmpFile;
- int status;
-
- SL_ENTER(_("sh_unix_checksum_size"));
-
- tmpFile = SH_ALLOC(sizeof(file_type));
- tmpFile->link_path = NULL;
-
- if (sh.flag.checkSum != SH_CHECK_INIT)
- {
- /* lookup file in database */
- if (is_max_size == S_TRUE) {
- status = sh_hash_get_it (filename, tmpFile, NULL);
- if ((status != 0) || (tmpFile->size > size)) {
- goto out;
- }
- } else {
- tmpFile->size = size;
- }
- }
- else
- {
- tmpFile->size = size;
- }
-
- /* if last <= current get checksum */
- if (tmpFile->size <= size)
- {
- char hashbuf[KEYBUF_SIZE];
- UINT64 local_length = (UINT64) (tmpFile->size < 0 ? 0 : tmpFile->size);
- if (sh.flag.opts == S_TRUE) sh_tiger_set_hashtype_mask(mask);
- sl_strlcpy(fileHash,
- sh_tiger_generic_hash (filename, fd, &(local_length),
- alert_timeout, hashbuf, sizeof(hashbuf)),
- KEY_LEN+1);
-
- /* return */
- if (tmpFile->link_path) SH_FREE(tmpFile->link_path);
- SH_FREE(tmpFile);
- SL_RETURN( 0, _("sh_unix_checksum_size"));
- }
-
- out:
- if (tmpFile->link_path) SH_FREE(tmpFile->link_path);
- SH_FREE(tmpFile);
- sl_strlcpy(fileHash, SH_KEY_NULL, KEY_LEN+1);
- SL_RETURN( -1, _("sh_unix_checksum_size"));
-}
-
-/********************************************************
- * Search rotated logfile
- */
-extern char * sh_rotated_log_search(const char * path, struct stat * buf);
-
-int sh_check_rotated_log (const char * path,
- UINT64 old_size, UINT64 old_inode, const char * old_hash, unsigned long mask)
-{
- struct stat obuf;
- UINT64 length_nolim = TIGER_NOLIM;
- int retval = S_FALSE;
-
- if (old_size != length_nolim)
- {
- char hashbuf[KEYBUF_SIZE];
- char * rotated_file;
-
- obuf.st_ino = old_inode;
- rotated_file = sh_rotated_log_search(path, &obuf);
-
- if (rotated_file && (0 != strcmp(path, rotated_file)))
- {
- SL_TICKET fd = sl_open_fastread (FIL__, __LINE__, rotated_file, SL_YESPRIV);
- if (!SL_ISERROR(fd))
- {
- sh_unix_checksum_size (rotated_file, old_size, S_FALSE,
- hashbuf, 120 /* alert_timeout */, fd, mask);
-
- sl_close(fd);
-
- if (strncmp (old_hash, hashbuf, KEY_LEN) == 0) {
- retval = S_TRUE;
- }
- }
- SH_FREE(rotated_file);
- }
- }
- return retval;
-}
-
-
-int sh_unix_check_selinux = S_FALSE;
-int sh_unix_check_acl = S_FALSE;
-
-#ifdef USE_ACL
-
-#include <sys/acl.h>
-static char * sh_unix_getinfo_acl (char * path, int fd, struct stat * buf)
-{
- /* system.posix_acl_access, system.posix_acl_default
- */
- char * out = NULL;
- char * collect = NULL;
- char * tmp;
- char * out_compact;
- ssize_t len;
- acl_t result;
-
- SL_ENTER(_("sh_unix_getinfo_acl"));
-
- result = (fd == -1) ?
- acl_get_file (path, ACL_TYPE_ACCESS) :
- acl_get_fd (fd);
-
- if (result)
- {
- out = acl_to_text (result, &len);
- if (out && (len > 0)) {
- out_compact = sh_util_acl_compact (out, len);
- acl_free(out);
- if (out_compact)
- {
- collect = sh_util_strconcat (_("acl_access:"), out_compact, NULL);
- SH_FREE(out_compact);
- }
- }
- acl_free(result);
- }
-
-
- if ( S_ISDIR(buf->st_mode) )
- {
- result = acl_get_file (path, ACL_TYPE_DEFAULT);
-
- if (result)
- {
- out = acl_to_text (result, &len);
- if (out && (len > 0)) {
- out_compact = sh_util_acl_compact (out, len);
- acl_free(out);
- if (out_compact) {
- if (collect) {
- tmp = sh_util_strconcat (_("acl_default:"),
- out_compact, ":", collect, NULL);
- SH_FREE(collect);
- }
- else {
- tmp = sh_util_strconcat (_("acl_default:"), out_compact, NULL);
- }
- SH_FREE(out_compact);
- collect = tmp;
- }
- }
- acl_free(result);
- }
- }
-
- SL_RETURN((collect),_("sh_unix_getinfo_acl"));
-}
-#endif
-
-#ifdef USE_XATTR
-
-#include <attr/xattr.h>
-static char * sh_unix_getinfo_xattr_int (char * path, int fd, char * name)
-{
- char * out = NULL;
- char * tmp = NULL;
- size_t size = 256;
- ssize_t result;
-
- SL_ENTER(_("sh_unix_getinfo_xattr_int"));
-
- out = SH_ALLOC(size);
-
- result = (fd == -1) ?
- lgetxattr (path, name, out, size-1) :
- fgetxattr (fd, name, out, size-1);
-
- if (result == -1 && errno == ERANGE)
- {
- SH_FREE(out);
- result = (fd == -1) ?
- lgetxattr (path, name, NULL, 0) :
- fgetxattr (fd, name, NULL, 0);
- size = result + 1;
- out = SH_ALLOC(size);
- result = (fd == -1) ?
- lgetxattr (path, name, out, size-1) :
- fgetxattr (fd, name, out, size-1);
- }
-
- if ((result > 0) && ((size_t)result < size))
- {
- out[size-1] = '\0';
- tmp = out;
- }
- else
- {
- SH_FREE(out);
- }
-
- SL_RETURN((tmp),_("sh_unix_getinfo_xattr_int"));
-}
-
-
-static char * sh_unix_getinfo_xattr (char * path, int fd, struct stat * buf)
-{
- /* system.posix_acl_access, system.posix_acl_default, security.selinux
- */
- char * tmp;
- char * out = NULL;
- char * collect = NULL;
-
- SL_ENTER(_("sh_unix_getinfo_xattr"));
-
-#ifdef USE_ACL
- /*
- * we need the acl_get_fd/acl_get_file functions, getxattr will only
- * yield the raw bytes
- */
- if (sh_unix_check_acl == S_TRUE)
- {
- out = sh_unix_getinfo_acl(path, fd, buf);
-
- if (out)
- {
- collect = out;
- }
- }
-#else
- (void) buf;
-#endif
-
- if (sh_unix_check_selinux == S_TRUE)
- {
- out = sh_unix_getinfo_xattr_int(path, fd, _("security.selinux"));
-
- if (out)
- {
- if (collect) {
- tmp = sh_util_strconcat(_("selinux:"), out, ":", collect, NULL);
- SH_FREE(collect);
- }
- else {
- tmp = sh_util_strconcat(_("selinux:"), out, NULL);
- }
- SH_FREE(out);
- collect = tmp;
- }
- }
-
- SL_RETURN((collect),_("sh_unix_getinfo_xattr"));
-}
-#endif
-
-#ifdef USE_XATTR
-int sh_unix_setcheckselinux (const char * c)
-{
- int i;
- SL_ENTER(_("sh_unix_setcheckselinux"));
- i = sh_util_flagval(c, &(sh_unix_check_selinux));
-
- SL_RETURN(i, _("sh_unix_setcheckselinux"));
-}
-#endif
-
-#ifdef USE_ACL
-int sh_unix_setcheckacl (const char * c)
-{
- int i;
- SL_ENTER(_("sh_unix_setcheckacl"));
- i = sh_util_flagval(c, &(sh_unix_check_acl));
-
- SL_RETURN(i, _("sh_unix_setcheckacl"));
-}
-#endif
-
-#ifdef HAVE_LIBZ
-#include <zlib.h>
-#endif
-
-
-static void * sh_dummy_filename;
-static void * sh_dummy_tmp;
-static void * sh_dummy_tmp2;
-
-int sh_unix_getinfo (int level, const char * filename, file_type * theFile,
- char * fileHash, int policy)
-{
- char timestr[81];
- long runtim;
- struct stat buf;
- struct stat lbuf;
- struct stat fbuf;
- volatile int stat_return;
- volatile int stat_errno = 0;
-
- ShFileType type;
- unsigned int mode;
- char * tmp;
- char * tmp2;
-
- char * linknamebuf;
- volatile int linksize;
-
- extern int get_the_fd (SL_TICKET ticket);
-
- volatile SL_TICKET rval_open;
- volatile int err_open = 0;
-
- volatile int fd;
- volatile int fstat_return;
- volatile int fstat_errno = 0;
- volatile int try = 0;
-
- sh_string * content = NULL;
-
- time_t tend;
- time_t tstart;
-
-
- char * path = NULL;
-
- volatile int alert_timeout = 120;
-
- path = theFile->fullpath;
-
- SL_ENTER(_("sh_unix_getinfo"));
-
- if (!MODI_INITIALIZED(theFile->check_flags))
- {
- tmp2 = sh_util_safe_name (theFile->fullpath);
- SH_MUTEX_LOCK(mutex_thread_nolog);
- sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_E_SUBGPATH,
- _("Uninitialized check mask"), _("sh_unix_getinfo"),
- tmp2);
- SH_MUTEX_UNLOCK(mutex_thread_nolog);
- SH_FREE(tmp2);
- SL_RETURN((-1),_("sh_unix_getinfo"));
- }
-
- /* Take the address to keep gcc from putting it into a register.
- * Avoids the 'clobbered by longjmp' warning.
- */
- sh_dummy_filename = (void *) &filename;
- sh_dummy_tmp = (void *) &tmp;
- sh_dummy_tmp2 = (void *) &tmp2;
-
- /* --- Stat the file, and get checksum. ---
- */
- tstart = time(NULL);
-
- stat_return = retry_lstat (FIL__, __LINE__,
- path /* theFile->fullpath */, &buf);
-
- if (stat_return)
- stat_errno = errno;
-
- theFile->link_path = NULL;
-
- try_again:
-
- fd = -1;
- fstat_return = -1;
- rval_open = -1;
-
- if (stat_return == 0 && S_ISREG(buf.st_mode))
- {
- rval_open = sl_open_fastread (FIL__, __LINE__,
- path /* theFile->fullpath */, SL_YESPRIV);
- if (SL_ISERROR(rval_open))
- {
- char * stale = sl_check_stale();
-
- if (stale)
- {
- SH_MUTEX_LOCK(mutex_thread_nolog);
- sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, err_open, MSG_E_SUBGEN,
- stale, _("sh_unix_getinfo_open"));
- SH_MUTEX_UNLOCK(mutex_thread_nolog);
- }
-
- if (errno == EBADF && try == 0) /* obsolete, but we keep this, just in case */
- {
- ++try;
- goto try_again;
- }
- err_open = errno;
- }
-
- alert_timeout = 120; /* this is per 8K block now ! */
-
- if (path[1] == 'p' && path[5] == '/' && path[2] == 'r' &&
- path[3] == 'o' && path[4] == 'c' && path[0] == '/')
- {
- /* seven is magic */
- alert_timeout = 7;
- }
-
- fd = get_the_fd(rval_open);
- }
-
- tend = time(NULL);
-
- /* An unprivileged user may slow lstat/open to a crawl
- * with clever path/symlink setup
- */
- if ((tend - tstart) > (time_t) /* 60 */ 6)
- {
- tmp2 = sh_util_safe_name (theFile->fullpath);
- SH_MUTEX_LOCK(mutex_thread_nolog);
- sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_TOOLATE,
- (long)(tend - tstart), tmp2);
- SH_MUTEX_UNLOCK(mutex_thread_nolog);
- SH_FREE(tmp2);
- }
-
- if (fd >= 0)
- {
- fstat_return = retry_fstat (FIL__, __LINE__, fd, &fbuf);
-
- if (fstat_return)
- {
- char * stale;
-
- fstat_errno = errno;
-
- stale = sl_check_stale();
-
- if (stale)
- {
- SH_MUTEX_LOCK(mutex_thread_nolog);
- sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, fstat_errno,
- MSG_E_SUBGEN,
- stale, _("sh_unix_getinfo_fstat"));
- SH_MUTEX_UNLOCK(mutex_thread_nolog);
- }
-
- if (try == 0) /* obsolete, but we keep this, just in case */
- {
- ++try;
- sl_close(rval_open);
- goto try_again;
- }
- }
- }
- else
- {
- fd = -1;
- }
-
-
- /* --- case 1: lstat failed ---
- */
- if (stat_return != 0)
- {
- stat_return = errno;
- if (!SL_ISERROR(rval_open))
- sl_close(rval_open);
- if (sh.flag.checkSum == SH_CHECK_INIT ||
- (sh_hash_have_it (theFile->fullpath) >= 0 &&
- (!SH_FFLAG_REPORTED_SET(theFile->file_reported))))
- {
- if (S_FALSE == sh_ignore_chk_del(theFile->fullpath)) {
- int flags = sh_hash_getflags (theFile->fullpath);
-
- if ((flags >= 0) && (flags & SH_FFLAG_ENOENT) == 0) {
- char errbuf[SH_ERRBUF_SIZE];
- uid_t euid;
- (void) sl_get_euid(&euid);
- tmp2 = sh_util_safe_name (theFile->fullpath);
- SH_MUTEX_LOCK(mutex_thread_nolog);
- sh_error_handle (level, FIL__, __LINE__, stat_return, MSG_FI_STAT,
- _("lstat"),
- sh_error_message (stat_errno, errbuf, sizeof(errbuf)),
- (long) euid,
- tmp2);
- SH_MUTEX_UNLOCK(mutex_thread_nolog);
- SH_FREE(tmp2);
- sh_hash_set_flag (theFile->fullpath, SH_FFLAG_ENOENT);
- }
- }
- }
- SL_RETURN((-1),_("sh_unix_getinfo"));
- }
-
- /* --- case 2: not a regular file ---
- */
- else if (! S_ISREG(buf.st_mode))
- {
- if (fileHash != NULL)
- sl_strlcpy(fileHash, SH_KEY_NULL, KEY_LEN+1);
- }
-
- /* --- case 3a: a regular file, fstat ok ---
- */
- else if (fstat_return == 0 &&
- buf.st_mode == fbuf.st_mode &&
- buf.st_ino == fbuf.st_ino &&
- buf.st_uid == fbuf.st_uid &&
- buf.st_gid == fbuf.st_gid &&
- buf.st_dev == fbuf.st_dev )
- {
- if (fileHash != NULL)
- {
- if ((theFile->check_flags & MODI_CHK) == 0 ||
- sh_restrict_this(theFile->fullpath, (UINT64) fbuf.st_size,
- (UINT64) fbuf.st_mode, rval_open))
- {
- sl_strlcpy(fileHash, SH_KEY_NULL, KEY_LEN+1);
- }
- else if ((theFile->check_flags & MODI_PREL) != 0 &&
- S_TRUE == sh_prelink_iself(rval_open, fbuf.st_size,
- alert_timeout, theFile->fullpath))
- {
- if (0 != sh_prelink_run (theFile->fullpath,
- fileHash, alert_timeout, theFile->check_flags))
- sl_strlcpy(fileHash, SH_KEY_NULL, KEY_LEN+1);
- }
- else
- {
- char hashbuf[KEYBUF_SIZE];
- UINT64 length_current = TIGER_NOLIM;
-
- if (MODI_TXT_ENABLED(theFile->check_flags) && fbuf.st_size < (10 * SH_TXT_MAX))
- {
- sl_init_content (rval_open, fbuf.st_size);
- }
-
- if (sh.flag.opts == S_TRUE) sh_tiger_set_hashtype_mask(theFile->check_flags);
- sl_strlcpy(fileHash,
- sh_tiger_generic_hash (theFile->fullpath,
- rval_open, &length_current,
- alert_timeout,
- hashbuf, sizeof(hashbuf)),
- KEY_LEN+1);
-
- content = sl_get_content(rval_open);
- content = sh_string_copy(content);
-
- if ((theFile->check_flags & MODI_SGROW) != 0)
- {
- /* Update size so it matches the one for which the checksum
- has been computed */
- fbuf.st_size = length_current;
- buf.st_size = fbuf.st_size;
- sl_rewind(rval_open);
- sh_unix_checksum_size (theFile->fullpath, length_current, S_TRUE,
- &fileHash[KEY_LEN + 1],
- alert_timeout, rval_open, theFile->check_flags);
- }
- }
- }
- }
-
- /* --- case 3b: a regular file, fstat ok, but different ---
- */
- else if (fstat_return == 0 && S_ISREG(fbuf.st_mode))
- {
- memcpy (&buf, &fbuf, sizeof( struct stat ));
-
- if (fileHash != NULL)
- {
- if ((theFile->check_flags & MODI_CHK) == 0 ||
- sh_restrict_this(theFile->fullpath, (UINT64) fbuf.st_size,
- (UINT64) fbuf.st_mode, rval_open))
- {
- sl_strlcpy(fileHash, SH_KEY_NULL, KEY_LEN+1);
- }
- else if (policy == SH_LEVEL_PRELINK &&
- S_TRUE == sh_prelink_iself(rval_open, fbuf.st_size,
- alert_timeout, theFile->fullpath))
- {
- if (0 != sh_prelink_run (theFile->fullpath,
- fileHash, alert_timeout, theFile->check_flags))
- sl_strlcpy(fileHash, SH_KEY_NULL, KEY_LEN+1);
- }
- else
- {
- char hashbuf[KEYBUF_SIZE];
- UINT64 length_current = TIGER_NOLIM;
-
- if (MODI_TXT_ENABLED(theFile->check_flags) && fbuf.st_size < (10 * SH_TXT_MAX))
- {
- sl_init_content (rval_open, fbuf.st_size);
- }
-
- if (sh.flag.opts == S_TRUE) sh_tiger_set_hashtype_mask(theFile->check_flags);
- sl_strlcpy(fileHash,
- sh_tiger_generic_hash (theFile->fullpath, rval_open,
- &length_current,
- alert_timeout,
- hashbuf, sizeof(hashbuf)),
- KEY_LEN + 1);
-
- content = sl_get_content(rval_open);
- content = sh_string_copy(content);
-
- if ((theFile->check_flags & MODI_SGROW) != 0)
- {
- /* Update size so it matches the one for which the checksum
- has been computed */
- fbuf.st_size = length_current;
- buf.st_size = fbuf.st_size;
- sl_rewind(rval_open);
- sh_unix_checksum_size (theFile->fullpath, length_current, S_TRUE,
- &fileHash[KEY_LEN + 1],
- alert_timeout, rval_open, theFile->check_flags);
- }
- }
- }
- }
-
- /* --- case 4: a regular file, fstat failed ---
- */
-
- else /* fstat_return != 0 or !S_ISREG(fbuf.st_mode) or open() failed */
- {
- uid_t euid;
-
- if (fileHash != NULL)
- sl_strlcpy(fileHash, SH_KEY_NULL, KEY_LEN+1);
-
- if ((theFile->check_flags & MODI_CHK) != 0)
- {
- tmp2 = sh_util_safe_name (theFile->fullpath);
-
-
- if (fd >= 0 && fstat_return != 0)
- {
- char errbuf[SH_ERRBUF_SIZE];
- (void) sl_get_euid(&euid);
-
- SH_MUTEX_LOCK(mutex_thread_nolog);
- sh_error_handle (level, FIL__, __LINE__, stat_return, MSG_FI_STAT,
- _("fstat"),
- sh_error_message (fstat_errno, errbuf, sizeof(errbuf)),
- (long) euid,
- tmp2);
- SH_MUTEX_UNLOCK(mutex_thread_nolog);
- }
- else if (fd >= 0 && !S_ISREG(fbuf.st_mode))
- {
- SH_MUTEX_LOCK(mutex_thread_nolog);
- sh_error_handle (level, FIL__, __LINE__, fstat_errno,
- MSG_E_NOTREG, tmp2);
- SH_MUTEX_UNLOCK(mutex_thread_nolog);
- }
- else
- {
- char errbuf[SH_ERRBUF_SIZE];
- char errbuf2[SH_ERRBUF_SIZE];
- sl_strlcpy(errbuf, sl_error_string(rval_open), sizeof(errbuf));
- sh_error_message(err_open, errbuf2, sizeof(errbuf2));
- SH_MUTEX_LOCK(mutex_thread_nolog);
- sh_error_handle (level, FIL__, __LINE__, err_open,
- MSG_E_READ, errbuf, errbuf2, tmp2);
- SH_MUTEX_UNLOCK(mutex_thread_nolog);
- }
- SH_FREE(tmp2);
- }
- }
-
-
- /* --- Determine file type. ---
- */
- memset (theFile->c_mode, '-', CMODE_SIZE-1);
- theFile->c_mode[CMODE_SIZE-1] = '\0';
-
- memset (theFile->link_c_mode, '-', CMODE_SIZE-1);
- theFile->link_c_mode[CMODE_SIZE-1] = '\0';
-
- sh_unix_getinfo_type (&buf, &type, theFile->c_mode);
- theFile->type = type;
-
-#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
-
- /* --- Determine file attributes. ---
- */
- memset (theFile->c_attributes, '-', ATTRBUF_SIZE);
- theFile->c_attributes[ATTRBUF_USED] = '\0';
- theFile->attributes = 0;
-
-#if (defined(__linux__) && (defined(HAVE_LINUX_EXT2_FS_H) || defined(HAVE_EXT2FS_EXT2_FS_H))) || defined(HAVE_STAT_FLAGS)
- if (theFile->c_mode[0] != 'c' && theFile->c_mode[0] != 'b' &&
- theFile->c_mode[0] != 'l' )
- sh_unix_getinfo_attr(theFile->fullpath,
- &theFile->attributes, theFile->c_attributes,
- fd, &buf);
-#endif
-#endif
-
-#if defined(USE_XATTR) && defined(USE_ACL)
- if (sh_unix_check_selinux == S_TRUE || sh_unix_check_acl == S_TRUE)
- theFile->attr_string = sh_unix_getinfo_xattr (theFile->fullpath, fd, &buf);
-#elif defined(USE_XATTR)
- if (sh_unix_check_selinux == S_TRUE)
- theFile->attr_string = sh_unix_getinfo_xattr (theFile->fullpath, fd, &buf);
-#elif defined(USE_ACL)
- if (sh_unix_check_acl == S_TRUE)
- theFile->attr_string = sh_unix_getinfo_acl (theFile->fullpath, fd, &buf);
-#else
- theFile->attr_string = NULL;
-#endif
-
- if (!SL_ISERROR(rval_open))
- sl_close(rval_open);
-
-
- /* --- I/O limit. ---
- */
- if (IO_Limit > 0)
- {
- runtim = (long) (time(NULL) - sh.statistics.time_start);
-
- if (runtim > 0 && (long)(sh.statistics.bytes_hashed/runtim) > IO_Limit)
- retry_msleep(1, 0);
- }
-
- /* --- Determine permissions. ---
- */
- sh_unix_getinfo_mode (&buf, &mode, theFile->c_mode);
-
- /* --- Trivia. ---
- */
- theFile->dev = buf.st_dev;
- theFile->ino = buf.st_ino;
- theFile->mode = buf.st_mode;
- theFile->hardlinks = buf.st_nlink;
- theFile->owner = buf.st_uid;
- theFile->group = buf.st_gid;
- theFile->rdev = buf.st_rdev;
- theFile->size = buf.st_size;
- theFile->blksize = (unsigned long) buf.st_blksize;
- theFile->blocks = (unsigned long) buf.st_blocks;
- theFile->atime = buf.st_atime;
- theFile->mtime = buf.st_mtime;
- theFile->ctime = buf.st_ctime;
-
-
- /* --- Owner and group. ---
- */
-
- if (NULL == sh_unix_getGIDname(SH_ERR_ALL, buf.st_gid, theFile->c_group, GROUP_MAX+1)) {
-
- tmp2 = sh_util_safe_name (theFile->fullpath);
-
- if (policy == SH_LEVEL_ALLIGNORE)
- {
- SH_MUTEX_LOCK(mutex_thread_nolog);
- sh_error_handle (SH_ERR_ALL, FIL__, __LINE__, ENOENT,
- MSG_FI_NOGRP,
- (long) buf.st_gid, tmp2);
- SH_MUTEX_UNLOCK(mutex_thread_nolog);
- }
- else
- {
- SH_MUTEX_LOCK(mutex_thread_nolog);
- sh_error_handle (ShDFLevel[SH_ERR_T_NAME], FIL__, __LINE__, ENOENT,
- MSG_FI_NOGRP,
- (long) buf.st_gid, tmp2);
- SH_MUTEX_UNLOCK(mutex_thread_nolog);
- }
- SH_FREE(tmp2);
- sl_snprintf(theFile->c_group, GROUP_MAX+1, "%d", (long) buf.st_gid);
- }
-
-
- if (NULL == sh_unix_getUIDname(SH_ERR_ALL, buf.st_uid, theFile->c_owner, USER_MAX+1)) {
-
- tmp2 = sh_util_safe_name (theFile->fullpath);
-
- if (policy == SH_LEVEL_ALLIGNORE)
- {
- SH_MUTEX_LOCK(mutex_thread_nolog);
- sh_error_handle (SH_ERR_ALL, FIL__, __LINE__, ENOENT,
- MSG_FI_NOUSR,
- (long) buf.st_uid, tmp2);
- SH_MUTEX_UNLOCK(mutex_thread_nolog);
- }
- else
- {
- SH_MUTEX_LOCK(mutex_thread_nolog);
- sh_error_handle (ShDFLevel[SH_ERR_T_NAME], FIL__, __LINE__, ENOENT,
- MSG_FI_NOUSR,
- (long) buf.st_uid, tmp2);
- SH_MUTEX_UNLOCK(mutex_thread_nolog);
- }
- SH_FREE(tmp2);
- sl_snprintf(theFile->c_owner, USER_MAX+1, "%d", (long) buf.st_uid);
- }
-
- /* --- Output the file. ---
- */
- if (flag_err_debug == S_TRUE)
- {
- tmp2 = sh_util_safe_name ((filename == NULL) ?
- theFile->fullpath : filename);
- (void) sh_unix_time(theFile->mtime, timestr, sizeof(timestr));
- SH_MUTEX_LOCK(mutex_thread_nolog);
- sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_LIST,
- theFile->c_mode,
- theFile->hardlinks,
- theFile->c_owner,
- theFile->c_group,
- (unsigned long) theFile->size,
- timestr,
- tmp2);
- SH_MUTEX_UNLOCK(mutex_thread_nolog);
- SH_FREE(tmp2);
- }
-
- /* --- Check for links. ---
- */
- if (theFile->c_mode[0] == 'l')
- {
- linknamebuf = SH_ALLOC(PATH_MAX);
-
- /* flawfinder: ignore */
- linksize = readlink (theFile->fullpath, linknamebuf, PATH_MAX-1);
-
- if (linksize < (PATH_MAX-1) && linksize >= 0)
- linknamebuf[linksize] = '\0';
- else
- linknamebuf[PATH_MAX-1] = '\0';
-
- if (linksize < 0)
- {
- char errbuf[SH_ERRBUF_SIZE];
- linksize = errno;
- tmp2 = sh_util_safe_name (theFile->fullpath);
- SH_MUTEX_LOCK(mutex_thread_nolog);
- sh_error_handle (level, FIL__, __LINE__, linksize, MSG_FI_RDLNK,
- sh_error_message (linksize, errbuf, sizeof(errbuf)), tmp2);
- SH_MUTEX_UNLOCK(mutex_thread_nolog);
- SH_FREE(tmp2);
- SH_FREE(linknamebuf);
- theFile->link_path = sh_util_strdup("-");
- SL_RETURN((-1),_("sh_unix_getinfo"));
- }
-
- if (linknamebuf[0] == '/')
- {
- theFile->link_path = sh_util_strdup (linknamebuf);
- }
- else
- {
- tmp = sh_util_dirname(theFile->fullpath);
- if (tmp) {
- theFile->link_path = SH_ALLOC(PATH_MAX);
- sl_strlcpy (theFile->link_path, tmp, PATH_MAX);
- SH_FREE(tmp);
- } else {
- theFile->link_path = SH_ALLOC(PATH_MAX);
- theFile->link_path[0] = '\0';
- }
- /*
- * Only attach '/' if not root directory. Handle "//", which
- * according to POSIX is implementation-defined, and may be
- * different from "/" (however, three or more '/' will collapse
- * to one).
- */
- tmp = theFile->link_path; while (*tmp == '/') ++tmp;
- if (*tmp != '\0')
- {
- sl_strlcat (theFile->link_path, "/", PATH_MAX);
- }
- sl_strlcat (theFile->link_path, linknamebuf, PATH_MAX);
- }
-
- /* stat the link
- */
- stat_return = retry_lstat (FIL__, __LINE__, theFile->link_path, &lbuf);
-
- /* check for error
- */
- if (stat_return != 0)
- {
- stat_return = errno;
- tmp = sh_util_safe_name (theFile->fullpath);
- tmp2 = sh_util_safe_name (theFile->link_path);
- if (stat_return != ENOENT)
- {
- uid_t euid;
- char errbuf[SH_ERRBUF_SIZE];
-
- (void) sl_get_euid(&euid);
- SH_MUTEX_LOCK(mutex_thread_nolog);
- sh_error_handle (level, FIL__, __LINE__, stat_return,
- MSG_FI_STAT,
- _("lstat (link target)"),
- sh_error_message (stat_return,errbuf, sizeof(errbuf)),
- (long) euid,
- tmp2);
- SH_MUTEX_UNLOCK(mutex_thread_nolog);
- }
- else
- {
- /* a dangling link -- everybody seems to have plenty of them
- */
- SH_MUTEX_LOCK(mutex_thread_nolog);
- sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_DLNK,
- tmp, tmp2);
- SH_MUTEX_UNLOCK(mutex_thread_nolog);
- }
- theFile->linkisok = BAD;
- SH_FREE(tmp);
- SH_FREE(tmp2);
- SH_FREE(linknamebuf);
- /*
- * changed Tue Feb 10 16:16:13 CET 2004:
- * add dangling symlinks into database
- * SL_RETURN((-1),_("sh_unix_getinfo"));
- */
- theFile->linkmode = 0;
- SL_RETURN((0),_("sh_unix_getinfo"));
- }
-
- theFile->linkisok = GOOD;
-
-
- /* --- Determine file type. ---
- */
- sh_unix_getinfo_type (&lbuf, &type, theFile->link_c_mode);
- theFile->type = type;
-
- /* --- Determine permissions. ---
- */
- sh_unix_getinfo_mode (&lbuf, &mode, theFile->link_c_mode);
- theFile->linkmode = lbuf.st_mode;
-
- /* --- Output the link. ---
- */
- if (theFile->linkisok == GOOD)
- {
- tmp2 = sh_util_safe_name (linknamebuf);
- SH_MUTEX_LOCK(mutex_thread_nolog);
- sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_LLNK,
- theFile->link_c_mode, tmp2);
- SH_MUTEX_UNLOCK(mutex_thread_nolog);
- SH_FREE(tmp2);
- }
- SH_FREE(linknamebuf);
- }
- else /* not a link, theFile->c_mode[0] != 'l' */
- {
- if (content)
- {
-#ifdef HAVE_LIBZ
- unsigned long clen;
- unsigned char * compressed;
-#ifdef HAVE_COMPRESSBOUND
- clen = compressBound(sh_string_len(content));
-#else
- if (sh_string_len(content) > 10*SH_TXT_MAX)
- clen = SH_TXT_MAX;
- else
- clen = 13 + (int)(1.0001*sh_string_len(content));
-#endif
- compressed = SH_ALLOC(clen);
- if (Z_OK == compress(compressed, &clen,
- (unsigned char *) sh_string_str(content),
- sh_string_len(content)))
- {
- if (clen < SH_TXT_MAX)
- {
- sh_util_base64_enc_alloc (&(theFile->link_path),
- (char *) compressed, clen);
- }
- else
- {
- char tmsg[128];
- char * tpath = sh_util_safe_name (theFile->fullpath);
- sl_snprintf(tmsg, sizeof(tmsg),
- _("compressed file too large (%lu bytes)"),
- clen);
- SH_MUTEX_LOCK(mutex_thread_nolog);
- sh_error_handle (SH_ERR_WARN, FIL__, __LINE__, -1,
- MSG_E_SUBGPATH, tmsg,
- _("sh_unix_getinfo"), tpath);
- SH_MUTEX_UNLOCK(mutex_thread_nolog);
- SH_FREE(tpath);
- }
- }
- SH_FREE(compressed);
-#endif
- sh_string_destroy(&content);
- }
- }
- SL_RETURN((0),_("sh_unix_getinfo"));
-}
-
-/* #if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE) */
-#endif
-
-int sh_unix_unlock(char * lockfile, char * flag)
-{
- int error = 0;
-
- SL_ENTER(_("sh_unix_unlock"));
-
- if (sh.flag.isdaemon == S_FALSE && flag == NULL)
- SL_RETURN((0),_("sh_unix_unlock"));
-
- /* --- Logfile is not locked to us. ---
- */
- if (sh.flag.islocked == BAD && flag != NULL)
- SL_RETURN((-1),_("sh_unix_unlock"));
-
- /* --- Check whether the directory is secure. ---
- */
- if (0 != tf_trust_check (lockfile, SL_YESPRIV))
- SL_RETURN((-1),_("sh_unix_unlock"));
-
- /* --- Delete the lock file. ---
- */
- error = retry_aud_unlink (FIL__, __LINE__, lockfile);
-
- if (error == 0)
- {
- if (flag != NULL)
- sh.flag.islocked = BAD; /* not locked anymore */
- }
- else if (flag != NULL)
- {
- char errbuf[SH_ERRBUF_SIZE];
- error = errno;
- sh_error_handle ((-1), FIL__, __LINE__, error, MSG_E_UNLNK,
- sh_error_message(error, errbuf, sizeof(errbuf)),
- lockfile);
- SL_RETURN((-1),_("sh_unix_unlock"));
- }
- SL_RETURN((0),_("sh_unix_unlock"));
-}
-
-int sh_unix_check_piddir (char * pidpath)
-{
- static struct stat buf;
- int status = 0;
- char * pid_dir;
-
- SL_ENTER(_("sh_unix_check_piddir"));
-
- pid_dir = sh_util_dirname (pidpath);
-
- status = retry_lstat (FIL__, __LINE__, pid_dir, &buf);
-
- if (status < 0 && errno == ENOENT)
- {
- status = mkdir (pid_dir, 0777);
- if (status < 0)
- {
- sh_error_handle ((-1), FIL__, __LINE__, status,
- MSG_E_SUBGEN,
- _("Cannot create PID directory"),
- _("sh_unix_check_piddir"));
- SH_FREE(pid_dir);
- SL_RETURN((-1),_("sh_unix_check_piddir"));
- }
- }
- else if (!S_ISDIR(buf.st_mode))
- {
- sh_error_handle ((-1), FIL__, __LINE__, status,
- MSG_E_SUBGEN,
- _("Path of PID directory refers to a non-directory object"),
- _("sh_unix_check_piddir"));
- SH_FREE(pid_dir);
- SL_RETURN((-1),_("sh_unix_check_piddir"));
- }
- SH_FREE(pid_dir);
- SL_RETURN((0),_("sh_unix_check_piddir"));
-}
-
-int sh_unix_lock (char * lockfile, char * flag)
-{
- int filed;
- int errnum;
- char myPid[64];
- SL_TICKET fd;
- extern int get_the_fd (SL_TICKET ticket);
-
- SL_ENTER(_("sh_unix_lock"));
-
- sprintf (myPid, "%ld\n", (long) sh.pid); /* known to fit */
-
- if (flag == NULL) /* PID file, check for directory */
- {
- if (0 != sh_unix_check_piddir (lockfile))
- {
- SL_RETURN((-1),_("sh_unix_lock"));
- }
- }
-
- fd = sl_open_safe_rdwr (FIL__, __LINE__,
- lockfile, SL_YESPRIV); /* fails if file exists */
-
- if (!SL_ISERROR(fd))
- {
- errnum = sl_write (fd, myPid, sl_strlen(myPid));
- filed = get_the_fd(fd);
- fchmod (filed, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
- sl_close (fd);
-
- if (!SL_ISERROR(errnum))
- {
- if (flag != NULL)
- sh.flag.islocked = GOOD;
- SL_RETURN((0),_("sh_unix_lock"));
- }
- }
-
- TPT((0, FIL__, __LINE__, _("msg=<open pid file failed>\n")));
- if (flag != NULL)
- sh.flag.islocked = BAD;
- SL_RETURN((-1),_("sh_unix_lock"));
-
- /* notreached */
-}
-
-
-/* check whether file is locked
- */
-int sh_unix_test_and_lock (char * filename, char * lockfile)
-{
- static struct stat buf;
- int status = 0;
-
-
- SL_TICKET fd;
- char line_in[128];
-
- SL_ENTER(_("sh_unix_test_and_lock"));
-
- status = retry_lstat (FIL__, __LINE__, lockfile, &buf);
-
- /* --- No lock file found, try to lock. ---
- */
-
- if (status < 0 && errno == ENOENT)
- {
- if (0 == sh_unix_lock (lockfile, filename))
- {
- if (filename != NULL)
- sh.flag.islocked = GOOD;
- SL_RETURN((0),_("sh_unix_test_and_lock"));
- }
- else
- {
- sh_error_handle ((-1), FIL__, __LINE__, status,
- MSG_E_SUBGEN,
- (filename == NULL) ? _("Cannot create PID file (1)") : _("Cannot create lock file (1)"),
- _("sh_unix_test_and_lock"));
- SL_RETURN((-1),_("sh_unix_test_and_lock"));
- }
- }
- else if (status == 0 && buf.st_size == 0)
- {
- if (filename != NULL)
- sh.flag.islocked = GOOD;
- sh_unix_unlock (lockfile, filename);
- if (filename != NULL)
- sh.flag.islocked = BAD;
- if (0 == sh_unix_lock (lockfile, filename))
- {
- if (filename != NULL)
- sh.flag.islocked = GOOD;
- SL_RETURN((0),_("sh_unix_test_and_lock"));
- }
- else
- {
- sh_error_handle ((-1), FIL__, __LINE__, status,
- MSG_E_SUBGEN,
- (filename == NULL) ? _("Cannot create PID file (2)") : _("Cannot create lock file (2)"),
- _("sh_unix_test_and_lock"));
- SL_RETURN((-1),_("sh_unix_test_and_lock"));
- }
- }
-
- /* --- Check on lock. ---
- */
-
- if (status >= 0)
- {
- fd = sl_open_read (FIL__, __LINE__, lockfile, SL_YESPRIV);
- if (SL_ISERROR(fd))
- sh_error_handle ((-1), FIL__, __LINE__, fd,
- MSG_E_SUBGEN,
- (filename == NULL) ? _("Cannot open PID file for read") : _("Cannot open lock file for read"),
- _("sh_unix_test_and_lock"));
- }
- else
- fd = -1;
-
- if (!SL_ISERROR(fd))
- {
- /* read the PID in the lock file
- */
- status = sl_read (fd, line_in, sizeof(line_in));
- line_in[sizeof(line_in)-1] = '\0';
-
- /* convert to numeric
- */
- if (status > 0)
- {
- errno = 0;
- status = strtol(line_in, (char **)NULL, 10);
- if (errno == ERANGE || status <= 0)
- {
- sh_error_handle ((-1), FIL__, __LINE__, status,
- MSG_E_SUBGEN,
- (filename == NULL) ? _("Bad PID in PID file") : _("Bad PID in lock file"),
- _("sh_unix_test_and_lock"));
-
- status = -1;
- }
- }
- else
- {
- sh_error_handle ((-1), FIL__, __LINE__, status,
- MSG_E_SUBGEN,
- (filename == NULL) ? _("Cannot read PID file") : _("Cannot read lock file"),
- _("sh_unix_test_and_lock"));
- }
- sl_close(fd);
-
- if (status > 0 && (unsigned int) status == sh.pid)
- {
- if (filename != NULL)
- sh.flag.islocked = GOOD;
- SL_RETURN((0),_("sh_unix_test_and_lock"));
- }
-
-
- /* --- Check whether the process exists. ---
- */
- if (status > 0)
- {
- errno = 0;
- status = aud_kill (FIL__, __LINE__, status, 0);
-
- /* Does not exist, so remove the stale lock
- * and create a new one.
- */
- if (status < 0 && errno == ESRCH)
- {
- if (filename != NULL)
- sh.flag.islocked = GOOD;
- if (0 != sh_unix_unlock(lockfile, filename) && (filename !=NULL))
- sh.flag.islocked = BAD;
- else
- {
- if (0 == sh_unix_lock (lockfile, filename))
- {
- if (filename != NULL)
- sh.flag.islocked = GOOD;
- SL_RETURN((0),_("sh_unix_test_and_lock"));
- }
- else
- {
- sh_error_handle ((-1), FIL__, __LINE__, status,
- MSG_E_SUBGEN,
- (filename == NULL) ? _("Cannot create PID file (3)") : _("Cannot create lock file (3)"),
- _("sh_unix_test_and_lock"));
- }
- if (filename != NULL)
- sh.flag.islocked = BAD;
- }
- }
- else
- {
- sh_error_handle ((-1), FIL__, __LINE__, status,
- MSG_E_SUBGEN,
- (filename == NULL) ? _("Cannot remove stale PID file, PID may be a running process") : _("Cannot remove stale lock file, PID may be a running process"),
- _("sh_unix_test_and_lock"));
- if (filename != NULL)
- sh.flag.islocked = BAD;
- }
- }
- }
- SL_RETURN((-1),_("sh_unix_testlock"));
-}
-
-/* write the PID file
- */
-int sh_unix_write_pid_file()
-{
- return sh_unix_test_and_lock(NULL, sh.srvlog.alt);
-}
-
-/* write lock for filename
- */
-int sh_unix_write_lock_file(char * filename)
-{
- size_t len;
- int res;
- char * lockfile;
-
- if (filename == NULL)
- return (-1);
-
- len = sl_strlen(filename);
- if (sl_ok_adds(len, 6))
- len += 6;
- lockfile = SH_ALLOC(len);
- sl_strlcpy(lockfile, filename, len);
- sl_strlcat(lockfile, _(".lock"), len);
- res = sh_unix_test_and_lock(filename, lockfile);
- SH_FREE(lockfile);
- return res;
-}
-
-/* rm lock for filename
- */
-int sh_unix_rm_lock_file(char * filename)
-{
- size_t len;
- int res;
- char * lockfile;
-
- if (filename == NULL)
- return (-1);
-
- len = sl_strlen(filename);
- if (sl_ok_adds(len, 6))
- len += 6;
- lockfile = SH_ALLOC(len);
- sl_strlcpy(lockfile, filename, len);
- sl_strlcat(lockfile, _(".lock"), len);
-
- res = sh_unix_unlock(lockfile, filename);
- SH_FREE(lockfile);
- return res;
-}
-
-/* rm lock for filename
- */
-int sh_unix_rm_pid_file()
-{
- return sh_unix_unlock(sh.srvlog.alt, NULL);
-}
-
-/* Test whether file exists
- */
-int sh_unix_file_exists(char * path)
-{
- struct stat buf;
-
- SL_ENTER(_("sh_unix_file_exists"));
-
- if (0 == retry_lstat(FIL__, __LINE__, path, &buf))
- SL_RETURN( S_TRUE, _("sh_unix_file_exists"));
- else
- SL_RETURN( S_FALSE, _("sh_unix_file_exists"));
-}
-
-
-/* Test whether file exists, is a character device, and allows read
- * access.
- */
-int sh_unix_device_readable(int fd)
-{
- struct stat buf;
-
- SL_ENTER(_("sh_unix_device_readable"));
-
- if (retry_fstat(FIL__, __LINE__, fd, &buf) == -1)
- SL_RETURN( (-1), _("sh_unix_device_readable"));
- else if ( S_ISCHR(buf.st_mode) && 0 != (S_IROTH & buf.st_mode) )
- SL_RETURN( (0), _("sh_unix_device_readable"));
- else
- SL_RETURN( (-1), _("sh_unix_device_readable"));
-}
-
-static char preq[16];
-
-/* return true if database is remote
- */
-int file_is_remote ()
-{
- static int init = 0;
- struct stat buf;
-
- SL_ENTER(_("file_is_remote"));
-
- if (init == 0)
- {
- sl_strlcpy(preq, _("REQ_FROM_SERVER"), 16);
- ++init;
- }
- if (0 == sl_strncmp (sh.data.path, preq, 15))
- {
- if (sh.data.path[15] != '\0') /* should be start of path */
- {
- if (0 == stat(&(sh.data.path[15]), &buf))
- {
- SL_RETURN( S_FALSE, _("file_is_remote"));
- }
- else
- {
- char * tmp = sh_util_safe_name (&(sh.data.path[15]));
- sh_error_handle((-1), FIL__, __LINE__, S_FALSE, MSG_E_SUBGPATH,
- _("No local baseline database at expected path"),
- _("file_is_remote"),
- tmp);
- SH_FREE(tmp);
- }
- }
- else
- {
- sh_error_handle((-1), FIL__, __LINE__, S_FALSE, MSG_E_SUBGEN,
- _("No local baseline database path known"),
- _("file_is_remote"));
- }
- SL_RETURN( S_TRUE, _("file_is_remote"));
- }
- SL_RETURN( S_FALSE, _("file_is_remote"));
-}
-
-/* Return the path to the configuration/database file.
- */
-char * file_path(char what, char flag)
-{
- static int init = 0;
-
- SL_ENTER(_("file_path"));
-
- if (init == 0)
- {
- sl_strlcpy(preq, _("REQ_FROM_SERVER"), 16);
- ++init;
- }
-
- switch (what)
- {
-
- case 'C':
- if (0 == sl_strncmp (sh.conf.path, preq, 15))
- {
-#if defined(SH_WITH_SERVER)
- if (sh.flag.isserver == S_TRUE && sl_strlen(sh.conf.path) == 15)
- SL_RETURN( NULL, _("file_path"));
- if (sh.flag.isserver == S_TRUE)
- SL_RETURN( &(sh.conf.path[15]), _("file_path"));
-#endif
- if (flag == 'R')
- SL_RETURN( preq, _("file_path"));
- if (flag == 'I')
- {
- if (sl_strlen(sh.conf.path) == 15)
- SL_RETURN( NULL, _("file_path"));
- else
- SL_RETURN( &(sh.conf.path[15]), _("file_path"));
- }
- SL_RETURN ( preq, _("file_path"));
- }
- else
- SL_RETURN( sh.conf.path, _("file_path"));
- /* break; *//* unreachable */
-
- case 'D':
- if (0 == sl_strncmp (sh.data.path, preq, 15))
- {
- if (flag == 'R')
- SL_RETURN( preq, _("file_path"));
- if (flag == 'W' && sl_strlen(sh.data.path) == 15)
- SL_RETURN (NULL, _("file_path"));
- if (flag == 'W')
- SL_RETURN( &(sh.data.path[15]), _("file_path"));
- }
- else
- SL_RETURN( sh.data.path, _("file_path"));
- break;
-
- default:
- SL_RETURN( NULL, _("file_path"));
- }
-
- return NULL; /* notreached */
-}
-/************************************************/
-/**** Mlock Utilities ****/
-/************************************************/
-
-#include <limits.h>
-
-int sh_unix_pagesize()
-{
- int pagesize = 4096;
-#if defined(_SC_PAGESIZE)
- pagesize = sysconf(_SC_PAGESIZE);
-#elif defined(_SC_PAGE_SIZE)
- pagesize = sysconf(_SC_PAGE_SIZE);
-#elif defined(HAVE_GETPAGESIZE)
- pagesize = getpagesize();
-#elif defined(PAGESIZE)
- pagesize = PAGESIZE;
-#endif
-
- return ((pagesize > 0) ? pagesize : 4096);
-}
-
-typedef struct sh_page_lt {
- unsigned long page_start;
- int page_refcount;
- char file[64];
- int line;
- struct sh_page_lt * next;
-} sh_page_l;
-
-sh_page_l * sh_page_locked = NULL;
-volatile int page_locking = 0;
-
-unsigned long sh_unix_lookup_page (void * in_addr, size_t len, int * num_pages)
-{
- int pagesize = sh_unix_pagesize();
- unsigned long addr = (unsigned long) in_addr;
-
- unsigned long pagebase;
- unsigned long pagediff;
- unsigned long pagenum = addr / pagesize;
-
- SL_ENTER(_("sh_unix_lookup_page"));
-#if 0
- fprintf(stderr, "mlock: --> base %ld, pagenum: %ld\n",
- addr, pagenum);
-#endif
-
- /* address of first page
- */
- pagebase = pagenum * pagesize;
-
- /* number of pages
- */
- pagediff = (addr + len) - pagebase;
- pagenum = pagediff / pagesize;
- if (pagenum * pagesize < pagediff)
- ++pagenum;
-
-#if 0
- fprintf(stderr, "mlock: --> pagebase %ld, pagediff %ld, (addr + len) %ld\n",
- pagebase, pagediff, (addr + len));
-#endif
-
- *num_pages = pagenum;
- SL_RETURN((pagebase), _("sh_unix_lookup_page"));
-}
-
-
-#if defined(HAVE_MLOCK) && !defined(HAVE_BROKEN_MLOCK)
-
-SH_MUTEX_STATIC(mutex_mlock,PTHREAD_MUTEX_INITIALIZER);
-
-int sh_unix_mlock (const char * file, int line, void * in_addr, size_t len)
-{
- int num_pages;
- int status = 0;
- int pagesize;
- sh_page_l * page_list;
- unsigned long addr;
-#ifdef TEST_MLOCK
- int i = 0;
-#endif
-
- SL_ENTER(_("sh_unix_mlock"));
-
- /* There's no cancellation point here, except if tracing is on
- */
- SH_MUTEX_LOCK_UNSAFE(mutex_mlock);
-
- page_list = sh_page_locked;
-
- if (0 != page_locking)
- {
- status = -1;
- goto exit_mlock;
- }
-
- page_locking = 1;
-
- pagesize = sh_unix_pagesize();
- addr = sh_unix_lookup_page (in_addr, len, &num_pages);
-
-#ifdef TEST_MLOCK
- fprintf(stderr, "mlock: addr %ld, base %ld, pages: %d, length %d\n",
- (unsigned long) in_addr, addr, num_pages, len);
-#endif
-
- /* increase refcount of locked pages
- * addr is first page; num_pages is #(consecutive pages) to lock
- */
-
- while ((page_list != NULL) && (num_pages > 0))
- {
-#ifdef TEST_MLOCK
- fprintf(stderr, "mlock: check page %d: %ld [%d]\n",
- i, page_list->page_start, page_list->page_refcount);
-#endif
- if (page_list->page_start == addr)
- {
- page_list->page_refcount += 1;
- num_pages -= 1;
- addr += pagesize;
-#ifdef TEST_MLOCK
- fprintf(stderr, "mlock: found page %d: %ld [%d], next page %ld\n",
- i, page_list->page_start, page_list->page_refcount, addr);
-#endif
- }
-#ifdef TEST_MLOCK
- ++i;
-#endif
- page_list = page_list->next;
- }
-
- /* mlock some more pages, if needed
- */
- while (num_pages > 0)
- {
-#ifdef TEST_MLOCK
- fprintf(stderr, "mlock: lock page %d: mlock %ld [num_pages %d]\n",
- i, addr, num_pages);
- ++i;
-#endif
- page_list = SH_ALLOC(sizeof(sh_page_l));
- page_list->page_start = addr;
- page_list->page_refcount = 1;
- sl_strlcpy(page_list->file, file, 64);
- page_list->line = line;
- status = mlock( (void *) addr, pagesize);
- if (status != 0)
- {
-#ifdef TEST_MLOCK
- char errbuf[SH_ERRBUF_SIZE];
- fprintf(stderr, "mlock: error: %s\n",
- sh_error_message(errno, errbuf, sizeof(errbuf)));
-#endif
- SH_FREE(page_list);
- page_locking = 0;
- goto exit_mlock;
- }
- page_list->next = sh_page_locked;
- sh_page_locked = page_list;
- num_pages -= 1;
- addr += pagesize;
- }
- page_locking = 0;
-
- exit_mlock:
- SH_MUTEX_UNLOCK_UNSAFE(mutex_mlock);
-
- SL_RETURN((status), _("sh_unix_mlock"));
-}
-#else
-int sh_unix_mlock (const char * file, int line, void * in_addr, size_t len)
-{
- (void) file; (void) line;
- (void) in_addr; (void) len;
- return -1;
-}
-#endif
-
-#if defined(HAVE_MLOCK) && !defined(HAVE_BROKEN_MLOCK)
-int sh_unix_munlock (void * in_addr, size_t len)
-{
- int num_pages;
- int unlocked;
- int status;
- int pagesize;
- sh_page_l * page_list;
- sh_page_l * page_last;
- unsigned long addr;
-
- int test_count;
- int test_status;
- int test_pages;
-
-#ifdef TEST_MLOCK
- int i = 0;
-#endif
-
- SL_ENTER(_("sh_unix_munlock"));
-
- /* There's no cancellation point here, except if tracing is on
- */
- SH_MUTEX_LOCK_UNSAFE(mutex_mlock);
-
- unlocked = 0;
- status = 0;
- page_list = sh_page_locked;
-
- if (0 != page_locking)
- {
- status = -1;
- goto exit_munlock;
- }
- page_locking = 1;
-
- pagesize = sh_unix_pagesize();
- addr = sh_unix_lookup_page (in_addr, len, &num_pages);
-
-#ifdef TEST_MLOCK
- fprintf(stderr, "munlock: in_addr %ld, addr %ld, pages: %d, length %d\n",
- (unsigned long) in_addr, addr, num_pages, len);
-#endif
-
- test_pages = num_pages;
-
- /* reduce refcount of locked pages
- * addr is first page; num_pages is #(consecutive pages) to lock
- */
- while ((page_list != NULL) && (num_pages > 0))
- {
-#ifdef TEST_MLOCK
- fprintf(stderr, "munlock: page %d: %ld [%d]\n",
- i, page_list->page_start, page_list->page_refcount);
-#endif
-
- test_status = 0;
- for (test_count = 0; test_count < test_pages; ++test_count)
- {
- if (page_list->page_start == (addr + (test_count * pagesize)))
- {
- test_status = 1;
- break;
- }
- }
-
- if (test_status == 1)
- {
- page_list->page_refcount -= 1;
- if (page_list->page_refcount == 0)
- {
- status = munlock ( (void *) addr, pagesize);
- ++unlocked;
- }
- num_pages -= 1;
-#ifdef TEST_MLOCK
- fprintf(stderr,
- "munlock: page %d: %ld [refcount %d], refcount reduced\n",
- i, page_list->page_start, page_list->page_refcount);
-#endif
- }
-#ifdef TEST_MLOCK
- ++i;
-#endif
- page_list = page_list->next;
- }
-
-#ifdef TEST_MLOCK
- i = 0;
-#endif
-
- if (unlocked > 0)
- {
- page_list = sh_page_locked;
- page_last = sh_page_locked;
-
- while ((page_list != NULL) && (unlocked > 0))
- {
- if (page_list->page_refcount == 0)
- {
-#ifdef TEST_MLOCK
- fprintf(stderr, "munlock: remove page %d: %ld [refcount %d]\n",
- i, page_list->page_start, page_list->page_refcount);
-#endif
- if (page_last != page_list)
- {
- page_last->next = page_list->next;
- SH_FREE(page_list);
- page_list = page_last->next;
- }
- else
- {
- page_last = page_list->next;
- if (page_list == sh_page_locked)
- sh_page_locked = page_list->next;
- SH_FREE(page_list);
- page_list = page_last;
- }
- --unlocked;
- }
- else
- {
-#ifdef TEST_MLOCK
- fprintf(stderr, "munlock: skip page %d: %ld [refcount %d]\n",
- i, page_list->page_start, page_list->page_refcount);
-#endif
-
- page_last = page_list;
- page_list = page_list->next;
- }
-#ifdef TEST_MLOCK
- ++i;
-#endif
- }
- }
-
- page_locking = 0;
-
- exit_munlock:
- SH_MUTEX_UNLOCK_UNSAFE(mutex_mlock);
- SL_RETURN((status), _("sh_unix_munlock"));
-}
-#else
-int sh_unix_munlock (void * in_addr, size_t len)
-{
- (void) in_addr; (void) len;
- return -1;
-}
-#endif
-
-int sh_unix_count_mlock()
-{
- unsigned int i = 0;
- char str[32][64];
- sh_page_l * page_list;
-
- SL_ENTER(_("sh_unix_count_mlock"));
-
-#if defined(HAVE_MLOCK) && !defined(HAVE_BROKEN_MLOCK)
- /* There's no cancellation point here, except if tracing is on
- */
- SH_MUTEX_LOCK_UNSAFE(mutex_mlock);
-#endif
-
- page_list = sh_page_locked;
-
- while (page_list != NULL)
- {
-#ifdef WITH_TPT
- if (i < 32)
- sl_snprintf(str[i], 64, _("file: %s line: %d page: %d"),
- page_list->file, page_list->line, i+1);
-#endif
- page_list = page_list->next;
- ++i;
- }
-
-#if defined(HAVE_MLOCK) && !defined(HAVE_BROKEN_MLOCK)
- SH_MUTEX_UNLOCK_UNSAFE(mutex_mlock);
-#endif
-
-#ifdef WITH_TPT
- {
- unsigned int j = 0;
- while (j < i && j < 32)
- {
- sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, j, MSG_E_SUBGEN,
- str[j], _("sh_unix_count_mlock"));
- ++j;
- }
- }
-#endif
-
- sl_snprintf(str[0], 64, _("%d pages locked"), i);
- sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, i, MSG_E_SUBGEN,
- str[0], _("sh_unix_count_mlock"));
- SL_RETURN((i), _("sh_unix_count_mlock"));
-}
-
-/************************************************/
-/************************************************/
-/**** Stealth Utilities ****/
-/************************************************/
-/************************************************/
-#ifdef SH_STEALTH
-
-void sh_unix_xor_code (char * str, int len)
-{
- register int i;
-
- for (i = 0; i < len; ++i) str[i] ^= (char) XOR_CODE;
- return;
-}
-
-#if !defined(SH_STEALTH_MICRO)
-
-
-int hideout_hex_block(SL_TICKET fd, unsigned char * str, int len,
- unsigned long * bytes_read);
-unsigned long first_hex_block(SL_TICKET fd, unsigned long * max);
-
-/*
- * --- Get hidden data from a block of hex data. ---
- */
-int sh_unix_getline_stealth (SL_TICKET fd, char * str, int len)
-{
- int add_off = 0, llen;
- static unsigned long off_data = 0;
- static unsigned long max_data = 0;
- static unsigned long bytes_read = 0;
- static int stealth_init = BAD;
-
- SL_ENTER(_("sh_unix_getline_stealth"));
-
- if (str == NULL)
- {
- off_data = 0;
- max_data = 0;
- bytes_read = 0;
- stealth_init = BAD;
- SL_RETURN(0, _("sh_unix_getline_stealth"));
- }
-
- /* --- Initialize. ---
- */
- if (stealth_init == BAD)
- {
- off_data = first_hex_block(fd, &max_data);
- if (off_data == 0)
- {
- dlog(1, FIL__, __LINE__,
- _("The stealth config file does not contain any steganographically\nhidden data. This file must be an image file in _uncompressed_\npostscript format.\nTo hide data in it, use:\n samhain_stealth -s postscript_file orig_config_file\n mv postscript_file /path/to/config/file\n"));
- sh_error_handle ((-1), FIL__, __LINE__, EIO, MSG_P_NODATA,
- _("Stealth config file."));
- aud_exit (FIL__, __LINE__, EXIT_FAILURE);
- }
- stealth_init = GOOD;
- max_data += off_data;
- }
-
- /* --- Seek to proper position. ---
- */
- if (bytes_read >= max_data || add_off < 0)
- {
- dlog(1, FIL__, __LINE__,
- _("The capacity of the container image file for the stealth config file seems to be too small. Your config file is likely truncated.\n"));
- sh_error_handle ((-1), FIL__, __LINE__, EIO, MSG_P_NODATA,
- _("Stealth config file."));
- aud_exit (FIL__, __LINE__, EXIT_FAILURE);
- }
- sl_seek(fd, off_data);
-
- /* --- Read one line. ---
- */
- add_off = hideout_hex_block(fd, (unsigned char *) str, len, &bytes_read);
- off_data += add_off;
-
- llen = sl_strlen(str);
- SL_RETURN(llen, _("sh_unix_getline_stealth"));
-}
-
-int hideout_hex_block(SL_TICKET fd, unsigned char * str, int len,
- unsigned long * bytes_read)
-{
-
- register int i, j, k;
- unsigned char c, e;
- register int num;
- unsigned char mask[9] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
- unsigned long here = 0;
- unsigned long retval = 0;
- unsigned long bread = 0;
-
- SL_ENTER(_("hideout_hex_block"));
-
- ASSERT_RET((len > 1), _("len > 1"), (0));
-
- --len;
-
- i = 0;
- while (i < len)
- {
- for (j = 0; j < 8; ++j)
- {
-
- /* --- Get a low byte, modify, read back. ---
- */
- for (k = 0; k < 2; ++k)
- {
- /* -- Skip whitespace. ---
- */
- c = ' ';
- do {
- do {
- num = sl_read (fd, &c, 1);
- } while (num == 0 && errno == EINTR);
- if (num > 0)
- ++here;
- else if (num == 0)
- SL_RETURN((0), _("hideout_hex_block"));
- else
- SL_RETURN((-1), _("hideout_hex_block"));
- } while (c == '\n' || c == '\t' || c == '\r' ||
- c == ' ');
- }
-
-
- /* --- e is the value of the low byte. ---
- */
- e = (unsigned char) sh_util_hexchar( c );
- if ((e & mask[7]) != 0) /* bit is set */
- str[i] |= mask[j];
- else /* bit is not set */
- str[i] &= ~mask[j];
-
- bread += 1;
- }
- if (str[i] == '\n') break;
- ++i;
- }
-
- if (i != 0)
- str[i] = '\0';
- else
- str[i+1] = '\0'; /* keep newline and terminate */
- retval += here;
- *bytes_read += (bread/8);
-
- SL_RETURN(retval, _("hideout_hex_block"));
-}
-
-/* --- Get offset of first data block. ---
- */
-unsigned long first_hex_block(SL_TICKET fd, unsigned long * max)
-{
- unsigned int i;
- long num = 1;
- unsigned long lnum;
- char c;
- int nothex = 0;
- unsigned long retval = 0;
- unsigned int this_line = 0;
- char theline[SH_BUFSIZE];
-
- SL_ENTER(_("first_hex_block"));
-
- *max = 0;
-
- while (1)
- {
- theline[0] = '\0';
- this_line = 0;
- c = '\0';
- while (c != '\n' && this_line < (sizeof(theline)-1))
- {
- do {
- num = sl_read (fd, &c, 1);
- } while (num == 0 && errno == EINTR);
- if (num > 0)
- theline[this_line] = c;
- else
- SL_RETURN((0), _("first_hex_block"));
- ++this_line;
- }
- theline[this_line] = '\0';
-
- /* not only 'newline' */
- if (this_line > 60)
- {
- nothex = 0;
- i = 0;
- while (nothex == 0 && i < (this_line-1))
- {
- if (! isxdigit((int)theline[i])) nothex = 1;
- ++i;
- }
- if (nothex == 1) retval += this_line;
- }
- else
- {
- nothex = 1;
- retval += this_line;
- }
-
- if (nothex == 0)
- {
- *max = 0;
- do {
- do {
- num = sl_read (fd, theline, SH_BUFSIZE);
- } while (num == 0 && errno == EINTR);
- if (num > 0)
- {
- lnum = (unsigned long) num;
- for (i = 0; i < lnum; ++i)
- {
- c = theline[i];
- if (c == '\n' || c == '\t' || c == '\r' || c == ' ')
- ;
- else if (!isxdigit((int)c))
- break;
- else
- *max += 1;
- }
- }
- } while (num > 0);
-
- *max /= 16;
- SL_RETURN((retval), _("first_hex_block"));
- }
-
- }
- /* SL_RETURN((0), _("first_hex_block")); *//* unreachable */
-}
-
- /* if !defined(SH_STEALTH_MICRO) */
-#endif
-
- /* ifdef SH_STEALTH */
-#endif
-
-/*
- * anti-debugger code
- */
-#if defined(SCREW_IT_UP)
-
-#if defined(HAVE_PTHREAD)
-
-static pthread_key_t gSigtrapVariables_key;
-static pthread_once_t gSigtrapVariables_key_once = PTHREAD_ONCE_INIT;
-
-static inline void make_gSigtrapVariables_key()
-{
- (void) pthread_key_create(&gSigtrapVariables_key, free);
-}
-
-struct sh_sigtrap_variables * sh_sigtrap_variables_get()
-{
- void * ptr;
-
- (void) pthread_once(&gSigtrapVariables_key_once, make_gSigtrapVariables_key);
-
- ptr = pthread_getspecific(gSigtrapVariables_key);
- if (ptr == NULL) {
- ptr = calloc(1,sizeof(struct sh_sigtrap_variables));
- if (ptr == NULL) {
- return NULL;
- }
- (void) pthread_setspecific(gSigtrapVariables_key, ptr);
- }
-
- return (struct sh_sigtrap_variables *) ptr;
-}
-
-/* !defined(HAVE_PTHREAD) */
-#else
-
-static struct sh_sigtrap_variables global_sigtrap_variables;
-struct sh_sigtrap_variables * sh_sigtrap_variables_get()
-{
- return &global_sigtrap_variables;
-}
-
-#endif
-
-int sh_sigtrap_max_duration_set (const char * str)
-{
- /* For security (prevent reloading with larger value)
- * this value can only be set once.
- */
- static int once = 0;
- int i;
-
- SL_ENTER(_("sh_sigtrap_max_duration_set"));
-
- i = atoi (str);
-
- if (i >= 0 && once == 0)
- {
- sh.sigtrap_max_duration = i;
- once = 1;
- }
- else
- {
- SL_RETURN ((-1), _("sh_sigtrap_max_duration_set"));
- }
- SL_RETURN( (0), _("sh_sigtrap_max_duration_set"));
-}
-
-void sh_sigtrap_handler (int signum)
-{
- struct sh_sigtrap_variables * sigtrap_variables;
- sigtrap_variables = sh_sigtrap_variables_get();
- if (sigtrap_variables == NULL) {
- /* Perhaps, it's better to not die, and to continue using Samhain,
- even if this part does not work. */
- return;
- }
-
-#ifdef HAVE_GETTIMEOFDAY
- {
- struct timeval tv;
- long difftv;
-
- gettimeofday(&tv, NULL);
- difftv = (tv.tv_sec - sigtrap_variables->save_tv.tv_sec) * 1000000 +
- (tv.tv_usec - sigtrap_variables->save_tv.tv_usec);
- if (difftv > sh.sigtrap_max_duration)
- raise(SIGKILL);
- }
-#endif
-
- sigtrap_variables->not_traced = signum;
- /* cppcheck-suppress memleak */
- return;
-}
-#endif