summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/#sh_unix.c#5710
-rw-r--r--src/bignum.c9
-rw-r--r--src/cutest_sh_unix.c4
-rw-r--r--src/cutest_slib.c21
-rw-r--r--src/cutest_zAVLTree.c1
-rw-r--r--src/depend-gen.c2
-rw-r--r--src/dnmalloc.c97
-rw-r--r--src/samhain.c26
-rw-r--r--src/samhain_setpwd.c4
-rw-r--r--src/sh_audit.c183
-rw-r--r--src/sh_calls.c8
-rw-r--r--src/sh_cat.c6
-rw-r--r--src/sh_checksum.c4
-rw-r--r--src/sh_database.c10
-rw-r--r--src/sh_dbIO.c137
-rw-r--r--src/sh_entropy.c26
-rw-r--r--src/sh_err_console.c115
-rw-r--r--src/sh_err_log.c14
-rw-r--r--src/sh_error.c25
-rw-r--r--src/sh_extern.c1
-rw-r--r--src/sh_fInotify.c6
-rw-r--r--src/sh_files.c108
-rw-r--r--src/sh_filetype.c2
-rw-r--r--src/sh_filter.c3
-rw-r--r--src/sh_getopt.c17
-rw-r--r--src/sh_gpg.c1035
-rw-r--r--src/sh_hash.c23
-rw-r--r--src/sh_inotify.c2
-rw-r--r--src/sh_ipvx.c50
-rw-r--r--src/sh_log_check.c8
-rw-r--r--src/sh_log_evalrule.c15
-rw-r--r--src/sh_log_parse_apache.c2
-rw-r--r--src/sh_log_parse_samba.c2
-rw-r--r--src/sh_log_parse_syslog.c2
-rw-r--r--src/sh_log_repeat.c6
-rw-r--r--src/sh_login_track.c14
-rw-r--r--src/sh_mem.c19
-rw-r--r--src/sh_mounts.c8
-rw-r--r--src/sh_port2proc.c4
-rw-r--r--src/sh_portcheck.c759
-rw-r--r--src/sh_prelude.c3
-rw-r--r--src/sh_processcheck.c5
-rw-r--r--src/sh_readconf.c51
-rw-r--r--src/sh_registry.c15
-rw-r--r--src/sh_restrict.c2
-rw-r--r--src/sh_sem.c25
-rw-r--r--src/sh_sig.c1789
-rw-r--r--src/sh_socket.c6
-rw-r--r--src/sh_srp.c28
-rw-r--r--src/sh_static.c68
-rw-r--r--src/sh_string.c6
-rw-r--r--src/sh_subuid.c245
-rw-r--r--src/sh_suidchk.c23
-rw-r--r--src/sh_tiger0.c12
-rw-r--r--src/sh_tiger1_64.c2
-rw-r--r--src/sh_tools.c24
-rw-r--r--src/sh_unix.c199
-rw-r--r--src/sh_utils.c10
-rw-r--r--src/sh_utmp.c639
-rw-r--r--src/sh_xfer_client.c22
-rw-r--r--src/sh_xfer_server.c190
-rw-r--r--src/sh_xfer_syslog.c2
-rw-r--r--src/slib.c102
-rw-r--r--src/sstrip.c538
-rw-r--r--src/t-test0.c4
-rw-r--r--src/t-test1.c2
-rw-r--r--src/yulectl.c27
67 files changed, 4186 insertions, 8341 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
diff --git a/src/bignum.c b/src/bignum.c
index bd1bd71..8a622c1 100644
--- a/src/bignum.c
+++ b/src/bignum.c
@@ -174,7 +174,7 @@ init_digit_blocks(void)
for (base = 2; base <= 36; base++)
{
- tmp = ((1 << (DIGIT_BITS - 1)) / base);
+ tmp = ((1U << (DIGIT_BITS - 1)) / base);
maxdigit = tmp * 2;
curdigit = 1;
digcnt = 0;
@@ -424,6 +424,7 @@ static int
ucompare_digits(bignum *a, bignum *b)
{
DIGIT *a_ptr, *b_ptr;
+ int retval = 0;
if (a->dgs_used == b->dgs_used)
{
@@ -436,12 +437,14 @@ ucompare_digits(bignum *a, bignum *b)
}
if (a_ptr < a->dp)
{
- return 0;
+ return retval;
}
else
{
- return (*a_ptr > *b_ptr) ? 1 : -1;
+ if (retval == 0)
+ retval = (*a_ptr > *b_ptr) ? 1 : -1;
}
+ return retval;
}
return (a->dgs_used > b->dgs_used) ? 1 : -1;
}
diff --git a/src/cutest_sh_unix.c b/src/cutest_sh_unix.c
index 57fb7e6..b4428cf 100644
--- a/src/cutest_sh_unix.c
+++ b/src/cutest_sh_unix.c
@@ -20,6 +20,7 @@ void Test_dnmalloc (CuTest *tc) {
char * buf;
char * area[256];
+#if !defined(USE_SYSTEM_MALLOC) && !defined(__clang__)
/* test reuse of last freed chunk */
buf = malloc(1024);
CuAssertPtrNotNull(tc, buf);
@@ -27,7 +28,8 @@ void Test_dnmalloc (CuTest *tc) {
area[0] = malloc(1024);
CuAssertTrue(tc, buf == area[0]);
free(area[0]);
-
+#endif
+
/* test realloc */
buf = malloc(16);
CuAssertPtrNotNull(tc, buf);
diff --git a/src/cutest_slib.c b/src/cutest_slib.c
index 1e0e6c4..4350815 100644
--- a/src/cutest_slib.c
+++ b/src/cutest_slib.c
@@ -57,6 +57,27 @@ void Test_sl_snprintf (CuTest *tc) {
CuAssertTrue(tc, input[4] == 'X');
}
+void Test_sl_ts_strncmp (CuTest *tc) {
+ char one[64], two[64];
+ int res;
+
+ strcpy(one, "foo");
+ strcpy(two, "foo");
+ res = sl_ts_strncmp(one, two, 3);
+ CuAssertIntEquals(tc, 0, res);
+
+ strcpy(one, "fox");
+ strcpy(two, "foo");
+ res = sl_ts_strncmp(one, two, 2);
+ CuAssertIntEquals(tc, 0, res);
+
+ strcpy(one, "f9o");
+ strcpy(two, "foo");
+ res = sl_ts_strncmp(one, two, 3);
+ CuAssertTrue(tc, 0 != res);
+
+}
+
void Test_sl_strcasecmp (CuTest *tc) {
char one[64], two[64];
int res;
diff --git a/src/cutest_zAVLTree.c b/src/cutest_zAVLTree.c
index 1201ac9..b616925 100644
--- a/src/cutest_zAVLTree.c
+++ b/src/cutest_zAVLTree.c
@@ -512,6 +512,7 @@ void Test_zAVLTree(CuTest *tc) {
CuAssertTrue(tc, str == NULL);
zAVL_string_reset(ztest_tree);
+ ztest_tree = NULL;
str = zAVL_string_get(ztest_tree, "foo");
CuAssertTrue(tc, str == NULL);
str = zAVL_string_get(ztest_tree, "bar");
diff --git a/src/depend-gen.c b/src/depend-gen.c
index 586feee..c38b941 100644
--- a/src/depend-gen.c
+++ b/src/depend-gen.c
@@ -244,7 +244,7 @@ int main (int argc, char * argv[])
* EXCEPTIONS
*
**************************************************/
- if (0 == strcmp(p, "sh_gpg_chksum.h") ||
+ if (0 == strcmp(p, "sh_sig_chksum.h") ||
0 == strcmp(p, "sh_gpg_fp.h"))
{
/* fprintf(stderr, "Excluding %s\n", p); */
diff --git a/src/dnmalloc.c b/src/dnmalloc.c
index 4ab3b9a..9f7bacc 100644
--- a/src/dnmalloc.c
+++ b/src/dnmalloc.c
@@ -164,7 +164,7 @@
*
* HAVE_SYS_PARAM_H Define to #include <sys/param.h> (for pagesize)
*
- * HAVE_MALLOC_H Define to #include <malloc.h> (for struct mallinfo)
+ * HAVE_MALLOC_H Define to #include <malloc.h> (for struct mallinfo2)
*
* HAVE_FCNTL_H Define to #include <fcntl.h>
*
@@ -530,7 +530,7 @@ assert_handler_tp *dnmalloc_set_handler(assert_handler_tp *new)
#define rEALLOc public_rEALLOc
#define vALLOc public_vALLOc
#define pVALLOc public_pVALLOc
-#define mALLINFo public_mALLINFo
+#define mALLINFo2 public_mALLINFo2
#define mALLOPt public_mALLOPt
#define mTRIm public_mTRIm
#define mSTATs public_mSTATs
@@ -546,7 +546,7 @@ assert_handler_tp *dnmalloc_set_handler(assert_handler_tp *new)
#define public_rEALLOc dlrealloc
#define public_vALLOc dlvalloc
#define public_pVALLOc dlpvalloc
-#define public_mALLINFo dlmallinfo
+#define public_mALLINFo2 dlmallinfo2
#define public_mALLOPt dlmallopt
#define public_mTRIm dlmalloc_trim
#define public_mSTATs dlmalloc_stats
@@ -560,7 +560,7 @@ assert_handler_tp *dnmalloc_set_handler(assert_handler_tp *new)
#define public_rEALLOc realloc
#define public_vALLOc valloc
#define public_pVALLOc pvalloc
-#define public_mALLINFo mallinfo
+#define public_mALLINFo2 mallinfo2
#define public_mALLOPt mallopt
#define public_mTRIm malloc_trim
#define public_mSTATs malloc_stats
@@ -790,27 +790,27 @@ extern Void_t* sbrk();
#endif
/*
- This version of malloc supports the standard SVID/XPG mallinfo
+ This version of malloc supports the standard SVID/XPG mallinfo2
routine that returns a struct containing usage properties and
statistics. It should work on any SVID/XPG compliant system that has
- a /usr/include/malloc.h defining struct mallinfo. (If you'd like to
+ a /usr/include/malloc.h defining struct mallinfo2. (If you'd like to
install such a thing yourself, cut out the preliminary declarations
as described above and below and save them in a malloc.h file. But
there's no compelling reason to bother to do this.)
- The main declaration needed is the mallinfo struct that is returned
- (by-copy) by mallinfo(). The SVID/XPG malloinfo struct contains a
+ The main declaration needed is the mallinfo2 struct that is returned
+ (by-copy) by mallinfo2(). The SVID/XPG malloinfo2 struct contains a
bunch of fields that are not even meaningful in this version of
- malloc. These fields are are instead filled by mallinfo() with
+ malloc. These fields are are instead filled by mallinfo2() with
other numbers that might be of interest.
HAVE_MALLOC_H should be set if you have a
/usr/include/malloc.h file that includes a declaration of struct
- mallinfo. If so, it is included; else an SVID2/XPG2 compliant
+ mallinfo2. If so, it is included; else an SVID2/XPG2 compliant
version is declared below. These must be precisely the same for
- mallinfo() to work. The original SVID version of this struct,
- defined on most systems with mallinfo, declares all fields as
- ints. But some others define as unsigned long. If your system
+ mallinfo2() to work. The original SVID version of this struct,
+ defined on most systems with mallinfo2, declares all fields as
+ size_2. But some others define as unsigned long. If your system
defines the fields using a type of different width than listed here,
you must #include your system version and #define
HAVE_MALLOC_H.
@@ -821,23 +821,23 @@ extern Void_t* sbrk();
/* On *BSD, malloc.h is deprecated, and on some *BSD including
* it may actually raise an error.
*/
-#if defined(HAVE_MALLOC_H) && !defined(__OpenBSD__) && !defined(__FreeBSD__) && !defined(__NetBSD__)
+#if defined(HAVE_MALLOC_H) && !defined(__OpenBSD__) && !defined(__FreeBSD__) && !defined(__NetBSD__) && defined(__GLIBC_PREREQ) && __GLIBC_PREREQ(2, 33)
#include <malloc.h>
#else
-/* SVID2/XPG mallinfo structure */
-
-struct mallinfo {
- int arena; /* non-mmapped space allocated from system */
- int ordblks; /* number of free chunks */
- int smblks; /* number of fastbin blocks */
- int hblks; /* number of mmapped regions */
- int hblkhd; /* space in mmapped regions */
- int usmblks; /* maximum total allocated space */
- int fsmblks; /* space available in freed fastbin blocks */
- int uordblks; /* total allocated space */
- int fordblks; /* total free space */
- int keepcost; /* top-most, releasable (via malloc_trim) space */
+/* SVID2/XPG mallinfo2 structure */
+
+struct mallinfo2 {
+ size_t arena; /* non-mmapped space allocated from system */
+ size_t ordblks; /* number of free chunks */
+ size_t smblks; /* number of fastbin blocks */
+ size_t hblks; /* number of mmapped regions */
+ size_t hblkhd; /* space in mmapped regions */
+ size_t usmblks; /* maximum total allocated space */
+ size_t fsmblks; /* space available in freed fastbin blocks */
+ size_t uordblks; /* total allocated space */
+ size_t fordblks; /* total free space */
+ size_t keepcost; /* top-most, releasable (via malloc_trim) space */
};
/*
@@ -1007,7 +1007,7 @@ int public_mALLOPt();
/*
- mallinfo()
+ mallinfo2()
Returns (by copy) a struct containing various summary statistics:
arena: current total non-mmapped bytes allocated from system
@@ -1030,9 +1030,9 @@ int public_mALLOPt();
thus be inaccurate.
*/
#if __STD_C
-struct mallinfo public_mALLINFo(void);
+struct mallinfo2 public_mALLINFo2(void);
#else
-struct mallinfo public_mALLINFo();
+struct mallinfo2 public_mALLINFo2();
#endif
/*
@@ -1114,7 +1114,7 @@ size_t public_mUSABLe();
(normally sbrk) outside of malloc.
malloc_stats prints only the most commonly interesting statistics.
- More information can be obtained by calling mallinfo.
+ More information can be obtained by calling mallinfo2.
*/
#if __STD_C
@@ -1365,7 +1365,7 @@ static int mTRIm(size_t);
static size_t mUSABLe(Void_t*);
static void mSTATs();
static int mALLOPt(int, int);
-static struct mallinfo mALLINFo(void);
+static struct mallinfo2 mALLINFo2(void);
#else
static Void_t* mALLOc();
static void fREe();
@@ -1379,7 +1379,7 @@ static int mTRIm();
static size_t mUSABLe();
static void mSTATs();
static int mALLOPt();
-static struct mallinfo mALLINFo();
+static struct mallinfo2 mALLINFo2();
#endif
/*
@@ -1686,14 +1686,14 @@ void public_mSTATs() {
}
}
-struct mallinfo public_mALLINFo() {
- struct mallinfo m;
+struct mallinfo2 public_mALLINFo2() {
+ struct mallinfo2 m;
if (MALLOC_PREACTION == 0) {
- m = mALLINFo();
+ m = mALLINFo2();
(void) MALLOC_POSTACTION;
return m;
} else {
- struct mallinfo nm = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+ struct mallinfo2 nm = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
return nm;
}
}
@@ -5292,10 +5292,10 @@ DL_STATIC size_t mUSABLe(mem) Void_t* mem;
------------------------------ mallinfo ------------------------------
*/
-DL_STATIC struct mallinfo mALLINFo()
+DL_STATIC struct mallinfo2 mALLINFo2()
{
mstate av = get_malloc_state();
- struct mallinfo mi;
+ static struct mallinfo2 mi;
unsigned int i;
mbinptr b;
chunkinfoptr p;
@@ -5311,6 +5311,10 @@ DL_STATIC struct mallinfo mALLINFo()
}
check_malloc_state();
+ if (!av || av->top == 0) {
+ return mi;
+ }
+
/* Account for top */
avail = chunksize(av->top);
nblocks = 1; /* top always exists */
@@ -5356,19 +5360,18 @@ DL_STATIC struct mallinfo mALLINFo()
DL_STATIC void mSTATs()
{
- struct mallinfo mi = mALLINFo();
+ struct mallinfo2 mi = mALLINFo2();
fprintf(stderr, "hashtable = %10lu MB\n",
(CHUNK_SIZE_T)(HASHTABLESIZE / (1024*1024)));
fprintf(stderr, "max system bytes = %10lu\n",
- (CHUNK_SIZE_T)(mi.usmblks));
+ (CHUNK_SIZE_T)(mi.usmblks));
fprintf(stderr, "system bytes = %10lu (%10lu sbrked, %10lu mmaped)\n",
- (CHUNK_SIZE_T)(mi.arena + mi.hblkhd),
- (CHUNK_SIZE_T)(mi.arena),
- (CHUNK_SIZE_T)(mi.hblkhd));
+ (CHUNK_SIZE_T)(mi.arena + mi.hblkhd),
+ (CHUNK_SIZE_T)(mi.arena),
+ (CHUNK_SIZE_T)(mi.hblkhd));
fprintf(stderr, "in use bytes = %10lu\n",
- (CHUNK_SIZE_T)(mi.uordblks + mi.hblkhd));
-
+ (CHUNK_SIZE_T)(mi.uordblks + mi.hblkhd));
}
@@ -5521,7 +5524,7 @@ arc4_stir(void)
struct {
struct timeval tv1;
struct timeval tv2;
- u_int rnd[(128 - 2*sizeof(struct timeval)) / sizeof(u_int)];
+ unsigned char rnd[(128 - 2*sizeof(struct timeval)) / sizeof(unsigned char)];
} rdat;
#if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__)
ssize_t sz = 0;
diff --git a/src/samhain.c b/src/samhain.c
index 43503cd..f5883e9 100644
--- a/src/samhain.c
+++ b/src/samhain.c
@@ -76,7 +76,7 @@
#include "sh_nmail.h"
#include "sh_tiger.h"
-#include "sh_gpg.h"
+#include "sh_sig.h"
#include "sh_mem.h"
#include "sh_xfer.h"
#include "sh_tools.h"
@@ -347,7 +347,11 @@ void sh_init (void)
sig_force_silent = 0; /* SIGTSTP */
sh_global_check_silent = 0;
sh_load_delta_flag = 0;
- strcpy ( sh_sig_msg, _("None"));
+ sh_sig_msg[4] = '\0';
+ sh_sig_msg[3] = 'e';
+ sh_sig_msg[2] = 'n';
+ sh_sig_msg[1] = 'o';
+ sh_sig_msg[0] = 'N';
#ifdef MKB_01
ErrFlag[1] |= (1 << 0);
@@ -772,6 +776,7 @@ static void exit_handler(void)
sh_files_delglobstack ();
sh_hash_hashdelete();
sh_files_hle_reg (NULL);
+ (void) sh_ignore_clean ();
/*
* Only flush on exit if running as deamon.
* Otherwise we couldn't run another instance
@@ -833,7 +838,7 @@ static void exit_handler(void)
if (sh.flag.isdaemon == S_TRUE)
(void) sh_unix_rm_pid_file ();
if (skey != NULL)
- memset (skey, (int) '\0', sizeof(sh_key_t));
+ memset (skey, 0, sizeof(sh_key_t));
/* --- Exit. ---
*/
@@ -876,6 +881,7 @@ static pid_t * procdirSamhain (void)
if (NULL == (dp = opendir(_("/proc"))))
{
+ /* cppcheck-suppress resourceLeak */
return NULL;
}
@@ -1374,7 +1380,7 @@ void do_reconf()
}
else
{
- sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_MOD_OK,
+ sh_error_handle ((-1), FIL__, __LINE__, status, MSG_MOD_OK,
_(modList[modnum].name));
modList[modnum].initval = status;
}
@@ -1901,9 +1907,9 @@ int undef_main(int argc, char * argv[])
#if defined(SH_WITH_SERVER) && !defined(SH_WITH_CLIENT)
-#if (defined(WITH_GPG) || defined(WITH_PGP))
+#if defined(WITH_GPG)
/* log startup */
- sh_gpg_log_startup ();
+ sh_sig_log_startup ();
#else
sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_START_1H,
sh.prg_name, (long) sh.real.uid,
@@ -1924,9 +1930,9 @@ int undef_main(int argc, char * argv[])
if (sh.flag.checkSum == SH_CHECK_CHECK)
{
-#if (defined(WITH_GPG) || defined(WITH_PGP))
+#if defined(WITH_GPG)
/* log startup */
- sh_gpg_log_startup ();
+ sh_sig_log_startup ();
#else
sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_START_2H,
sh.prg_name, (long) sh.real.uid,
@@ -1936,9 +1942,9 @@ int undef_main(int argc, char * argv[])
}
else
{
-#if (defined(WITH_GPG) || defined(WITH_PGP))
+#if defined(WITH_GPG)
/* log startup */
- sh_gpg_log_startup ();
+ sh_sig_log_startup ();
#else
sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_START_1H,
sh.prg_name, (long) sh.real.uid,
diff --git a/src/samhain_setpwd.c b/src/samhain_setpwd.c
index e8de644..a12b801 100644
--- a/src/samhain_setpwd.c
+++ b/src/samhain_setpwd.c
@@ -245,8 +245,8 @@ int main (int argc, char * argv[])
char * newpwd = (char *) malloc(5 * 8 + 2);
char * oldpwd = (char *) malloc(5 * 8 + 2);
- memset (newpwd, '\0', 5 * 8 + 2);
- memset (oldpwd, '\0', 5 * 8 + 2);
+ memset (newpwd, 0, 5 * 8 + 2);
+ memset (oldpwd, 0, 5 * 8 + 2);
if (argc < 4)
diff --git a/src/sh_audit.c b/src/sh_audit.c
index 52d0c70..d4d4dd2 100644
--- a/src/sh_audit.c
+++ b/src/sh_audit.c
@@ -74,7 +74,7 @@ static int listRecords (auparse_state_t * au, struct recordState * state)
sl_strlcpy(state->syscall, auparse_interpret_field(au), REC_SIZE_SYSCALL);
if (auparse_find_field(au, _("success")))
- strncpy(state->success, auparse_interpret_field(au), REC_SIZE_SUCCESS);
+ sl_strlcpy(state->success, auparse_interpret_field(au), REC_SIZE_SUCCESS);
if (auparse_find_field(au, "uid"))
state->uid = auparse_get_field_int(au);
@@ -147,7 +147,7 @@ static char * doAuparse (const char * file, time_t time, int tol, char * result,
goto err;
}
- memset(&state, '\0', sizeof(state));
+ memset(&state, 0, sizeof(state));
while (ausearch_next_event(au) == 1)
{
@@ -179,10 +179,13 @@ static char * doAuparse (const char * file, time_t time, int tol, char * result,
if (0 == strcmp(state.success, "yes"))
{
+ char time_str[81];
char * tmp_exe = sh_util_safe_name(state.exe);
+
+ (void) sh_unix_gmttime (state.time, time_str, sizeof(time_str));
sl_snprintf(result, rsize,
- _("time=%lu.%u, syscall=%s, auid=%u, uid=%u, gid=%u, euid=%u, egid=%u, fsuid=%u, fsgid=%u, exe=%s"),
- (unsigned long) state.time, state.milli,
+ _("time=%lu.%u, timestamp=%s, syscall=%s, auid=%u, uid=%u, gid=%u, euid=%u, egid=%u, fsuid=%u, fsgid=%u, exe=%s"),
+ (unsigned long) state.time, state.milli, time_str,
state.syscall,
state.auid, state.uid, state.gid, state.euid, state.egid,
state.fsuid, state.fsgid, tmp_exe);
@@ -196,6 +199,23 @@ static char * doAuparse (const char * file, time_t time, int tol, char * result,
return NULL;
}
+#define SH_AUDIT_DEF "wa"
+static char sh_audit_flags[32] = SH_AUDIT_DEF;
+
+int sh_audit_set_flags(const char * str)
+{
+ if (!str || strlen(str) >= sizeof(sh_audit_flags))
+ return -1;
+ sl_strlcpy(sh_audit_flags, str, sizeof(sh_audit_flags));
+ return 0;
+}
+static void reset_audit_flags()
+{
+ sl_strlcpy(sh_audit_flags, SH_AUDIT_DEF, sizeof(sh_audit_flags));
+ return;
+}
+
+
static int sh_audit_checkdaemon();
static int actl_pnum = -1;
static char * actl_paths[4] =
@@ -206,20 +226,23 @@ static char * actl_paths[4] =
N_("/usr/bin/auditctl")
};
+static char * getflags (char * file);
/* Public function to fetch an audit record for path 'file', time 'time'
* The 'result' array should be sized ~256 char.
*/
-char * sh_audit_fetch (char * file, time_t mtime, time_t ctime, char * result, size_t rsize)
+char * sh_audit_fetch (char * file, time_t mtime, time_t ctime, time_t atime, char * result, size_t rsize)
{
- char * res = NULL;
+ char * res = NULL;
+ char * flags = getflags(file);
if (sh_audit_checkdaemon() >= 0)
{
time_t new;
-
- if (mtime >= ctime) { new = mtime; }
- else { new = ctime; }
+
+ if (flags && (strchr(flags, 'r') || strchr(flags, 'x')) && atime >= ctime && atime >= mtime) { new = atime; }
+ else if (mtime >= ctime) { new = mtime; }
+ else { new = ctime; }
res = doAuparse (file, new, 1, result, rsize, S_FALSE);
@@ -250,6 +273,7 @@ void sh_audit_delete_all ()
sl_strlcpy(ctl, _(actl_paths[p]), sizeof(ctl));
sh_ext_system(ctl, ctl, "-D", "-k", _("samhain"), NULL);
}
+ reset_audit_flags();
return;
}
@@ -262,7 +286,7 @@ static int sh_audit_isdir(const char * file)
return S_FALSE;
}
-static void sh_audit_mark_int (const char * file)
+static void sh_audit_mark_int (const char * file, const char * flags)
{
static int flushRules = 0;
@@ -285,10 +309,10 @@ static void sh_audit_mark_int (const char * file)
char a1[32];
char a2[32];
char a3[32];
+ char a4[32];
- sl_snprintf(command, len, _("%s -w %s -p wa -k samhain"),
- _(actl_paths[p]),
- file);
+ sl_snprintf(command, len, _("%s -w %s -p %s -k samhain"),
+ _(actl_paths[p]), file, flags);
safe = sh_util_safe_name_keepspace(command);
sh_error_handle (SH_ERR_ALL, FIL__, __LINE__,
@@ -302,7 +326,8 @@ static void sh_audit_mark_int (const char * file)
sl_strlcpy(command, file, len);
sl_strlcpy(a3, _("samhain"), sizeof(a3));
- sh_ext_system(ctl, ctl, "-w", command, "-p", "wa", "-k", a3, NULL);
+ sl_strlcpy(a4, flags, sizeof(a4));
+ sh_ext_system(ctl, ctl, "-w", command, "-p", a4, "-k", a3, NULL);
/* Placing a watch on a directory will not place a watch on the
* directory inode, so we do this explicitely.
@@ -318,7 +343,8 @@ static void sh_audit_mark_int (const char * file)
sl_strlcpy(command, _("path="), len);
sl_strlcat(command, file, len);
sl_strlcpy(a1, _("always,exit"), sizeof(a1));
- sl_strlcpy(a2, _("perm=wa"), sizeof(a2));
+ sl_strlcpy(a2, _("perm="), sizeof(a2));
+ sl_strlcat(a2, flags, sizeof(a2));
sh_ext_system(ctl, ctl, "-a", a1, "-F", command, "-F", a2, "-k", a3, NULL);
}
SH_FREE(command);
@@ -326,12 +352,47 @@ static void sh_audit_mark_int (const char * file)
return;
}
+#define SH_AU_FLAGS_SIZ 32
struct aud_list {
char * file;
+ char flags[SH_AU_FLAGS_SIZ];
struct aud_list * next;
};
struct aud_list * mark_these = NULL;
+static int marked_committed = 0;
+
+static void delete_listofmarked()
+{
+ struct aud_list * tmp;
+ struct aud_list * this = mark_these;
+
+ mark_these = NULL;
+
+ while (this)
+ {
+ tmp = this;
+ this = this->next;
+
+ SH_FREE(tmp->file);
+ SH_FREE(tmp);
+ }
+ marked_committed = 0;
+}
+
+static char * getflags (char * file)
+{
+ struct aud_list * this = mark_these;
+
+ while (this)
+ {
+ if (0 == strcmp(file, this->file))
+ return this->flags;
+ this = this->next;
+ }
+ /* no explicit rule for this file */
+ return NULL;
+}
static void add_this (char * file)
{
@@ -339,8 +400,12 @@ static void add_this (char * file)
size_t len = strlen(file);
this->file = sh_util_strdup(file);
+
+ /* strip trailing '/' */
if ((len > 1) && (file[len-1] == '/'))
this->file[len-1] = '\0';
+
+ sl_strlcpy(this->flags, sh_audit_flags, SH_AU_FLAGS_SIZ);
this->next = mark_these;
mark_these = this;
@@ -349,44 +414,50 @@ static void add_this (char * file)
/* Check whether it is already covered by a higher directory
*/
-static int test_exchange (struct aud_list * this, char * file)
+static int test_exchange (struct aud_list * this, const char * file)
{
size_t len0 = sl_strlen(this->file);
size_t len1 = sl_strlen(file);
int ret = -1;
+ if (!file || !this || !this->file)
+ return 0;
+
if (len0 == len1)
{
return strcmp(this->file, file);
}
else
{
- char * s0 = SH_ALLOC(len0 + 2);
- char * s1 = SH_ALLOC(len1 + 2);
-
- sl_strlcpy(s0, this->file, len0 + 2);
- sl_strlcpy(s1, file, len1 + 2);
-
- if (s0 < s1)
- {
- sl_strlcat(s0, "/", len0 + 2);
- ret = strncmp(s0, s1, len0 + 1);
- }
- else
- {
- sl_strlcat(s1, "/", len1 + 2);
- if (0 == strncmp(s0, s1, len1 + 1))
- {
- size_t len = strlen(file);
- SH_FREE(this->file);
- this->file = sh_util_strdup(file);
- if ((len > 1) && (file[len-1] == '/'))
- this->file[len-1] = '\0';
- ret = 0;
- }
- }
- SH_FREE(s0);
- SH_FREE(s1);
+ if (0 == strcmp(this->flags, sh_audit_flags))
+ {
+ char * s0 = SH_ALLOC(len0 + 2);
+ char * s1 = SH_ALLOC(len1 + 2);
+
+ sl_strlcpy(s0, this->file, len0 + 2);
+ sl_strlcpy(s1, file, len1 + 2);
+
+ if (s0 < s1)
+ {
+ sl_strlcat(s0, "/", len0 + 2);
+ ret = strncmp(s0, s1, len0 + 1);
+ }
+ else
+ {
+ sl_strlcat(s1, "/", len1 + 2);
+ if (0 == strncmp(s0, s1, len1 + 1))
+ {
+ size_t len = strlen(file);
+ SH_FREE(this->file);
+ this->file = sh_util_strdup(file);
+ if ((len > 1) && (file[len-1] == '/'))
+ this->file[len-1] = '\0';
+ ret = 0;
+ }
+ }
+ SH_FREE(s0);
+ SH_FREE(s1);
+ }
}
return ret;
@@ -396,13 +467,18 @@ static int test_exchange (struct aud_list * this, char * file)
*/
void sh_audit_mark (char * file)
{
- struct aud_list * this = mark_these;
+ struct aud_list * this;
+ if (marked_committed != 0)
+ delete_listofmarked();
+
if (!mark_these) {
add_this (file);
return;
}
+ this = mark_these;
+
while (this)
{
/* Check whether it is already covered by a higher
@@ -410,6 +486,7 @@ void sh_audit_mark (char * file)
*/
if (0 == test_exchange(this, file))
return;
+
this = this->next;
}
@@ -419,20 +496,14 @@ void sh_audit_mark (char * file)
void sh_audit_commit ()
{
- struct aud_list * next;
struct aud_list * this = mark_these;
- mark_these = NULL;
-
while (this)
{
- sh_audit_mark_int (this->file);
- next = this->next;
- SH_FREE(this->file);
- SH_FREE(this);
- this = next;
+ sh_audit_mark_int (this->file, this->flags);
+ this = this->next;
}
-
+ marked_committed = 1;
}
static int sh_audit_checkdaemon()
@@ -537,11 +608,12 @@ static int sh_audit_checkdaemon()
/* HAVE_AUPARSE_H */
#else
-char * sh_audit_fetch (char * file, time_t mtime, time_t ctime, char * result, size_t rsize)
+char * sh_audit_fetch (char * file, time_t mtime, time_t ctime, time_t atime, char * result, size_t rsize)
{
(void) file;
(void) mtime;
(void) ctime;
+ (void) atime;
(void) result;
(void) rsize;
@@ -563,6 +635,11 @@ void sh_audit_commit ()
{
return;
}
+int sh_audit_set_flags(const char * str)
+{
+ (void) str;
+ return -1;
+}
#endif
/* client || standalone */
diff --git a/src/sh_calls.c b/src/sh_calls.c
index 2269836..cf4c4c5 100644
--- a/src/sh_calls.c
+++ b/src/sh_calls.c
@@ -50,7 +50,6 @@
#include "samhain.h"
#include "sh_error.h"
-#include "sh_calls.h"
#include "sh_ipvx.h"
#include "sh_sub.h"
#include "sh_utils.h"
@@ -533,8 +532,8 @@ long int retry_msleep (int sec, int millisec)
***************************************************/
long int retry_aud_execve (const char * file, int line,
- const char *dateiname, char * argv[],
- char * envp[])
+ const char *dateiname, char *const argv[],
+ char *const envp[])
{
uid_t a = geteuid();
gid_t b = getegid();
@@ -736,6 +735,7 @@ long int aud_open_noatime (const char * file, int line, int privs,
if ((val_return < 0) && (*o_noatime != 0))
{
+ /* cppcheck-suppress resourceLeak */
val_return = open (pathname, flags, mode);
if (val_return >= 0)
*o_noatime = 0;
@@ -932,7 +932,7 @@ int aud_setgid (const char * file, int line, gid_t gid)
SL_RETURN(i, _("aud_setgid"));
}
-int aud_pipe (const char * file, int line, int * modus)
+int aud_pipe (const char * file, int line, int modus[2])
{
int error;
int i = pipe (modus);
diff --git a/src/sh_cat.c b/src/sh_cat.c
index dfffae1..9328543 100644
--- a/src/sh_cat.c
+++ b/src/sh_cat.c
@@ -71,7 +71,8 @@ cat_entry msg_cat[] = {
{ MSG_CHECK_1, SH_ERR_STAMP, STAMP, N_("msg=\"File check completed.\" time=\"%ld\" kBps=\"%f\"")},
{ MSG_CHECK_2, SH_ERR_STAMP, STAMP, N_("msg=\"File check starting.\"")},
{ MSG_STAMP, SH_ERR_STAMP, STAMP, N_("msg=\"---- TIMESTAMP ----\"")},
-
+ { MSG_DCLOSE, SH_ERR_NOTICE, RUN, N_("msg=\"Finished writing baseline database.\"")},
+
{ MSG_D_START, SH_ERR_INFO, RUN, N_("msg=\"Downloading configuration file\"")},
{ MSG_D_DSTART, SH_ERR_INFO, RUN, N_("msg=\"Downloading database file\"")},
{ MSG_D_FAIL, SH_ERR_INFO, RUN, N_("msg=\"No file from server, trying local file\"")},
@@ -223,6 +224,7 @@ cat_entry msg_cat[] = {
{ MSG_TCP_EBGN, SH_ERR_ERR, TCP, N_("msg=\"Error in big integer library\"")},
{ MSG_TCP_CREG, SH_ERR_ALL, TCP, N_("msg=\"Registered %s, salt %s, verifier %s\"")},
+ { MSG_TCP_AREG, SH_ERR_ALL, TCP, N_("msg=\"Registered %s, hostname %s\"")},
{ MSG_TCP_FAUTH, SH_ERR_INFO, TCP, N_("msg=\"Force authentication\" host=\"%s\"")},
{ MSG_TCP_RESCLT, SH_ERR_SEVERE, TCP, N_("msg=\"Cannot resolve client name\" host=\"%s\"")},
@@ -402,6 +404,7 @@ cat_entry msg_cat[] = {
{ MSG_CHECK_1, SH_ERR_STAMP, STAMP, N_("msg=<File check completed.>, time=<%ld>, kBps=<%f>")},
{ MSG_CHECK_2, SH_ERR_STAMP, STAMP, N_("msg=<File check starting.>")},
{ MSG_STAMP, SH_ERR_STAMP, STAMP, N_("msg=<---- TIMESTAMP ---->")},
+ { MSG_DCLOSE, SH_ERR_NOTICE, RUN, N_("msg=<Finished writing baseline database.>")},
{ MSG_D_START, SH_ERR_INFO, RUN, N_("msg=<Downloading configuration file>")},
{ MSG_D_DSTART, SH_ERR_INFO, RUN, N_("msg=<Downloading database file>")},
@@ -566,6 +569,7 @@ cat_entry msg_cat[] = {
{ MSG_TCP_EBGN, SH_ERR_ERR, TCP, N_("msg=<Error in big integer library>")},
{ MSG_TCP_CREG, SH_ERR_ALL, TCP, N_("msg=<Registered %s, salt %s, verifier %s>")},
+ { MSG_TCP_AREG, SH_ERR_ALL, TCP, N_("msg=<Registered %s, hostname %s>")},
{ MSG_TCP_FAUTH, SH_ERR_INFO, TCP, N_("msg=<Force authentication>, client=<%s>")},
{ MSG_TCP_RESCLT, SH_ERR_SEVERE, TCP, N_("msg=<Cannot resolve client name> host=<%s>")},
diff --git a/src/sh_checksum.c b/src/sh_checksum.c
index 0587edc..e434d5c 100644
--- a/src/sh_checksum.c
+++ b/src/sh_checksum.c
@@ -407,7 +407,7 @@ void SHA256_Update(SHA256_CTX* context, const sha2_byte *data, size_t len) {
usedspace = freespace = 0;
}
-void SHA256_Final(sha2_byte digest[], SHA256_CTX* context)
+void SHA256_Final(sha2_byte digest[SHA256_DIGEST_LENGTH], SHA256_CTX* context)
{
sha2_word32 *d = (sha2_word32*)digest;
unsigned int usedspace;
@@ -481,7 +481,7 @@ void SHA256_Final(sha2_byte digest[], SHA256_CTX* context)
#include "sh_utils.h"
/* If buffer is of length KEYBUF_SIZE, the digest will fit */
-char *SHA256_End(SHA256_CTX* context, char buffer[])
+char *SHA256_End(SHA256_CTX* context, char buffer[KEYBUF_SIZE])
{
sha2_byte digest[SHA256_DIGEST_LENGTH];
diff --git a/src/sh_database.c b/src/sh_database.c
index fdeed45..31a5919 100644
--- a/src/sh_database.c
+++ b/src/sh_database.c
@@ -283,7 +283,7 @@ static int insert_value (char * ptr, const char * str)
static void init_db_entry (dbins * ptr)
{
- memset (ptr, (int) '\0', sizeof(dbins));
+ memset (ptr, 0, sizeof(dbins));
ptr->next = NULL;
return;
}
@@ -1122,12 +1122,7 @@ int sh_database_query (char * query, /*@out@*/ long * id)
* We don't check the return value because it's useless (failure due
* to lack of access permission is not reported).
*/
-#if !defined(__x86_64__)
- /*
- * libmysql segfaults on x86-64 if this is used
- */
mysql_options(db_conn, MYSQL_READ_DEFAULT_GROUP, _("samhain"));
-#endif
status = 0;
@@ -1148,6 +1143,7 @@ int sh_database_query (char * query, /*@out@*/ long * id)
SL_RETURN(0, _("sh_database_query"));
}
}
+
connection_status = S_TRUE;
}
else
@@ -1410,7 +1406,7 @@ long sh_database_entry (dbins * db_entry, long id)
}
/*@-type@*//* byte* versus char[..] */
if (attr_tab[i].inHash == 1 &&
- ((char *)(db_entry)+attr_tab[i].off) != '\0')
+ *((char *)(db_entry)+attr_tab[i].off) != '\0')
{
(void)md5Update(&crc,
(sh_byte*) ((char *)(db_entry)+attr_tab[i].off),
diff --git a/src/sh_dbIO.c b/src/sh_dbIO.c
index 0ac9194..1f9b152 100644
--- a/src/sh_dbIO.c
+++ b/src/sh_dbIO.c
@@ -30,7 +30,7 @@
#include "sh_dbIO_int.h"
#include "sh_hash.h"
#include "sh_dbIO.h"
-#include "sh_gpg.h"
+#include "sh_sig.h"
#include "sh_tiger.h"
#include "sh_xfer.h"
#include "sh_pthread.h"
@@ -151,6 +151,8 @@ static int sh_dbIO_setdataent (SL_TICKET fd, char * line, int size,
SL_RETURN( retval, _("sh_dbIO_setdataent"));
}
+/* Seek to [SOF] and truncate remainder of file
+ */
static int sh_dbIO_setdataent_old (SL_TICKET fd, char * line, int size,
const char * file)
{
@@ -224,12 +226,10 @@ static unsigned short * swap_short (unsigned short * iptr)
else
{
/* alignment problem */
- unsigned char swap;
- static unsigned short ooop;
- unsigned char * ii;
- ooop = *iptr;
- ii = (unsigned char *) &ooop;
- swap = ii[0]; ii[0] = ii[1]; ii[1] = swap;
+ static unsigned short ooop = *iptr;
+ unsigned short hi = (ooop & 0xff00);
+ unsigned short lo = (ooop & 0xff);
+ ooop = (lo << 8) | (hi >> 8);
return &ooop;
}
return iptr;
@@ -378,10 +378,87 @@ static char * unquote_path(char * line, long i)
(void) sl_strlcpy (path, tmp, len);
if (tmp)
SH_FREE(tmp);
+ /* do not strip newline twice...
if (len > 1) {
if (path[len-2] == '\n')
path[len-2] = '\0';
}
+ ****/
+ return path;
+}
+
+/******************************************************************
+ *
+ * Use different init rootfs (patch by Kemal H.)
+ *
+ ******************************************************************/
+
+static char * sh_dbIO_rootfs = NULL;
+static size_t sh_dbIO_rootfs_len = 0;
+
+int sh_dbIO_init_rootfs (const char * rootfs)
+{
+ if (NULL == sh_dbIO_rootfs)
+ {
+ sh_dbIO_rootfs = sh_util_strdup (rootfs);
+ sh_dbIO_rootfs_len = sl_strlen(sh_dbIO_rootfs);
+ return 0;
+ }
+ return -1;
+}
+
+size_t sh_dbIO_get_rootfs_len()
+{
+ return sh_dbIO_rootfs_len;
+}
+
+/* Prepend rootfs when reading from config file ('path' must be allocated with sufficient space).
+ */
+char * sh_dbIO_rootfs_prepend(char * path)
+{
+ if (0 == sh_dbIO_rootfs_len)
+ return path;
+
+ memmove (path + sh_dbIO_rootfs_len, path, sl_strlen(path) + 1);
+ memcpy (path, sh_dbIO_rootfs, sh_dbIO_rootfs_len);
+
+ return path;
+}
+
+
+/* Strip rootfs when writing to database file.
+ */
+char * sh_dbIO_rootfs_strip(char * path)
+{
+ if (sh_dbIO_rootfs_len == 0)
+ {
+ return path;
+ }
+ else
+ {
+ size_t len = sl_strlen(path);
+
+ memmove (path, path + sh_dbIO_rootfs_len, len + 1 - sh_dbIO_rootfs_len);
+ if(path[0] != '/')
+ {
+ path[0]='/';
+ path[1]='\0';
+ }
+ }
+
+ return path;
+}
+
+char * sh_dbIO_rootfs_strip_link(char * path)
+{
+ if (sh_dbIO_rootfs_len == 0)
+ return path;
+ if (strstr(path, sh_dbIO_rootfs) == path)
+ {
+ size_t len = sl_strlen(path);
+
+ memmove (path, path + sh_dbIO_rootfs_len, len + 1 - sh_dbIO_rootfs_len);
+ }
return path;
}
@@ -406,7 +483,7 @@ static void corrupt_record(char * file, int line, const char * filepath)
static void wrong_version(char * file, int line, const char * filepath)
{
dlog(1, file, line,
- _("There is a record with a bad version number in the file signature database: %s\n"),
+ _("There is a record with a bad version number in the file signature database: %s\nThis may be caused by using '-t init' repeatedly to initialise the database, without (re)moving the database file.\n"),
(NULL == filepath) ? _("(null)") : filepath);
sh_error_handle((-1), file, line, 0, MSG_E_SUBGPATH,
_("Record with bad version number in file signature database"),
@@ -457,7 +534,7 @@ static size_t dbIO_fread_struct (sh_filestore_t * ptr, FILE *stream,
if (1 == 0)
hexdump((unsigned char *)&old_struct, sizeof(old_struct));
- memset(&try_struct, '\0', sizeof(try_struct));
+ memset(&try_struct, 0, sizeof(try_struct));
if (!memcmp(&old_struct, &try_struct, sizeof(try_struct)))
return 0; /* NULL read */
if (1 != fread (try, sizeof(try), 1, stream))
@@ -580,7 +657,7 @@ static sh_file_t * sh_dbIO_getdataent (char * line, int size,
}
fullpath = unquote_path(line, i);
-
+
/* Read next record -- Part Three -- Linkpath
*/
i = sh_dbIO_getline (sh_fin_fd, line, size);
@@ -774,12 +851,12 @@ static SL_TICKET load_data_from_disk(const char * filepath)
static SL_TICKET verify_data (SL_TICKET fd)
{
-#if defined(WITH_GPG) || defined(WITH_PGP)
+#if defined(WITH_SIG)
SL_TICKET fdTmp;
/* extract the data and copy to temporary file
*/
- fdTmp = sh_gpg_extract_signed(fd);
+ fdTmp = sh_sig_extract_signed(fd);
if (sig_termfast == 1) /* SIGTERM */
{
@@ -793,12 +870,16 @@ static SL_TICKET verify_data (SL_TICKET fd)
/* Validate signature of open file.
*/
- if (0 != sh_gpg_check_sign (fd, SIG_DATA))
+ if (0 != sh_sig_check_signature (fd, SIG_DATA))
{
sl_close(fd);
return -1;
}
sl_rewind (fd);
+
+ fdTmp = sh_sig_extract_signed_data(fd);
+ sl_close(fd);
+ fd = fdTmp;
#endif
return fd;
@@ -1116,15 +1197,19 @@ static void seek_writeout_data(SL_TICKET fd, const char * path)
return;
}
+/* Seek to [SOF] and truncate remainder
+ */
static int seek_writeout_data_old(SL_TICKET fd, const char * path)
{
char * line = SH_ALLOC(MAX_PATH_STORE+1);
+ /* This will do an ftruncate() after the sof marker
+ */
if (SL_ISERROR(sh_dbIO_setdataent_old (fd, line, MAX_PATH_STORE, path)))
{
SH_FREE(line);
sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGPATH,
- _("Failed to seek to end of baseline database"),
+ _("Failed to seek to start of baseline database"),
_("seek_writeout_data_old"),
path);
aud_exit(FIL__, __LINE__, EXIT_FAILURE);
@@ -1329,6 +1414,7 @@ static void write_record(SL_TICKET fd, sh_filestore_t * p,
if (!linkpath || 0 == sl_strlen(linkpath))
lpath = ll;
else
+ /* cppcheck-suppress uninitvar */
lpath = linkpath;
if (pushdata_stdout == S_FALSE)
@@ -1413,6 +1499,7 @@ static void sh_dbIO_data_write_int (file_type * buf, char * fileHash,
else
{
pushdata_fd = open_writeout_data(outpath);
+ /* Seek to eof */
seek_writeout_data(pushdata_fd, outpath);
}
}
@@ -1423,13 +1510,13 @@ static void sh_dbIO_data_write_int (file_type * buf, char * fileHash,
{
TPT((0, FIL__, __LINE__, _("msg=<Update.>\n")));
pushdata_fd = open_writeout_data(outpath);
+ /* Seek to sof and truncate */
seek_writeout_data_old(pushdata_fd, outpath);
}
}
-
- if (!buf) {
- memset(&p, '\0', sizeof(sh_filestore_t));
- }
+
+ /* unconditionally initialize the structure */
+ memset(&p, 0, sizeof(sh_filestore_t));
if (buf != NULL)
{
@@ -1478,7 +1565,19 @@ static void sh_dbIO_data_write_int (file_type * buf, char * fileHash,
{
if (sh.flag.checkSum != SH_CHECK_INIT || (buf == NULL && fileHash == NULL))
{
- sl_close (pushdata_fd);
+ if (SL_ISERROR(sl_close (pushdata_fd)))
+ {
+ char * tmp = sh_util_safe_name(outpath);
+ sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGPATH,
+ _("Failed to close baseline database"),
+ _("sh_dbIO_data_write_int"),
+ tmp);
+ SH_FREE(tmp);
+ }
+ else {
+ if (sh.flag.checkSum == SH_CHECK_INIT)
+ sh_error_handle((-1), FIL__, __LINE__, 0, MSG_DCLOSE);
+ }
pushdata_fd = -1;
}
}
diff --git a/src/sh_entropy.c b/src/sh_entropy.c
index bf2a3ee..c55dad6 100644
--- a/src/sh_entropy.c
+++ b/src/sh_entropy.c
@@ -333,7 +333,7 @@ int sh_entropy(int nbytes, char * nbuf)
if (nbytes > KEY_BYT)
nbytes = KEY_BYT;
- memset(nbuf, '\0', nbytes);
+ memset(nbuf, 0, nbytes);
#ifdef NAME_OF_DEV_URANDOM
m_count = read_mbytes ( 10, NAME_OF_DEV_URANDOM, nbuf, nbytes);
@@ -369,7 +369,7 @@ int sh_entropy(int nbytes, char * nbuf)
{
/* -- Add previous entropy into the new pool. --
*/
- memset(addbuf, '\0', sizeof(addbuf));
+ memset(addbuf, 0, sizeof(addbuf));
for (i = 0; i < m_count; ++i)
addbuf[i] = nbuf[i];
for (i = 0; i < KEY_BYT; ++i)
@@ -377,7 +377,7 @@ int sh_entropy(int nbytes, char * nbuf)
keybuf = (char *) sh_tiger_hash_uint32 (addbuf,
TIGER_DATA, 2 * KEY_BYT,
kbuf, KEY_BYT/sizeof(UINT32));
- memset(addbuf, '\0', sizeof(addbuf));
+ memset(addbuf, 0, sizeof(addbuf));
/* -- Give out nbytes bytes from the new pool. --
*/
@@ -389,8 +389,8 @@ int sh_entropy(int nbytes, char * nbuf)
nbuf[i] = keybuf[i];
}
SH_MUTEX_UNLOCK_UNSAFE(mutex_skey);
- memset (keybuf, '\0', KEY_BYT);
- memset (kbuf, '\0', sizeof(kbuf));
+ memset (keybuf, 0, KEY_BYT);
+ memset (kbuf, 0, sizeof(kbuf));
SL_RETURN(0, _("sh_entropy"));
}
@@ -415,7 +415,7 @@ int sh_entropy(int nbytes, char * nbuf)
#define FD_SETSIZE 32
#endif
#ifndef FD_ZERO
-#define FD_ZERO(p) memset((char *)(p), '\0', sizeof(*(p)))
+#define FD_ZERO(p) memset((char *)(p), 0, sizeof(*(p)))
#endif
#include "sh_static.h"
@@ -952,7 +952,7 @@ int sh_entropy(int nbytes, char * nbuf)
keybuf = (char *) sh_tiger_hash_uint32 ((char *) tseed,
TIGER_DATA, sizeof(tseed),
kbuf, KEY_BYT/sizeof(UINT32));
- memset(addbuf, '\0', sizeof(addbuf));
+ memset(addbuf, 0, sizeof(addbuf));
for (i = 0; i < KEY_BYT; ++i)
{
addbuf[i] = keybuf[i];
@@ -973,7 +973,7 @@ int sh_entropy(int nbytes, char * nbuf)
/* add previous entropy into the new pool
*/
- memset(addbuf, '\0', sizeof(addbuf));
+ memset(addbuf, 0, sizeof(addbuf));
for (i = 0; i < KEY_BYT; ++i)
{
addbuf[i] = keybuf[i];
@@ -982,7 +982,7 @@ int sh_entropy(int nbytes, char * nbuf)
keybuf = (char *) sh_tiger_hash_uint32 (addbuf,
TIGER_DATA, sizeof(addbuf),
kbuf, KEY_BYT/sizeof(UINT32));
- memset(addbuf, '\0', sizeof(addbuf));
+ memset(addbuf, 0, sizeof(addbuf));
/* store in system pool
*/
@@ -991,8 +991,8 @@ int sh_entropy(int nbytes, char * nbuf)
skey->poolv[i] = keybuf[i];
skey->poolc = KEY_BYT;
SH_MUTEX_UNLOCK_UNSAFE(mutex_skey);
- memset (buffer, '\0', BUF_ENT+2);
- memset (keybuf, '\0', KEY_BYT);
+ memset (buffer, 0, BUF_ENT+2);
+ memset (keybuf, 0, KEY_BYT);
SH_FREE(buffer);
}
else
@@ -1029,13 +1029,13 @@ void Test_entropy (CuTest *tc)
for (count = 0; count < 20; ++count)
{
- memset(skey->poolv, '\0', KEY_BYT);
+ memset(skey->poolv, 0, KEY_BYT);
skey->poolc = 0;
status = sh_entropy (24, bufx);
CuAssertTrue(tc, 0 == status);
- memset(skey->poolv, '\0', KEY_BYT);
+ memset(skey->poolv, 0, KEY_BYT);
skey->poolc = 0;
status = sh_entropy (24, bufy);
diff --git a/src/sh_err_console.c b/src/sh_err_console.c
index c3a8269..c813039 100644
--- a/src/sh_err_console.c
+++ b/src/sh_err_console.c
@@ -32,8 +32,11 @@
#include <stdio.h>
#include <sys/types.h>
#include <fcntl.h>
+#include <sys/stat.h>
#include <unistd.h>
#include <signal.h>
+#include <sys/socket.h>
+#include <sys/un.h>
extern int OnlyStderr;
@@ -140,7 +143,7 @@ static void remove_message()
MSG_NOERROR|IPC_NOWAIT);
} while (rc < 0 && errno == EINTR);
- memset(&recv_msg, '\0', sizeof(recv_msg));
+ memset(&recv_msg, 0, sizeof(recv_msg));
return;
}
@@ -189,7 +192,7 @@ static int push_message_queue (const char * msg)
if (count > 1)
{
- memset(recv_msg, '\0', MY_MAX_MSG+1);
+ memset(recv_msg, 0, MY_MAX_MSG+1);
SH_FREE(recv_msg);
SL_RETURN(-1, _("push_message_queue"));
}
@@ -213,13 +216,13 @@ static int push_message_queue (const char * msg)
} else {
TPT(( 0, FIL__, __LINE__, _("msg=<msgsnd: %s> errno=<%d>\n"),
sh_error_message(errno, errbuf, sizeof(errbuf)), errno));
- memset(recv_msg, '\0', MY_MAX_MSG+1);
+ memset(recv_msg, 0, MY_MAX_MSG+1);
SH_FREE(recv_msg);
SL_RETURN(-1, _("push_message_queue"));
}
}
- memset(recv_msg, '\0', MY_MAX_MSG+1);
+ memset(recv_msg, 0, MY_MAX_MSG+1);
SH_FREE(recv_msg);
SL_RETURN(0, _("push_message_queue"));
@@ -244,9 +247,19 @@ void close_ipc() { sh_sem_close(); return; }
static int count_dev_console = 0;
+typedef enum { SH_LOG_UNIX, SH_LOG_OTHER, SH_LOG_INDEF } sh_log_devtype;
+
+static sh_log_devtype dt[2] = { SH_LOG_INDEF, SH_LOG_INDEF };
+static int st[2] = { SOCK_DGRAM, SOCK_DGRAM };
+
void reset_count_dev_console(void)
{
count_dev_console = 0;
+ dt[0] = SH_LOG_INDEF;
+ dt[1] = SH_LOG_INDEF;
+ st[0] = SOCK_DGRAM;
+ st[1] = SOCK_DGRAM;
+
return;
}
@@ -283,6 +296,88 @@ char * sh_log_console_name (void)
#define STDERR_FILENO 2
#endif
+static int find_socktype(const char * name)
+{
+#ifdef SOCK_SEQPACKET
+ int socktypes[3] = { SOCK_DGRAM, SOCK_SEQPACKET, SOCK_STREAM };
+ int try = 3;
+#else
+ int socktypes[2] = { SOCK_DGRAM, SOCK_STREAM };
+ int try = 2;
+#endif
+ int i;
+ for (i = 0; i < try; ++i) {
+ struct sockaddr_un addr;
+ int fd;
+
+ if ( (fd = socket(AF_UNIX, socktypes[i], 0)) == -1) {
+ return -1;
+ }
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_UNIX;
+ sl_strlcpy(addr.sun_path, name, sizeof(addr.sun_path));
+ if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)) == 0) {
+ close(fd);
+ return socktypes[i];
+ }
+ close(fd);
+ }
+ return -1;
+}
+
+int sh_log_console_open (const char * name, int slot)
+{
+ int fd = -1;
+
+ if (dt[slot] == SH_LOG_INDEF)
+ {
+ struct stat sb;
+ if (retry_stat(FIL__, __LINE__, name, &sb) == 0)
+ {
+ if ((sb.st_mode & S_IFMT) == S_IFSOCK)
+ {
+ dt[slot] = SH_LOG_UNIX;
+ st[slot] = find_socktype(name);
+ if (st[slot] == -1) {
+ sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
+ _("Could not determine socket type."),
+ name);
+ }
+ }
+ else
+ dt[slot] = SH_LOG_OTHER;
+ }
+ }
+
+ if (dt[slot] == SH_LOG_OTHER) {
+ fd = open ( name, O_WRONLY|O_APPEND|O_NOCTTY|O_NONBLOCK);
+ }
+ else if (dt[slot] == SH_LOG_UNIX && st[slot] != -1) {
+ struct sockaddr_un addr;
+
+ if ( (fd = socket(AF_UNIX, st[slot], 0)) == -1) {
+ char ebuf[SH_ERRBUF_SIZE];
+ int errnum = errno;
+ sh_error_handle ((-1), FIL__, __LINE__, errnum, MSG_E_SUBGEN,
+ sh_error_message(errnum, ebuf, sizeof(ebuf)),
+ name);
+ return -1;
+ }
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_UNIX;
+ sl_strlcpy(addr.sun_path, name, sizeof(addr.sun_path));
+ if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
+ char ebuf[SH_ERRBUF_SIZE];
+ int errnum = errno;
+ sh_error_handle ((-1), FIL__, __LINE__, errnum, MSG_E_SUBGEN,
+ sh_error_message(errnum, ebuf, sizeof(ebuf)),
+ name);
+ return -1;
+ }
+ }
+ return fd;
+}
+
/* ---- Print out a message. ----
*/
int sh_log_console (const /*@null@*/char *errmsg)
@@ -335,11 +430,11 @@ int sh_log_console (const /*@null@*/char *errmsg)
*/
if ( OnlyStderr == S_FALSE )
{
- fd[0] = open ( sh.srvcons.name, O_WRONLY|O_APPEND|O_NOCTTY|O_NONBLOCK);
+ fd[0] = sh_log_console_open ( sh.srvcons.name, 0);
if (sh.srvcons.alt[0] != '\0')
{
- fd[1] = open (sh.srvcons.alt, O_WRONLY|O_APPEND|O_NOCTTY|O_NONBLOCK);
+ fd[1] = sh_log_console_open (sh.srvcons.alt, 1);
ccMax = 2;
}
@@ -360,9 +455,11 @@ int sh_log_console (const /*@null@*/char *errmsg)
do {
val_return = write(fd[cc], errmsg, strlen(errmsg));
} while (val_return < 0 && errno == EINTR);
- do {
- val_return = write(fd[cc], "\r\n", 2);
- } while (val_return < 0 && errno == EINTR);
+ if (dt[cc] != SH_LOG_UNIX || st[cc] == SOCK_STREAM) {
+ do {
+ val_return = write(fd[cc], "\r\n", 2);
+ } while (val_return < 0 && errno == EINTR);
+ }
(void) sl_close_fd(FIL__, __LINE__, fd[cc]);
service_failure[cc] = 0;
}
diff --git a/src/sh_err_log.c b/src/sh_err_log.c
index da6ed06..8fc93b9 100644
--- a/src/sh_err_log.c
+++ b/src/sh_err_log.c
@@ -742,9 +742,9 @@ int sh_log_file (/*@null@*/char *errmsg, /*@null@*/char * inet_peer)
(void) sl_strlcpy(current->logfile, logfile, strlen(logfile) + 1);
current->service_failure = 0;
current->log_start = S_TRUE;
- memset(current->sigkey_old, (int)'\0', KEY_LEN+1);
- memset(current->sigkey_new, (int)'\0', KEY_LEN+1);
- memset(current->crypto, (int)'\0', KEY_LEN+1);
+ memset(current->sigkey_old, 0, KEY_LEN+1);
+ memset(current->sigkey_new, 0, KEY_LEN+1);
+ memset(current->crypto, 0, KEY_LEN+1);
current->next = logfile_list;
logfile_list = current;
}
@@ -943,7 +943,7 @@ int sh_log_file (/*@null@*/char *errmsg, /*@null@*/char * inet_peer)
errFlags.databaselevel = store7;
- memset (crypto, (int) '\0', KEY_LEN);
+ memset (crypto, 0, KEY_LEN);
sh.flag.log_start = S_FALSE;
current->log_start = S_FALSE;
}
@@ -1045,8 +1045,8 @@ int sh_log_file (/*@null@*/char *errmsg, /*@null@*/char * inet_peer)
/* --- Clean up and free record. ---
*/
- memset (log_msg.msg, (int)'\0', (size_t)(status + 2*KEY_LEN + 32));
- memset (log_msg.signature, (int)'\0', KEY_LEN);
+ memset (log_msg.msg, 0, (size_t)(status + 2*KEY_LEN + 32));
+ memset (log_msg.signature, 0, KEY_LEN);
(void) sh_unix_munlock (log_msg.msg,
(size_t)(status + 2*KEY_LEN + 32));
SH_FREE(log_msg.msg);
@@ -1283,7 +1283,7 @@ void sh_efile_report()
status = sl_forward(fd);
if (!SL_ISERROR(status))
- status = sl_write (fd, report, strlen(report));
+ sl_write (fd, report, strlen(report));
(void) sl_sync(fd);
/* make group writeable, such that nagios can truncate */
diff --git a/src/sh_error.c b/src/sh_error.c
index 5ec934b..82ee3c8 100644
--- a/src/sh_error.c
+++ b/src/sh_error.c
@@ -243,6 +243,7 @@ void sh_error_dbg_switch(void)
static int sh_error_set_classmask (const char * str, int * facility_mask)
{
char * p;
+ char * q;
int num = 0;
unsigned int i;
size_t len;
@@ -289,6 +290,8 @@ static int sh_error_set_classmask (const char * str, int * facility_mask)
if (p == NULL)
break;
+ q = p; while (*q != '\0') { *q = toupper( (int) *q); ++q; }
+
for (i = 0; i < SH_CLA_MAX; ++i)
{
if (i < SH_CLA_RAW_MAX) {
@@ -494,15 +497,20 @@ int sh_error_convert_level (const char * str_s)
{
int i;
int level = (-1);
+ char * tmp;
+ char * q;
SL_ENTER(_("sh_error_convert_level"));
if (str_s == NULL)
SL_RETURN( -1, _("sh_error_convert_level"));
+ q = sh_util_strdup(str_s);
+ tmp = q; while (*tmp != '\0') { *tmp = tolower( (int) *tmp); ++tmp; }
+
for (i = 0; i < SH_EEF_MAX; ++i)
{
- if (0 == sl_strncmp(str_s, _(eef_tab[i].str),
+ if (0 == sl_strncmp(q, _(eef_tab[i].str),
sl_strlen(eef_tab[i].str)))
{
level = eef_tab[i].val;
@@ -510,6 +518,7 @@ int sh_error_convert_level (const char * str_s)
}
}
+ SH_FREE(q);
SL_RETURN( level, _("sh_error_convert_level"));
}
@@ -553,10 +562,17 @@ int sh_error_set_level(const char * str_in, int * facility)
register int i, j, f = BAD;
int old_facility;
- const char * str_s = str_in;
+ char * str_s;
+ char * str_orig;
+ char * tmp;
SL_ENTER(_("sh_error_set_level"));
+ str_s = sh_util_strdup(str_in);
+ str_orig = str_s;
+
+ tmp = str_s; while (*tmp != '\0') { *tmp = tolower( (int) *tmp); ++tmp; }
+
if (IsInitialized == BAD)
(void) sh_error_init();
@@ -649,6 +665,7 @@ int sh_error_set_level(const char * str_in, int * facility)
if (!str_s)
{
+ if (str_orig) SH_FREE(str_orig);
SL_RETURN ((-1), _("sh_error_set_level"));
}
/* skip to end of string
@@ -674,10 +691,12 @@ int sh_error_set_level(const char * str_in, int * facility)
*facility = old_facility;
sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS,
_("priority"), str_in);
+ SH_FREE(str_orig);
SL_RETURN (-1, _("sh_error_set_level"));
}
compute_flag_err_debug();
compute_flag_err_info();
+ SH_FREE(str_orig);
SL_RETURN (0, _("sh_error_set_level"));
}
@@ -1422,7 +1441,7 @@ void sh_error_handle (int sev1, const char * file, long line,
SH_FREE( lmsg->msg );
sh_replace_free(hexmsg);
- memset ( lmsg, (int) '\0', sizeof(struct _log_t) );
+ memset ( lmsg, 0, sizeof(struct _log_t) );
MUNLOCK( (char *) lmsg, sizeof(struct _log_t) );
SH_FREE( lmsg );
own_block = 0;
diff --git a/src/sh_extern.c b/src/sh_extern.c
index c048873..bc6fc47 100644
--- a/src/sh_extern.c
+++ b/src/sh_extern.c
@@ -992,6 +992,7 @@ char * sh_ext_popen_str (const char * command)
sh_string_read(s, task.pipe, 0);
if (sh_string_len(s) == 0)
{
+ /* cppcheck-suppress syntaxError */
--try; retry_msleep(0, 100);
}
} while (sh_string_len(s) == 0 && try != 0);
diff --git a/src/sh_fInotify.c b/src/sh_fInotify.c
index 67162e7..8cdadf8 100644
--- a/src/sh_fInotify.c
+++ b/src/sh_fInotify.c
@@ -196,13 +196,13 @@ int sh_fInotify_run()
/* Blocking read from inotify file descriptor.
*/
- len = sh_inotify_read_timeout(buffer, 16384, 1);
+ len = sh_inotify_read_timeout (buffer, 16384, 1);
if (len > 0)
{
struct inotify_event *event;
- int i = 0;
-
+ long i = 0;
+
while (i < len)
{
event = (struct inotify_event *) &(buffer[i]);
diff --git a/src/sh_files.c b/src/sh_files.c
index c32c4bc..09fc559 100644
--- a/src/sh_files.c
+++ b/src/sh_files.c
@@ -19,7 +19,37 @@
#include "config_xor.h"
-#if defined(HAVE_PTHREAD_MUTEX_RECURSIVE)
+#if defined(HAVE_PTHREAD_MUTEX_RECURSIVE) && defined(HAVE_DIRENT_H) && defined(HAVE_SCANDIR)
+
+/* Linux */
+#if defined(__linux__)
+#define _XOPEN_SOURCE 700
+#define SH_USE_SCANDIR 1
+
+/* FreeBSD */
+#elif defined(__FreeBSD__)
+
+#if __FreeBSD__ >= 8
+#define __XSI_VISIBLE 700
+#define SH_USE_SCANDIR 1
+#endif
+
+/* OpenBSD */
+#elif defined(__OpenBSD__)
+#define __POSIX_VISIBLE 200809
+#define SH_USE_SCANDIR 1
+
+#elif defined(__NetBSD__)
+#define _NETBSD_SOURCE
+#define SH_USE_SCANDIR 1
+
+/* other os */
+#else
+#define _XOPEN_SOURCE 500
+
+#endif
+
+#elif defined(HAVE_PTHREAD_MUTEX_RECURSIVE)
#define _XOPEN_SOURCE 500
#endif
@@ -35,7 +65,6 @@
*/
#include <sys/types.h>
#include <unistd.h>
-#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
@@ -214,12 +243,18 @@ static char * sh_files_C_dequote (char * s, size_t * length)
char * sh_files_parse_input(const char * str_s, size_t * len)
{
char * p;
-
+
if (!str_s || *str_s == '\0')
return NULL;
*len = sl_strlen(str_s);
-
+ if (sh.flag.checkSum == SH_CHECK_INIT)
+ {
+ size_t addspace = sh_dbIO_get_rootfs_len();
+ if (addspace != 0 && S_TRUE == sl_ok_adds (*len, addspace))
+ *len += addspace;
+ }
+
if ( (str_s[0] == '"' && str_s[*len-1] == '"' ) ||
(str_s[0] == '\'' && str_s[*len-1] == '\'') )
{
@@ -621,7 +656,7 @@ static char * intern_find_morespecific_dir(zAVLTree * tree,
size_t l_path = strlen(path);
size_t l_name;
char * candidate = NULL;
- size_t l_candidate = 0;
+ volatile size_t l_candidate = 0;
if (NULL == tree)
return NULL;
@@ -1420,6 +1455,9 @@ static int sh_files_pushfile (int class, const char * str_s)
if (!p || len == 0)
SL_RETURN((-1), _("sh_files_pushfile"));
+ if (sh.flag.checkSum == SH_CHECK_INIT)
+ p = sh_dbIO_rootfs_prepend(p);
+
if (len >= PATH_MAX)
{
/* Name too long
@@ -1854,6 +1892,9 @@ static int sh_files_pushdir (int class, const char * str_s)
SL_RETURN((-1), _("sh_files_pushdir"));
}
+ if (sh.flag.checkSum == SH_CHECK_INIT)
+ tail = sh_dbIO_rootfs_prepend(tail);
+
len = sl_strlen(tail);
if (len >= PATH_MAX)
@@ -2045,8 +2086,16 @@ static int sh_files_hle_test (int offset, char * path)
}
#endif
-static void * sh_dummy_dirlist;
-static void * sh_dummy_tmpcat;
+/* This is the LCG from Numerical Recipies. Deterministic.
+ */
+static unsigned int simple_rand(unsigned int * state)
+{
+ *state = 1664525 * (*state) + 1013904223;
+ return *state;
+}
+
+void * sh_dummy_dirlist;
+void * sh_dummy_tmpcat;
/* -- Check a single directory and its content. Does not
* check the directory inode itself.
@@ -2060,6 +2109,10 @@ int sh_files_checkdir (int iclass, unsigned long check_flags,
DIR * thisDir = NULL;
struct dirent * thisEntry;
+#if defined(SH_USE_SCANDIR)
+ struct dirent **entryList;
+ int entry;
+#endif
int status;
int dummy = S_FALSE;
dir_type * theDir;
@@ -2246,25 +2299,46 @@ int sh_files_checkdir (int iclass, unsigned long check_flags,
dirlist = NULL;
dirlist_orig = NULL;
+#if defined(SH_USE_SCANDIR)
+ entry = scandir(iname, &entryList, 0, alphasort);
+ while(entry > 0) { /* scandir() may return -1 on error! */
+ entry--;
+ thisEntry = entryList[entry];
+#else
do {
thisEntry = readdir (thisDir);
+#endif
if (thisEntry != NULL)
{
++theDir->NumAll;
if (sl_strcmp (thisEntry->d_name, ".") == 0)
{
++theDir->NumDirs;
+#if defined(SH_USE_SCANDIR)
+ free(entryList[entry]); /* scandir() mallocs entries */
+#endif
continue;
}
if (sl_strcmp (thisEntry->d_name, "..") == 0)
{
++theDir->NumDirs;
+#if defined(SH_USE_SCANDIR)
+ free(entryList[entry]); /* scandir() mallocs entries */
+#endif
continue;
}
dirlist = addto_sh_dirlist (thisEntry, dirlist);
+#if defined(SH_USE_SCANDIR)
+ free(entryList[entry]); /* scandir() mallocs entries */
+#endif
}
- } while (thisEntry != NULL);
-
+ }
+#if defined(SH_USE_SCANDIR)
+ free(entryList);
+#else
+ while (thisEntry != NULL);
+#endif
+
SH_MUTEX_UNLOCK(mutex_readdir);
closedir (thisDir);
@@ -2289,11 +2363,7 @@ int sh_files_checkdir (int iclass, unsigned long check_flags,
BREAKEXIT(sh_derr);
-#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_RAND_R)
- if (0 == (rand_r(&state) % 5)) (void) sh_derr();
-#else
- if (0 == state * (rand() % 5)) (void) sh_derr();
-#endif
+ if (0 == (simple_rand(&state) % 5)) (void) sh_derr();
/* ---- Check the file. ----
*/
@@ -2636,11 +2706,7 @@ ShFileType sh_files_filecheck (int class, unsigned long check_flags,
BREAKEXIT(sh_derr);
-#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_RAND_R)
- if (0 == (rand_r(&state) % 2)) (void) sh_derr();
-#else
- if (0 == state * (rand() % 2)) (void) sh_derr();
-#endif
+ if (0 == (simple_rand(&state) % 2)) (void) sh_derr();
if (dirName && infileName && (dirName[0] == '/') && (dirName[1] == '\0')
&& (infileName[0] == '/') && (infileName[1] == '\0'))
@@ -2762,6 +2828,10 @@ ShFileType sh_files_filecheck (int class, unsigned long check_flags,
if (S_TRUE == sh_ignore_chk_mod(theFile->fullpath))
MODI_SET(theFile->check_flags, MODI_NOCHECK);
sh_tiger_get_mask_hashtype(&(theFile->check_flags));
+
+ sh_dbIO_rootfs_strip(theFile->fullpath);
+ if (theFile->link_path)
+ sh_dbIO_rootfs_strip_link(theFile->link_path);
sh_dbIO_data_write (theFile, fileHash);
}
else if (sh.flag.checkSum == SH_CHECK_CHECK
diff --git a/src/sh_filetype.c b/src/sh_filetype.c
index 9abac46..3993d0b 100644
--- a/src/sh_filetype.c
+++ b/src/sh_filetype.c
@@ -596,6 +596,8 @@ int main (int argc, char * argv[])
fprintf(stdout, "%s: %s\n", argv[1], filetype);
+ fclose(fh);
+
return 0;
}
return 1;
diff --git a/src/sh_filter.c b/src/sh_filter.c
index 4cd9578..aa9c471 100644
--- a/src/sh_filter.c
+++ b/src/sh_filter.c
@@ -114,6 +114,7 @@ int sh_filter_add (const char * str, sh_filter_type * filter, int type)
SL_RETURN((-1), _("sh_filter_filteradd"));
}
+ /* cppcheck-suppress uninitvar */
i = *ntok;
if (i == SH_FILT_NUM) {
SL_RETURN((-1), _("sh_filter_filteradd"));
@@ -292,7 +293,7 @@ sh_filter_type * sh_filter_alloc(void)
{
sh_filter_type * filter = SH_ALLOC(sizeof(sh_filter_type));
- memset(filter, '\0', sizeof(sh_filter_type));
+ memset(filter, 0, sizeof(sh_filter_type));
filter->for_c = 0;
filter->fand_c = 0;
filter->fnot_c = 0;
diff --git a/src/sh_getopt.c b/src/sh_getopt.c
index 7969d4e..8480614 100644
--- a/src/sh_getopt.c
+++ b/src/sh_getopt.c
@@ -290,6 +290,11 @@ static opttable_t op_table[] = {
N_("Create database from file list"),
HAS_ARG_YES,
sh_dbCreate},
+ { N_("init-rootfs"),
+ '-',
+ N_("Build database based on another rootfs"),
+ HAS_ARG_YES,
+ sh_dbIO_init_rootfs},
{ N_("wait-on-check"),
'w',
N_("Timed wait for end of filecheck (0 for no timeout)"),
@@ -417,8 +422,8 @@ static void sh_getopt_print_log_facilities (void)
#endif
#ifdef HAVE_LIBPRELUDE
- if (num > 0) fputc ('\n', stdout); ++num;
- fputs (_(" prelude (0.9.6+)"), stdout);
+ if (num > 0) fputc ('\n', stdout);
+ fputs (_(" prelude (0.9.6+)"), stdout); ++num;
#endif
if (num == 0)
@@ -475,10 +480,10 @@ static void sh_getopt_print_options (void)
#ifdef WITH_GPG
if (num > 0) fputc ('\n', stdout);
- printf (_(" GnuPG signatures (%s)"), DEFAULT_GPG_PATH); ++num;
-#ifdef HAVE_GPG_CHECKSUM
+ printf (_(" GnuPG signatures (%s)"), DEFAULT_SIG_PATH); ++num;
+#ifdef HAVE_SIG_CHECKSUM
if (num > 0) fputc ('\n', stdout);
- printf (_(" -- GnuPG checksum: %s"), GPG_HASH); ++num;
+ printf (_(" -- GnuPG checksum: %s"), SIG_HASH); ++num;
#endif
#ifdef USE_FINGERPRINT
if (num > 0) fputc ('\n', stdout);
@@ -634,7 +639,7 @@ static int sh_getopt_version (const char * dummy)
static int sh_getopt_copyright (const char * dummy)
{
fprintf (stdout, "%s",
- _("Copyright (C) 1999-2008 Rainer Wichmann"\
+ _("Copyright (C) 1999-2019 Rainer Wichmann"\
" (http://la-samhna.de).\n\n"));
fprintf (stdout, "%s",
diff --git a/src/sh_gpg.c b/src/sh_gpg.c
deleted file mode 100644
index e06d42c..0000000
--- a/src/sh_gpg.c
+++ /dev/null
@@ -1,1035 +0,0 @@
-/* SAMHAIN file system integrity testing */
-/* Copyright (C) 1999, 2000 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>
-
-
-#if defined(WITH_GPG) || defined(WITH_PGP)
-
-#include <unistd.h>
-#include <fcntl.h>
-#include <signal.h>
-#if defined(SH_WITH_SERVER)
-#include <pwd.h>
-#endif
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <errno.h>
-#include <sys/wait.h>
-
-#include <string.h>
-#ifdef HAVE_MEMORY_H
-#include <memory.h>
-#endif
-
-
-#if !defined(O_NONBLOCK)
-#if defined(O_NDELAY)
-#define O_NONBLOCK O_NDELAY
-#else
-#define O_NONBLOCK 0
-#endif
-#endif
-
-
-#include "samhain.h"
-#include "sh_utils.h"
-#include "sh_error.h"
-#include "sh_tiger.h"
-#if defined(SH_WITH_SERVER)
-#define SH_NEED_PWD_GRP 1
-#include "sh_static.h"
-#endif
-#include "sh_gpg.h"
-
-static struct {
- char conf_id[SH_MINIBUF+1];
- char conf_fp[SH_MINIBUF+1];
- char data_id[SH_MINIBUF+1];
- char data_fp[SH_MINIBUF+1];
-} gp;
-
-typedef struct {
- pid_t pid;
- FILE * pipe;
-} sh_gpg_popen_t;
-
-#define SH_GPG_OK 0
-#define SH_GPG_BAD 1
-#define SH_GPG_BADSIGN 2
-
-/* replace #if 0 by #if 1 and set an appropriate path in front of '/pdbg.'
- * for debugging
- */
-#if 0
-#define PDGBFILE "/pdbg."
-#endif
-
-#if defined(PDGBFILE)
-FILE * pdbg;
-FILE * pdbgc;
-#define PDBG_OPEN pdbg = fopen(PDGBFILE"main", "a")
-#define PDBG_CLOSE sl_fclose (FIL__, __LINE__, pdbg)
-#define PDBG(arg) fprintf(pdbg, "PDBG: step %d\n", arg); fflush(pdbg)
-#define PDBG_D(arg) fprintf(pdbg, "PDBG: %d\n", arg); fflush(pdbg)
-#define PDBG_S(arg) fprintf(pdbg, "PDBG: %s\n", arg); fflush(pdbg)
-
-#define PDBGC_OPEN pdbgc = fopen(PDGBFILE"child", "a")
-#define PDBGC_CLOSE sl_fclose (FIL__, __LINE__, pdbgc)
-#define PDBGC(arg) fprintf(pdbgc, "PDBG: step %d\n", arg); fflush(pdbgc)
-#define PDBGC_D(arg) fprintf(pdbgc, "PDBG: %d\n", arg); fflush(pdbgc)
-#define PDBGC_S(arg) fprintf(pdbgc, "PDBG: %s\n", arg); fflush(pdbgc)
-#else
-#define PDBG_OPEN
-#define PDBG_CLOSE
-#define PDBG(arg)
-#define PDBG_D(arg)
-#define PDBG_S(arg)
-#define PDBGC_OPEN
-#define PDBGC_CLOSE
-#define PDBGC(arg)
-#define PDBGC_D(arg)
-#define PDBGC_S(arg)
-#endif
-
-#undef FIL__
-#define FIL__ _("sh_gpg.c")
-
-#ifdef GPG_HASH
-
-static int sh_gpg_checksum (SL_TICKET checkfd, int flag)
-{
- char * test_gpg;
- char * test_ptr1 = NULL;
- char * test_ptr2 = NULL;
- char wstrip1[128];
- char wstrip2[128];
- int i, k;
-#include "sh_gpg_chksum.h"
-
- SL_ENTER(_("sh_gpg_checksum"));
-
- test_gpg = sh_tiger_hash_gpg (DEFAULT_GPG_PATH, checkfd, TIGER_NOLIM);
-
- test_ptr1 = strchr(GPG_HASH, ':');
- if (test_gpg != NULL)
- test_ptr2 = strchr(test_gpg, ':');
-
- if (test_ptr2 != NULL)
- test_ptr2 += 2;
- else
- test_ptr2 = test_gpg;
- if (test_ptr1 != NULL)
- test_ptr1 += 2;
- else
- test_ptr1 = GPG_HASH;
-
- /* Tue Jun 24 23:11:54 CEST 2003 (1.7.9) -- strip whitespace
- */
- k = 0;
- for (i = 0; i < 127; ++i)
- {
- if (test_ptr1[i] == '\0')
- break;
- if (test_ptr1[i] != ' ')
- {
- wstrip1[k] = test_ptr1[i];
- ++k;
- }
- }
- wstrip1[k] = '\0';
-
- for(i = 0; i < KEY_LEN; ++i)
- {
- if (gpgchk[i] != wstrip1[i])
- {
- sh_error_handle(SH_ERR_SEVERE, FIL__, __LINE__, 0, MSG_E_GPG_CHK,
- gpgchk, wstrip1);
- break;
- }
- }
-
- k = 0;
- if (test_ptr2)
- {
- for (i = 0; i < 127; ++i)
- {
- if (test_ptr2[i] == '\0')
- break;
- if (test_ptr2[i] != ' ')
- {
- wstrip2[k] = test_ptr2[i];
- ++k;
- }
- }
- }
- wstrip2[k] = '\0';
-
- if (0 != sl_strncmp(wstrip1, wstrip2, 127))
- {
- TPT(((0), FIL__, __LINE__, _("msg=<pgp checksum: %s>\n"), test_gpg));
- TPT(((0), FIL__, __LINE__, _("msg=<Compiled-in : %s>\n"), GPG_HASH));
- TPT(((0), FIL__, __LINE__, _("msg=<wstrip1 : %s>\n"), wstrip1));
- TPT(((0), FIL__, __LINE__, _("msg=<wstrip2 : %s>\n"), wstrip2));
- if (flag == 1)
- sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_GPG,
- GPG_HASH, test_gpg);
- dlog(1, FIL__, __LINE__, _("The compiled-in checksum of the gpg binary\n(%s)\ndoes not match the actual checksum\n(%s).\nYou need to recompile with the correct checksum."), wstrip1, wstrip2);
- SH_FREE(test_gpg);
- SL_RETURN((-1), _("sh_gpg_checksum"));
- }
- SH_FREE(test_gpg);
- SL_RETURN( (0), _("sh_gpg_checksum"));
-}
-#endif
-
-struct startup_info {
- long line;
- char * program;
- long uid;
- char * path;
- char * key_uid;
- char * key_id;
-};
-
-static struct startup_info startInfo = { 0, NULL, 0, NULL, NULL, NULL };
-
-void sh_gpg_log_startup (void)
-{
- if (startInfo.program != NULL)
- {
- sh_error_handle ((-1), FIL__, startInfo.line, 0, MSG_START_GH,
- startInfo.program, startInfo.uid,
- startInfo.path,
- startInfo.key_uid, startInfo.key_id);
- }
- return;
-}
-
-static void sh_gpg_fill_startup (long line, char * program, long uid, char * path,
- char * key_uid, char * key_id)
-{
- startInfo.line = line;
- startInfo.program = sh_util_strdup(program);
- startInfo.uid = uid;
- startInfo.path = sh_util_strdup(path);
- startInfo.key_uid = sh_util_strdup(key_uid);
- startInfo.key_id = sh_util_strdup(key_id);
- return;
-}
-
-static FILE * sh_gpg_popen (sh_gpg_popen_t *source, int fd,
- int mode, char * id, char * homedir)
-{
- extern int flag_err_debug;
- int pipedes[2];
- FILE * outf = NULL;
- char * envp[2];
- size_t len;
- char path[256];
- char cc1[32];
- char cc2[32];
-
- char cc0[2] = "-";
- char cc3[32];
- char cc4[SH_PATHBUF+32];
- char cc5[32];
-
-
- char * arg[9];
-
-#if defined(HAVE_GPG_CHECKSUM)
- SL_TICKET checkfd = -1;
- int myrand;
- int i;
-#if defined(__linux__)
- int get_the_fd(SL_TICKET);
- char pname[128];
- int pfd;
- int val_return;
-#endif
-#endif
-
- SL_ENTER(_("sh_gpg_popen"));
-
- /* -- GnuPG -- */
- sl_strlcpy (path, DEFAULT_GPG_PATH, 256);
- sl_strlcpy (cc1, _("--status-fd"), 32);
- sl_strlcpy (cc2, _("--verify"), 32);
- sl_strlcpy (cc3, _("--homedir"), 32);
- /* sl_strlcpy (cc4, sh.effective.home, SH_PATHBUF+32); */
- sl_strlcpy (cc4, homedir, SH_PATHBUF+32);
- sl_strlcat (cc4, _("/.gnupg"), SH_PATHBUF+32);
- sl_strlcpy (cc5, _("--no-tty"), 32);
-
- /* fprintf(stderr, "YULE: homedir=%s\n", homedir); */
-
-#if defined(SH_WITH_SERVER)
- if (0 == sl_ret_euid()) /* privileges not dropped yet */
- {
- struct stat lbuf;
- int status_stat = 0;
-#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);
- status_stat = -1;
- }
- if (!tempres->pw_dir || tempres->pw_dir[0] == '\0')
- {
- dlog(1, FIL__, __LINE__,
- _("User %s does not have a home directory.\nPlease add the home directory for this user to your system.\n"),
- DEFAULT_IDENT);
- status_stat = -2;
- }
- if (status_stat == 0)
- {
- sl_strlcpy (cc4, tempres->pw_dir, SH_PATHBUF+32);
- sl_strlcat (cc4, _("/.gnupg"), SH_PATHBUF+32);
- status_stat = retry_lstat(FIL__, __LINE__, cc4, &lbuf);
- if (status_stat == -1)
- {
- dlog(1, FIL__, __LINE__,
- _("Gnupg directory %s for user %s\ndoes not exist or is not accessible.\nPlease add the directory and put the keyring (pubring.gpg) there\nto verify the configuration file.\n"),
- cc4, DEFAULT_IDENT);
- status_stat = -3;
- }
- }
- if (status_stat == 0 && lbuf.st_uid != tempres->pw_uid)
- {
- dlog(1, FIL__, __LINE__,
- _("Gnupg directory %s\nis not owned by user %s.\n"),
- cc4, DEFAULT_IDENT);
- status_stat = -4;
- }
- if (status_stat == 0)
- {
- sl_strlcat (cc4, _("/pubring.gpg"), SH_PATHBUF+32);
- status_stat = retry_lstat(FIL__, __LINE__, cc4, &lbuf);
- if (status_stat == -1)
- {
- dlog(1, FIL__, __LINE__,
- _("Gnupg public keyring %s for user %s\ndoes not exist or is not accessible.\nPlease add the directory and put the keyring (pubring.gpg) there\nto verify the configuration file.\n"),
- cc4, DEFAULT_IDENT);
- status_stat = -5;
- }
- }
- if (status_stat == 0 && lbuf.st_uid != tempres->pw_uid)
- {
- dlog(1, FIL__, __LINE__,
- _("Gnupg public keyring %s\nis not owned by user %s.\n"),
- cc4, DEFAULT_IDENT);
- status_stat = -6;
- }
- if (status_stat != 0)
- {
- sh_error_handle((-1), FIL__, __LINE__, status_stat, MSG_EXIT_ABORT1,
- sh.prg_name);
- aud_exit (FIL__, __LINE__, EXIT_FAILURE);
- }
- sl_strlcpy (cc4, tempres->pw_dir, SH_PATHBUF+32);
- sl_strlcat (cc4, _("/.gnupg"), SH_PATHBUF+32);
-#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
- SH_FREE(buffer);
-#endif
- }
-#endif
-
- arg[0] = path;
- arg[1] = cc1;
- arg[2] = "1";
- arg[3] = cc2;
- arg[4] = cc3;
- arg[5] = cc4;
- arg[6] = cc5;
- arg[7] = cc0;
- arg[8] = NULL;
-
- /* catch 'unused parameter' compiler warning
- */
- (void) mode;
- (void) id;
-
- /* use homedir of effective user
- */
- len = sl_strlen(sh.effective.home) + 6;
- envp[0] = calloc(1, len); /* free() ok */
- if (envp[0] != NULL)
- sl_snprintf (envp[0], len, _("HOME=%s"), sh.effective.home);
- envp[1] = NULL;
-
- /* Create the pipe
- */
- if (aud_pipe(FIL__, __LINE__, pipedes) < 0)
- {
- if (envp[0] != NULL)
- free(envp[0]);
- SL_RETURN( (NULL), _("sh_gpg_popen"));
- }
-
- fflush (NULL);
-
- source->pid = aud_fork(FIL__, __LINE__);
-
- /* Failure
- */
- if (source->pid == (pid_t) - 1)
- {
- sl_close_fd(FIL__, __LINE__, pipedes[0]);
- sl_close_fd(FIL__, __LINE__, pipedes[1]);
- if (envp[0] != NULL)
- free(envp[0]);
- SL_RETURN( (NULL), _("sh_gpg_popen"));
- }
-
- if (source->pid == (pid_t) 0)
- {
-
- /* child - make read side of the pipe stdout
- */
- if (retry_aud_dup2(FIL__, __LINE__,
- pipedes[STDOUT_FILENO], STDOUT_FILENO) < 0)
- {
- TPT(((0), FIL__, __LINE__, _("msg=<dup2 on pipe failed>\n")));
- dlog(1, FIL__, __LINE__, _("Internal error: dup2 failed\n"));
- aud__exit(FIL__, __LINE__, EXIT_FAILURE);
- }
-
- /* close the pipe descriptors
- */
- sl_close_fd (FIL__, __LINE__, pipedes[STDIN_FILENO]);
- sl_close_fd (FIL__, __LINE__, pipedes[STDOUT_FILENO]);
-
- if (retry_aud_dup2(FIL__, __LINE__, fd, STDIN_FILENO) < 0)
- {
- TPT(((0), FIL__, __LINE__, _("msg=<dup2 on fd failed>\n")));
- dlog(1, FIL__, __LINE__, _("Internal error: dup2 failed\n"));
- aud__exit(FIL__, __LINE__, EXIT_FAILURE);
- }
-
- /* don't leak file descriptors
- */
- sh_unix_closeall (3, -1, S_TRUE); /* in child process */
-
- if (flag_err_debug != S_TRUE)
- {
- if (NULL == freopen(_("/dev/null"), "r+", stderr))
- {
- dlog(1, FIL__, __LINE__, _("Internal error: freopen failed\n"));
- aud__exit(FIL__, __LINE__, EXIT_FAILURE);
- }
- }
-
-
- /* We should become privileged if SUID,
- * to be able to read the keyring.
- * We have checked that gpg is OK,
- * AND that only a trusted user could overwrite
- * gpg.
- */
- memset (skey, '\0', sizeof(sh_key_t));
- aud_setuid(FIL__, __LINE__, geteuid());
-
- PDBGC_OPEN;
- PDBGC_D((int)getuid());
- PDBGC_D((int)geteuid());
-
- {
- int i = 0;
- while (arg[i] != NULL)
- {
- PDBGC_S(arg[i]);
- ++i;
- }
- }
- PDBGC_CLOSE;
-
- /* exec the program */
-
-#if defined(__linux__) && defined(HAVE_GPG_CHECKSUM)
- /*
- * -- emulate an fexecve with checksum testing
- */
- checkfd = sl_open_read(FIL__, __LINE__, DEFAULT_GPG_PATH, SL_NOPRIV);
-
- if (0 != sh_gpg_checksum(checkfd, 0))
- {
- sl_close(checkfd);
- aud__exit(FIL__, __LINE__, EXIT_FAILURE);
- }
-
- pfd = get_the_fd(checkfd);
- do {
- val_return = dup (pfd);
- } while (val_return < 0 && errno == EINTR);
- pfd = val_return;
- sl_close(checkfd);
- /* checkfd = -1; *//* never read */
-
- sl_snprintf(pname, sizeof(pname), _("/proc/self/fd/%d"), pfd);
- if (0 == access(pname, R_OK|X_OK)) /* flawfinder: ignore */
-
- {
- fcntl (pfd, F_SETFD, FD_CLOEXEC);
- retry_aud_execve (FIL__, __LINE__, pname, arg, envp);
-
- dlog(1, FIL__, __LINE__, _("Unexpected error: execve %s failed\n"),
- pname);
- /* failed
- */
- aud__exit(FIL__, __LINE__, EXIT_FAILURE);
- }
-
- /* procfs not working, go ahead
- */
-#endif
-
-#if defined(HAVE_GPG_CHECKSUM)
- /* This is an incredibly ugly kludge to prevent an attacker
- * from knowing when it is safe to slip in a fake executable
- * between the integrity check and the execve
- */
- myrand = (int) taus_get ();
-
- myrand = (myrand < 0) ? (-myrand) : myrand;
- myrand = (myrand % 32) + 2;
-
- for (i = 0; i < myrand; ++i)
- {
- checkfd = sl_open_fastread(FIL__, __LINE__,
- DEFAULT_GPG_PATH, SL_NOPRIV);
-
- if (0 != sh_gpg_checksum(checkfd, 0)) {
- aud__exit(FIL__, __LINE__, EXIT_FAILURE);
- }
- sl_close(checkfd);
- }
-#endif
-
- retry_aud_execve (FIL__, __LINE__, DEFAULT_GPG_PATH, arg, envp);
- dlog(1, FIL__, __LINE__, _("Unexpected error: execve %s failed\n"),
- DEFAULT_GPG_PATH);
-
- /* failed
- */
- TPT(((0), FIL__, __LINE__, _("msg=<execve failed>\n")));
- dlog(1, FIL__, __LINE__, _("Unexpected error: execve failed\n"));
- aud__exit(FIL__, __LINE__, EXIT_FAILURE);
- }
-
- /* parent
- */
-
- if (envp[0] != NULL)
- free(envp[0]);
-
- sl_close_fd (FIL__, __LINE__, pipedes[STDOUT_FILENO]);
- retry_fcntl (FIL__, __LINE__, pipedes[STDIN_FILENO], F_SETFD, FD_CLOEXEC);
- retry_fcntl (FIL__, __LINE__, pipedes[STDIN_FILENO], F_SETFL, O_NONBLOCK);
-
- outf = fdopen (pipedes[STDIN_FILENO], "r");
-
- if (outf == NULL)
- {
- aud_kill (FIL__, __LINE__, source->pid, SIGKILL);
- sl_close_fd (FIL__, __LINE__, pipedes[STDOUT_FILENO]);
- waitpid (source->pid, NULL, 0);
- source->pid = 0;
- SL_RETURN( (NULL), _("sh_gpg_popen"));
- }
-
- SL_RETURN( (outf), _("sh_gpg_popen"));
-}
-
-
-static int sh_gpg_pclose (sh_gpg_popen_t *source)
-{
- int status = 0;
-
- SL_ENTER(_("sh_gpg_pclose"));
-
- status = sl_fclose(FIL__, __LINE__, source->pipe);
- if (status)
- SL_RETURN( (-1), _("sh_gpg_pclose"));
-
- if (waitpid(source->pid, NULL, 0) != source->pid)
- status = -1;
-
- source->pipe = NULL;
- source->pid = 0;
- SL_RETURN( (status), _("sh_gpg_pclose"));
-}
-
-static
-int sh_gpg_check_file_sign(int fd, char * sign_id, char * sign_fp,
- char * homedir, int whichfile)
-{
- struct stat buf;
- char line[256];
- sh_gpg_popen_t source;
- int have_id = BAD, have_fp = BAD, status = 0;
-
-#ifdef HAVE_GPG_CHECKSUM
- SL_TICKET checkfd;
-#endif
-
- SL_ENTER(_("sh_gpg_check_file_sign"));
-
- /* check whether GnuPG exists and has the correct checksum
- */
- TPT(((0), FIL__, __LINE__, _("msg=<Check signature>\n")));
- TPT(((0), FIL__, __LINE__, _("msg=<gpg is %s>\n"), DEFAULT_GPG_PATH));
-
- if (0 != retry_lstat(FIL__, __LINE__, DEFAULT_GPG_PATH, &buf))
- {
- char errbuf[SH_ERRBUF_SIZE];
-
- status = errno;
- sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, status, MSG_ERR_LSTAT,
- sh_error_message(status, errbuf, sizeof(errbuf)), DEFAULT_GPG_PATH);
- SL_RETURN( SH_GPG_BAD, _("sh_gpg_check_file_sign"));
- }
-
- if (0 != tf_trust_check (DEFAULT_GPG_PATH, SL_YESPRIV))
- SL_RETURN( SH_GPG_BAD, _("sh_gpg_check_file_sign"));
-
-#ifdef HAVE_GPG_CHECKSUM
- checkfd = sl_open_read(FIL__, __LINE__, DEFAULT_GPG_PATH, SL_YESPRIV);
-
- if (0 != sh_gpg_checksum(checkfd, 1))
- {
- sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
- _("Checksum mismatch"),
- _("gpg_check_file_sign"));
- sl_close(checkfd);
- SL_RETURN( SH_GPG_BAD, _("sh_gpg_check_file_sign"));
- }
- sl_close(checkfd);
-#endif
-
- TPT(((0), FIL__, __LINE__, _("msg=<Open pipe to check signature>\n")));
-
- fflush(NULL);
-
- source.pipe = sh_gpg_popen ( &source, fd, 0, NULL, homedir );
-
- if (NULL == source.pipe)
- {
- sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
- _("Could not open pipe"),
- _("gpg_check_file_sign"));
- SL_RETURN( SH_GPG_BAD, _("sh_gpg_check_file_sign"));
- }
-
- TPT(((0), FIL__, __LINE__, _("msg=<Open pipe success>\n")));
-
- xagain:
-
- errno = 0;
-
- while (NULL != fgets(line, sizeof(line), source.pipe))
- {
-
- TPT(((0), FIL__, __LINE__, _("msg=<gpg out: %s>\n"), line));
- if (line[strlen(line)-1] == '\n')
- line[strlen(line)-1] = ' ';
- sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, 0, MSG_E_SUBGEN,
- line,
- _("gpg_check_file_sign"));
-
- if (sl_strlen(line) < 18)
- continue;
-
- /* Sun May 27 18:40:05 CEST 2001
- */
- if (0 == sl_strncmp(_("BADSIG"), &line[9], 6) ||
- 0 == sl_strncmp(_("ERRSIG"), &line[9], 6) ||
- 0 == sl_strncmp(_("NO_PUBKEY"), &line[9], 6) ||
- 0 == sl_strncmp(_("NODATA"), &line[9], 6) ||
- 0 == sl_strncmp(_("SIGEXPIRED"), &line[9], 6))
- {
- if (0 == sl_strncmp(_("BADSIG"), &line[9], 6)) {
- dlog(1, FIL__, __LINE__,
- _("%s file is signed, but the signature is invalid."),
- ((whichfile == 1) ? _("Configuration") : _("Database")));
- }
- else if (0 == sl_strncmp(_("NO_PUBKEY"), &line[9], 6)) {
- dlog(1, FIL__, __LINE__,
- _("%s file is signed, but the public key to verify the signature is not in my keyring %s/.gnupg/pubring.asc."),
- ((whichfile == 1) ? _("Configuration") : _("Database")),
- homedir);
- }
- else if (0 == sl_strncmp(_("ERRSIG"), &line[9], 6)) {
- dlog(1, FIL__, __LINE__,
- _("%s file is signed, but the public key to verify the signature is not in my keyring %s/.gnupg/pubring.asc."),
- ((whichfile == 1) ? _("Configuration") : _("Database")),
- homedir);
- }
- else if (0 == sl_strncmp(_("SIGEXPIRED"), &line[9], 6)) {
- dlog(1, FIL__, __LINE__,
- _("%s file is signed, but the public key to verify the signature has expired."),
- ((whichfile == 1) ? _("Configuration") : _("Database")));
- }
- else if (0 == sl_strncmp(_("NODATA"), &line[9], 6)) {
- dlog(1, FIL__, __LINE__,
- _("%s file is not signed."),
- ((whichfile == 1) ? _("Configuration") : _("Database")));
- }
-
- have_fp = BAD; have_id = BAD;
- break;
- }
- if (0 == sl_strncmp(_("GOODSIG"), &line[9], 7))
- {
- sl_strlcpy (sign_id, &line[25], SH_MINIBUF+1);
- if (sign_id)
- sign_id[sl_strlen(sign_id)-1] = '\0'; /* remove trailing '"' */
- have_id = GOOD;
- }
- if (0 == sl_strncmp(_("VALIDSIG"), &line[9], 8))
- {
- strncpy (sign_fp, &line[18], 40);
- sign_fp[40] = '\0';
- have_fp = GOOD;
- }
- }
-
- if (ferror(source.pipe) && errno == EAGAIN)
- {
- /* sleep 10 ms to avoid starving the gpg child writing to the pipe */
- retry_msleep(0,10);
- clearerr(source.pipe);
- goto xagain;
- }
-
- sh_gpg_pclose (&source);
-
- TPT(((0), FIL__, __LINE__, _("msg=<Close pipe>\n")));
-
- if (have_id == GOOD)
- {
- TPT(((0), FIL__, __LINE__, _("msg=<Got signator ID>\n")));
- }
- if (have_fp == GOOD)
- {
- TPT(((0), FIL__, __LINE__, _("msg=<Got fingerprint>\n")));
- }
-
- if (have_id == GOOD && have_fp == GOOD)
- SL_RETURN( SH_GPG_OK, _("sh_gpg_check_file_sign"));
- else
- {
- if (have_id == BAD)
- sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
- _("No good signature"),
- _("gpg_check_file_sign"));
- else
- sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
- _("No fingerprint for key"),
- _("gpg_check_file_sign"));
- SL_RETURN( SH_GPG_BADSIGN, _("sh_gpg_check_file_sign"));
- }
-}
-
-int get_the_fd(SL_TICKET file_1);
-
-#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && \
- defined(HAVE_GETPWNAM_R)
-#define USE_GETPWNAM_R 1
-#endif
-
-int sh_gpg_check_sign (long file, int what)
-{
- int status = SH_GPG_BAD;
- int fd = 0;
-
- static int smsg = S_FALSE;
- char * tmp;
-
- char * sig_id;
- char * sig_fp;
-
- char * homedir = sh.effective.home;
-#if defined(SH_WITH_SERVER)
- struct passwd * tempres;
-#if defined(USE_GETPWNAM_R)
- struct passwd pwd;
- char * buffer = SH_ALLOC(SH_PWBUF_SIZE);
-#endif
-#endif
-
-#ifdef USE_FINGERPRINT
-#include "sh_gpg_fp.h"
-#endif
-
- SL_ENTER(_("sh_gpg_check_sign"));
-
-
- if (what == SIG_CONF)
- fd = get_the_fd(file);
- if (what == SIG_DATA)
- fd = get_the_fd(file);
-
-
- if (fd < 0)
- {
- TPT(((0), FIL__, __LINE__, _("msg=<GPG_CHECK: FD = %d>\n"), fd));
- dlog(1, FIL__, __LINE__,
- _("This looks like an unexpected internal error.\n"));
-#if defined(SH_WITH_SERVER) && defined(USE_GETPWNAM_R)
- SH_FREE(buffer);
-#endif
- SL_RETURN( (-1), _("sh_gpg_check_sign"));
- }
-
-#if defined(SH_WITH_SERVER)
-#if defined(USE_GETPWNAM_R)
- sh_getpwnam_r(DEFAULT_IDENT, &pwd, buffer, SH_PWBUF_SIZE, &tempres);
-#else
- tempres = sh_getpwnam(DEFAULT_IDENT);
-#endif
- if ((tempres != NULL) && (0 == sl_ret_euid()))
- {
- /* privileges not dropped yet*/
- homedir = tempres->pw_dir;
- }
-#endif
-
- if (what == SIG_CONF)
- {
- TPT(((0), FIL__, __LINE__, _("msg=<GPG_CHECK: FD = %d>\n"), fd));
- status = sh_gpg_check_file_sign(fd, gp.conf_id, gp.conf_fp, homedir, 1);
- TPT(((0), FIL__, __LINE__, _("msg=<CONF SIGUSR: |%s|>\n"), gp.conf_id));
- TPT(((0), FIL__, __LINE__, _("msg=<CONF SIGFP: |%s|>\n"), gp.conf_fp));
- sig_id = gp.conf_id; sig_fp = gp.conf_fp;
- }
-
- if (what == SIG_DATA)
- {
- TPT(((0), FIL__, __LINE__, _("msg=<GPG_CHECK: FD = %d>\n"), fd));
- status = sh_gpg_check_file_sign(fd, gp.data_id, gp.data_fp, homedir, 2);
- TPT(((0), FIL__, __LINE__, _("msg=<DATA SIGUSR: |%s|>\n"), gp.data_id));
- TPT(((0), FIL__, __LINE__, _("msg=<DATA SIGFP: |%s|>\n"), gp.data_fp));
- sig_id = gp.data_id; sig_fp = gp.data_fp;
- }
-
- if (SH_GPG_OK == status)
- {
-#ifdef USE_FINGERPRINT
- if ((sl_strcmp(SH_GPG_FP, sig_fp) == 0))
- {
- int i;
-
- for(i = 0; i < (int) sl_strlen(sig_fp); ++i) {
- if (gpgfp[i] != sig_fp[i]) {
- sh_error_handle(SH_ERR_SEVERE, FIL__, __LINE__, 0,
- MSG_E_GPG_FP, gpgfp, sig_fp);
- break; }
- }
-
- if (smsg == S_FALSE) {
- tmp = sh_util_safe_name(sig_id);
- sh_gpg_fill_startup (__LINE__, sh.prg_name, sh.real.uid,
- (sh.flag.hidefile == S_TRUE) ?
- _("(hidden)") : file_path('C', 'R'),
- tmp,
- sig_fp);
- SH_FREE(tmp); }
- smsg = S_TRUE;
-
-#if defined(SH_WITH_SERVER) && defined(USE_GETPWNAM_R)
- SH_FREE(buffer);
-#endif
- SL_RETURN(0, _("sh_gpg_check_sign"));
- }
- else
- {
- /* fp mismatch */
- dlog(1, FIL__, __LINE__,
- _("The fingerprint of the signing key: %s\ndoes not match the compiled-in fingerprint: %s.\nTherefore the signature could not be verified.\n"),
- sig_fp, SH_GPG_FP);
- sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
- _("Fingerprint mismatch"), _("gpg_check_sign"));
- status = SH_GPG_BADSIGN;
- }
-#else /* ifdef USE_FINGERPRINT */
- if (smsg == S_FALSE)
- {
- tmp = sh_util_safe_name(sig_id);
- sh_gpg_fill_startup (__LINE__,
- sh.prg_name, sh.real.uid,
- (sh.flag.hidefile == S_TRUE) ?
- _("(hidden)") : file_path('C', 'R'),
- tmp, sig_fp);
- SH_FREE(tmp);
- }
- smsg = S_TRUE;
-
-#if defined(SH_WITH_SERVER) && defined(USE_GETPWNAM_R)
- SH_FREE(buffer);
-#endif
-
- SL_RETURN(0, _("sh_gpg_check_sign"));
-#endif /* !ifdef USE_FINGERPRINT */
- }
-
- if (status != SH_GPG_OK)
- {
- uid_t e_uid = sl_ret_euid();
- char * e_home = sh.effective.home;
-
-#if defined(SH_WITH_SERVER)
-#if defined(USE_GETPWNAM_R)
- struct passwd e_pwd;
- char * e_buffer = SH_ALLOC(SH_PWBUF_SIZE);
- struct passwd * e_tempres;
- sh_getpwnam_r(DEFAULT_IDENT, &e_pwd, e_buffer, SH_PWBUF_SIZE, &e_tempres);
-#else
- struct passwd * e_tempres = sh_getpwnam(DEFAULT_IDENT);
-#endif
-
- if ((e_tempres != NULL) && (0 == sl_ret_euid()))
- {
- /* privileges not dropped yet */
- e_uid = e_tempres->pw_uid;
- e_home = e_tempres->pw_dir;
- }
-#endif
- dlog(1, FIL__, __LINE__,
- _("The signature of the configuration file or the file signature database\ncould not be verified. Possible reasons are:\n - gpg binary (%s) not found\n - invalid signature\n - the signature key is not in the private keyring of UID %d,\n - there is no keyring in %s/.gnupg, or\n - the file is not signed - did you move /filename.asc to /filename ?\nTo create a signed file, use (remove old signatures before):\n gpg -a --clearsign --not-dash-escaped FILE\n mv FILE.asc FILE\n"),
- DEFAULT_GPG_PATH,
- (int) e_uid, e_home);
-
-#if defined(SH_WITH_SERVER) && defined(USE_GETPWNAM_R)
- SH_FREE(e_buffer);
-#endif
- }
-
- TPT(((0), FIL__, __LINE__, _("msg=<Status = %d>\n"), status));
-
- return (-1); /* make compiler happy */
-}
-
-#define FGETS_BUF 16384
-
-SL_TICKET sh_gpg_extract_signed(SL_TICKET fd)
-{
- FILE * fin_cp = NULL;
- char * buf = NULL;
- int bufc;
- int flag_pgp = S_FALSE;
- int flag_nohead = S_FALSE;
- SL_TICKET fdTmp = (-1);
- SL_TICKET open_tmp (void);
-
- /* extract the data and copy to temporary file
- */
- fdTmp = open_tmp();
- if (SL_ISERROR(fdTmp))
- {
- dlog(1, FIL__, __LINE__, _("Error opening temporary file.\n"));
- sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
- _("Error opening temporary file."),
- _("sh_gpg_extract_signed"));
- return -1;
- }
-
- fin_cp = fdopen(dup(get_the_fd(fd)), "rb");
- buf = SH_ALLOC(FGETS_BUF);
-
- while (NULL != fgets(buf, FGETS_BUF, fin_cp))
- {
- bufc = 0;
- while (bufc < FGETS_BUF) {
- if (buf[bufc] == '\n') { ++bufc; break; }
- ++bufc;
- }
-
- if (flag_pgp == S_FALSE &&
- (0 == sl_strcmp(buf, _("-----BEGIN PGP SIGNED MESSAGE-----\n"))||
- 0 == sl_strcmp(buf, _("-----BEGIN PGP MESSAGE-----\n")))
- )
- {
- flag_pgp = S_TRUE;
- sl_write(fdTmp, buf, bufc);
- continue;
- }
-
- if (flag_pgp == S_TRUE && flag_nohead == S_FALSE)
- {
- if (buf[0] == '\n')
- {
- flag_nohead = S_TRUE;
- sl_write(fdTmp, buf, 1);
- continue;
- }
- else if (0 == sl_strncmp(buf, _("Hash:"), 5) ||
- 0 == sl_strncmp(buf, _("NotDashEscaped:"), 15))
- {
- sl_write(fdTmp, buf, bufc);
- continue;
- }
- else
- continue;
- }
-
- if (flag_pgp == S_TRUE && buf[0] == '\n')
- {
- sl_write(fdTmp, buf, 1);
- }
- else if (flag_pgp == S_TRUE)
- {
- /* sl_write_line(fdTmp, buf, bufc); */
- sl_write(fdTmp, buf, bufc);
- }
-
- if (flag_pgp == S_TRUE &&
- 0 == sl_strcmp(buf, _("-----END PGP SIGNATURE-----\n")))
- break;
- }
- SH_FREE(buf);
- sl_fclose(FIL__, __LINE__, fin_cp); /* fin_cp = fdopen(dup(), "rb"); */
- sl_rewind (fdTmp);
-
- return fdTmp;
-}
-
-/* #ifdef WITH_GPG */
-#endif
-
-
-
-
-
-
-
-
diff --git a/src/sh_hash.c b/src/sh_hash.c
index 345475d..f1adec4 100644
--- a/src/sh_hash.c
+++ b/src/sh_hash.c
@@ -23,6 +23,9 @@
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
+#ifdef HAVE_SYS_SYSMACROS_H
+#include <sys/sysmacros.h>
+#endif
#include <sys/stat.h>
#include <unistd.h>
#include <ctype.h>
@@ -50,7 +53,7 @@
#include "sh_hash.h"
#include "sh_error.h"
#include "sh_tiger.h"
-#include "sh_gpg.h"
+#include "sh_sig.h"
#include "sh_unix.h"
#include "sh_files.h"
#include "sh_ignore.h"
@@ -1254,7 +1257,7 @@ char * sh_hash_db2pop (const char * key, struct store2db * save)
******************************************************************/
sh_file_t * sh_hash_push_int (file_type * buf, char * fileHash)
{
- sh_file_t * fp;
+ sh_file_t * fp = NULL;
sh_filestore_t p;
size_t len;
@@ -1265,6 +1268,9 @@ sh_file_t * sh_hash_push_int (file_type * buf, char * fileHash)
SL_ENTER(_("sh_hash_push_int"));
+ if (!buf)
+ SL_RETURN(NULL, _("sh_hash_push_int"));
+
fp = SH_ALLOC(sizeof(sh_file_t));
p.mark = REC_MAGIC;
@@ -1806,6 +1812,9 @@ static int handle_notfound(int log_severity, int class,
sh_file_t * p;
int retval = 0;
+ if (!theFile)
+ return retval;
+
if (S_FALSE == sh_ignore_chk_new(theFile->fullpath))
{
char * tmp = sh_util_safe_name(theFile->fullpath);
@@ -1898,7 +1907,10 @@ int sh_hash_compdata (int class, file_type * theFile, char * fileHash,
SL_ENTER(_("sh_hash_compdata"));
- if (IsInit != 1) sh_hash_init();
+ if (!theFile)
+ SL_RETURN(0, _("sh_hash_compdata"));
+
+ if (IsInit != 1) sh_hash_init();
if (severity_override < 0)
log_severity = ShDFLevel[class];
@@ -2018,7 +2030,7 @@ int sh_hash_compdata (int class, file_type * theFile, char * fileHash,
TIGER_DATA,
sl_strlen(theFile->link_path),
hashbuf, sizeof(hashbuf)),
- MAX_PATH_STORE+1);
+ sizeof(linkHash));
linkComp = linkHash;
maxcomp = KEY_LEN;
}
@@ -2584,7 +2596,8 @@ int sh_hash_compdata (int class, file_type * theFile, char * fileHash,
_("Fetching audit record"),
_("sh_hash"), theFile->fullpath );
- if (NULL != sh_audit_fetch (theFile->fullpath, theFile->mtime, theFile->ctime, result, sizeof(result)))
+ if (NULL != sh_audit_fetch (theFile->fullpath, theFile->mtime, theFile->ctime, theFile->atime,
+ result, sizeof(result)))
{
#ifdef SH_USE_XML
sl_strlcat(msg, _("obj=\""), SH_MSG_BUF);
diff --git a/src/sh_inotify.c b/src/sh_inotify.c
index 5fc8dab..6aa6582 100644
--- a/src/sh_inotify.c
+++ b/src/sh_inotify.c
@@ -235,7 +235,7 @@ ssize_t sh_inotify_read_timeout(char * buffer, size_t count, int timeout)
ssize_t len;
int ifd = sh_inotify_getfd();
- len = sl_read_timeout_fd (ifd, buffer, count, timeout, S_FALSE);
+ len = sl_read_timeout_fd_once (ifd, buffer, count, timeout, S_FALSE);
return len;
}
diff --git a/src/sh_ipvx.c b/src/sh_ipvx.c
index 84ceec9..41f23ef 100644
--- a/src/sh_ipvx.c
+++ b/src/sh_ipvx.c
@@ -200,6 +200,7 @@ char * sh_ipvx_print_sockaddr (struct sockaddr * sa, int sa_family)
struct sh_sockaddr ss;
static char ipbuf[SH_IP_BUF];
+ memset(&ss, 0, sizeof(struct sh_sockaddr));
sh_ipvx_save(&ss, sa_family, sa);
sh_ipvx_ntoa (ipbuf, sizeof(ipbuf), &ss);
return ipbuf;
@@ -207,8 +208,6 @@ char * sh_ipvx_print_sockaddr (struct sockaddr * sa, int sa_family)
void sh_ipvx_save(struct sh_sockaddr * ss, int sa_family, struct sockaddr * sa)
{
- /* memset(ss, '\0', sizeof(struct sh_sockaddr)); */
-
switch (sa_family)
{
case AF_INET:
@@ -250,23 +249,22 @@ int sh_ipvx_set_port(struct sh_sockaddr * ss, int port)
#endif
}
-int sh_ipvx_get_port(struct sockaddr * sa, int sa_family)
+int sh_ipvx_get_port(struct sh_sockaddr * sa)
{
int port = 0;
#if defined(USE_IPVX)
- switch (sa_family)
+ switch (sa->ss_family)
{
case AF_INET:
- port = ntohs(((struct sockaddr_in *)sa)->sin_port);
+ port = ntohs((sa->sin).sin_port);
break;
case AF_INET6:
- port = ntohs(((struct sockaddr_in6 *)sa)->sin6_port);
+ port = ntohs((sa->sin6).sin6_port);
break;
}
#else
- (void) sa_family;
- port = ntohs(((struct sockaddr_in *)sa)->sin_port);
+ port = ntohs((sa->sin).sin_port);
#endif
return port;
}
@@ -278,7 +276,7 @@ int sh_ipvx_aton (const char * name, struct sh_sockaddr * ss)
struct addrinfo hints;
struct addrinfo *res;
- memset(&hints, '\0', sizeof(hints));
+ memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_UNSPEC;
hints.ai_flags = AI_NUMERICHOST;
ret = getaddrinfo(name, NULL, &hints, &res);
@@ -286,7 +284,7 @@ int sh_ipvx_aton (const char * name, struct sh_sockaddr * ss)
if (ret)
return 0;
- memset(ss, '\0', sizeof(struct sh_sockaddr));
+ memset(ss, 0, sizeof(struct sh_sockaddr));
switch(res->ai_family)
{
case AF_INET:
@@ -301,6 +299,7 @@ int sh_ipvx_aton (const char * name, struct sh_sockaddr * ss)
return 0;
break;
}
+ freeaddrinfo(res);
return 1;
#else
int ret = inet_aton(name, &((ss->sin).sin_addr));
@@ -354,6 +353,8 @@ char * sh_ipvx_canonical(const char * hostname, char * numeric, size_t nlen)
const char * host;
char hostbuf[SH_BUFSIZE];
+ SL_ENTER(_("sh_ipvx_canonical"));
+
numeric[0] = '\0';
sh_dummy_341_out = (void *) &out;
@@ -381,6 +382,8 @@ char * sh_ipvx_canonical(const char * hostname, char * numeric, size_t nlen)
err = getaddrinfo(host, NULL, &hints, &res);
if (err == 0)
{
+ struct addrinfo * res_orig = res;
+
#if defined(AI_CANONNAME)
if (res->ai_canonname && strlen(res->ai_canonname) > 0)
{
@@ -412,6 +415,8 @@ char * sh_ipvx_canonical(const char * hostname, char * numeric, size_t nlen)
res = res->ai_next;
}
+
+ freeaddrinfo(res_orig);
}
#else
struct hostent *he;
@@ -419,6 +424,8 @@ char * sh_ipvx_canonical(const char * hostname, char * numeric, size_t nlen)
volatile int isNum = 0;
struct sockaddr_in *sin;
+ SL_ENTER(_("sh_ipvx_canonical"));
+
numeric[0] = '\0';
sh_dummy_341_out = (void *) &out;
@@ -454,14 +461,15 @@ char * sh_ipvx_canonical(const char * hostname, char * numeric, size_t nlen)
SH_MUTEX_UNLOCK(mutex_resolv);
#endif
- if (flag)
- return out;
+ if (flag) {
+ SL_RETURN(out, _("sh_ipvx_canonical"));
+ }
if (out)
SH_FREE(out);
if (numeric[0] == '\0')
sl_strlcpy (numeric, _("0.0.0.0"), nlen);
- return NULL;
+ SL_RETURN(NULL, _("sh_ipvx_canonical"));
}
char * sh_ipvx_addrtoname(struct sh_sockaddr * ss)
@@ -500,15 +508,17 @@ int sh_ipvx_reverse_check_ok (char * peer, int port, struct sh_sockaddr * ss)
char sport[32];
struct addrinfo *p;
+ SL_ENTER(_("sh_ipvx_reverse_check_ok"));
+
sl_snprintf(sport, sizeof(sport), "%d", port);
- memset(&hints, '\0', sizeof(hints));
+ memset(&hints, 0, sizeof(hints));
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_ADDRCONFIG;
if (getaddrinfo(peer, sport, &hints, &res) != 0)
{
- return 0;
+ SL_RETURN((0), _("sh_ipvx_reverse_check_ok"));
}
p = res;
@@ -528,7 +538,7 @@ int sh_ipvx_reverse_check_ok (char * peer, int port, struct sh_sockaddr * ss)
if (0 == sl_strcmp(dst1, dst2))
{
- return 1;
+ SL_RETURN((1), _("sh_ipvx_reverse_check_ok"));
}
}
p = p->ai_next;
@@ -541,17 +551,19 @@ int sh_ipvx_reverse_check_ok (char * peer, int port, struct sh_sockaddr * ss)
(void) port;
+ SL_ENTER(_("sh_ipvx_reverse_check_ok"));
+
he = sh_gethostbyname(peer);
if (he != NULL)
{
for (p = he->h_addr_list; *p; ++p)
{
- if (0 == memcmp (*p, &(sin->sin_addr), sizeof(in_addr_t)) )
- return 1;
+ if (0 == memcmp (*p, &(sin->sin_addr), sizeof(in_addr_t)) ) {
+ SL_RETURN((1), _("sh_ipvx_reverse_check_ok")); }
}
}
#endif
- return 0;
+ SL_RETURN((0), _("sh_ipvx_reverse_check_ok"));
}
#ifdef SH_CUTEST
diff --git a/src/sh_log_check.c b/src/sh_log_check.c
index cc6fc4f..3114060 100644
--- a/src/sh_log_check.c
+++ b/src/sh_log_check.c
@@ -600,7 +600,7 @@ int sh_open_for_reader (struct sh_logfile * logfile)
SH_FREE(tmp);
SH_MUTEX_UNLOCK(mutex_thread_nolog);
- memset (&(logfile->offset), '\0', sizeof(fpos_t));
+ memset (&(logfile->offset), 0, sizeof(fpos_t));
logfile->flags |= SH_LOGFILE_REWIND;
return 0;
}
@@ -622,7 +622,7 @@ int sh_open_for_reader (struct sh_logfile * logfile)
{
/* done with rotated file, start with current file
*/
- memset (&(logfile->offset), '\0', sizeof(fpos_t));
+ memset (&(logfile->offset), 0, sizeof(fpos_t));
logfile->flags |= SH_LOGFILE_REWIND;
logfile->flags &= ~SH_LOGFILE_MOVED;
logfile->inode = buf.st_ino;
@@ -645,7 +645,7 @@ int sh_open_for_reader (struct sh_logfile * logfile)
}
else
{
- memset (&(logfile->offset), '\0', sizeof(fpos_t));
+ memset (&(logfile->offset), 0, sizeof(fpos_t));
logfile->flags |= SH_LOGFILE_REWIND;
logfile->inode = buf.st_ino;
logfile->device_id = buf.st_dev;
@@ -964,7 +964,7 @@ sh_string * sh_binary_reader (void * s, size_t size,
if (status != 1)
{
- memset(s, '\0', size);
+ memset(s, 0, size);
if (ferror(logfile->fp) && (logfile->flags & SH_LOGFILE_PIPE) == 0)
{
char * tmp;
diff --git a/src/sh_log_evalrule.c b/src/sh_log_evalrule.c
index 98a36d0..b053975 100644
--- a/src/sh_log_evalrule.c
+++ b/src/sh_log_evalrule.c
@@ -185,7 +185,7 @@ int sh_eval_gadd (const char * str)
group_extra = NULL; /* pcre_study(group, 0, &error); */
ng = SH_ALLOC(sizeof(struct sh_geval));
- memset(ng, '\0', sizeof(struct sh_geval));
+ memset(ng, 0, sizeof(struct sh_geval));
ng->label = sh_string_new_from_lchar(splits[0], lengths[0]);
ng->flags = RFL_ISGROUP;
@@ -293,7 +293,7 @@ int sh_eval_hadd (const char * str)
host_extra = NULL; /* pcre_study(host, 0, &error); */
nh = SH_ALLOC(sizeof(struct sh_heval));
- memset(nh, '\0', sizeof(struct sh_heval));
+ memset(nh, 0, sizeof(struct sh_heval));
nh->hostname = host;
nh->hostname_extra = host_extra;
@@ -361,7 +361,7 @@ int sh_eval_qadd (const char * str)
}
nq = SH_ALLOC(sizeof(struct sh_qeval));
- memset(nq, '\0', sizeof(struct sh_qeval));
+ memset(nq, 0, sizeof(struct sh_qeval));
nq->label = sh_string_new_from_lchar(splits[0], lengths[0]);
nq->alias = NULL;
@@ -457,7 +457,7 @@ static char * get_label_and_time(const char * inprefix, char * str,
if (splits && nfields == 2 && lengths[0] > 0 && lengths[1] > 0)
{
*seconds = strtoul(splits[0], &endptr, 10);
- if ((endptr == '\0' || endptr != splits[0]) && (*seconds != ULONG_MAX))
+ if ((*endptr == '\0') && (endptr != splits[0]) && (*seconds != ULONG_MAX))
{
res = sh_util_strdup(splits[1]);
}
@@ -494,6 +494,9 @@ int sh_eval_radd (const char * str)
char * s = new;
volatile char pflag = '-';
+ if (s == NULL)
+ return -1;
+ /* cppcheck-suppress uninitdata */
while ( *s && isspace((int)*s) ) ++s;
if (0 == strncmp(s, _("KEEP"), 4) ||
0 == strncmp(s, _("CORRELATE"), 9) ||
@@ -616,7 +619,7 @@ int sh_eval_radd (const char * str)
SH_FREE(new);
nr = SH_ALLOC(sizeof(struct sh_geval));
- memset(nr, '\0', sizeof(struct sh_geval));
+ memset(nr, 0, sizeof(struct sh_geval));
nr->label = NULL;
nr->flags = RFL_ISRULE;
@@ -1138,7 +1141,7 @@ static struct sh_ceval * find_counter(struct sh_geval * rule,
DEBUG("debug: no counter found\n");
counter = SH_ALLOC(sizeof(struct sh_ceval));
- memset(counter, '\0', sizeof(struct sh_ceval));
+ memset(counter, 0, sizeof(struct sh_ceval));
counter->hostname = sh_string_new_from_lchar(sh_string_str(host),
sh_string_len(host));
diff --git a/src/sh_log_parse_apache.c b/src/sh_log_parse_apache.c
index 06cdf4e..5e40aab 100644
--- a/src/sh_log_parse_apache.c
+++ b/src/sh_log_parse_apache.c
@@ -353,7 +353,7 @@ struct sh_logrecord * sh_parse_apache (sh_string * logline, void * fileinfo)
struct tm btime;
char * ptr = NULL;
- memset(&btime, '\0', sizeof(struct tm));
+ memset(&btime, 0, sizeof(struct tm));
btime.tm_isdst = -1;
/* example: 01/Jun/2008:07:55:28 +0200 */
diff --git a/src/sh_log_parse_samba.c b/src/sh_log_parse_samba.c
index 820bbe3..e84302a 100644
--- a/src/sh_log_parse_samba.c
+++ b/src/sh_log_parse_samba.c
@@ -74,7 +74,7 @@ struct sh_logrecord * sh_parse_samba (sh_string * logline, void * fileinfo)
struct tm btime;
char * ptr;
- memset(&btime, '\0', sizeof(struct tm));
+ memset(&btime, 0, sizeof(struct tm));
btime.tm_isdst = -1;
ptr = strptime(sh_string_str(logline), format_1, &btime);
diff --git a/src/sh_log_parse_syslog.c b/src/sh_log_parse_syslog.c
index ae9f801..167abd2 100644
--- a/src/sh_log_parse_syslog.c
+++ b/src/sh_log_parse_syslog.c
@@ -93,7 +93,7 @@ struct sh_logrecord * sh_parse_syslog (sh_string * logline, void * fileinfo)
int flag;
size_t lengths[3];
- memset(&btime, '\0', sizeof(struct tm));
+ memset(&btime, 0, sizeof(struct tm));
btime.tm_isdst = -1;
/* This is RFC 3164.
diff --git a/src/sh_log_repeat.c b/src/sh_log_repeat.c
index 9285c82..1125662 100644
--- a/src/sh_log_repeat.c
+++ b/src/sh_log_repeat.c
@@ -58,11 +58,15 @@ static int free_slots = 0; /* free slots available */
#define SH_CLEANUP 256
+void * sh_dummy_g_array = NULL;
+
static struct gestalt * add_entry (unsigned char * flags, UINT16 * sum,
time_t ltime)
{
struct gestalt * array = NULL;
+ sh_dummy_g_array = (void*) &array;
+
start:
if (urec < nrec)
{
@@ -164,6 +168,8 @@ static struct gestalt * update_or_add (unsigned char * flags, UINT16 * sum,
unsigned int i;
struct gestalt * array = arec;
+ sh_dummy_g_array = (void*) &array;
+
memcpy(flint, flags, SH_NFIELDS);
for (i = 0; i < urec; ++i)
diff --git a/src/sh_login_track.c b/src/sh_login_track.c
index 854df9e..7df22fe 100644
--- a/src/sh_login_track.c
+++ b/src/sh_login_track.c
@@ -231,7 +231,7 @@ static struct sh_track * load_data_int (char * path)
struct sh_track * urecord;
urecord = SH_ALLOC(sizeof(struct sh_track));
- memset(urecord, '\0', sizeof(struct sh_track));
+ memset(urecord, 0, sizeof(struct sh_track));
uhead = &(urecord->head);
uhead->version = SH_LTRACK_VERSION;
@@ -401,7 +401,7 @@ static struct sh_track_dates * find_user(const char * user)
while(u)
{
- if (0 == strcmp(user, u->user))
+ if (0 == sl_strcmp(user, u->user))
{
return u;
}
@@ -444,7 +444,7 @@ int sh_login_set_user_allow(const char * c)
if (!u)
{
u = SH_ALLOC(sizeof(struct sh_track_dates));
- memset(u, '\0', sizeof(struct sh_track_dates));
+ memset(u, 0, sizeof(struct sh_track_dates));
sl_strlcpy(u->user, user, SH_LTRACK_USIZE);
flag = 1;
}
@@ -838,15 +838,17 @@ static char * stripped_hostname (const char * host)
}
else
{
- q = strchr(host, '.');
+ char * tmp = sh_util_strdup(host);
+ q = strchr(tmp, '.');
if (q && *q)
{
++q;
p = sh_util_strdup(q);
+ SH_FREE(tmp);
}
else
{
- p = sh_util_strdup(host);
+ p = tmp;
}
}
return p;
@@ -912,7 +914,7 @@ static struct sh_track_entry * check_host(struct sh_track_entry * list,
else
{
entry = SH_ALLOC(sizeof(struct sh_track_entry));
- memset(entry, '\0', sizeof(struct sh_track_entry));
+ memset(entry, 0, sizeof(struct sh_track_entry));
(entry->data).last_login = time;
(entry->data).array[index] = 1;
sl_strlcpy((entry->data).hostname, q, SH_LTRACK_HSIZE);
diff --git a/src/sh_mem.c b/src/sh_mem.c
index 453640f..6d402fa 100644
--- a/src/sh_mem.c
+++ b/src/sh_mem.c
@@ -76,20 +76,25 @@ unsigned long Mem_Current = 0, Mem_Max = 0;
SH_MUTEX_RECURSIVE(mutex_mem);
#endif
-/* define MEM_LOG to an absolute filename to enable this */
+/* define MEM_LOG to enable this */
+/* #define MEM_LOG 1 */
#ifdef MEM_LOG
void sh_mem_dump ()
{
memlist_t * this = memlist;
FILE * fd;
+ static unsigned int nr = 0;
+ char filename[256];
+ snprintf(filename, sizeof(filename), "sh_mem_dump.%04u.%lu", nr, (unsigned long) sh.pid);
+
SH_MUTEX_RECURSIVE_INIT(mutex_mem);
SH_MUTEX_RECURSIVE_LOCK(mutex_mem);
- fd = fopen(MEM_LOG, "w");
+ fd = fopen(filename, "w");
if (!fd)
{
- perror(MEM_LOG);
+ perror(filename);
_exit(EXIT_FAILURE);
}
@@ -102,7 +107,9 @@ void sh_mem_dump ()
sl_fclose(FIL__, __LINE__, fd);
SH_MUTEX_RECURSIVE_UNLOCK(mutex_mem);
- _exit(EXIT_SUCCESS);
+ ++nr;
+ /* _exit(EXIT_SUCCESS); */
+ return;
}
#else
void sh_mem_dump ()
@@ -317,8 +324,8 @@ void * sh_mem_malloc (size_t size, char * file, int line)
SL_RETURN( theAddress, _("sh_mem_malloc"));
}
-static void ** sh_mem_dummy_a;
-static memlist_t ** sh_mem_merr_3;
+void ** sh_mem_dummy_a;
+memlist_t ** sh_mem_merr_3;
void sh_mem_free (void * aa, char * file, int line)
{
diff --git a/src/sh_mounts.c b/src/sh_mounts.c
index 736fa7b..51429eb 100644
--- a/src/sh_mounts.c
+++ b/src/sh_mounts.c
@@ -397,7 +397,7 @@ int sh_mounts_config_sevopt (const char * opt)
*/
/* FreeBSD includes */
-#if defined(HOST_IS_FREEBSD) || defined(HOST_IS_OPENBSD)
+#if defined(HOST_IS_FREEBSD) || defined(HOST_IS_OPENBSD) || defined(HOST_IS_DARWIN)
#include <sys/param.h>
#include <sys/ucred.h>
#include <sys/mount.h>
@@ -571,10 +571,10 @@ static int aix_fs_get (FILE *fd, AixMountTableEntry *prop)
}
/* end AIX helper routines */
-#endif
+#endif
#endif
-#if defined(HOST_IS_FREEBSD) || defined(HOST_IS_OPENBSD)
+#if defined(HOST_IS_FREEBSD) || defined(HOST_IS_OPENBSD) || defined(HOST_IS_DARWIN)
/* FreeBSD returns flags instead of strings as mount options, so we'll convert
* them here. */
@@ -682,7 +682,7 @@ static struct sh_mounts_mnt * readmounts(void) {
list = m;
/* The Open/FreeBSD way */
-#if defined(HOST_IS_FREEBSD) || defined(HOST_IS_OPENBSD)
+#if defined(HOST_IS_FREEBSD) || defined(HOST_IS_OPENBSD) || defined(HOST_IS_DARWIN)
{
struct statfs *fsp;
int entries;
diff --git a/src/sh_port2proc.c b/src/sh_port2proc.c
index 61357f1..7289ef8 100644
--- a/src/sh_port2proc.c
+++ b/src/sh_port2proc.c
@@ -634,7 +634,7 @@ static void * xrealloc(void * buf, size_t len0, size_t len)
if (len0 <= len)
memcpy(xbuf, buf, len0);
else
- memset(xbuf, '\0', len);
+ memset(xbuf, 0, len);
SH_FREE(buf);
}
return xbuf;
@@ -822,7 +822,7 @@ gather_inet(int proto)
}
sock = SH_ALLOC(sizeof *sock);
- memset(sock, '\0', sizeof (*sock));
+ memset(sock, 0, sizeof (*sock));
#ifndef in6p_lport
#define in6p_lport inp_lport
diff --git a/src/sh_portcheck.c b/src/sh_portcheck.c
index 507f028..106d9cb 100644
--- a/src/sh_portcheck.c
+++ b/src/sh_portcheck.c
@@ -32,15 +32,20 @@
#include <stdio.h>
#include <string.h>
+#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
+#ifdef HAVE_IFADDRS_H
+#include <ifaddrs.h>
+#include <netdb.h>
+#endif
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
-#define PORTCHK_VERSION "1.0"
+#define PORTCHK_VERSION "1.1"
#if defined(TEST_ONLY) || (defined(SH_USE_PORTCHECK) && (defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)))
@@ -134,9 +139,11 @@ static struct sh_portentry * portlist_udp = NULL;
#define SH_PORTCHK_INTERVAL 300
-static int sh_portchk_check_udp = 1;
-static int sh_portchk_active = 1;
-static int sh_portchk_interval = SH_PORTCHK_INTERVAL;
+static int sh_portchk_check_udp = 1;
+static int sh_portchk_active = 1;
+static int sh_portchk_same_ports = 1;
+static int sh_portchk_transients = 1;
+static int sh_portchk_interval = SH_PORTCHK_INTERVAL;
static int sh_portchk_minport = -1;
static int sh_portchk_maxport = -1;
@@ -150,6 +157,9 @@ struct sh_port {
static struct sh_port * blacklist_tcp = NULL;
static struct sh_port * blacklist_udp = NULL;
+static struct sh_port * transient_tcp = NULL;
+static struct sh_port * transient_udp = NULL;
+
SH_MUTEX_STATIC(mutex_port_check, PTHREAD_MUTEX_INITIALIZER);
static int sh_portchk_severity = SH_ERR_SEVERE;
@@ -181,10 +191,21 @@ static int sh_portchk_add_blacklist (const char * str);
*/
static int sh_portchk_add_interface (const char * str);
+#if defined(HAVE_IFADDRS_H)
+/* Exported interface to add an ethernet device
+ */
+static int sh_portchk_add_device (const char * str);
+#endif
+
/* verify whether port/interface is blacklisted (do not check)
*/
static int sh_portchk_is_blacklisted(int port, struct sh_sockaddr * haddr, int proto);
+/* verify whether port/interface is transient (used as source port hence no check required)
+ */
+static int sh_portchk_is_transient(int port, struct sh_sockaddr * haddr, int proto);
+static int sh_portchk_transient(int port, struct sh_sockaddr * haddr, int proto);
+
#ifndef TEST_ONLY
static int sh_portchk_set_interval (const char * c)
@@ -232,27 +253,37 @@ static int sh_portchk_set_port_minmax (const char * c, int * setthis)
}
-static int sh_portchk_set_minport (const char * str)
+static int sh_portchk_set_minport (const char * str)
{
return sh_portchk_set_port_minmax (str, &sh_portchk_minport);
}
-static int sh_portchk_set_maxport (const char * str)
+static int sh_portchk_set_maxport (const char * str)
{
return sh_portchk_set_port_minmax (str, &sh_portchk_maxport);
}
-static int sh_portchk_set_active (const char * str)
+static int sh_portchk_set_active (const char * str)
{
return sh_util_flagval(str, &sh_portchk_active);
}
-static int sh_portchk_set_udp (const char * str)
+static int sh_portchk_set_udp (const char * str)
{
return sh_util_flagval(str, &sh_portchk_check_udp);
}
+#if defined(SH_ALLOW_RESTORE)
+static int sh_portchk_set_transients (const char * str)
+{
+ return sh_util_flagval(str, &sh_portchk_transients);
+}
-static int sh_portchk_set_severity (const char * str)
+static int sh_portchk_set_same_ports (const char * str)
+{
+ return sh_util_flagval(str, &sh_portchk_same_ports);
+}
+#endif
+static int sh_portchk_set_severity (const char * str)
{
char tmp[32];
tmp[0] = '='; tmp[1] = '\0';
@@ -285,6 +316,12 @@ sh_rconf sh_portchk_table[] = {
N_("portcheckactive"),
sh_portchk_set_active,
},
+#if defined(HAVE_IFADDRS_H)
+ {
+ N_("portcheckdevice"),
+ sh_portchk_add_device,
+ },
+#endif
{
N_("portcheckinterface"),
sh_portchk_add_interface,
@@ -305,6 +342,16 @@ sh_rconf sh_portchk_table[] = {
N_("portcheckudp"),
sh_portchk_set_udp,
},
+#if defined(SH_ALLOW_RESTORE)
+ {
+ N_("portchecktransients"),
+ sh_portchk_set_transients,
+ },
+ {
+ N_("portchecksameports"),
+ sh_portchk_set_same_ports,
+ },
+#endif
{
NULL,
NULL
@@ -382,6 +429,7 @@ static char * sh_getrpcbynumber (int number, char * buf, size_t len)
sh_string_destroy(&s);
sl_fclose(FIL__, __LINE__, fp);
}
+ /* cppcheck-suppress resourceLeak */
return NULL;
}
#endif
@@ -432,6 +480,7 @@ static char * sh_getservbyport (int port, const char * proto_in, char * buf, siz
sh_string_destroy(&s);
sl_fclose(FIL__, __LINE__, fp);
}
+ /* cppcheck-suppress resourceLeak */
return NULL;
}
@@ -523,6 +572,19 @@ static struct sh_port * sh_portchk_kill_blacklist (struct sh_port * head)
return NULL;
}
+static struct sh_port * sh_portchk_kill_transient (struct sh_port * head)
+{
+ if (head)
+ {
+ if (head->next)
+ sh_portchk_kill_transient (head->next);
+
+ SH_FREE(head->paddr);
+ SH_FREE(head);
+ }
+ return NULL;
+}
+
/* These variables are not used anywhere. They only exist
* to assign &pre, &ptr to them, which keeps gcc from
* putting it into a register, and avoids the 'clobbered
@@ -538,7 +600,7 @@ static void sh_portchk_check_list (struct sh_portentry ** head,
{
struct sh_portentry * ptr = *head;
struct sh_portentry * pre = *head;
- char errbuf[256];
+ char errbuf[512];
/* Take the address to keep gcc from putting them into registers.
* Avoids the 'clobbered by longjmp' warning.
@@ -629,6 +691,7 @@ static struct sh_portentry * sh_portchk_get_from_list (int proto, int port,
struct sh_portentry * portlist;
char str_addr[SH_IP_BUF];
+
if (proto == IPPROTO_TCP)
portlist = portlist_tcp;
else
@@ -667,7 +730,7 @@ static void sh_portchk_cmp_to_list (int proto, int port,
struct sh_sockaddr * paddr, char * service)
{
struct sh_portentry * portent;
- char errbuf[256];
+ char errbuf[512];
portent = sh_portchk_get_from_list (proto, port, paddr, service);
@@ -886,6 +949,9 @@ static char * check_rpc_list (int port, struct sockaddr_in * address,
return NULL;
}
+void * sh_dummy_950_p = NULL;
+void * sh_dummy_951_p = NULL;
+
static int check_port_udp_internal (int fd, int port, struct sh_sockaddr * paddr)
{
int retval;
@@ -893,11 +959,17 @@ static int check_port_udp_internal (int fd, int port, struct sh_sockaddr * paddr
char buf[8];
#ifndef TEST_ONLY
char errmsg[256];
- int nerr;
+ volatile int nerr;
#endif
char errbuf[SH_ERRBUF_SIZE];
char ipbuf[SH_IP_BUF];
+ struct sh_sockaddr saddr;
+ socklen_t slen = 0;
+ volatile int sport = 0;
+
+ sh_dummy_950_p = (void*) &p;
+
sh_ipvx_set_port(paddr, port);
do {
@@ -923,85 +995,155 @@ static int check_port_udp_internal (int fd, int port, struct sh_sockaddr * paddr
}
else
{
- do {
- retval = send (fd, buf, 0, 0);
- } while (retval < 0 && errno == EINTR);
+ /* Register the used source port as transient. This will avoid
+ * the issue of lingering source ports being reported as a spurious
+ * service. The lingering source port is effectvely a race condition.
+ *
+ * Also use this code to obtain the source port. Sometimes Samhain
+ * reports on a port where it connects back to itself. In that case
+ * source and destination port are the same.
+ *
+ * AGH, 23 Apr 2017 (www.2024sight.com).
+ */
- if (retval == -1 && errno == ECONNREFUSED)
- {
- sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
- if (portchk_debug)
- fprintf(stderr, _("check port_udp: %5d/udp on %15s established/time_wait\n"),
- port, ipbuf);
- }
- else
- {
- /* Only the second send() may catch the error
- */
- do {
+#if defined(USE_IPVX)
+ if (paddr->ss_family == AF_INET)
+ {
+ saddr.ss_family = AF_INET;
+ slen = sizeof( struct sockaddr_in );
+ retval = getsockname(fd, (struct sockaddr *)&(saddr.sin), &slen);
+ }
+ else
+ {
+ saddr.ss_family = AF_INET6;
+ slen = sizeof( struct sockaddr_in6 );
+ retval = getsockname(fd, (struct sockaddr *)&(saddr.sin6), &slen);
+ }
+#else
+ saddr.ss_family = AF_INET;
+ slen = sizeof( struct sockaddr_in );
+ retval = getsockname(fd, (struct sockaddr *)&(saddr.sin), &slen);
+#endif
+
+ if ( retval == 0 )
+ {
+ sport = sh_ipvx_get_port(&saddr);
+ sh_portchk_transient(sport, &saddr, IPPROTO_UDP);
+ }
+ else
+ {
+#ifdef TEST_ONLY
+ if (portchk_debug)
+ perror(_("getsockname"));
+#else
+ sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
+ nerr = errno;
+ sl_snprintf(errmsg, sizeof(errmsg), _("source port transient for %15s:%d/udp: %s"),
+ ipbuf, port, sh_error_message(errno, errbuf, sizeof(errbuf)));
+ SH_MUTEX_LOCK(mutex_thread_nolog);
+ sh_error_handle((-1), FIL__, __LINE__, nerr, MSG_E_SUBGEN, errmsg, _("getsockname"));
+ SH_MUTEX_UNLOCK(mutex_thread_nolog);
+#endif
+ }
+
+ if (( sport != port ) || ( sh_portchk_same_ports == S_FALSE ))
+ {
+ do {
retval = send (fd, buf, 0, 0);
- } while (retval < 0 && errno == EINTR);
+ } while (retval < 0 && errno == EINTR);
- if (retval == -1 && errno == ECONNREFUSED)
+ if (retval == -1 && errno == ECONNREFUSED)
{
sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
if (portchk_debug)
- fprintf(stderr, _("check port: %5d/udp on %15s established/time_wait\n"),
- port, ipbuf);
+ fprintf(stderr, _("check port_udp: %5d/udp on %15s established/time_wait\n"),
+ port, ipbuf);
}
- else if (retval != -1)
+ else
{
- /* Try to get service name from portmap
+ /* Only the second send() may catch the error
*/
- if (paddr->ss_family == AF_INET)
- {
- p = check_rpc_list (port,
- (struct sockaddr_in *) sh_ipvx_sockaddr_cast(paddr),
- IPPROTO_UDP);
- }
+ do {
+ retval = send (fd, buf, 0, 0);
+ } while (retval < 0 && errno == EINTR);
+
+ if (retval == -1 && errno == ECONNREFUSED)
+ {
+ sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
+ if (portchk_debug)
+ fprintf(stderr, _("check port: %5d/udp on %15s established/time_wait\n"),
+ port, ipbuf);
+ }
+ else if (retval != -1)
+ {
+ /* Try to get service name from portmap
+ */
+ if (paddr->ss_family == AF_INET)
+ {
+ p = check_rpc_list (port,
+ (struct sockaddr_in *) sh_ipvx_sockaddr_cast(paddr),
+ IPPROTO_UDP);
+ }
- sh_portchk_cmp_to_list (IPPROTO_UDP, port, paddr, p ? p : NULL);
+ sh_portchk_cmp_to_list (IPPROTO_UDP, port, paddr, p ? p : NULL);
- /* If not an RPC service, try to get name from /etc/services
- */
- if (!p)
- p = check_services(port, IPPROTO_UDP);
+ /* If not an RPC service, try to get name from /etc/services
+ */
+ if (!p)
+ p = check_services(port, IPPROTO_UDP);
- if (portchk_debug)
- {
- sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
- fprintf(stderr, _("check port_udp: %5d/udp on %15s open %s\n"),
- port, ipbuf, p);
- }
+ if (portchk_debug)
+ {
+ sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
+ fprintf(stderr, _("check port_udp: %5d/udp on %15s open %s\n"),
+ port, ipbuf, p);
+ }
+ }
+ else
+ {
+ if (portchk_debug)
+ {
+ sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
+ fprintf(stderr, _("check port_udp: %5d/udp on %15s ERRNO %d\n"),
+ port, ipbuf, errno);
+ }
+ }
}
- else
- {
- if (portchk_debug)
- {
- sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
- fprintf(stderr, _("check port_udp: %5d/udp on %15s ERRNO %d\n"),
- port, ipbuf, errno);
- }
- }
- }
+ }
+ else
+ {
+ if (portchk_debug)
+ {
+ sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
+ fprintf(stderr, _("check port_udp: %5d/udp on %15s same source and destination port\n"),
+ port, ipbuf);
+ }
+ }
}
sl_close_fd (FIL__, __LINE__, fd);
+ sh_dummy_950_p = NULL;
return 0;
}
static int check_port_tcp_internal (int fd, int port, struct sh_sockaddr * paddr)
{
- int retval;
+ volatile int retval;
int flags;
char * p = NULL;
#ifndef TEST_ONLY
char errmsg[256];
- int nerr;
+ volatile int nerr;
#endif
char errbuf[SH_ERRBUF_SIZE];
char ipbuf[SH_IP_BUF];
+ struct sh_sockaddr saddr;
+ socklen_t slen = 0;
+ volatile int sport = 0;
+
+ sh_dummy_951_p = (void*) &p;
+
sh_ipvx_set_port(paddr, port);
do {
@@ -1035,28 +1177,92 @@ static int check_port_tcp_internal (int fd, int port, struct sh_sockaddr * paddr
}
else
{
- /* Try to get service name from portmap
+ /* Register the used source port as transient. This will avoid
+ * the issue of lingering source ports being reported as a spurious
+ * service. The lingering source port is effectively a race condition.
+ *
+ * Also use this code to obtain the source port. Sometimes Samhain
+ * reports on a port where it connects back to itself. In that case
+ * source and destination port are the same.
+ *
+ * AGH, 23 Apr 2017 (www.2024sight.com).
*/
+
+#if defined(USE_IPVX)
if (paddr->ss_family == AF_INET)
- {
- p = check_rpc_list (port,
- (struct sockaddr_in *) sh_ipvx_sockaddr_cast(paddr),
- IPPROTO_TCP);
- }
+ {
+ saddr.ss_family = AF_INET;
+ slen = sizeof( struct sockaddr_in );
+ retval = getsockname(fd, (struct sockaddr *)&(saddr.sin), &slen);
+ }
+ else
+ {
+ saddr.ss_family = AF_INET6;
+ slen = sizeof( struct sockaddr_in6 );
+ retval = getsockname(fd, (struct sockaddr *)&(saddr.sin6), &slen);
+ }
+#else
+ saddr.ss_family = AF_INET;
+ slen = sizeof( struct sockaddr_in );
+ retval = getsockname(fd, (struct sockaddr *)&(saddr.sin), &slen);
+#endif
+
+ if ( retval == 0 )
+ {
+ sport = sh_ipvx_get_port(&saddr);
+ sh_portchk_transient(sport, &saddr, IPPROTO_TCP);
+ }
+ else
+ {
+#ifdef TEST_ONLY
+ if (portchk_debug)
+ perror(_("getsockname"));
+#else
+ sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
+ nerr = errno;
+ sl_snprintf(errmsg, sizeof(errmsg), _("source port transient for %15s:%d/tcp: %s"),
+ ipbuf, port, sh_error_message(errno, errbuf, sizeof(errbuf)));
+ SH_MUTEX_LOCK(mutex_thread_nolog);
+ sh_error_handle((-1), FIL__, __LINE__, nerr, MSG_E_SUBGEN,
+ errmsg, _("getsockname"));
+ SH_MUTEX_UNLOCK(mutex_thread_nolog);
+#endif
+ }
- sh_portchk_cmp_to_list (IPPROTO_TCP, port, paddr, p ? p : NULL);
+ if (( sport != port ) || ( sh_portchk_same_ports == S_FALSE ))
+ {
+ /* Try to get service name from portmap
+ */
+ if (paddr->ss_family == AF_INET)
+ {
+ p = check_rpc_list (port,
+ (struct sockaddr_in *) sh_ipvx_sockaddr_cast(paddr),
+ IPPROTO_TCP);
+ }
- /* If not an RPC service, try to get name from /etc/services
- */
- if (!p)
- p = check_services(port, IPPROTO_TCP);
+ sh_portchk_cmp_to_list (IPPROTO_TCP, port, paddr, p ? p : NULL);
- if (portchk_debug)
- {
- sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
- fprintf(stderr, _("check port_tcp: %5d on %15s open %s\n"),
- port, ipbuf, p);
- }
+ /* If not an RPC service, try to get name from /etc/services
+ */
+ if (!p)
+ p = check_services(port, IPPROTO_TCP);
+
+ if (portchk_debug)
+ {
+ sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
+ fprintf(stderr, _("check port_tcp: %5d on %15s open %s\n"),
+ port, ipbuf, p);
+ }
+ }
+ else
+ {
+ if (portchk_debug)
+ {
+ sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), paddr);
+ fprintf(stderr, _("check port_udp: %5d/tcp on %15s same source and destination port\n"),
+ port, ipbuf);
+ }
+ }
#if !defined(O_NONBLOCK)
#if defined(O_NDELAY)
@@ -1108,6 +1314,7 @@ static int check_port_tcp_internal (int fd, int port, struct sh_sockaddr * paddr
port);
}
sl_close_fd (FIL__, __LINE__, fd);
+ sh_dummy_951_p = NULL;
return 0;
}
@@ -1118,14 +1325,17 @@ static int check_port_tcp_internal (int fd, int port, struct sh_sockaddr * paddr
* };
*/
-#define SH_IFACE_MAX 16
+#define SH_IFACE_MAX 64
+#define SH_IFACE_ADDR 0
+#define SH_IFACE_DEV 1
struct portchk_interfaces {
- struct sh_sockaddr iface[SH_IFACE_MAX];
- int used;
+ struct sh_sockaddr iface;
+ int type;
};
-static struct portchk_interfaces iface_list;
+static struct portchk_interfaces iface_list[SH_IFACE_MAX];
+static int iface_list_used = 0;
static int iface_initialized = 0;
#ifdef TEST_ONLY
@@ -1158,7 +1368,7 @@ static int sh_portchk_init_internal (void)
SH_MUTEX_LOCK(mutex_port_check);
if (iface_initialized == 0)
{
- iface_list.used = 0;
+ iface_list_used = 0;
iface_initialized = 1;
}
@@ -1166,7 +1376,7 @@ static int sh_portchk_init_internal (void)
SH_MUTEX_LOCK(mutex_resolv);
hent = sh_gethostbyname(portchk_hostname);
i = 0;
- while (hent && hent->h_addr_list[i] && (iface_list.used < SH_IFACE_MAX))
+ while (hent && hent->h_addr_list[i] && (iface_list_used < SH_IFACE_MAX))
{
struct sockaddr_in sin;
struct sh_sockaddr iface_tmp;
@@ -1174,31 +1384,32 @@ static int sh_portchk_init_internal (void)
memcpy(&(sin.sin_addr.s_addr), hent->h_addr_list[i], sizeof(in_addr_t));
sh_ipvx_save(&iface_tmp, AF_INET, (struct sockaddr *)&sin);
- for (j = 0; j < iface_list.used; ++j)
+ for (j = 0; j < iface_list_used; ++j)
{
- if (0 == sh_ipvx_cmp(&iface_tmp, &(iface_list.iface[j])))
+ if (0 == sh_ipvx_cmp(&iface_tmp, &(iface_list[j].iface)))
{
goto next_iface;
}
}
- sh_ipvx_save(&(iface_list.iface[iface_list.used]),
+ sh_ipvx_save(&(iface_list[iface_list_used].iface),
AF_INET, (struct sockaddr *)&sin);
+ iface_list[iface_list_used].type = SH_IFACE_ADDR;
if (portchk_debug)
{
char buf[256];
- sh_ipvx_ntoa(buf, sizeof(buf), &(iface_list.iface[iface_list.used]));
+ sh_ipvx_ntoa(buf, sizeof(buf), &(iface_list[iface_list_used].iface));
fprintf(stderr, _("added interface[%d]: %s\n"), i, buf);
}
- ++iface_list.used;
+ ++iface_list_used;
next_iface:
++i;
}
SH_MUTEX_UNLOCK(mutex_resolv);
#else
- memset(&hints, '\0', sizeof(hints));
+ memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_UNSPEC;
hints.ai_flags = AI_ADDRCONFIG;
@@ -1207,37 +1418,37 @@ static int sh_portchk_init_internal (void)
struct addrinfo *p = res;
struct sh_sockaddr iface_tmp;
- while ((p != NULL) && (iface_list.used < SH_IFACE_MAX))
+ while ((p != NULL) && (iface_list_used < SH_IFACE_MAX))
{
sh_ipvx_save(&iface_tmp, p->ai_family, p->ai_addr);
- for (j = 0; j < iface_list.used; ++j)
+ for (j = 0; j < iface_list_used; ++j)
{
if (portchk_debug)
{
char buf1[256], buf2[256];
- sh_ipvx_ntoa(buf1, sizeof(buf1), &(iface_list.iface[j]));
+ sh_ipvx_ntoa(buf1, sizeof(buf1), &(iface_list[j].iface));
sh_ipvx_ntoa(buf2, sizeof(buf2), &iface_tmp);
fprintf(stderr, _("check interface[%d]: %s vs %s\n"), j, buf1, buf2);
}
- if (0 == sh_ipvx_cmp(&iface_tmp, &(iface_list.iface[j])))
+ if (0 == sh_ipvx_cmp(&iface_tmp, &(iface_list[j].iface)))
{
if (portchk_debug)
fprintf(stderr, _("skipping interface[%d]\n"), j);
goto next_iface;
}
}
- sh_ipvx_save(&(iface_list.iface[iface_list.used]),
+ sh_ipvx_save(&(iface_list[iface_list_used].iface),
p->ai_family, p->ai_addr);
-
+ iface_list[iface_list_used].type = SH_IFACE_ADDR;
if (portchk_debug)
{
char buf[256];
- sh_ipvx_ntoa(buf, sizeof(buf), &(iface_list.iface[iface_list.used]));
- fprintf(stderr, _("added interface[%d]: %s\n"), iface_list.used, buf);
+ sh_ipvx_ntoa(buf, sizeof(buf), &(iface_list[iface_list_used].iface));
+ fprintf(stderr, _("added interface[%d]: %s\n"), iface_list_used, buf);
}
- ++iface_list.used;
+ ++iface_list_used;
next_iface:
p = p->ai_next;
@@ -1246,9 +1457,9 @@ static int sh_portchk_init_internal (void)
}
#endif
- for (i = 0; i < iface_list.used; ++i)
+ for (i = 0; i < iface_list_used; ++i)
{
- sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), &(iface_list.iface[i]));
+ sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), &(iface_list[i].iface));
sl_snprintf(errbuf, sizeof(errbuf), _("added interface: %s"), ipbuf);
SH_MUTEX_LOCK(mutex_thread_nolog);
@@ -1284,13 +1495,14 @@ int sh_portchk_init (struct mod_type * arg)
else if (arg != NULL && arg->initval == SH_MOD_THREAD &&
(sh.flag.isdaemon == S_TRUE || sh.flag.loop == S_TRUE))
{
+ (void) sh_portchk_init_internal();
return SH_MOD_THREAD;
}
#endif
return sh_portchk_init_internal();
}
-
+static void dev_list_kill();
#if !defined(TEST_ONLY)
int sh_portchk_reconf (void)
@@ -1304,6 +1516,8 @@ int sh_portchk_reconf (void)
sh_portchk_minport = -1;
sh_portchk_maxport = -1;
+ dev_list_kill();
+
portlist_udp = sh_portchk_kill_list (portlist_udp);
portlist_tcp = sh_portchk_kill_list (portlist_tcp);
@@ -1344,9 +1558,9 @@ static int check_port_generic (int port, int domain, int type, int protocol)
/* Check all interfaces for this host
*/
- while (i < iface_list.used)
+ while (i < iface_list_used)
{
- memcpy(&paddr, &(iface_list.iface[i]), sizeof(paddr));
+ memcpy(&paddr, &(iface_list[i].iface), sizeof(paddr));
if (paddr.ss_family != domain)
{
@@ -1360,6 +1574,12 @@ static int check_port_generic (int port, int domain, int type, int protocol)
continue;
}
+ if (0 != sh_portchk_is_transient(port, &paddr, protocol))
+ {
+ ++i;
+ continue;
+ }
+
if ((sock = socket(paddr.ss_family, type, protocol)) < 0 )
{
++i;
@@ -1549,6 +1769,12 @@ static int sh_portchk_scan_ports_generic (int min_port, int max_port_arg,
sl_close_fd (FIL__, __LINE__, sock);
}
}
+
+ if (protocol == IPPROTO_TCP)
+ transient_tcp=sh_portchk_kill_transient(transient_tcp);
+ else
+ transient_udp=sh_portchk_kill_transient(transient_udp);
+
return 0;
}
@@ -1576,7 +1802,7 @@ static int sh_portchk_scan_ports_udp (int min_port, int max_port)
*/
void * sh_dummy_1564_str = NULL; /* fix clobbered by.. warning */
-static int sh_portchk_add_interface (const char * str)
+static int sh_portchk_add_interface_int (const char * str, int type)
{
struct sh_sockaddr saddr;
char errbuf[256];
@@ -1586,7 +1812,7 @@ static int sh_portchk_add_interface (const char * str)
if (iface_initialized == 0)
{
- iface_list.used = 0;
+ iface_list_used = 0;
iface_initialized = 1;
}
@@ -1608,7 +1834,7 @@ static int sh_portchk_add_interface (const char * str)
if (0 == sh_ipvx_aton(buf, &saddr))
return -1;
- if (iface_list.used == SH_IFACE_MAX)
+ if (iface_list_used == SH_IFACE_MAX)
return -1;
sh_ipvx_ntoa(ipbuf, sizeof(ipbuf), &saddr);
@@ -1618,8 +1844,9 @@ static int sh_portchk_add_interface (const char * str)
errbuf, _("sh_portchk_add_interface"));
SH_MUTEX_UNLOCK(mutex_thread_nolog);
- memcpy (&(iface_list.iface[iface_list.used]), &(saddr), sizeof(saddr));
- ++iface_list.used;
+ memcpy (&(iface_list[iface_list_used].iface), &(saddr), sizeof(saddr));
+ iface_list[iface_list_used].type = type;
+ ++iface_list_used;
}
} while (*str);
@@ -1627,6 +1854,230 @@ static int sh_portchk_add_interface (const char * str)
return 0;
}
+static int sh_portchk_add_interface (const char * str)
+{
+ return sh_portchk_add_interface_int (str, SH_IFACE_ADDR);
+}
+
+#if defined(HAVE_IFADDRS_H)
+/*
+ * subroutines to add a device
+ */
+void * sh_dummy_1651_ifa = NULL; /* fix clobbered by.. warning */
+
+static int portchk_add_device_int (const char * buf)
+{
+ struct ifaddrs *ifaddr, *ifa;
+ int family;
+#ifndef NI_MAXHOST
+#define NI_MAXHOST 1025
+#endif
+ char host[NI_MAXHOST];
+
+ sh_dummy_1651_ifa = (void*) &ifa;
+
+ if (getifaddrs(&ifaddr) == -1)
+ {
+ volatile int nerr = errno;
+ char errbuf[SH_ERRBUF_SIZE];
+ sh_error_message(errno, errbuf, sizeof(errbuf));
+ SH_MUTEX_LOCK(mutex_thread_nolog);
+ sh_error_handle((-1), FIL__, __LINE__, nerr, MSG_E_SUBGEN,
+ errbuf, _("getifaddrs"));
+ SH_MUTEX_UNLOCK(mutex_thread_nolog);
+ return -1;
+ }
+
+ for ( ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next)
+ {
+ if (ifa->ifa_addr == NULL)
+ continue;
+
+ if (strcmp(ifa->ifa_name, buf) == 0)
+ {
+ volatile int s = 0;
+ family = ifa->ifa_addr->sa_family;
+
+ if (family == AF_INET)
+ {
+ s = getnameinfo( ifa->ifa_addr, sizeof(struct sockaddr_in),
+ host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST );
+
+ if (s == 0)
+ {
+ if (sh_portchk_add_interface_int(host, SH_IFACE_DEV) < 0)
+ {
+ freeifaddrs(ifaddr);
+ return -1;
+ }
+ }
+ }
+
+#if defined(USE_IPVX)
+ if (family == AF_INET6)
+ {
+ s = getnameinfo( ifa->ifa_addr, sizeof(struct sockaddr_in6),
+ host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST );
+
+ if (s == 0)
+ {
+ if (sh_portchk_add_interface_int(host, SH_IFACE_DEV) < 0)
+ {
+ freeifaddrs(ifaddr);
+ return -1;
+ }
+ }
+ }
+#endif
+
+ if (s != 0)
+ {
+ char errbuf[SH_ERRBUF_SIZE];
+ sl_strlcpy(errbuf, buf, sizeof(errbuf));
+ sl_strlcat(errbuf, ": ", sizeof(errbuf));
+ sl_strlcat(errbuf, gai_strerror(s), sizeof(errbuf));
+ SH_MUTEX_LOCK(mutex_thread_nolog);
+ sh_error_handle((-1), FIL__, __LINE__, s, MSG_E_SUBGEN,
+ errbuf, _("getnameinfo"));
+ SH_MUTEX_UNLOCK(mutex_thread_nolog);
+ }
+
+ }
+ }
+
+ freeifaddrs(ifaddr);
+ return 0;
+}
+
+struct added_dev {
+ char dev[64];
+ struct added_dev * next;
+};
+
+static struct added_dev * dev_list = NULL;
+
+static void dev_list_add (char * buf)
+{
+ struct added_dev * new = SH_ALLOC(sizeof(struct added_dev));
+ sl_strlcpy(new->dev, buf, 64);
+ new->next = dev_list;
+ dev_list = new;
+ return;
+}
+
+static void dev_list_kill ()
+{
+ struct added_dev * old;
+ struct added_dev * new = dev_list;
+ dev_list = NULL;
+
+ while (new)
+ {
+ old = new;
+ new = new->next;
+ SH_FREE(old);
+ }
+ return;
+}
+
+static int sh_portchk_add_device (const char * str)
+{
+ char buf[64];
+
+ do {
+
+ while (*str == ',' || *str == ' ' || *str == '\t') ++str;
+
+ if (*str)
+ {
+ unsigned int i = 0;
+ while (*str && i < (sizeof(buf)-1) &&
+ *str != ',' && *str != ' ' && *str != '\t') {
+ buf[i] = *str; ++str; ++i;
+ }
+ buf[i] = '\0';
+
+ if (portchk_add_device_int (buf) < 0)
+ return -1;
+
+ dev_list_add(buf);
+ }
+ } while (*str);
+
+ return 0;
+}
+
+static int iface_comp (const void *a, const void *b)
+{
+ const struct portchk_interfaces * aa = (const struct portchk_interfaces *) a;
+ const struct portchk_interfaces * bb = (const struct portchk_interfaces *) b;
+ return (aa->type - bb->type);
+}
+
+static void iface_qsort()
+{
+ qsort(&iface_list[0], iface_list_used, sizeof(struct portchk_interfaces),
+ iface_comp);
+ return;
+}
+
+static void recheck_devices()
+{
+ if (dev_list)
+ {
+ struct added_dev * dev = dev_list;
+ int i, j;
+
+ if (portchk_debug)
+ {
+ for (j = 0; j < iface_list_used; ++j)
+ {
+ char buf[SH_IP_BUF];
+ struct portchk_interfaces * aa = &(iface_list[j]);
+ sh_ipvx_ntoa(buf, sizeof(buf), &(aa->iface));
+ fprintf(stderr, _("presort: iface[%d] type(%d) %s\n"), j, iface_list[j].type, buf);
+ }
+ }
+
+ iface_qsort();
+
+ if (portchk_debug)
+ {
+ for (j = 0; j < iface_list_used; ++j)
+ {
+ char buf[SH_IP_BUF];
+ struct portchk_interfaces * aa = &(iface_list[j]);
+ sh_ipvx_ntoa(buf, sizeof(buf), &(aa->iface));
+ fprintf(stderr, _("postsor: iface[%d] type(%d) %s\n"), j, iface_list[j].type, buf);
+ }
+ }
+
+ i = 0;
+ for (j = 0; j < iface_list_used; ++j)
+ if (iface_list[j].type == SH_IFACE_DEV) ++i;
+ iface_list_used -= i;
+
+ if (portchk_debug)
+ {
+ for (j = 0; j < iface_list_used; ++j)
+ {
+ char buf[SH_IP_BUF];
+ struct portchk_interfaces * aa = &(iface_list[j]);
+ sh_ipvx_ntoa(buf, sizeof(buf), &(aa->iface));
+ fprintf(stderr, _("postdel: iface[%d] type(%d) %s\n"), j, iface_list[j].type, buf);
+ }
+ }
+
+ while (dev)
+ {
+ portchk_add_device_int (dev->dev);
+ dev = dev->next;
+ }
+ }
+ return;
+}
+#endif
+
/* verify whether port/interface is blacklisted (do not check)
*/
static int sh_portchk_is_blacklisted(int port, struct sh_sockaddr * saddr,
@@ -1641,14 +2092,8 @@ static int sh_portchk_is_blacklisted(int port, struct sh_sockaddr * saddr,
while (head)
{
- if (head->port == port)
- {
- if (sh_ipvx_isany(head->paddr) ||
- 0 == sh_ipvx_cmp(head->paddr, saddr))
- return 1;
- else
- return 0;
- }
+ if (head->port == port && ( sh_ipvx_isany(head->paddr) || 0 == sh_ipvx_cmp(head->paddr, saddr) ))
+ return 1;
head = head->next;
}
return 0;
@@ -1694,8 +2139,75 @@ static int sh_portchk_blacklist(int port, struct sh_sockaddr * saddr, int proto)
}
return 0;
}
+
+
+/* verify whether port/interface is transient (used as source port
+ *hence no check required)
+ */
+static int sh_portchk_is_transient(int port, struct sh_sockaddr * saddr,
+ int proto)
+{
+ struct sh_port * head;
-
+ if (proto == IPPROTO_TCP)
+ head = transient_tcp;
+ else
+ head = transient_udp;
+
+ while (head)
+ {
+ if (head->port == port && ( sh_ipvx_isany(head->paddr) || 0 == sh_ipvx_cmp(head->paddr, saddr) ))
+ return 1;
+ head = head->next;
+ }
+ return 0;
+}
+
+
+static int sh_portchk_transient(int port, struct sh_sockaddr * saddr, int proto)
+{
+ struct sh_port * transient;
+ struct sh_port * head;
+
+ if (sh_portchk_transients == S_FALSE)
+ return 0;
+
+ if (proto == IPPROTO_TCP)
+ head = transient_tcp;
+ else
+ head = transient_udp;
+
+ transient = head;
+
+ while (transient)
+ {
+ if (transient->port == port &&
+ 0 == sh_ipvx_cmp(head->paddr, saddr))
+ return -1;
+ transient = transient->next;
+ }
+
+ transient = SH_ALLOC (sizeof(struct sh_port));
+ transient->paddr = SH_ALLOC (sizeof(struct sh_sockaddr));
+ transient->port = port;
+ memcpy(transient->paddr, saddr, sizeof(struct sh_sockaddr));
+ transient->next = head;
+
+ if (proto == IPPROTO_TCP)
+ transient_tcp = transient;
+ else
+ transient_udp = transient;
+
+ if (portchk_debug)
+ {
+ int checkit = sh_portchk_is_transient(port, saddr, proto);
+ fprintf(stderr, _("port transient: %d %s\n"), port,
+ (checkit == 1) ? _("ok") : _("fail"));
+ }
+ return 0;
+}
+
+
/* Subroutine to add a required or optional port/service
*/
static int sh_portchk_add_required_port_generic (char * service,
@@ -1717,9 +2229,9 @@ static int sh_portchk_add_required_port_generic (char * service,
p = strchr(buf, '/');
if (!p)
return -1;
- if (0 == strcmp(p, _("/tcp")))
+ if (0 == strcasecmp(p, _("/tcp")))
proto = IPPROTO_TCP;
- else if (0 == strcmp(p, _("/udp")))
+ else if (0 == strcasecmp(p, _("/udp")))
proto = IPPROTO_UDP;
else
return -1;
@@ -1927,6 +2439,11 @@ int sh_portchk_check ()
SH_MUTEX_UNLOCK(mutex_thread_nolog);
sh_portchk_reset_lists();
+
+#if defined(HAVE_IFADDRS_H)
+ recheck_devices();
+#endif
+
if ((0 != geteuid()) && (min_port < 1024))
{
min_port = 1024;
diff --git a/src/sh_prelude.c b/src/sh_prelude.c
index 74fda3a..d00e9b4 100644
--- a/src/sh_prelude.c
+++ b/src/sh_prelude.c
@@ -37,6 +37,7 @@
#include <stdio.h>
#include <string.h>
+#include <ctype.h>
#include <sys/types.h>
#if TIME_WITH_SYS_TIME
@@ -809,8 +810,6 @@ static int get_service_info(char *msg, idmef_alert_t *alert)
port = strtol(ptr, &end, 0);
if ( *ptr && *end == '\0' && port >= 0 && port < 65536) {
- char * tmpw;
-
if ( ! source ) {
ret = idmef_alert_new_source(alert, &source, IDMEF_LIST_APPEND);
if ( ret < 0 ) {
diff --git a/src/sh_processcheck.c b/src/sh_processcheck.c
index f5601c9..a5786f0 100644
--- a/src/sh_processcheck.c
+++ b/src/sh_processcheck.c
@@ -751,7 +751,7 @@ static short sh_processes_check (pid_t pid, short res)
#endif
#endif
-#if !defined(sun) && !defined(__sun) && !defined(__sun__)
+#if !defined(sun) && !defined(__sun) && !defined(__sun__) && !defined(__OpenBSD__) && !defined(__APPLE__)
#ifdef _POSIX_PRIORITY_SCHEDULING
struct sched_param p;
#endif
@@ -785,8 +785,9 @@ static short sh_processes_check (pid_t pid, short res)
#endif
/* sched_getparam() is broken on solaris 10, may segfault in librt
+ * also not on MacOS
*/
-#if !defined(sun) && !defined(__sun) && !defined(__sun__)
+#if !defined(sun) && !defined(__sun) && !defined(__sun__) && !defined(__OpenBSD__) && !defined(__APPLE__)
#ifdef _POSIX_PRIORITY_SCHEDULING
if (0 == sched_getparam (pid, &p))
{
diff --git a/src/sh_readconf.c b/src/sh_readconf.c
index 892be10..a37bc4e 100644
--- a/src/sh_readconf.c
+++ b/src/sh_readconf.c
@@ -33,7 +33,7 @@
#include "sh_unix.h"
#include "sh_files.h"
#include "sh_xfer.h"
-#include "sh_gpg.h"
+#include "sh_sig.h"
#include "sh_hash.h"
#include "sh_dbIO.h"
#include "sh_ignore.h"
@@ -351,8 +351,8 @@ int sh_readconf_read (void)
#if defined(SH_STEALTH) && !defined(SH_STEALTH_MICRO)
SL_TICKET fdTmp = -1;
#endif
-#if defined(WITH_GPG) || defined(WITH_PGP)
- SL_TICKET fdGpg = -1;
+#if defined(WITH_SIG)
+ SL_TICKET fdSIG = -1;
#endif
char * tmp;
@@ -368,7 +368,7 @@ int sh_readconf_read (void)
int local_file = 1;
char local_flag = 'R';
-#if defined(WITH_GPG) || defined(WITH_PGP)
+#if defined(WITH_SIG)
int signed_content = S_FALSE;
int true_content = S_FALSE;
#endif
@@ -469,8 +469,8 @@ int sh_readconf_read (void)
{
sl_write_line(fdTmp, line_in, sl_strlen(line_in));
}
-#if defined(WITH_GPG) || defined(WITH_PGP)
- if (0 == sl_strncmp(line_in, _("-----END PGP SIGNATURE-----"), 25))
+#if defined(WITH_SIG)
+ if (S_TRUE == sh_sig_data_end(line_in))
break;
#else
if (0 == sl_strncmp(line_in, _("[EOF]"), 5))
@@ -484,18 +484,18 @@ int sh_readconf_read (void)
sl_rewind (fd);
#endif
-#if defined(WITH_GPG) || defined(WITH_PGP)
+#if defined(WITH_SIG)
/* extract the data and copy to temporary file
*/
- fdGpg = sh_gpg_extract_signed(fd);
+ fdSIG = sh_sig_extract_signed(fd);
sl_close(fd);
- fd = fdGpg;
+ fd = fdSIG;
/* Validate signature of open file.
*/
- if (0 != sh_gpg_check_sign (fd, SIG_CONF))
+ if (0 != sh_sig_check_signature (fd, SIG_CONF))
{
SH_FREE(line_in);
sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_EXIT_ABORT1, sh.prg_name);
@@ -519,26 +519,19 @@ int sh_readconf_read (void)
/* Sun May 27 18:40:05 CEST 2001
*/
-#if defined(WITH_GPG) || defined(WITH_PGP)
+#if defined(WITH_SIG)
if (signed_content == S_FALSE)
{
- if (0 == sl_strcmp(line, _("-----BEGIN PGP SIGNED MESSAGE-----")))
+ if (S_TRUE == sh_sig_msg_start(line))
signed_content = S_TRUE;
else
continue;
}
- else if (true_content == S_FALSE)
- {
- if (line[0] == '\n')
- true_content = S_TRUE;
- else
- continue;
- }
- else if (signed_content == S_TRUE)
+ else /* if (signed_content == S_TRUE) */
{
- if (0 == sl_strcmp(line, _("-----BEGIN PGP SIGNATURE-----")))
+ if (S_TRUE == sh_sig_msg_end(line))
break;
- else if (0 == sl_strcmp(line, _("-----BEGIN PGP SIGNED MESSAGE-----")))
+ else if (S_TRUE == sh_sig_msg_start(line))
{
sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
_("second signed message in file"),
@@ -551,6 +544,14 @@ int sh_readconf_read (void)
aud_exit (FIL__, __LINE__,EXIT_FAILURE);
}
}
+
+ if (true_content == S_FALSE) /* continue if in header */
+ {
+ if (S_TRUE == sh_sig_msg_startdata(line))
+ true_content = S_TRUE;
+ else
+ continue;
+ }
#endif
/* Skip leading white space.
@@ -1017,6 +1018,10 @@ cfg_options ext_table[] = {
{ N_("useaclcheck"), SH_SECTION_MISC, SH_SECTION_NONE,
sh_unix_setcheckacl },
#endif
+#if !defined(SH_COMPILE_STATIC) && defined(__linux__) && defined(HAVE_AUPARSE_H) && defined(HAVE_AUPARSE_LIB)
+ { N_("setauditdflags"), SH_SECTION_MISC, SH_SECTION_NONE,
+ sh_audit_set_flags },
+#endif
{ N_("loosedircheck"), SH_SECTION_MISC, SH_SECTION_NONE,
sh_hash_loosedircheck },
{ N_("addokchars"), SH_SECTION_MISC, SH_SECTION_NONE,
@@ -1142,6 +1147,8 @@ cfg_options ext_table[] = {
sh_xfer_set_port },
{ N_("setserverinterface"), SH_SECTION_SRV, SH_SECTION_MISC,
sh_xfer_set_interface },
+ { N_("alias"), SH_SECTION_CLIENTS, SH_SECTION_NONE,
+ sh_xfer_register_alias },
{ N_("client"), SH_SECTION_CLIENTS, SH_SECTION_NONE,
sh_xfer_register_client },
#endif
diff --git a/src/sh_registry.c b/src/sh_registry.c
index 16502a6..f940cd2 100644
--- a/src/sh_registry.c
+++ b/src/sh_registry.c
@@ -349,7 +349,7 @@ static void report_missing_entry(const char * path)
char timestr[32];
struct store2db save;
- memset(&save, '\0', sizeof(struct store2db));
+ memset(&save, 0, sizeof(struct store2db));
sh_hash_db2pop (path, &save);
(void) sh_unix_gmttime (save.val1, timestr, sizeof(timestr));
@@ -681,7 +681,7 @@ int QueryKey(HKEY hKey, char * path, size_t pathlen, int isSingle)
{
struct store2db save;
- memset(&save, '\0', sizeof(struct store2db));
+ memset(&save, 0, sizeof(struct store2db));
if (tPath)
{
@@ -773,7 +773,7 @@ int QueryKey(HKEY hKey, char * path, size_t pathlen, int isSingle)
{
struct store2db save;
- memset(&save, '\0', sizeof(struct store2db));
+ memset(&save, 0, sizeof(struct store2db));
save.val0 = totalSize;
save.val1 = fTime;
@@ -840,6 +840,9 @@ int CheckThisSubkey (HKEY key, char * subkey, char * path, int isSingle,
char * newpath;
size_t len;
int retval = -1;
+
+ if (!subkey)
+ return 0;
len = strlen(path) + 1 + strlen(subkey) + 1;
newpath = SH_ALLOC(len);
@@ -933,7 +936,7 @@ int CheckThisSubkey (HKEY key, char * subkey, char * path, int isSingle,
int check_key (char * key, int isSingle)
{
HKEY topKey;
- char * subkey;
+ char * subkey = NULL;
char path[20] = "";
int pos = 0;
@@ -973,7 +976,7 @@ int check_key (char * key, int isSingle)
}
else
{
-
+ /* We bail out here if the topKey is undefined */
char * tmp = sh_util_safe_name_keepspace(key);
size_t tlen = sl_strlen(tmp);
@@ -1002,6 +1005,8 @@ int check_key (char * key, int isSingle)
}
*************************/
+ /* Returns 0 if !subkey */
+ /* cppcheck-suppress uninitvar */
return CheckThisSubkey (topKey, subkey, path, isSingle, 0);
}
diff --git a/src/sh_restrict.c b/src/sh_restrict.c
index 4e255e3..7409751 100644
--- a/src/sh_restrict.c
+++ b/src/sh_restrict.c
@@ -603,7 +603,7 @@ void Test_restrict (CuTest *tc) {
CuAssertIntEquals(tc,0,res);
CuAssertPtrNotNull(tc, sh_restrict_list);
-#if !defined(HOST_IS_CYGWIN)
+#if !defined(HOST_IS_CYGWIN) && !defined(HOST_IS_DARWIN)
res = sh_restrict_this("/bin/sh", 1000, 0755, fd);
CuAssertIntEquals(tc,1,res);
#endif
diff --git a/src/sh_sem.c b/src/sh_sem.c
index 3de83b4..66c21db 100644
--- a/src/sh_sem.c
+++ b/src/sh_sem.c
@@ -43,11 +43,12 @@ typedef enum {
exit_err = 3
} sh_estat;
-#if 0
+
/* FreeBSD 6.1 defines this in <sys/sem.h> too... */
#if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)
/* union semun is defined by including <sys/sem.h> */
#else
+#if !defined(HAVE_UNION_SEMUN)
/* according to X/OPEN we have to define it ourselves */
union semun {
int val;
@@ -57,6 +58,7 @@ union semun {
#endif
#endif
+
#define SH_SEMVMX 32767
static int get_semaphore (void)
@@ -74,8 +76,12 @@ static int get_semaphore (void)
static void sem_purge(int sem_id)
{
+ union semun tmp;
+
+ tmp.val = 0;
+
if (sem_id != -1)
- semctl(sem_id, 0, IPC_RMID, (int)0);
+ semctl(sem_id, 0, IPC_RMID, tmp);
return;
}
@@ -102,6 +108,7 @@ static int init_semaphore (int nsems)
mode_t mask;
int semid;
int errnum;
+ union semun tmp;
key_t key = ftok(DEFAULT_DATAROOT, '#');
if (key < 0)
@@ -111,11 +118,13 @@ static int init_semaphore (int nsems)
semid = semget (key, nsems, IPC_CREAT | IPC_EXCL | 0660);
errnum = errno;
umask(mask);
+
+ tmp.val = 1;
if (semid < 0)
return report_err(errnum, FIL__, __LINE__, _("semget"));
for (i=0; i<nsems; ++i)
- if (semctl (semid, i, SETVAL, (int) 1) == -1)
+ if (semctl (semid, i, SETVAL, tmp) == -1)
return report_err(errnum, FIL__, __LINE__, _("semclt"));
return semid;
}
@@ -123,18 +132,24 @@ static int init_semaphore (int nsems)
static int sem_set(int semid, int sem_no, int val)
{
+ union semun tmp;
+
+ tmp.val = val;
+
if (semid < 0)
return -1;
- if (semctl (semid, sem_no, SETVAL, val) == -1)
+ if (semctl (semid, sem_no, SETVAL, tmp) == -1)
return -1;
return 0;
}
static int sem_get(int semid, int sem_no)
{
+ union semun tmp;
if (semid < 0)
return -1;
- return semctl (semid, sem_no, GETVAL, (int) 0);
+ tmp.val = 0;
+ return semctl (semid, sem_no, GETVAL, tmp);
}
diff --git a/src/sh_sig.c b/src/sh_sig.c
new file mode 100644
index 0000000..ea8c3cb
--- /dev/null
+++ b/src/sh_sig.c
@@ -0,0 +1,1789 @@
+/* SAMHAIN file system integrity testing */
+/* Copyright (C) 1999, 2000 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>
+
+
+#if defined(WITH_SIG)
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <signal.h>
+#if defined(SH_WITH_SERVER)
+#include <pwd.h>
+#endif
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <sys/wait.h>
+
+#include <string.h>
+#ifdef HAVE_MEMORY_H
+#include <memory.h>
+#endif
+
+
+#if !defined(O_NONBLOCK)
+#if defined(O_NDELAY)
+#define O_NONBLOCK O_NDELAY
+#else
+#define O_NONBLOCK 0
+#endif
+#endif
+
+
+#include "samhain.h"
+#include "sh_utils.h"
+#include "sh_error.h"
+#include "sh_tiger.h"
+#if defined(SH_WITH_SERVER)
+#define SH_NEED_PWD_GRP 1
+#include "sh_static.h"
+#endif
+#include "sh_sig.h"
+
+int get_the_fd(SL_TICKET file_1);
+
+#if defined(WITH_GPG)
+static struct {
+ char conf_id[SH_MINIBUF+1];
+ char conf_fp[SH_MINIBUF+1];
+ char data_id[SH_MINIBUF+1];
+ char data_fp[SH_MINIBUF+1];
+} gp;
+#endif
+
+typedef struct {
+ pid_t pid;
+ FILE * pipe;
+} sh_gpg_popen_t;
+
+#define SH_SIG_OK 0
+#define SH_SIG_BAD 1
+#define SH_SIG_BADSIGN 2
+
+/* replace #if 0 by #if 1 and set an appropriate path in front of '/pdbg.'
+ * for debugging
+ */
+#if 0
+#define PDGBFILE "/pdbg."
+#endif
+
+#if defined(PDGBFILE)
+FILE * pdbg;
+FILE * pdbgc;
+#define PDBG_OPEN pdbg = fopen(PDGBFILE"main", "a")
+#define PDBG_CLOSE sl_fclose (FIL__, __LINE__, pdbg)
+#define PDBG(arg) fprintf(pdbg, "PDBG: step %d\n", arg); fflush(pdbg)
+#define PDBG_D(arg) fprintf(pdbg, "PDBG: %d\n", arg); fflush(pdbg)
+#define PDBG_S(arg) fprintf(pdbg, "PDBG: %s\n", arg); fflush(pdbg)
+
+#define PDBGC_OPEN pdbgc = fopen(PDGBFILE"child", "a")
+#define PDBGC_CLOSE sl_fclose (FIL__, __LINE__, pdbgc)
+#define PDBGC(arg) fprintf(pdbgc, "PDBG: step %d\n", arg); fflush(pdbgc)
+#define PDBGC_D(arg) fprintf(pdbgc, "PDBG: %d\n", arg); fflush(pdbgc)
+#define PDBGC_S(arg) fprintf(pdbgc, "PDBG: %s\n", arg); fflush(pdbgc)
+#else
+#define PDBG_OPEN
+#define PDBG_CLOSE
+#define PDBG(arg)
+#define PDBG_D(arg)
+#define PDBG_S(arg)
+#define PDBGC_OPEN
+#define PDBGC_CLOSE
+#define PDBGC(arg)
+#define PDBGC_D(arg)
+#define PDBGC_S(arg)
+#endif
+
+#undef FIL__
+#define FIL__ _("sh_sig.c")
+
+#if defined(SIG_HASH) || defined(SIG_KEY_HASH)
+
+typedef enum { SIG_HASH_REPORT, SIG_HASH_REPORTFULL, SIG_HASH_OTHER } checksum_flag;
+
+static int sh_sig_checksum (SL_TICKET checkfd, checksum_flag flag, const char * expected_in, const char * path)
+{
+ char * test_sig;
+ char * expected = NULL;
+ char * test_ptr1 = NULL;
+ char * test_ptr2 = NULL;
+ char wstrip1[128];
+ char wstrip2[128];
+ int i, k;
+#include "sh_sig_chksum.h"
+
+ SL_ENTER(_("sh_sig_checksum"));
+
+
+ if (flag == SIG_HASH_OTHER)
+ expected = sh_util_strdup(expected_in);
+
+ if (flag == SIG_HASH_OTHER)
+ test_sig = sh_tiger_hash_gpg (path, checkfd, TIGER_NOLIM);
+ else
+ test_sig = sh_tiger_hash_gpg (DEFAULT_SIG_PATH, checkfd, TIGER_NOLIM);
+
+ test_ptr1 = (flag == SIG_HASH_OTHER) ? strchr(expected, ':') : strchr(SIG_HASH, ':');
+ if (test_ptr1 != NULL)
+ test_ptr1 += 2;
+ else
+ test_ptr1 = (flag == SIG_HASH_OTHER) ? expected : SIG_HASH;
+
+ if (test_sig != NULL)
+ test_ptr2 = strchr(test_sig, ':');
+ if (test_ptr2 != NULL)
+ test_ptr2 += 2;
+ else
+ test_ptr2 = test_sig;
+
+ /* Tue Jun 24 23:11:54 CEST 2003 (1.7.9) -- strip whitespace
+ */
+ k = 0;
+ for (i = 0; i < 127; ++i)
+ {
+ if (test_ptr1[i] == '\0')
+ break;
+ if (test_ptr1[i] != ' ')
+ {
+ wstrip1[k] = test_ptr1[i];
+ ++k;
+ }
+ }
+ wstrip1[k] = '\0';
+
+ if (flag != SIG_HASH_OTHER)
+ {
+ for(i = 0; i < KEY_LEN; ++i)
+ {
+ if (sigchk[i] != wstrip1[i])
+ {
+ sh_error_handle(SH_ERR_SEVERE, FIL__, __LINE__, 0, MSG_E_GPG_CHK,
+ sigchk, wstrip1);
+ break;
+ }
+ }
+ }
+
+ k = 0;
+ if (test_ptr2)
+ {
+ for (i = 0; i < 127; ++i)
+ {
+ if (test_ptr2[i] == '\0')
+ break;
+ if (test_ptr2[i] != ' ')
+ {
+ wstrip2[k] = test_ptr2[i];
+ ++k;
+ }
+ }
+ }
+ wstrip2[k] = '\0';
+
+ if (0 != sl_strncmp(wstrip1, wstrip2, 127))
+ {
+ TPT(((0), FIL__, __LINE__, _("msg=<sig checksum: %s>\n"), test_sig));
+ TPT(((0), FIL__, __LINE__, _("msg=<compiled in : %s>\n"), (flag == SIG_HASH_OTHER) ? expected : SIG_HASH));
+ TPT(((0), FIL__, __LINE__, _("msg=<wstrip1 : %s>\n"), wstrip1));
+ TPT(((0), FIL__, __LINE__, _("msg=<wstrip2 : %s>\n"), wstrip2));
+ if (flag == SIG_HASH_REPORTFULL)
+ sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_GPG,
+ SIG_HASH, test_sig);
+ if (flag == SIG_HASH_OTHER)
+ dlog(1, FIL__, __LINE__, _("The compiled-in checksum of the public key %s\n(%s)\ndoes not match the actual checksum\n(%s).\nYou need to recompile with the correct checksum."), path, wstrip1, wstrip2);
+ else
+ dlog(1, FIL__, __LINE__, _("The compiled-in checksum of the signature checking binary %s\n(%s)\ndoes not match the actual checksum\n(%s).\nYou need to recompile with the correct checksum."), DEFAULT_SIG_PATH, wstrip1, wstrip2);
+ SH_FREE(test_sig);
+ if (expected)
+ SH_FREE(expected);
+ SL_RETURN((-1), _("sh_sig_checksum"));
+ }
+ SH_FREE(test_sig);
+ if (expected)
+ SH_FREE(expected);
+ SL_RETURN( (0), _("sh_sig_checksum"));
+}
+#endif
+
+struct startup_info {
+ long line;
+ char * program;
+ long uid;
+ char * path;
+ char * key_uid;
+ char * key_id;
+};
+
+static struct startup_info startInfo = { 0, NULL, 0, NULL, NULL, NULL };
+
+static void sh_sig_fill_startup (long line, char * program, long uid, char * path,
+ char * key_uid, char * key_id)
+{
+ startInfo.line = line;
+ startInfo.program = sh_util_strdup(program);
+ startInfo.uid = uid;
+ startInfo.path = sh_util_strdup(path);
+ if (key_uid)
+ startInfo.key_uid = sh_util_strdup(key_uid);
+ else
+ startInfo.key_uid = sh_util_strdup(_("(not given)"));
+ if (key_id)
+ startInfo.key_id = sh_util_strdup(key_id);
+ else
+ startInfo.key_id = sh_util_strdup(_("(not given)"));
+ return;
+}
+
+typedef enum { SIG_DATASIG, SIG_DATAONLY } extractlevel;
+
+
+static FILE * sh_sig_popen (char *const argv[], sh_gpg_popen_t *source, int fd);
+
+
+static FILE * sh_sig_popen (char *const arg[], sh_gpg_popen_t *source, int fd)
+{
+ size_t len;
+ extern int flag_err_debug;
+ int pipedes[2];
+ FILE * outf = NULL;
+ char * envp[2];
+
+#if defined(HAVE_SIG_CHECKSUM)
+ SL_TICKET checkfd = -1;
+ int myrand;
+ int i;
+#if defined(__linux__)
+ int get_the_fd(SL_TICKET);
+ char pname[128];
+ int pfd;
+ int val_return;
+#endif
+#endif
+
+ SL_ENTER(_("sh_sig_popen"));
+
+ /* use homedir of effective user
+ */
+ len = sl_strlen(sh.effective.home) + 6;
+ envp[0] = calloc(1, len); /* free() ok */
+ if (envp[0] != NULL)
+ sl_snprintf (envp[0], len, _("HOME=%s"), sh.effective.home);
+ envp[1] = NULL;
+
+ /* Create the pipe
+ */
+ if (aud_pipe(FIL__, __LINE__, pipedes) < 0)
+ {
+ if (envp[0] != NULL)
+ free(envp[0]);
+ SL_RETURN( (NULL), _("sh_gpg_popen"));
+ }
+
+ fflush (NULL);
+
+ source->pid = aud_fork(FIL__, __LINE__);
+
+ /* Failure
+ */
+ if (source->pid == (pid_t) - 1)
+ {
+ sl_close_fd(FIL__, __LINE__, pipedes[0]);
+ sl_close_fd(FIL__, __LINE__, pipedes[1]);
+ if (envp[0] != NULL)
+ free(envp[0]);
+ SL_RETURN( (NULL), _("sh_sig_popen"));
+ }
+
+ if (source->pid == (pid_t) 0)
+ {
+
+ /* child - make read side of the pipe stdout
+ */
+ if (retry_aud_dup2(FIL__, __LINE__,
+ pipedes[STDOUT_FILENO], STDOUT_FILENO) < 0)
+ {
+ TPT(((0), FIL__, __LINE__, _("msg=<dup2 on pipe failed>\n")));
+ dlog(1, FIL__, __LINE__, _("Internal error: dup2 failed\n"));
+ aud__exit(FIL__, __LINE__, EXIT_FAILURE);
+ }
+
+ /* close the pipe descriptors
+ */
+ sl_close_fd (FIL__, __LINE__, pipedes[STDIN_FILENO]);
+ sl_close_fd (FIL__, __LINE__, pipedes[STDOUT_FILENO]);
+
+ if (retry_aud_dup2(FIL__, __LINE__, fd, STDIN_FILENO) < 0)
+ {
+ TPT(((0), FIL__, __LINE__, _("msg=<dup2 on fd failed>\n")));
+ dlog(1, FIL__, __LINE__, _("Internal error: dup2 failed\n"));
+ aud__exit(FIL__, __LINE__, EXIT_FAILURE);
+ }
+
+ /* don't leak file descriptors
+ */
+ sh_unix_closeall (3, -1, S_TRUE); /* in child process */
+
+ if (flag_err_debug != S_TRUE)
+ {
+ if (NULL == freopen(_("/dev/null"), "r+", stderr))
+ {
+ dlog(1, FIL__, __LINE__, _("Internal error: freopen failed\n"));
+ aud__exit(FIL__, __LINE__, EXIT_FAILURE);
+ }
+ }
+
+
+ /* We should become privileged if SUID,
+ * to be able to read the keyring.
+ * We have checked that gpg is OK,
+ * AND that only a trusted user could overwrite
+ * gpg.
+ */
+ memset (skey, 0, sizeof(sh_key_t));
+ aud_setuid(FIL__, __LINE__, geteuid());
+
+ PDBGC_OPEN;
+ PDBGC_D((int)getuid());
+ PDBGC_D((int)geteuid());
+
+ {
+ int i = 0;
+ while (arg[i] != NULL)
+ {
+ PDBGC_S(arg[i]);
+ ++i;
+ }
+ }
+ PDBGC_CLOSE;
+
+ /* exec the program */
+
+#if defined(__linux__) && defined(HAVE_SIG_CHECKSUM)
+ /*
+ * -- emulate an fexecve with checksum testing
+ */
+ checkfd = sl_open_read(FIL__, __LINE__, DEFAULT_SIG_PATH, SL_NOPRIV);
+
+ if (0 != sh_sig_checksum(checkfd, SIG_HASH_REPORT, NULL, NULL))
+ {
+ sl_close(checkfd);
+ aud__exit(FIL__, __LINE__, EXIT_FAILURE);
+ }
+
+ pfd = get_the_fd(checkfd);
+ do {
+ val_return = dup (pfd);
+ } while (val_return < 0 && errno == EINTR);
+ pfd = val_return;
+ sl_close(checkfd);
+ /* checkfd = -1; *//* never read */
+
+ sl_snprintf(pname, sizeof(pname), _("/proc/self/fd/%d"), pfd);
+ if (0 == access(pname, R_OK|X_OK)) /* flawfinder: ignore */
+
+ {
+ fcntl (pfd, F_SETFD, FD_CLOEXEC);
+ retry_aud_execve (FIL__, __LINE__, pname, arg, envp);
+
+ dlog(1, FIL__, __LINE__, _("Unexpected error: execve %s failed\n"),
+ pname);
+ /* failed
+ */
+ aud__exit(FIL__, __LINE__, EXIT_FAILURE);
+ }
+
+ /* procfs not working, go ahead
+ */
+#endif
+
+#if defined(HAVE_SIG_CHECKSUM)
+ /* This is an incredibly ugly kludge to prevent an attacker
+ * from knowing when it is safe to slip in a fake executable
+ * between the integrity check and the execve
+ */
+ myrand = (int) taus_get ();
+
+ myrand = (myrand < 0) ? (-myrand) : myrand;
+ myrand = (myrand % 32) + 2;
+
+ for (i = 0; i < myrand; ++i)
+ {
+ checkfd = sl_open_fastread(FIL__, __LINE__,
+ DEFAULT_SIG_PATH, SL_NOPRIV);
+
+ if (0 != sh_sig_checksum(checkfd, SIG_HASH_REPORT, NULL, NULL)) {
+ aud__exit(FIL__, __LINE__, EXIT_FAILURE);
+ }
+ sl_close(checkfd);
+ }
+#endif
+
+ retry_aud_execve (FIL__, __LINE__, DEFAULT_SIG_PATH, arg, envp);
+ dlog(1, FIL__, __LINE__, _("Unexpected error: execve %s failed\n"),
+ DEFAULT_SIG_PATH);
+
+ /* failed
+ */
+ TPT(((0), FIL__, __LINE__, _("msg=<execve failed>\n")));
+ dlog(1, FIL__, __LINE__, _("Unexpected error: execve failed\n"));
+ aud__exit(FIL__, __LINE__, EXIT_FAILURE);
+ }
+
+ /* parent
+ */
+
+ if (envp[0] != NULL)
+ free(envp[0]);
+
+ sl_close_fd (FIL__, __LINE__, pipedes[STDOUT_FILENO]);
+ retry_fcntl (FIL__, __LINE__, pipedes[STDIN_FILENO], F_SETFD, FD_CLOEXEC);
+ retry_fcntl (FIL__, __LINE__, pipedes[STDIN_FILENO], F_SETFL, O_NONBLOCK);
+
+ outf = fdopen (pipedes[STDIN_FILENO], "r");
+
+ if (outf == NULL)
+ {
+ aud_kill (FIL__, __LINE__, source->pid, SIGKILL);
+ sl_close_fd (FIL__, __LINE__, pipedes[STDOUT_FILENO]);
+ waitpid (source->pid, NULL, 0);
+ source->pid = 0;
+ SL_RETURN( (NULL), _("sh_sig_popen"));
+ }
+
+ SL_RETURN( (outf), _("sh_sig_popen"));
+}
+
+
+static int sh_sig_pclose (sh_gpg_popen_t *source)
+{
+ int status = 0;
+
+ SL_ENTER(_("sh_sig_pclose"));
+
+ status = sl_fclose(FIL__, __LINE__, source->pipe);
+ if (status)
+ SL_RETURN( (-1), _("sh_sig_pclose"));
+
+ if (waitpid(source->pid, NULL, 0) != source->pid)
+ status = -1;
+
+ source->pipe = NULL;
+ source->pid = 0;
+ SL_RETURN( (status), _("sh_sig_pclose"));
+}
+
+/* This is signify specific stuff
+ */
+#if defined(WITH_SIGNIFY)
+
+#include <ctype.h>
+
+static
+int sh_signify_comp_comm(const char * line, size_t * commlen)
+{
+ /* check for a valid comment line: not exceeding 1023 chars and
+ * starting with 'untrusted comment: ' */
+ static char cmp[SH_MINIBUF];
+ static size_t cmp_len = 0;
+
+ size_t len = sl_strlen(line);
+
+ if (cmp_len == 0) {
+ sl_strlcpy(cmp, _("untrusted comment: "), sizeof(cmp));
+ cmp_len = strlen(cmp);
+ }
+
+ if (line[len-1] == '\n') {
+ /* signify will replace the '\n' with '\0', so 1024 -> 1023, which fits */
+ if (len > 1024) return S_FALSE;
+ else *commlen = len;
+ } else {
+ if (len > 1023) return S_FALSE;
+ else *commlen = (len+1);
+ }
+
+ if (len >= cmp_len && 0 == strncmp(cmp, line, cmp_len))
+ return S_TRUE;
+ return S_FALSE;
+}
+
+static const char bto64_0[] = N_("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/");
+static char bto64[65] = { '\0' };
+
+static
+int sh_signify_comp_sig(const char * line, size_t commlen)
+{
+ char cmp[128];
+ char out[128];
+ size_t len = sl_strlen(line);
+ size_t i, j = 0;
+ int padf = 0;
+
+ if (bto64[0] == '\0')
+ memcpy(bto64, _(bto64_0), 65);
+
+ if (line[len-1] == '\n') {
+ if ((len+commlen) > 2047) return S_FALSE;
+ } else {
+ if ((len+commlen) > 2046) return S_FALSE;
+ }
+
+ for (i = 0; i < len; ++i)
+ {
+ if (isspace(line[i])) {
+ /* signify will skip arbitrary space, using isspace() */
+ continue;
+ }
+ if (line[i] == '=') {
+ if (padf > 1) /* more than two padding '=' */
+ return S_FALSE;
+ else
+ ++padf;
+ } else if (!strchr(bto64, line[i]) || (line[i] == '=' && padf > 0)) {
+ return S_FALSE;
+ }
+ if (j < sizeof(cmp)) {
+ cmp[j] = line[i]; ++j;
+ }
+ }
+
+ /* signature is 'Ed' + 8 byte random + 64 bytes = 74 bytes
+ * => 1 pad byte => 75 bytes => 100 b64 bytes */
+ if (j != 100 || padf != 1)
+ return S_FALSE;
+
+ cmp[j] = '\0'; /* j == 100 */
+ sh_util_base64_dec((unsigned char *) out, (unsigned char *) cmp, j);
+ if(out[0] == 'E' && out[1] == 'd')
+ return S_TRUE;
+
+ return S_FALSE;
+}
+static
+int sh_signify_msg_start(const char * line)
+{
+ static int step = 0;
+ static size_t commlen = 0;
+
+ if (step == 0) {
+ if (S_TRUE == sh_signify_comp_comm(line, &commlen))
+ ++step;
+ }
+ else if (step == 1) {
+ if (S_TRUE == sh_signify_comp_sig(line, commlen)) {
+ ++step;
+ }
+ else {
+ step = 0; commlen = 0;
+ }
+ }
+ else if (step == 2) {
+ step = 0; commlen = 0;
+ return S_TRUE;
+ }
+ return S_FALSE;
+}
+
+static
+int sh_signify_msg_startdata(const char * line)
+{
+ (void) line;
+ return S_TRUE;
+}
+
+static
+int sh_signify_msg_end(const char * line)
+{
+ if (line[0] != '\0')
+ return S_FALSE;
+ return S_TRUE;
+}
+
+static
+int sh_signify_data_end(const char * line)
+{
+ if (line[0] == '[' && line[1] == 'E' && line[2] == 'O' &&
+ line[3] == 'F' && line[4] == ']')
+ return S_TRUE;
+ else if (line[0] != '\0')
+ return S_FALSE;
+ return S_TRUE;
+}
+
+static
+SL_TICKET sh_signify_extract_signed(SL_TICKET fd, extractlevel extract_level)
+{
+ const int fgets_buf_size = 16384;
+ FILE * fin_cp = NULL;
+ char * buf = NULL;
+ int bufc;
+ char * comment = NULL;
+ size_t commlen = 0;
+
+ int flag_comm = S_FALSE;
+ int flag_sig = S_FALSE;
+ SL_TICKET fdTmp = (-1);
+ SL_TICKET open_tmp (void);
+
+ /* extract the data and copy to temporary file
+ */
+ fdTmp = open_tmp();
+ if (SL_ISERROR(fdTmp))
+ {
+ dlog(1, FIL__, __LINE__, _("Error opening temporary file.\n"));
+ sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
+ _("Error opening temporary file."),
+ _("sh_signify_extract_signed"));
+ return -1;
+ }
+
+ fin_cp = fdopen(dup(get_the_fd(fd)), "rb");
+ buf = SH_ALLOC(fgets_buf_size);
+
+ while (NULL != fgets(buf, fgets_buf_size, fin_cp))
+ {
+
+ bufc = 0;
+ while (bufc < fgets_buf_size) {
+ if (buf[bufc] == '\n') { ++bufc; break; }
+ ++bufc;
+ }
+
+ if (flag_comm == S_FALSE)
+ {
+ if (sh_signify_comp_comm(buf, &commlen) == S_TRUE)
+ {
+ flag_comm = S_TRUE;
+ if (extract_level == SIG_DATASIG)
+ {
+ comment = sh_util_strdup(buf);
+ commlen = bufc;
+ }
+ }
+ continue;
+ }
+ else if (flag_comm == S_TRUE && flag_sig == S_FALSE)
+ {
+ if (sh_signify_comp_sig(buf, commlen) == S_TRUE)
+ {
+ flag_sig = S_TRUE;
+ if (extract_level == SIG_DATASIG)
+ {
+ sl_write(fdTmp, comment, commlen);
+ sl_write(fdTmp, buf, bufc);
+ }
+ if (comment != NULL)
+ SH_FREE(comment);
+ comment = NULL;
+ }
+ else
+ {
+ if (comment != NULL)
+ SH_FREE(comment);
+ comment = NULL; commlen = 0; flag_comm = 0;
+ }
+ continue;
+ }
+
+ if (flag_sig == S_TRUE)
+ {
+ sl_write(fdTmp, buf, bufc);
+ }
+ }
+ if (comment != NULL)
+ SH_FREE(comment);
+ sl_fclose(FIL__, __LINE__, fin_cp);
+ sl_rewind (fdTmp);
+
+#if defined(SH_DEBUG_SIGNIFY)
+ fin_cp = fdopen(dup(get_the_fd(fdTmp)), "rb");
+ FILE * fout = fopen("xxx.out", "w+");
+ while (NULL != fgets(buf, fgets_buf_size, fin_cp))
+ {
+ fputs(buf, fout);
+ }
+ fclose(fout);
+ sl_rewind(fdTmp);
+#endif
+
+ SH_FREE(buf);
+ return fdTmp;
+}
+
+
+static FILE * sh_signify_popen (sh_gpg_popen_t *source, int fd, char * homedir)
+{
+ char path[256];
+ char cc1[32];
+ char cc2[32];
+ char cc3[32];
+ char cc4[SH_PATHBUF+32];
+ char cc5[32];
+ char cc6[32];
+ char * argv[9];
+ FILE * retval = NULL;
+
+ struct stat lbuf;
+ int status_stat = 0;
+
+#ifdef HAVE_SIG_KEY_HASH
+ SL_TICKET checkfd;
+#endif
+
+
+ SL_ENTER(_("sh_signify_popen"));
+
+ sl_strlcpy (path, DEFAULT_SIG_PATH, 256);
+
+ sl_strlcpy (cc1, _("-Vem"), 32);
+ sl_strlcpy (cc2, _("/dev/null"), 32);
+
+ sl_strlcpy (cc3, _("-p"), 32);
+ sl_strlcpy (cc4, homedir, SH_PATHBUF+32);
+ sl_strlcat (cc4, _("/.signify/"), SH_PATHBUF+32);
+ sl_strlcat (cc4, SH_INSTALL_NAME, SH_PATHBUF+32);
+ sl_strlcat (cc4, _(".pub"), SH_PATHBUF+32);
+
+ /* read signed message from stdin */
+ sl_strlcpy (cc5, _("-x"), 32);
+ sl_strlcpy (cc6, _("-"), 32);
+
+ status_stat = retry_lstat(FIL__, __LINE__, cc4, &lbuf);
+ if (status_stat == -1)
+ {
+ dlog(1, FIL__, __LINE__,
+ _("Signify public key %s\ndoes not exist or is not accessible.\nPlease add the directory and put the key there\nto allow signature verification.\n"),
+ cc4);
+ sh_error_handle((-1), FIL__, __LINE__, status_stat, MSG_EXIT_ABORT1,
+ sh.prg_name);
+ aud_exit (FIL__, __LINE__, EXIT_FAILURE);
+ }
+#ifdef HAVE_SIG_KEY_HASH
+ checkfd = sl_open_read(FIL__, __LINE__, cc4, SL_YESPRIV);
+
+ if (0 != sh_sig_checksum(checkfd, SIG_HASH_OTHER, SIG_KEY_HASH, cc4))
+ {
+ sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
+ _("Checksum mismatch for signify public key"),
+ _("signify_popen"));
+ sl_close(checkfd);
+ sh_error_handle((-1), FIL__, __LINE__, status_stat, MSG_EXIT_ABORT1,
+ sh.prg_name);
+ aud_exit (FIL__, __LINE__, EXIT_FAILURE);
+ }
+ sl_close(checkfd);
+#endif
+
+ argv[0] = path;
+ argv[1] = cc1;
+ argv[2] = cc2;
+ argv[3] = cc3;
+ argv[4] = cc4;
+ argv[5] = cc5;
+ argv[6] = cc6;
+ argv[7] = NULL;
+
+ retval = sh_sig_popen(argv, source, fd);
+ SL_RETURN((retval), _("sh_signify_popen"));
+}
+
+static
+int sh_signify_check_file_sign(int fd, char * homedir)
+{
+ struct stat buf;
+ char line[256];
+ sh_gpg_popen_t source;
+ int status = 0;
+ unsigned int n_goodsig = 0;
+ unsigned int n_lines = 0;
+
+#ifdef HAVE_SIG_CHECKSUM
+ SL_TICKET checkfd;
+#endif
+
+ SL_ENTER(_("sh_signify_check_file_sign"));
+
+ /* check whether signify exists and has the correct checksum
+ */
+ TPT(((0), FIL__, __LINE__, _("msg=<Check signature>\n")));
+ TPT(((0), FIL__, __LINE__, _("msg=<signify is %s>\n"), DEFAULT_SIG_PATH));
+
+ if (0 != retry_lstat(FIL__, __LINE__, DEFAULT_SIG_PATH, &buf))
+ {
+ char errbuf[SH_ERRBUF_SIZE];
+
+ status = errno;
+ sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, status, MSG_ERR_LSTAT,
+ sh_error_message(status, errbuf, sizeof(errbuf)), DEFAULT_SIG_PATH);
+ SL_RETURN( SH_SIG_BAD, _("sh_signify_check_file_sign"));
+ }
+
+ if (0 != tf_trust_check (DEFAULT_SIG_PATH, SL_YESPRIV))
+ SL_RETURN( SH_SIG_BAD, _("sh_signify_check_file_sign"));
+
+#ifdef HAVE_SIG_CHECKSUM
+ checkfd = sl_open_read(FIL__, __LINE__, DEFAULT_SIG_PATH, SL_YESPRIV);
+
+ if (0 != sh_sig_checksum(checkfd, SIG_HASH_REPORTFULL, NULL, NULL))
+ {
+ sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
+ _("Checksum mismatch"),
+ _("signify_check_file_sign"));
+ sl_close(checkfd);
+ SL_RETURN( SH_SIG_BAD, _("sh_signify_check_file_sign"));
+ }
+ sl_close(checkfd);
+#endif
+
+ TPT(((0), FIL__, __LINE__, _("msg=<Open pipe to check signature>\n")));
+
+ fflush(NULL);
+
+ source.pipe = sh_signify_popen ( &source, fd, homedir );
+
+ if (NULL == source.pipe)
+ {
+ sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
+ _("Could not open pipe"),
+ _("signify_check_file_sign"));
+ SL_RETURN( SH_SIG_BAD, _("sh_signify_check_file_sign"));
+ }
+
+ TPT(((0), FIL__, __LINE__, _("msg=<Open pipe success>\n")));
+
+ xagain:
+
+ errno = 0;
+
+ while (NULL != fgets(line, sizeof(line), source.pipe))
+ {
+ TPT(((0), FIL__, __LINE__, _("msg=<signify out: %s>\n"), line));
+ if (line[strlen(line)-1] == '\n')
+ line[strlen(line)-1] = ' ';
+ sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, 0, MSG_E_SUBGEN,
+ line,
+ _("signify_check_file_sign"));
+
+ ++n_lines;
+
+ /* the '\n' has been replaced with ' ' for logging */
+ if (0 == sl_strcmp(_("Signature Verified "), line))
+ {
+ ++n_goodsig;
+ }
+ }
+
+ if (ferror(source.pipe) && errno == EAGAIN)
+ {
+ /* sleep 10 ms to avoid starving the gpg child writing to the pipe */
+ retry_msleep(0,10);
+ clearerr(source.pipe);
+ goto xagain;
+ }
+
+ if (0 != sh_sig_pclose (&source))
+ {
+ sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
+ _("Error on closing process pipe"),
+ _("signify_check_file_sign"));
+ n_goodsig = 0;
+ }
+
+ TPT(((0), FIL__, __LINE__, _("msg=<Close pipe>\n")));
+
+ if (n_goodsig == 1 && n_lines == 1)
+ {
+ TPT(((0), FIL__, __LINE__, _("msg=<Signature Verified>\n")));
+ SL_RETURN( SH_SIG_OK, _("sh_signature_check_file_sign"));
+ }
+ else
+ {
+ sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
+ _("Error verifying file signature"),
+ _("signify_check_file_sign"));
+ }
+ SL_RETURN( SH_SIG_BADSIGN, _("sh_signature_check_file_sign"));
+}
+
+
+int sh_signify_check_signature (SL_TICKET file, ShSigFile what)
+{
+ int status = SH_SIG_BAD;
+ int fd = 0;
+
+ static int smsg = S_FALSE;
+
+ char * homedir = sh.effective.home;
+ char * home_alloc = NULL;
+#if defined(SH_WITH_SERVER)
+ struct passwd * tempres;
+#if defined(USE_GETPWNAM_R)
+ struct passwd pwd;
+ char * buffer = SH_ALLOC(SH_PWBUF_SIZE);
+#endif
+#endif
+
+ SL_ENTER(_("sh_signify_check_sign"));
+
+ (void) what;
+
+ fd = get_the_fd(file);
+
+ if (fd < 0)
+ {
+ TPT(((0), FIL__, __LINE__, _("msg=<GPG_CHECK: FD = %d>\n"), fd));
+ dlog(1, FIL__, __LINE__,
+ _("This looks like an unexpected internal error.\n"));
+#if defined(SH_WITH_SERVER) && defined(USE_GETPWNAM_R)
+ SH_FREE(buffer);
+#endif
+ SL_RETURN( (-1), _("sh_signify_check_sign"));
+ }
+
+#if defined(SH_WITH_SERVER)
+#if defined(USE_GETPWNAM_R)
+ sh_getpwnam_r(DEFAULT_IDENT, &pwd, buffer, SH_PWBUF_SIZE, &tempres);
+#else
+ tempres = sh_getpwnam(DEFAULT_IDENT);
+#endif
+ if ((tempres != NULL) && (0 == sl_ret_euid()))
+ {
+ /* privileges not dropped yet*/
+ homedir = tempres->pw_dir;
+ }
+#endif
+
+ home_alloc = sh_util_strdup(homedir);
+
+ TPT(((0), FIL__, __LINE__, _("msg=<SIGNIFY_CHECK: FD = %d>\n"), fd));
+ status = sh_signify_check_file_sign(fd, homedir);
+
+ if (status != SH_SIG_OK)
+ {
+ TPT(((0), FIL__, __LINE__, _("msg=<Status = %d>\n"), status));
+ dlog(1, FIL__, __LINE__,
+ _("The signature of the configuration file or the file signature database\ncould not be verified. Possible reasons are:\n - signify binary (%s) not found\n - invalid signature\n - there is no keyfile in %s/.signify/%s.pub, or\n - the file is not signed - did you move /filename.sig to /filename ?\nTo create a signed file, use (remove old signatures before):\n signify|signify-openbsd -Se -s KEYNAME.sec -m FILE\n mv FILE.sig FILE\n"),
+ DEFAULT_SIG_PATH, home_alloc, SH_INSTALL_NAME);
+ SH_FREE(home_alloc);
+ SL_RETURN( (-1), _("sh_signify_check_sign"));
+ }
+
+ if (smsg == S_FALSE)
+ {
+ sh_sig_fill_startup (__LINE__,
+ sh.prg_name, sh.real.uid,
+ (sh.flag.hidefile == S_TRUE) ?
+ _("(hidden)") : file_path('C', 'R'),
+ NULL, NULL);
+ }
+ smsg = S_TRUE;
+
+ SH_FREE(home_alloc);
+ SL_RETURN(0, _("sh_signify_check_sign"));
+}
+
+/* This is GPG specific stuff
+ */
+#elif defined(WITH_GPG)
+static FILE * sh_gpg_popen (sh_gpg_popen_t *source, int fd, char * homedir)
+{
+ char path[256];
+ char cc1[32];
+ char cc2[32];
+
+ char cc0[2] = "-";
+ char cc3[32];
+ char cc4[SH_PATHBUF+32];
+ char cc5[32];
+ char * argv[9];
+ FILE * retval = NULL;
+
+
+ SL_ENTER(_("sh_gpg_popen"));
+
+ /* -- GnuPG -- */
+ sl_strlcpy (path, DEFAULT_SIG_PATH, 256);
+ sl_strlcpy (cc1, _("--status-fd"), 32);
+ sl_strlcpy (cc2, _("--verify"), 32);
+ sl_strlcpy (cc3, _("--homedir"), 32);
+ /* sl_strlcpy (cc4, sh.effective.home, SH_PATHBUF+32); */
+ sl_strlcpy (cc4, homedir, SH_PATHBUF+32);
+ sl_strlcat (cc4, _("/.gnupg"), SH_PATHBUF+32);
+ sl_strlcpy (cc5, _("--no-tty"), 32);
+
+#if defined(SH_WITH_SERVER)
+ if (0 == sl_ret_euid()) /* privileges not dropped yet */
+ {
+ struct stat lbuf;
+ int status_stat = 0;
+#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);
+ status_stat = -1;
+ }
+ if (!tempres->pw_dir || tempres->pw_dir[0] == '\0')
+ {
+ dlog(1, FIL__, __LINE__,
+ _("User %s does not have a home directory.\nPlease add the home directory for this user to your system.\n"),
+ DEFAULT_IDENT);
+ status_stat = -2;
+ }
+ if (status_stat == 0)
+ {
+ sl_strlcpy (cc4, tempres->pw_dir, SH_PATHBUF+32);
+ sl_strlcat (cc4, _("/.gnupg"), SH_PATHBUF+32);
+ status_stat = retry_lstat(FIL__, __LINE__, cc4, &lbuf);
+ if (status_stat == -1)
+ {
+ dlog(1, FIL__, __LINE__,
+ _("Gnupg directory %s for user %s\ndoes not exist or is not accessible.\nPlease add the directory and put the keyring (pubring.gpg or pubring.kbx) there\nto verify the configuration file.\n"),
+ cc4, DEFAULT_IDENT);
+ status_stat = -3;
+ }
+ }
+ if (status_stat == 0 && lbuf.st_uid != tempres->pw_uid)
+ {
+ dlog(1, FIL__, __LINE__,
+ _("Gnupg directory %s\nis not owned by user %s.\n"),
+ cc4, DEFAULT_IDENT);
+ status_stat = -4;
+ }
+ if (status_stat == 0)
+ {
+ char cc4_test[SH_PATHBUF+32];
+
+ sl_strlcpy(cc4_test, cc4, SH_PATHBUF+32);
+ sl_strlcat (cc4_test, _("/pubring.gpg"), SH_PATHBUF+32);
+
+ status_stat = retry_lstat(FIL__, __LINE__, cc4_test, &lbuf);
+ if (status_stat == -1)
+ {
+ sl_strlcpy(cc4_test, cc4, SH_PATHBUF+32);
+ sl_strlcat (cc4_test, _("/pubring.kbx"), SH_PATHBUF+32);
+
+ status_stat = retry_lstat(FIL__, __LINE__, cc4_test, &lbuf);
+ if (status_stat == -1)
+ {
+ sl_strlcpy(cc4_test, cc4, SH_PATHBUF+32);
+ sl_strlcat (cc4_test, _("/pubring.(gpg|kbx)"), SH_PATHBUF+32);
+
+ dlog(1, FIL__, __LINE__,
+ _("Gnupg public keyring %s for user %s\ndoes not exist or is not accessible.\nPlease add the directory and put the keyring (pubring.gpg or pubring.kbx) there\nto verify the configuration file.\n"),
+ cc4_test, DEFAULT_IDENT);
+ status_stat = -5;
+ }
+ }
+ }
+ if (status_stat == 0 && lbuf.st_uid != tempres->pw_uid)
+ {
+ dlog(1, FIL__, __LINE__,
+ _("Gnupg public keyring %s\nis not owned by user %s.\n"),
+ cc4, DEFAULT_IDENT);
+ status_stat = -6;
+ }
+ if (status_stat != 0)
+ {
+ sh_error_handle((-1), FIL__, __LINE__, status_stat, MSG_EXIT_ABORT1,
+ sh.prg_name);
+ aud_exit (FIL__, __LINE__, EXIT_FAILURE);
+ }
+ sl_strlcpy (cc4, tempres->pw_dir, SH_PATHBUF+32);
+ sl_strlcat (cc4, _("/.gnupg"), SH_PATHBUF+32);
+#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
+ SH_FREE(buffer);
+#endif
+ }
+#endif
+
+ argv[0] = path;
+ argv[1] = cc1;
+ argv[2] = "1";
+ argv[3] = cc2;
+ argv[4] = cc3;
+ argv[5] = cc4;
+ argv[6] = cc5;
+ argv[7] = cc0;
+ argv[8] = NULL;
+
+ retval = sh_sig_popen(argv, source, fd);
+ SL_RETURN((retval), _("sh_gpg_popen"));
+}
+
+static
+int sh_gpg_check_file_sign(int fd, char * sign_id, char * sign_fp,
+ char * homedir, ShSigFile whichfile)
+{
+ struct stat buf;
+ char line[256];
+ sh_gpg_popen_t source;
+ int have_id = BAD, have_fp = BAD, status = 0;
+ unsigned int n_newsig = 0;
+ unsigned int n_goodsig = 0;
+ unsigned int n_validsig = 0;
+
+#ifdef HAVE_SIG_CHECKSUM
+ SL_TICKET checkfd;
+#endif
+
+ SL_ENTER(_("sh_gpg_check_file_sign"));
+
+ /* check whether GnuPG exists and has the correct checksum
+ */
+ TPT(((0), FIL__, __LINE__, _("msg=<Check signature>\n")));
+ TPT(((0), FIL__, __LINE__, _("msg=<gpg is %s>\n"), DEFAULT_SIG_PATH));
+
+ if (0 != retry_lstat(FIL__, __LINE__, DEFAULT_SIG_PATH, &buf))
+ {
+ char errbuf[SH_ERRBUF_SIZE];
+
+ status = errno;
+ sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, status, MSG_ERR_LSTAT,
+ sh_error_message(status, errbuf, sizeof(errbuf)), DEFAULT_SIG_PATH);
+ SL_RETURN( SH_SIG_BAD, _("sh_gpg_check_file_sign"));
+ }
+
+ if (0 != tf_trust_check (DEFAULT_SIG_PATH, SL_YESPRIV))
+ SL_RETURN( SH_SIG_BAD, _("sh_gpg_check_file_sign"));
+
+#ifdef HAVE_SIG_CHECKSUM
+ checkfd = sl_open_read(FIL__, __LINE__, DEFAULT_SIG_PATH, SL_YESPRIV);
+
+ if (0 != sh_sig_checksum(checkfd, SIG_HASH_REPORTFULL, NULL, NULL))
+ {
+ sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
+ _("Checksum mismatch"),
+ _("gpg_check_file_sign"));
+ sl_close(checkfd);
+ SL_RETURN( SH_SIG_BAD, _("sh_gpg_check_file_sign"));
+ }
+ sl_close(checkfd);
+#endif
+
+ TPT(((0), FIL__, __LINE__, _("msg=<Open pipe to check signature>\n")));
+
+ fflush(NULL);
+
+ source.pipe = sh_gpg_popen ( &source, fd, homedir );
+
+ if (NULL == source.pipe)
+ {
+ sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
+ _("Could not open pipe"),
+ _("gpg_check_file_sign"));
+ SL_RETURN( SH_SIG_BAD, _("sh_gpg_check_file_sign"));
+ }
+
+ TPT(((0), FIL__, __LINE__, _("msg=<Open pipe success>\n")));
+
+ xagain:
+
+ errno = 0;
+
+ while (NULL != fgets(line, sizeof(line), source.pipe))
+ {
+
+ TPT(((0), FIL__, __LINE__, _("msg=<gpg out: %s>\n"), line));
+ if (line[strlen(line)-1] == '\n')
+ line[strlen(line)-1] = ' ';
+ sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, 0, MSG_E_SUBGEN,
+ line,
+ _("gpg_check_file_sign"));
+
+ if (sl_strlen(line) < 12)
+ continue;
+
+ /* Sun May 27 18:40:05 CEST 2001
+ */
+ if (0 == sl_strncmp(_("BADSIG"), &line[9], 6) ||
+ 0 == sl_strncmp(_("ERRSIG"), &line[9], 6) ||
+ 0 == sl_strncmp(_("NO_PUBKEY"), &line[9], 6) ||
+ 0 == sl_strncmp(_("NODATA"), &line[9], 6) ||
+ 0 == sl_strncmp(_("ERROR"), &line[9], 5) ||
+ 0 == sl_strncmp(_("SIGEXPIRED"), &line[9], 6))
+ {
+ if (0 == sl_strncmp(_("BADSIG"), &line[9], 6)) {
+ dlog(1, FIL__, __LINE__,
+ _("%s file is signed, but the signature is invalid."),
+ ((whichfile == SIG_CONF) ? _("Configuration") : _("Database")));
+ }
+ else if (0 == sl_strncmp(_("NO_PUBKEY"), &line[9], 6)) {
+ dlog(1, FIL__, __LINE__,
+ _("%s file is signed, but the public key to verify the signature is not in my keyring %s/.gnupg/pubring.asc."),
+ ((whichfile == SIG_CONF) ? _("Configuration") : _("Database")),
+ homedir);
+ }
+ else if (0 == sl_strncmp(_("ERRSIG"), &line[9], 6)) {
+ dlog(1, FIL__, __LINE__,
+ _("%s file is signed, but the public key to verify the signature is not in my keyring %s/.gnupg/pubring.asc."),
+ ((whichfile == SIG_CONF) ? _("Configuration") : _("Database")),
+ homedir);
+ }
+ else if (0 == sl_strncmp(_("SIGEXPIRED"), &line[9], 6)) {
+ dlog(1, FIL__, __LINE__,
+ _("%s file is signed, but the public key to verify the signature has expired."),
+ ((whichfile == SIG_CONF) ? _("Configuration") : _("Database")));
+ }
+ else if (0 == sl_strncmp(_("NODATA"), &line[9], 6)) {
+ dlog(1, FIL__, __LINE__,
+ _("%s file is not signed."),
+ ((whichfile == SIG_CONF) ? _("Configuration") : _("Database")));
+ }
+ else if (0 == sl_strncmp(_("ERROR"), &line[9], 5)) {
+ dlog(1, FIL__, __LINE__,
+ _("%s file is not correctly signed. An error occured while verifying the signature."),
+ ((whichfile == SIG_CONF) ? _("Configuration") : _("Database")));
+ }
+
+ have_fp = BAD; have_id = BAD;
+ break;
+ }
+ if (0 == sl_strncmp(_("GOODSIG"), &line[9], 7))
+ {
+ ++n_goodsig;
+ sl_strlcpy (sign_id, &line[25], SH_MINIBUF+1);
+ if (sign_id)
+ sign_id[sl_strlen(sign_id)-1] = '\0'; /* remove trailing '"' */
+ have_id = GOOD;
+ }
+ else if (0 == sl_strncmp(_("VALIDSIG"), &line[9], 8))
+ {
+ ++n_validsig;
+ strncpy (sign_fp, &line[18], 40);
+ sign_fp[40] = '\0';
+ have_fp = GOOD;
+ }
+ else if (0 == sl_strncmp(_("NEWSIG"), &line[9], 6))
+ {
+ ++n_newsig;
+ }
+
+ }
+
+ if (ferror(source.pipe) && errno == EAGAIN)
+ {
+ /* sleep 10 ms to avoid starving the gpg child writing to the pipe */
+ retry_msleep(0,10);
+ clearerr(source.pipe);
+ goto xagain;
+ }
+
+ if (0 != sh_sig_pclose (&source))
+ {
+ sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
+ _("Error on closing process pipe"),
+ _("gpg_check_file_sign"));
+ have_id = BAD;
+ }
+
+ TPT(((0), FIL__, __LINE__, _("msg=<Close pipe>\n")));
+
+ if (n_goodsig != n_validsig || n_newsig > 1 || n_goodsig > 1)
+ {
+ sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
+ _("Too many or invalid signatures"),
+ _("gpg_check_file_sign"));
+ have_id = BAD;
+ }
+
+ if (have_id == GOOD)
+ {
+ TPT(((0), FIL__, __LINE__, _("msg=<Got signator ID>\n")));
+ }
+ if (have_fp == GOOD)
+ {
+ TPT(((0), FIL__, __LINE__, _("msg=<Got fingerprint>\n")));
+ }
+
+ if (have_id == GOOD && have_fp == GOOD)
+ SL_RETURN( SH_SIG_OK, _("sh_gpg_check_file_sign"));
+ else
+ {
+ if (have_id == BAD)
+ sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
+ _("No good signature"),
+ _("gpg_check_file_sign"));
+ else
+ sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
+ _("No fingerprint for key"),
+ _("gpg_check_file_sign"));
+ SL_RETURN( SH_SIG_BADSIGN, _("sh_gpg_check_file_sign"));
+ }
+}
+
+#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && \
+ defined(HAVE_GETPWNAM_R)
+#define USE_GETPWNAM_R 1
+#endif
+
+static
+int sh_gpg_check_signature (SL_TICKET file, ShSigFile what)
+{
+ int status = SH_SIG_BAD;
+ int fd = 0;
+
+ static int smsg = S_FALSE;
+ char * tmp;
+
+ char * sig_id;
+ char * sig_fp;
+
+ char * homedir = sh.effective.home;
+#if defined(SH_WITH_SERVER)
+ struct passwd * tempres;
+#if defined(USE_GETPWNAM_R)
+ struct passwd pwd;
+ char * buffer = SH_ALLOC(SH_PWBUF_SIZE);
+#endif
+#endif
+
+#ifdef USE_FINGERPRINT
+#include "sh_gpg_fp.h"
+#endif
+
+ SL_ENTER(_("sh_gpg_check_sign"));
+
+
+ if (what == SIG_CONF)
+ fd = get_the_fd(file);
+ if (what == SIG_DATA)
+ fd = get_the_fd(file);
+
+
+ if (fd < 0)
+ {
+ TPT(((0), FIL__, __LINE__, _("msg=<GPG_CHECK: FD = %d>\n"), fd));
+ dlog(1, FIL__, __LINE__,
+ _("This looks like an unexpected internal error.\n"));
+#if defined(SH_WITH_SERVER) && defined(USE_GETPWNAM_R)
+ SH_FREE(buffer);
+#endif
+ SL_RETURN( (-1), _("sh_gpg_check_sign"));
+ }
+
+#if defined(SH_WITH_SERVER)
+#if defined(USE_GETPWNAM_R)
+ sh_getpwnam_r(DEFAULT_IDENT, &pwd, buffer, SH_PWBUF_SIZE, &tempres);
+#else
+ tempres = sh_getpwnam(DEFAULT_IDENT);
+#endif
+ if ((tempres != NULL) && (0 == sl_ret_euid()))
+ {
+ /* privileges not dropped yet*/
+ homedir = tempres->pw_dir;
+ }
+#endif
+
+ if (what == SIG_CONF)
+ {
+ TPT(((0), FIL__, __LINE__, _("msg=<GPG_CHECK: FD = %d>\n"), fd));
+ status = sh_gpg_check_file_sign(fd, gp.conf_id, gp.conf_fp, homedir, SIG_CONF);
+ TPT(((0), FIL__, __LINE__, _("msg=<CONF SIGUSR: |%s|>\n"), gp.conf_id));
+ TPT(((0), FIL__, __LINE__, _("msg=<CONF SIGFP: |%s|>\n"), gp.conf_fp));
+ sig_id = gp.conf_id; sig_fp = gp.conf_fp;
+ }
+
+ if (what == SIG_DATA)
+ {
+ TPT(((0), FIL__, __LINE__, _("msg=<GPG_CHECK: FD = %d>\n"), fd));
+ status = sh_gpg_check_file_sign(fd, gp.data_id, gp.data_fp, homedir, SIG_DATA);
+ TPT(((0), FIL__, __LINE__, _("msg=<DATA SIGUSR: |%s|>\n"), gp.data_id));
+ TPT(((0), FIL__, __LINE__, _("msg=<DATA SIGFP: |%s|>\n"), gp.data_fp));
+ sig_id = gp.data_id; sig_fp = gp.data_fp;
+ }
+
+ if (SH_SIG_OK == status)
+ {
+#ifdef USE_FINGERPRINT
+ if ((sl_strcmp(SH_GPG_FP, sig_fp) == 0))
+ {
+ int i;
+
+ for(i = 0; i < (int) sl_strlen(sig_fp); ++i) {
+ if (gpgfp[i] != sig_fp[i]) {
+ sh_error_handle(SH_ERR_SEVERE, FIL__, __LINE__, 0,
+ MSG_E_GPG_FP, gpgfp, sig_fp);
+ break; }
+ }
+
+ if (smsg == S_FALSE) {
+ tmp = sh_util_safe_name(sig_id);
+ sh_sig_fill_startup (__LINE__, sh.prg_name, sh.real.uid,
+ (sh.flag.hidefile == S_TRUE) ?
+ _("(hidden)") : file_path('C', 'R'),
+ tmp,
+ sig_fp);
+ SH_FREE(tmp); }
+ smsg = S_TRUE;
+
+#if defined(SH_WITH_SERVER) && defined(USE_GETPWNAM_R)
+ SH_FREE(buffer);
+#endif
+ SL_RETURN(0, _("sh_gpg_check_sign"));
+ }
+ else
+ {
+ /* fp mismatch */
+ dlog(1, FIL__, __LINE__,
+ _("The fingerprint of the signing key: %s\ndoes not match the compiled-in fingerprint: %s.\nTherefore the signature could not be verified.\n"),
+ sig_fp, SH_GPG_FP);
+ sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
+ _("Fingerprint mismatch"), _("gpg_check_sign"));
+ status = SH_SIG_BADSIGN;
+ }
+#else /* ifdef USE_FINGERPRINT */
+ if (smsg == S_FALSE)
+ {
+ tmp = sh_util_safe_name(sig_id);
+ sh_sig_fill_startup (__LINE__,
+ sh.prg_name, sh.real.uid,
+ (sh.flag.hidefile == S_TRUE) ?
+ _("(hidden)") : file_path('C', 'R'),
+ tmp, sig_fp);
+ SH_FREE(tmp);
+ }
+ smsg = S_TRUE;
+
+#if defined(SH_WITH_SERVER) && defined(USE_GETPWNAM_R)
+ SH_FREE(buffer);
+#endif
+
+ /* status == OK and no fp checking */
+ SL_RETURN(0, _("sh_gpg_check_sign"));
+#endif /* !ifdef USE_FINGERPRINT */
+ }
+
+ if (status != SH_SIG_OK)
+ {
+ uid_t e_uid = sl_ret_euid();
+ char * e_home = sh.effective.home;
+
+#if defined(SH_WITH_SERVER)
+#if defined(USE_GETPWNAM_R)
+ struct passwd e_pwd;
+ char * e_buffer = SH_ALLOC(SH_PWBUF_SIZE);
+ struct passwd * e_tempres;
+ sh_getpwnam_r(DEFAULT_IDENT, &e_pwd, e_buffer, SH_PWBUF_SIZE, &e_tempres);
+#else
+ struct passwd * e_tempres = sh_getpwnam(DEFAULT_IDENT);
+#endif
+
+ if ((e_tempres != NULL) && (0 == sl_ret_euid()))
+ {
+ /* privileges not dropped yet */
+ e_uid = e_tempres->pw_uid;
+ e_home = e_tempres->pw_dir;
+ }
+#endif
+ dlog(1, FIL__, __LINE__,
+ _("The signature of the configuration file or the file signature database\ncould not be verified. Possible reasons are:\n - gpg binary (%s) not found\n - invalid signature\n - the signature key is not in the private keyring of UID %d,\n - there is no keyring in %s/.gnupg, or\n - the file is not signed - did you move /filename.asc to /filename ?\nTo create a signed file, use (remove old signatures before):\n gpg -a --clearsign --not-dash-escaped FILE\n mv FILE.asc FILE\n"),
+ DEFAULT_SIG_PATH,
+ (int) e_uid, e_home);
+
+#if defined(SH_WITH_SERVER) && defined(USE_GETPWNAM_R)
+ SH_FREE(e_buffer);
+#endif
+ }
+
+ TPT(((0), FIL__, __LINE__, _("msg=<Status = %d>\n"), status));
+
+ SL_RETURN(-1, _("sh_gpg_check_sign")); /* make compiler happy */
+}
+
+static int sh_gpg_comp(const char * line, const char * cmp)
+{
+ int retval = S_FALSE;
+
+ if (line && line[0] == '-' && line[1] == '-')
+ {
+ char * dup = sh_util_strdup(line);
+ char * tmp = dup + sl_strlen( dup );
+ --tmp;
+ if (*tmp == '\n') { *tmp = '\0'; --tmp; }
+ while( (*tmp == '\t' || *tmp == ' ' || *tmp == '\r' ) && tmp >= dup ) *tmp-- = '\0';
+
+ if (0 == sl_strcmp(dup, cmp))
+ retval = S_TRUE;
+ SH_FREE(dup);
+ }
+ return retval;
+}
+
+static
+int sh_gpg_msg_start(const char * line)
+{
+ static char cmp[SH_MINIBUF];
+ static int initialized = 0;
+
+ if (initialized == 0) {
+ sl_strlcpy(cmp, _("-----BEGIN PGP SIGNED MESSAGE-----"), sizeof(cmp));
+ initialized = 1;
+ }
+ return sh_gpg_comp(line, cmp);
+}
+
+static
+int sh_gpg_msg_startdata(const char * line)
+{
+ if (line[0] == '\n')
+ return S_TRUE;
+ return S_FALSE;
+}
+
+static
+int sh_gpg_msg_end(const char * line)
+{
+ static char cmp[SH_MINIBUF];
+ static int initialized = 0;
+
+ if (initialized == 0) {
+ sl_strlcpy(cmp, _("-----BEGIN PGP SIGNATURE-----"), sizeof(cmp));
+ initialized = 1;
+ }
+ return sh_gpg_comp(line, cmp);
+}
+
+static
+int sh_gpg_sig_end(const char * line)
+{
+ static char cmp[SH_MINIBUF];
+ static int initialized = 0;
+
+ if (initialized == 0) {
+ sl_strlcpy(cmp, _("-----END PGP SIGNATURE-----"), sizeof(cmp));
+ initialized = 1;
+ }
+ return sh_gpg_comp(line, cmp);
+}
+
+static
+SL_TICKET sh_gpg_extract_signed(SL_TICKET fd, extractlevel extract_level)
+{
+ const int fgets_buf_size = 16384;
+ FILE * fin_cp = NULL;
+ char * buf = NULL;
+ int bufc;
+ int flag_pgp = S_FALSE;
+ int flag_nohead = S_FALSE;
+ SL_TICKET fdTmp = (-1);
+ SL_TICKET open_tmp (void);
+
+ /* extract the data and copy to temporary file
+ */
+ fdTmp = open_tmp();
+ if (SL_ISERROR(fdTmp))
+ {
+ dlog(1, FIL__, __LINE__, _("Error opening temporary file.\n"));
+ sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
+ _("Error opening temporary file."),
+ _("sh_gpg_extract_signed"));
+ return -1;
+ }
+
+ fin_cp = fdopen(dup(get_the_fd(fd)), "rb");
+ buf = SH_ALLOC(fgets_buf_size);
+
+ while (NULL != fgets(buf, fgets_buf_size, fin_cp))
+ {
+ bufc = 0;
+ while (bufc < fgets_buf_size) {
+ if (buf[bufc] == '\n') { ++bufc; break; }
+ ++bufc;
+ }
+
+ if (flag_pgp == S_FALSE && sh_gpg_msg_start(buf) == S_TRUE)
+ {
+ flag_pgp = S_TRUE;
+ if (extract_level == SIG_DATASIG)
+ sl_write(fdTmp, buf, bufc);
+ continue;
+ }
+
+ if (flag_pgp == S_TRUE && flag_nohead == S_FALSE)
+ {
+ /* Header finished */
+ if (buf[0] == '\n')
+ {
+ flag_nohead = S_TRUE;
+ if (extract_level == SIG_DATASIG)
+ sl_write(fdTmp, buf, 1);
+ continue;
+ }
+ /* copy these headers */
+ else if (0 == sl_strncmp(buf, _("Hash:"), 5) ||
+ 0 == sl_strncmp(buf, _("NotDashEscaped:"), 15))
+ {
+ if (extract_level == SIG_DATASIG)
+ sl_write(fdTmp, buf, bufc);
+ continue;
+ }
+ /* ignore other headers */
+ else
+ continue;
+ }
+
+ if (flag_pgp == S_TRUE && buf[0] == '\n')
+ {
+ sl_write(fdTmp, buf, 1);
+ }
+ else if (flag_pgp == S_TRUE)
+ {
+ if (extract_level == SIG_DATASIG) {
+ sl_write(fdTmp, buf, bufc);
+ }
+ else {
+ if (sh_gpg_msg_end(buf) == S_TRUE)
+ break;
+ else
+ sl_write(fdTmp, buf, bufc);
+ }
+ }
+
+ /* This is after the copy has been done. */
+ if (flag_pgp == S_TRUE && sh_gpg_sig_end(buf) == S_TRUE)
+ break;
+ }
+ SH_FREE(buf);
+ sl_fclose(FIL__, __LINE__, fin_cp);
+ sl_rewind (fdTmp);
+
+ return fdTmp;
+}
+#endif
+
+/*********************************************************************
+ *
+ * Exported functions
+ *
+ *********************************************************************/
+
+int sh_sig_check_signature (SL_TICKET file, ShSigFile what)
+{
+#if defined(WITH_GPG)
+ return sh_gpg_check_signature (file, what);
+#elif defined(WITH_SIGNIFY)
+ return sh_signify_check_signature (file, what);
+#else
+ return -1;
+#endif
+}
+
+SL_TICKET sh_sig_extract_signed(SL_TICKET fd)
+{
+#if defined(WITH_GPG)
+ return sh_gpg_extract_signed(fd, SIG_DATASIG);
+#elif defined(WITH_SIGNIFY)
+ return sh_signify_extract_signed(fd, SIG_DATASIG);
+#else
+ return -1;
+#endif
+}
+
+SL_TICKET sh_sig_extract_signed_data(SL_TICKET fd)
+{
+#if defined(WITH_GPG)
+ return sh_gpg_extract_signed(fd, SIG_DATAONLY);
+#elif defined(WITH_SIGNIFY)
+ return sh_signify_extract_signed(fd, SIG_DATAONLY);
+#else
+ return -1;
+#endif
+}
+
+int sh_sig_msg_start(const char * line)
+{
+#if defined(WITH_GPG)
+ return sh_gpg_msg_start(line);
+#elif defined(WITH_SIGNIFY)
+ return sh_signify_msg_start(line);
+#else
+ return -1;
+#endif
+}
+
+int sh_sig_msg_startdata(const char * line)
+{
+#if defined(WITH_GPG)
+ return sh_gpg_msg_startdata(line);
+#elif defined(WITH_SIGNIFY)
+ return sh_signify_msg_startdata(line);
+#else
+ return -1;
+#endif
+}
+
+int sh_sig_msg_end(const char * line)
+{
+#if defined(WITH_GPG)
+ return sh_gpg_msg_end(line);
+#elif defined(WITH_SIGNIFY)
+ return sh_signify_msg_end(line);
+#else
+ return -1;
+#endif
+}
+
+int sh_sig_data_end(const char * line)
+{
+#if defined(WITH_GPG)
+ return sh_gpg_sig_end(line);
+#elif defined(WITH_SIGNIFY)
+ return sh_signify_data_end(line);
+#else
+ return -1;
+#endif
+}
+
+void sh_sig_log_startup (void)
+{
+ if (startInfo.program != NULL)
+ {
+ sh_error_handle ((-1), FIL__, startInfo.line, 0, MSG_START_GH,
+ startInfo.program, startInfo.uid,
+ startInfo.path,
+ startInfo.key_uid, startInfo.key_id);
+ }
+ return;
+}
+
+/* #ifdef WITH_SIG */
+#endif
+
+
+
+
+
+
+
+
diff --git a/src/sh_socket.c b/src/sh_socket.c
index f4e9f56..e75433b 100644
--- a/src/sh_socket.c
+++ b/src/sh_socket.c
@@ -808,7 +808,7 @@ static int get_peer_uid(int talkfd)
#endif
#if defined(NEED_PASSWORD_AUTH)
-char * check_password(char * message, int * client_uid, int talkfd)
+char * check_password(char * message, size_t msglen, int * client_uid, int talkfd)
{
char * cmd = NULL;
char * eopw = NULL;
@@ -822,7 +822,7 @@ char * check_password(char * message, int * client_uid, int talkfd)
* message is null-terminated and >> goodpassword
*/
if (0 == strcmp(goodpassword, message) &&
- strlen(goodpassword) < (sizeof(message)/2))
+ strlen(goodpassword) < (msglen/2))
{
*client_uid = sh_socket_flaguid;
cmd = &message[strlen(goodpassword)+1];
@@ -901,7 +901,7 @@ int sh_socket_read (struct socket_cmd * srvcmd)
cmd = message;
#elif defined(NEED_PASSWORD_AUTH)
- cmd = check_password(message, &client_uid, talkfd);
+ cmd = check_password(message, sizeof(message), &client_uid, talkfd);
#else
sh_error_handle((-1), FIL__, __LINE__, errno, MSG_E_SUBGEN,
diff --git a/src/sh_srp.c b/src/sh_srp.c
index ecc757c..ab6cbcf 100644
--- a/src/sh_srp.c
+++ b/src/sh_srp.c
@@ -47,14 +47,14 @@ int big_errno = BIG_OK;
#define bignum MP_INT
-inline
+static
int big_create (bignum * a)
{
mpz_init(a);
return 0;
}
-inline
+static
int big_zerop (bignum * a)
{
mpz_t b;
@@ -68,14 +68,14 @@ int big_zerop (bignum * a)
return 1;
}
-inline
+static
int big_trunc (bignum * a, bignum * b, bignum * q, bignum *r)
{
mpz_tdiv_qr(q, r, a, b);
return 0;
}
-inline
+static
int big_exptmod (bignum * a, bignum * b, bignum * c, bignum *d)
{
mpz_powm(d, a, b, c);
@@ -118,7 +118,13 @@ char * big_string (bignum * a, int base)
if (ptr)
get_str_internal = ptr;
else
- { free(get_str_internal); get_str_internal = NULL; }
+ {
+ /* "If realloc() fails, the original block is left untouched;
+ * it is not freed or moved." */
+ /* cppcheck-suppress doubleFree */
+ free(get_str_internal);
+ get_str_internal = NULL;
+ }
}
if (get_str_internal == NULL)
{
@@ -135,34 +141,34 @@ char * big_string (bignum * a, int base)
return get_str_internal;
}
-inline
+static
int big_add(bignum * a, bignum * b, bignum * c)
{
mpz_add(c, a, b);
return 0;
}
-inline
+static
int big_sub(bignum * a, bignum * b, bignum * c)
{
mpz_sub(c, a, b);
return 0;
}
-inline
+static
int big_mul(bignum * a, bignum * b, bignum * c)
{
mpz_mul(c, a, b);
return 0;
}
-inline
+static
int big_greaterp(bignum * a, bignum * b)
{
return mpz_cmp(a, b) > 0;
}
-inline
+static
int big_set_big(bignum * a, bignum * b)
{
mpz_set(b, a);
@@ -170,7 +176,7 @@ int big_set_big(bignum * a, bignum * b)
}
-inline
+static
int big_set_string(const char * str, int base, bignum * a)
{
mpz_set_str (a, str, base);
diff --git a/src/sh_static.c b/src/sh_static.c
index 99ce783..f517b93 100644
--- a/src/sh_static.c
+++ b/src/sh_static.c
@@ -463,8 +463,9 @@ struct group * sh_getgrent(void)
int sh_initgroups(const char *user, gid_t gid)
{
FILE *grf;
- gid_t *group_list;
- int num_groups, rv;
+ gid_t *group_list = NULL;
+ size_t num_groups;
+ int rv;
char **m;
struct group group;
@@ -473,7 +474,7 @@ int sh_initgroups(const char *user, gid_t gid)
rv = -1;
/* We alloc space for 8 gids at a time. */
- if (((group_list = calloc(8,sizeof(gid_t *))) != NULL)
+ if (buff && ((group_list = calloc(8,sizeof(gid_t *))) != NULL)
&& ((grf = fopen(_PATH_GROUP, "r")) != NULL)
) {
@@ -488,14 +489,21 @@ int sh_initgroups(const char *user, gid_t gid)
for (m=group.gr_mem ; *m ; m++) {
if (!strcmp(*m, user)) {
if (!(num_groups & 7)) {
- gid_t *tmp = (gid_t *)
- realloc(group_list,
- (num_groups+8) * sizeof(gid_t *));
- if (!tmp) {
- rv = -1;
- goto DO_CLOSE;
- }
- group_list = tmp;
+ gid_t *tmp = NULL;
+ if (num_groups > (SIZE_MAX - 8)) {
+ rv = -1;
+ goto DO_CLOSE;
+ }
+ if ((num_groups+8) <= (SIZE_MAX / sizeof(gid_t *))) {
+ tmp = (gid_t *)
+ realloc(group_list,
+ (num_groups+8) * sizeof(gid_t *));
+ }
+ if (!tmp) {
+ rv = -1;
+ goto DO_CLOSE;
+ }
+ group_list = tmp;
}
group_list[num_groups++] = group.gr_gid;
break;
@@ -511,8 +519,9 @@ int sh_initgroups(const char *user, gid_t gid)
/* group_list will be NULL if initial malloc failed, which may trigger
* warnings from various malloc debuggers. */
- free(group_list);
- free(buff);
+ if (group_list) free(group_list);
+ if (buff) free(buff);
+ /* cppcheck-suppress resourceLeak */
return rv;
}
@@ -907,7 +916,7 @@ static int __searchdomains;
static char * __searchdomain[MAX_SEARCH];
#undef DEBUG
-/*#define DEBUG*/
+/* #define DEBUG */
#ifdef DEBUG
/* flawfinder: ignore *//* definition of debug macro */
@@ -999,13 +1008,15 @@ static int __length_dotted(const unsigned char *data, int offset)
return -1;
do {
-
- if (offset < INT_MAX)
+ l = data[offset];
+ if (offset < INT_MAX)
offset++;
else
return -1;
-
- l = data[offset];
+ if (!l)
+ break;
+
+ DPRINTF("l[%d] = %d\n", offset, l);
if ((l & 0xc0) == (0xc0)) {
if (offset < INT_MAX)
@@ -1022,6 +1033,7 @@ static int __length_dotted(const unsigned char *data, int offset)
} while (l);
+ DPRINTF("orig: %d now %d\n", orig_offset, offset);
return offset - orig_offset;
}
@@ -1264,7 +1276,7 @@ static int __dns_lookup(const char *name, int type, int nscount, char **nsip,
h.qdcount = 1;
h.rd = 1;
- DPRINTF("encoding header\n", h.rd);
+ DPRINTF("encoding header %d\n", h.rd);
i = __encode_header(&h, packet, PACKETSZ);
if (i < 0)
@@ -1470,6 +1482,7 @@ static void __open_etc_hosts(FILE **fp)
if ((*fp = fopen("/etc/hosts", "r")) == NULL) {
*fp = fopen("/etc/config/hosts", "r");
}
+ /* cppcheck-suppress resourceLeak */
return;
}
@@ -1545,6 +1558,9 @@ static int __read_etc_hosts_r(FILE * fp, const char * name, int type,
}
*h_errnop=HOST_NOT_FOUND;
+ if (fp == NULL) {
+ return ret;
+ }
while (fgets(buf, buflen, fp)) {
if ((cp = strchr(buf, '#')))
*cp = '\0';
@@ -1713,6 +1729,7 @@ static int sh_gethostbyname_r(const char * name,
int __nameserversXX;
char ** __nameserverXX;
+ DPRINTF("sh_gethostbyname_r: /%s/\n", name);
__open_nameservers();
*result=NULL;
@@ -1756,7 +1773,7 @@ static int sh_gethostbyname_r(const char * name,
if (buflen<256)
return ERANGE;
- strncpy(buf, name, buflen);
+ strncpy(buf, name, buflen-1);
/* First check if this is already an address */
if (inet_aton(name, in)) {
@@ -1783,7 +1800,7 @@ static int sh_gethostbyname_r(const char * name,
return TRY_AGAIN;
}
- strncpy(buf, a.dotted, buflen);
+ strncpy(buf, a.dotted, buflen-1);
free(a.dotted);
if (a.atype == T_CNAME) { /* CNAME */
@@ -1813,6 +1830,7 @@ static int sh_gethostbyname_r(const char * name,
} else {
free(packet);
*h_errnop=HOST_NOT_FOUND;
+ DPRINTF("host_not_found\n");
return TRY_AGAIN;
}
}
@@ -1829,9 +1847,9 @@ struct hostent * sh_gethostbyname(const char *name)
sizeof(struct in_addr *)*2 +
sizeof(char *)*(ALIAS_DIM) + 256/*namebuffer*/ + 32/* margin */];
struct hostent *hp;
-
+
+ DPRINTF("sh_gethostbyname: /%s/\n", name);
sh_gethostbyname_r(name, &h, buf, sizeof(buf), &hp, &h_errno);
-
return hp;
}
@@ -1890,6 +1908,7 @@ static int sh_gethostbyaddr_r (const void *addr, socklen_t len, int type,
int __nameserversXX;
char ** __nameserverXX;
+ DPRINTF("sh_gethostbyaddr_r called\n");
*result=NULL;
if (!addr)
return EINVAL;
@@ -2002,7 +2021,7 @@ static int sh_gethostbyaddr_r (const void *addr, socklen_t len, int type,
return TRY_AGAIN;
}
- strncpy(buf, a.dotted, buflen);
+ strncpy(buf, a.dotted, buflen-1);
free(a.dotted);
if (a.atype == T_CNAME) { /* CNAME */
@@ -2060,6 +2079,7 @@ struct hostent * sh_gethostbyaddr (const void *addr, socklen_t len, int type)
sizeof(char *)*(ALIAS_DIM) + 256/*namebuffer*/ + 32/* margin */];
struct hostent *hp;
+ DPRINTF("sh_gethostbyaddr called\n");
sh_gethostbyaddr_r(addr, len, type, &h, buf, sizeof(buf), &hp, &h_errno);
return hp;
diff --git a/src/sh_string.c b/src/sh_string.c
index a898dd9..58e8c06 100644
--- a/src/sh_string.c
+++ b/src/sh_string.c
@@ -643,7 +643,8 @@ sh_string * sh_string_replace(const sh_string * s,
{
len = (size_t) tlen;
- if (tlen > 0 && r->siz > (r->len + len))
+ if (tlen > 0 && r->siz > (r->len + len) &&
+ &(s->str[ovector[last]]) )
{
memcpy(p, &(s->str[ovector[last]]), (size_t)len);
p += len;
@@ -674,7 +675,8 @@ sh_string * sh_string_replace(const sh_string * s,
if (tlen > 0)
{
len = (size_t)tlen;
- if (r->siz >= (r->len + len)) {
+ if (r->siz >= (r->len + len) &&
+ &(s->str[ovector[2*i -1]]) ) {
memcpy(p, &(s->str[ovector[2*i -1]]), (size_t)len);
p += (len - 1);
r->len += (len - 1);
diff --git a/src/sh_subuid.c b/src/sh_subuid.c
new file mode 100644
index 0000000..33bf407
--- /dev/null
+++ b/src/sh_subuid.c
@@ -0,0 +1,245 @@
+/* SAMHAIN file system integrity testing */
+/* Copyright (C) 2018 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"
+
+#undef FIL__
+#define FIL__ _("sh_subuid.c")
+
+
+#include <sys/types.h>
+#include <time.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <stdlib.h>
+#include <errno.h>
+#include <limits.h>
+
+#if defined(__linux__)
+
+#include "samhain.h"
+#include "sh_unix.h"
+
+#define SH_SUBUID_FILE _("/etc/subuid")
+#define SH_SUBGID_FILE _("/etc/subgid")
+
+struct subuid_t {
+ char name[32];
+ unsigned long first;
+ unsigned long last;
+ struct subuid_t * next;
+};
+
+static time_t last_subuid = 0;
+static time_t last_subgid = 0;
+
+struct subuid_t * list_subuid = NULL;
+struct subuid_t * list_subgid = NULL;
+
+/* Check whether we need to re-read the subuid/subgid file
+ */
+static int needs_reread (char * file, time_t * last)
+{
+ int retval = S_FALSE;
+ struct stat buf;
+ int status = retry_lstat (FIL__, __LINE__, file, &buf);
+
+ if (status == 0)
+ {
+ if ((buf.st_mtime - *last) > 1)
+ {
+ *last = buf.st_mtime;
+ retval = S_TRUE;
+ }
+ }
+ else if (status && errno == ENOENT)
+ {
+ /* If there was a file make sure we attempt to re-read
+ * to zero out the list.
+ */
+ if (*last > 0) retval = S_TRUE;
+ *last = 0;
+ }
+ return retval;
+}
+
+/* free the whole list
+ */
+static void free_subordinate(struct subuid_t * head)
+{
+ struct subuid_t * prev;
+ struct subuid_t * curr = head;
+
+ while (curr)
+ {
+ prev = curr;
+ curr = curr->next;
+ SH_FREE(prev);
+ }
+ return;
+}
+
+#define NFIELDS_SUBUID 3
+
+static int get_ulong(char * str, unsigned long * result)
+{
+ char * endptr;
+
+ errno = 0;
+ *result = strtoul(str, &endptr, 0);
+ if (*str != '\0' && *endptr == '\0' && errno != ERANGE)
+ return S_TRUE;
+ return S_FALSE;
+}
+
+/* Parse a single line into name / startuid / lastuid
+ */
+static struct subuid_t * parse_subordinate(char * line)
+{
+ unsigned int nfields = NFIELDS_SUBUID;
+ size_t lengths[NFIELDS_SUBUID];
+ unsigned long start, count;
+ struct subuid_t * new;
+
+ char ** array = split_array(line, &nfields, ':', lengths);
+
+ if (nfields != NFIELDS_SUBUID)
+ { SH_FREE(array); return NULL; }
+
+ if (S_TRUE != get_ulong(array[1], &start))
+ { SH_FREE(array); return NULL; }
+ if ((S_TRUE != get_ulong(array[2], &count)) || (count == 0))
+ { SH_FREE(array); return NULL; }
+ if (lengths[0] == 0)
+ { SH_FREE(array); return NULL; }
+
+ /* we have checked that count != 0 */
+ --count;
+
+ if (start > (ULONG_MAX - count))
+ { SH_FREE(array); return NULL; }
+
+ new = SH_ALLOC(sizeof(struct subuid_t));
+ sl_strlcpy(new->name, array[0], 32);
+ new->first = start;
+ new->last = start + count; /* start+count-1, but we already did --count */
+ new->next = NULL;
+
+ SH_FREE(array);
+ return new;
+}
+
+/* (re-)read the subuid/subgid file
+ */
+static void reread_subordinate (char * file, struct subuid_t ** head_ref)
+{
+ SL_TICKET fd = (-1);
+ char line[1024];
+
+ if (*head_ref) { free_subordinate(*head_ref); *head_ref = NULL; }
+
+ fd = sl_open_read (FIL__, __LINE__, file, SL_YESPRIV);
+ if (!SL_ISERROR(fd))
+ {
+ while ( sh_unix_getline(fd, line, sizeof(line)) > 0 )
+ {
+ /* for invalid lines, NULL will be returned
+ */
+ struct subuid_t * new = parse_subordinate(line);
+
+ if (new)
+ {
+ new->next = *head_ref;
+ *head_ref = new;
+ }
+ }
+ sl_close(fd);
+ }
+ return;
+}
+
+/* Return the username for a given subuid/subgid
+ */
+static char * get_name4id (unsigned long id, struct subuid_t * head)
+{
+ struct subuid_t * cur = head;
+
+ while (cur)
+ {
+ if (id >= cur->first && id <= cur->last)
+ return cur->name;
+ cur = cur->next;
+ }
+ return NULL;
+}
+
+/***********************************************
+ *
+ * Public functions
+ *
+ ***********************************************/
+
+/* Returns username or NULL for a subuid
+ */
+char * sh_get_subuid (unsigned long subuid)
+{
+ static int init = 0;
+ static char file[256];
+
+ if (!init) { sl_strlcpy(file, SH_SUBUID_FILE, sizeof(file)); init = 1; }
+
+ if (S_TRUE == needs_reread(file, &last_subuid))
+ reread_subordinate(file, &list_subuid);
+
+ return get_name4id (subuid, list_subuid);
+}
+
+/* Returns group name or NULL for subgid
+ */
+char * sh_get_subgid (unsigned long subgid)
+{
+ static int init = 0;
+ static char file[256];
+
+ if (!init) { sl_strlcpy(file, SH_SUBGID_FILE, sizeof(file)); init = 1; }
+
+ if (S_TRUE == needs_reread(file, &last_subgid))
+ reread_subordinate(file, &list_subgid);
+
+ return get_name4id (subgid, list_subgid);
+}
+
+/* Not Linux, hence no sub(u|g)id
+ */
+#else
+
+char * sh_get_subuid (unsigned long subuid)
+{
+ (void) subuid;
+ return NULL;
+}
+
+char * sh_get_subgid (unsigned long subgid)
+{
+ (void) subgid;
+ return NULL;
+}
+
+#endif
diff --git a/src/sh_suidchk.c b/src/sh_suidchk.c
index d9cc1f9..30c397c 100644
--- a/src/sh_suidchk.c
+++ b/src/sh_suidchk.c
@@ -996,8 +996,8 @@ static void report_file (const char * tmpcat, file_type * theFile,
* putting it into a register, and avoids the 'clobbered
* by longjmp' warning. And no, 'volatile' proved insufficient.
*/
-static void * sh_dummy_dirlist = NULL;
-static void * sh_dummy_itmp = NULL;
+void * sh_dummy_idirlist = NULL;
+void * sh_dummy_itmp = NULL;
static
@@ -1027,8 +1027,8 @@ int sh_suidchk_check_internal (char * iname)
/* Take the address to keep gcc from putting it into a register.
* Avoids the 'clobbered by longjmp' warning.
*/
- sh_dummy_dirlist = (void*) &dirlist;
- sh_dummy_itmp = (void*) &tmp;
+ sh_dummy_idirlist = (void*) &dirlist;
+ sh_dummy_itmp = (void*) &tmp;
if (iname == NULL)
{
@@ -1145,7 +1145,7 @@ int sh_suidchk_check_internal (char * iname)
(void) retry_msleep((int)((FileLimTotal/(FileLimNow-FileLimStart))/
ShSuidchkFps) , 0);
}
-
+
status = (int) retry_lstat(FIL__, __LINE__, tmpcat, &buf);
if (status != 0)
@@ -1185,6 +1185,7 @@ int sh_suidchk_check_internal (char * iname)
/* fs is a STATIC string or NULL
*/
fs = filesystem_type (tmpcat, tmpcat, &buf);
+
if (fs != NULL
#ifndef SH_SUIDTESTDIR
&&
@@ -1301,6 +1302,7 @@ int sh_suidchk_check_internal (char * iname)
{
/* Running init. Report on files detected.
*/
+ sh_dbIO_rootfs_strip(theFile->fullpath);
sh_dbIO_data_write (theFile, fileHash); /* no call to sh_error_handle */
SH_MUTEX_LOCK(mutex_thread_nolog);
sh_error_handle ((-1), FIL__, __LINE__,
@@ -2210,6 +2212,7 @@ filesystem_type (char * path, char * relpath, struct stat * statp)
}
current_dev = statp->st_dev;
current_fstype = filesystem_type_uncached (path, relpath, statp);
+
return current_fstype;
}
@@ -2231,7 +2234,7 @@ filesystem_type_uncached (path, relpath, statp)
static char my_tmp_type[64];
#endif
-#ifdef FSTYPE_MNTENT /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
+#ifdef FSTYPE_MNTENT /* 4.3BSD, SunOS, HP-UX, Dynix, Irix,Linux */
char *table = MOUNTED;
FILE *mfp;
struct mntent *mnt;
@@ -2293,12 +2296,14 @@ filesystem_type_uncached (path, relpath, statp)
char errmsg[256];
volatile int elevel = SH_ERR_ERR;
size_t tlen = strlen(mnt->mnt_dir);
-
+
if (tlen >= 6 && 0 == strcmp(&((mnt->mnt_dir)[tlen-6]), _("/.gvfs")))
elevel = SH_ERR_NOTICE;
else if (tlen >= 5 && 0 == strcmp(&((mnt->mnt_dir)[tlen-5]), _("/gvfs")))
elevel = SH_ERR_NOTICE;
-
+ else if (0 == strcmp (mnt->mnt_type, _("tracefs")))
+ elevel = SH_ERR_NOTICE;
+
sl_snprintf(errmsg, sizeof(errmsg), _("stat(%s) failed"),
mnt->mnt_dir);
SH_MUTEX_LOCK(mutex_thread_nolog);
@@ -2306,7 +2311,7 @@ filesystem_type_uncached (path, relpath, statp)
errmsg,
_("filesystem_type_uncached") );
SH_MUTEX_UNLOCK(mutex_thread_nolog);
- return NULL;
+ continue;
}
dev = disk_stats.st_dev;
}
diff --git a/src/sh_tiger0.c b/src/sh_tiger0.c
index aea8158..8a7ec17 100644
--- a/src/sh_tiger0.c
+++ b/src/sh_tiger0.c
@@ -378,7 +378,7 @@ sh_word32 * sh_tiger_hash_val (const char * filename, TigerType what,
#ifdef TIGER_DBG
ncount = 0;
#endif
- sl_memset(bbuf, 0, 56 );
+ memset(bbuf, 0, 56 );
}
#ifdef TIGER_DBG
@@ -401,8 +401,8 @@ sh_word32 * sh_tiger_hash_val (const char * filename, TigerType what,
tiger_dbg (res, 7, nblocks, ncount);
#endif
- sl_memset (bbuf, '\0', sizeof(bbuf));
- sl_memset (buffer, '\0', sizeof(buffer));
+ memset (bbuf, 0, sizeof(bbuf));
+ memset (buffer, 0, sizeof(buffer));
if (what == TIGER_FILE)
(void) sl_close (fd);
@@ -1020,8 +1020,8 @@ char * sh_tiger_md5_hash (char * filename, TigerType what,
/*@-bufferoverflowhigh -usedef@*/
for (cnt = 0; cnt < 16; ++cnt)
- sprintf (&outbuf[cnt*2], _("%02X"), /* known to fit */
- (unsigned int) md5buffer[cnt]);
+ sl_snprintf (&outbuf[cnt*2], 3, _("%02X"), /* known to fit */
+ (unsigned int) md5buffer[cnt]);
/*@+bufferoverflowhigh +usedef@*/
for (cnt = 32; cnt < KEY_LEN; ++cnt)
outbuf[cnt] = '0';
@@ -1584,7 +1584,7 @@ static char * sh_tiger_sha1_hash (char * filename, TigerType what,
/*@-bufferoverflowhigh -usedef@*/
for (cnt = 0; cnt < 20; ++cnt)
- sprintf (&outbuf[cnt*2], _("%02X"), /* known to fit */
+ sl_snprintf (&outbuf[cnt*2], 3, _("%02X"), /* known to fit */
(unsigned int) sha1buffer[cnt]);
/*@+bufferoverflowhigh +usedef@*/
for (cnt = 40; cnt < KEY_LEN; ++cnt)
diff --git a/src/sh_tiger1_64.c b/src/sh_tiger1_64.c
index 9218d8a..d85a115 100644
--- a/src/sh_tiger1_64.c
+++ b/src/sh_tiger1_64.c
@@ -139,7 +139,7 @@ static /*volatile*/ const word64 XOR_CONST2=0x0123456789ABCDEFLL;
#define roundend(a,b,c,x) \
: "+r" (a), "+r" (b), "+r" (c) \
- : "r" (a), "r" (b), "r" (c), "m" (x), "r" (&tiger_table),\
+ : "g" (a), "g" (b), "g" (c), "m" (x), "r" (&tiger_table),\
"i" (MASK0), "i" (MASK8), "i" (MASK16), "r" (MASK32), "r" (MASK40), "r" (MASK48) \
: "3", "%rax","%rbx","%rcx","%rdx","%rsi", "%edi", "%r8" );
diff --git a/src/sh_tools.c b/src/sh_tools.c
index 6485a58..09677b6 100644
--- a/src/sh_tools.c
+++ b/src/sh_tools.c
@@ -69,7 +69,7 @@
#define FD_SETSIZE 32
#endif
#ifndef FD_ZERO
-#define FD_ZERO(p) memset((char *)(p), '\0', sizeof(*(p)))
+#define FD_ZERO(p) memset((char *)(p), 0, sizeof(*(p)))
#endif
@@ -134,7 +134,7 @@ int sh_tools_iface_is_present(char *str)
struct addrinfo hints;
int res;
- memset (&hints, '\0', sizeof (hints));
+ memset (&hints, 0, sizeof (hints));
hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
hints.ai_socktype = SOCK_STREAM;
res = getaddrinfo (str, _("2543"), &hints, &ai);
@@ -179,7 +179,7 @@ int sh_tools_iface_is_present(char *str)
struct sockaddr_in sin;
int sd;
- memset(&sin, '\0', sizeof(sin));
+ memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
if (inet_aton(str, &(sin.sin_addr)))
{
@@ -187,6 +187,7 @@ int sh_tools_iface_is_present(char *str)
if (-1 == (sd = socket(AF_INET, SOCK_STREAM, 0)))
{
+ /* cppcheck-suppress resourceLeak */
return 0;
}
@@ -863,6 +864,7 @@ int connect_port (char * address, int port,
{
if (tools_debug)
fputs(_("-03- cached\n"), stderr);
+ /* cppcheck-suppress uninitStructMember */
fd = socket(ss.ss_family, SOCK_STREAM, 0);
if (fd < 0)
{
@@ -878,8 +880,9 @@ int connect_port (char * address, int port,
if (fail != (-1))
{
+ /* cppcheck-suppress uninitStructMember */
int addrlen = SH_SS_LEN(ss);
-
+
if ( retry_connect(FIL__, __LINE__, fd,
sh_ipvx_sockaddr_cast(&ss), addrlen) < 0)
{
@@ -911,7 +914,7 @@ int connect_port (char * address, int port,
if (tools_debug)
fputs(_("-03- not cached\n"), stderr);
- memset (&hints, '\0', sizeof (hints));
+ memset (&hints, 0, sizeof (hints));
hints.ai_flags = AI_ADDRCONFIG;
#if defined(AI_CANONNAME)
hints.ai_flags |= AI_CANONNAME;
@@ -1382,6 +1385,7 @@ void sh_tools_probe_reset()
return;
}
+#ifdef SH_ENCRYPT
static int probe_ok(int flag)
{
(void) flag;
@@ -1389,6 +1393,7 @@ static int probe_ok(int flag)
return S_TRUE;
return S_FALSE;
}
+#endif
static unsigned char probe_header_set(unsigned char protocol)
{
@@ -1440,6 +1445,7 @@ unsigned char sh_tools_probe_store(unsigned char protocol, int * probe_flag)
return protocol;
}
+#ifdef SH_ENCRYPT
static int probe_ok(int flag)
{
if ((flag & SH_PROTO_IVA) != 0)
@@ -1448,6 +1454,8 @@ static int probe_ok(int flag)
}
#endif
+#endif
+
void get_header (unsigned char * head, unsigned long * bytes, char * u)
{
@@ -1664,10 +1672,10 @@ char * sh_tools_makePack (unsigned char * header, int flag,
if ((i_blk*16) > payload_size && !oflow)
{
- memset(&full_ret[16+payload_size], '\0', (i_blk*16) - payload_size);
+ memset(&full_ret[16+payload_size], 0, (i_blk*16) - payload_size);
payload_size = i_blk * 16;
}
- memset(&full_ret[16+payload_size], '\0', i_epad*16);
+ memset(&full_ret[16+payload_size], 0, i_epad*16);
/* rewrite header
*/
@@ -2071,7 +2079,7 @@ char * get_client_uuid_file (const char * peer, unsigned long * length, const ch
#endif
-#if defined(SH_WITH_CLIENT) || defined(SH_WITH_SERVER) || defined(SH_STEALTH) || defined(WITH_GPG) || defined(WITH_PGP)
+#if defined(SH_WITH_CLIENT) || defined(SH_WITH_SERVER) || defined(SH_STEALTH) || defined(WITH_SIG)
/* --------- secure temporary file ------------ */
diff --git a/src/sh_unix.c b/src/sh_unix.c
index c383bef..bb08dc2 100644
--- a/src/sh_unix.c
+++ b/src/sh_unix.c
@@ -82,7 +82,7 @@
#define FD_SETSIZE 32
#endif
#ifndef FD_ZERO
-#define FD_ZERO(p) memset((char *)(p), '\0', sizeof(*(p)))
+#define FD_ZERO(p) memset((char *)(p), 0, sizeof(*(p)))
#endif
@@ -513,7 +513,7 @@ void sh_unix_sigexit (int mysignal)
{
++immediate_exit_normal;
if ((skey != NULL) && (immediate_exit_normal == 2))
- memset (skey, '\0', sizeof(sh_key_t));
+ memset (skey, 0, sizeof(sh_key_t));
if (immediate_exit_normal == 2)
{
int val_return;
@@ -578,7 +578,7 @@ void sh_unix_sigexit_fast (int mysignal)
#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));
+ memset (skey, 0, sizeof(sh_key_t));
if (immediate_exit_fast < 2)
safe_logger (mysignal, 0, NULL);
raise(SIGKILL);
@@ -590,7 +590,7 @@ void sh_unix_sigexit_fast (int mysignal)
{
++immediate_exit_fast;
if (skey != NULL)
- memset (skey, '\0', sizeof(sh_key_t));
+ memset (skey, 0, sizeof(sh_key_t));
close_ipc ();
safe_logger (mysignal, 0, NULL);
do {
@@ -630,7 +630,7 @@ void sh_unix_sigexit_fast (int mysignal)
sh.prg_name, sh_sig_msg);
if (skey != NULL)
- memset (skey, '\0', sizeof(sh_key_t));
+ memset (skey, 0, sizeof(sh_key_t));
close_ipc ();
do {
@@ -1209,6 +1209,8 @@ int tf_trust_check (const char * file, int mode)
int status;
int level;
uid_t ff_euid = (uid_t) -1;
+ uid_t baduid;
+ gid_t badgid;
SL_ENTER(_("tf_trust_check"));
@@ -1255,11 +1257,14 @@ int tf_trust_check (const char * file, int mode)
else
level = SH_ERR_ERR;
- tmp = sh_util_safe_name (file);
- p = sl_trust_errfile();
+ tmp = sh_util_safe_name (file);
+ p = sh_util_strdup(sl_trust_errfile());
+ baduid = sl_trust_baduid();
+ badgid = sl_trust_badgid();
+
if (p && *p != '\0')
{
- tmp2 = sh_util_safe_name (sl_trust_errfile());
+ tmp2 = sh_util_safe_name (p);
sh_error_handle(level, FIL__, __LINE__, status, MSG_E_TRUST2,
sl_error_string(status), tmp, tmp2);
SH_FREE(tmp2);
@@ -1269,7 +1274,6 @@ int tf_trust_check (const char * file, int mode)
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 ||
@@ -1281,43 +1285,37 @@ int tf_trust_check (const char * file, int mode)
_("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);
+ (p) ? p : _("(null)"), 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);
+ (UID_CAST)baduid, (p) ? p : _("(null)"), 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);
+ (p) ? p : _("(null)"), tmp, (UID_CAST)badgid,
+ (UID_CAST)baduid);
break;
default:
break;
}
-
+ SH_FREE(tmp);
+ if (p) SH_FREE(p);
SL_RETURN((-1), _("tf_trust_check"));
}
+ else {
+ SH_FREE(tmp);
+ if (p) SH_FREE(p);
+ }
}
SL_RETURN((0), _("tf_trust_check"));
@@ -2342,11 +2340,11 @@ char * t_zone(const time_t * xx)
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 */
+ sl_snprintf (tz, sizeof(tz), _("%+03d%02d"), hh, mm); /* known to fit */
}
else
{
- sprintf (tz, _("%+03d%02d"), 0, 0);
+ sl_snprintf (tz, sizeof(tz), _("%+03d%02d"), 0, 0);
}
SL_RETURN(tz, _("t_zone"));
}
@@ -2484,6 +2482,7 @@ char * sh_unix_time (time_t thetime, char * buffer, size_t len)
sh_error_handle ((-1), FIL__, __LINE__, error_num,
MSG_E_NET, errmsg, error_call,
_("time"), sh.srvtime.name);
+ errflag = error_num;
fail = 1;
}
@@ -2828,7 +2827,9 @@ static char * sh_userid_get (uid_t id, int which, char * out, size_t len)
}
/* --------- end caching code --------- */
-
+
+#include "sh_subuid.h"
+
char * sh_unix_getUIDname (int level, uid_t uid, char * out, size_t len)
{
struct passwd * tempres;
@@ -2864,21 +2865,10 @@ char * sh_unix_getUIDname (int level, uid_t uid, char * out, size_t len)
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)
+ /* case 1: we have it
+ */
+ if (tempres && tempres->pw_name != NULL)
{
sl_strlcpy(out, tempres->pw_name, len);
@@ -2889,18 +2879,37 @@ char * sh_unix_getUIDname (int level, uid_t uid, char * out, size_t len)
#endif
SL_RETURN( out, _("sh_unix_getUIDname"));
- }
- else
+ }
+
+#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R)
+ SH_FREE(buffer);
+#endif
+
+ if (tempres == NULL)
{
+ char * pwname = sh_get_subuid ((unsigned long) uid);
+
+ if (pwname)
+ {
+ sl_strlcpy(out, pwname, len);
+ sh_userid_add(uid, out, CACHE_UID);
+ SL_RETURN( out, _("sh_unix_getUIDname"));
+ }
+
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
+ _("getpwuid"), (long) uid, _("completely missing"));
+ sh_userid_add(uid, NULL, CACHE_UID);
SL_RETURN( NULL, _("sh_unix_getUIDname"));
}
- /* notreached */
+
+
+ /* getwpuid returns struct, but no pw_name
+ */
+ sh_error_handle (level, FIL__, __LINE__, EINVAL, MSG_E_PWNULL,
+ sh_error_message(status, errbuf, sizeof(errbuf)),
+ _("getpwuid"), (long) uid, _("pw_user"));
+ SL_RETURN( NULL, _("sh_unix_getUIDname"));
}
char * sh_unix_getGIDname (int level, gid_t gid, char * out, size_t len)
@@ -2960,21 +2969,7 @@ char * sh_unix_getGIDname (int level, gid_t gid, char * out, size_t len)
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)
+ if (tempres && tempres->gr_name != NULL)
{
sl_strlcpy(out, tempres->gr_name, len);
@@ -2986,19 +2981,33 @@ char * sh_unix_getGIDname (int level, gid_t gid, char * out, size_t len)
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);
+ SH_FREE(buffer);
#endif
+ if (tempres == NULL)
+ {
+ char * grname = sh_get_subgid ((unsigned long) gid);
+
+ if (grname)
+ {
+ sl_strlcpy(out, grname, len);
+ sh_userid_add((uid_t)gid, out, CACHE_GID);
+ SL_RETURN( out, _("sh_unix_getGIDname"));
+ }
+
+ sh_error_handle (level, FIL__, __LINE__, EINVAL, MSG_E_GRNULL,
+ sh_error_message(status, errbuf, sizeof(errbuf)),
+ _("getgrgid"), (long) gid, _("completely missing"));
+ sh_userid_add(gid, NULL, CACHE_GID);
SL_RETURN( NULL, _("sh_unix_getGIDname"));
}
- /* notreached */
+
+ sh_error_handle (level, FIL__, __LINE__, EINVAL, MSG_E_GRNULL,
+ sh_error_message(status, errbuf, sizeof(errbuf)),
+ _("getgrgid"), (long) gid, _("gr_name"));
+ SL_RETURN( NULL, _("sh_unix_getGIDname"));
}
int sh_unix_getUser ()
@@ -3067,7 +3076,7 @@ int sh_unix_getUser ()
/* notreached */
}
-
+/* return >0 on success, -1 on EOF */
int sh_unix_getline (SL_TICKET fd, char * line, int sizeofline)
{
register int count;
@@ -3593,8 +3602,10 @@ int sh_check_rotated_log (const char * path,
retval = S_TRUE;
}
}
- SH_FREE(rotated_file);
}
+ if (rotated_file) {
+ SH_FREE(rotated_file);
+ }
}
return retval;
}
@@ -3793,8 +3804,8 @@ int sh_unix_setcheckacl (const char * c)
static void * sh_dummy_filename;
-static void * sh_dummy_tmp;
-static void * sh_dummy_tmp2;
+void * sh_dummy_tmp;
+void * sh_dummy_tmp2;
int sh_unix_getinfo (int level, const char * filename, file_type * theFile,
char * fileHash, int policy)
@@ -3894,6 +3905,7 @@ int sh_unix_getinfo (int level, const char * filename, file_type * theFile,
if (errno == EBADF && try == 0) /* obsolete, but we keep this, just in case */
{
+ /* cppcheck-suppress syntaxError */
++try;
goto try_again;
}
@@ -4593,7 +4605,7 @@ int sh_unix_lock (char * lockfile, char * flag)
SL_ENTER(_("sh_unix_lock"));
- sprintf (myPid, "%ld\n", (long) sh.pid); /* known to fit */
+ sl_snprintf (myPid, sizeof(myPid), "%ld\n", (long) sh.pid); /* known to fit */
if (flag == NULL) /* PID file, check for directory */
{
@@ -4861,8 +4873,8 @@ int sh_unix_file_exists(char * path)
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"));
+
+ SL_RETURN( S_FALSE, _("sh_unix_file_exists"));
}
@@ -4877,10 +4889,10 @@ int sh_unix_device_readable(int fd)
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) )
+ 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"));
+
+ SL_RETURN( (-1), _("sh_unix_device_readable"));
}
static char preq[16];
@@ -5397,6 +5409,7 @@ unsigned long first_hex_block(SL_TICKET fd, unsigned long * max);
int sh_unix_getline_stealth (SL_TICKET fd, char * str, int len)
{
int add_off = 0, llen;
+ unsigned long bread;
static unsigned long off_data = 0;
static unsigned long max_data = 0;
static unsigned long bytes_read = 0;
@@ -5444,8 +5457,13 @@ int sh_unix_getline_stealth (SL_TICKET fd, char * str, int len)
/* --- Read one line. ---
*/
- add_off = hideout_hex_block(fd, (unsigned char *) str, len, &bytes_read);
- off_data += add_off;
+ add_off = hideout_hex_block(fd, (unsigned char *) str, len, &bread);
+ if (add_off > 0)
+ off_data += add_off;
+ bytes_read += bread;
+
+ if (bread == 0 || add_off <= 0) /* EOF */
+ str[0] = '\0';
llen = sl_strlen(str);
SL_RETURN(llen, _("sh_unix_getline_stealth"));
@@ -5467,6 +5485,8 @@ int hideout_hex_block(SL_TICKET fd, unsigned char * str, int len,
ASSERT_RET((len > 1), _("len > 1"), (0));
+ str[0] = '\0';
+ *bytes_read = 0;
--len;
i = 0;
@@ -5484,14 +5504,17 @@ int hideout_hex_block(SL_TICKET fd, unsigned char * str, int len,
c = ' ';
do {
do {
+ errno = 0;
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
+ else if (num == 0) {
SL_RETURN((-1), _("hideout_hex_block"));
+ }
+ else {
+ SL_RETURN((-1), _("hideout_hex_block"));
+ }
} while (c == '\n' || c == '\t' || c == '\r' ||
c == ' ');
}
@@ -5513,8 +5536,10 @@ int hideout_hex_block(SL_TICKET fd, unsigned char * str, int len,
if (i != 0)
str[i] = '\0';
- else
+ else if (str[0] == '\n')
str[i+1] = '\0'; /* keep newline and terminate */
+ else
+ str[0] = '\0';
retval += here;
*bytes_read += (bread/8);
diff --git a/src/sh_utils.c b/src/sh_utils.c
index 4a162c2..204b131 100644
--- a/src/sh_utils.c
+++ b/src/sh_utils.c
@@ -826,12 +826,14 @@ static char * sh_util_hmac_tiger (char * hexkey,
for (i = 0; i < (KEY_LEN/8); ++i)
copy_four ( (unsigned char *) &(cc[i]), h1[i]);
+ /* cppcheck-suppress uninitvar */
h2 = sh_tiger_hash_uint32 ( inner, TIGER_DATA,
(unsigned long) KEY_BLOCK+textlen,
kbuf, KEY_BYT/sizeof(UINT32));
for (i = KEY_LEN/8; i < (KEY_LEN/4); ++i)
copy_four ( (unsigned char *) &(cc[i]), h2[i - (KEY_LEN/8)]);
+ /* cppcheck-suppress uninitvar */
SH_FREE(inner);
(void) sh_tiger_hash ((char *) &cc[0],
@@ -1087,7 +1089,7 @@ UINT32 taus_get ()
res_num = 1;
SH_MUTEX_UNLOCK_UNSAFE(mutex_skey);
- memset(taus_svec, '\0', TAUS_SAMPLE * sizeof(UINT32));
+ memset(taus_svec, 0, TAUS_SAMPLE * sizeof(UINT32));
return retval;
}
@@ -1243,9 +1245,10 @@ int sh_util_set_newkey (const char * new_in)
return -1;
}
- if (NULL == (new = calloc(1,strlen(new_in) + 1)))
+ len = strlen(new_in) + 1;
+ if (NULL == (new = calloc(1, len)))
goto bail_mem;
- sl_strncpy(new, new_in, strlen(new_in) + 1);
+ memcpy(new, new_in, len);
key = new;
len = strlen(new);
@@ -2200,6 +2203,7 @@ char * sh_util_strconcat (const char * arg1, ...)
else
SL_RETURN(NULL, _("sh_util_strconcat"));
+ /* cppcheck-suppress uninitvar */
strnew[0] = '\0';
(void) sl_strlcpy (strnew, arg1, length + 2);
diff --git a/src/sh_utmp.c b/src/sh_utmp.c
index 5c72209..444779b 100644
--- a/src/sh_utmp.c
+++ b/src/sh_utmp.c
@@ -140,41 +140,30 @@ SH_MUTEX_EXTERN(mutex_thread_nolog);
#ifdef HAVE_UTMPX_H
-#ifndef _PATH_UTMP
-#ifdef UTMPX_FILE
-#define _PATH_UTMP UTMPX_FILE
-#else
-#error You must define UTMPX_FILE in the file config.h
-#endif
-#endif
-#ifndef _PATH_WTMP
-#ifdef WTMPX_FILE
-#define _PATH_WTMP WTMPX_FILE
+#if defined(_PATH_UTMPX)
+#define SH_PATH_UTMP _PATH_UTMPX
+#elif defined(UTMPX_FILE)
+#define SH_PATH_UTMP UTMPX_FILE
+#elif defined(_PATH_UTMP)
+#define SH_PATH_UTMP _PATH_UTMP
#else
-#error You must define WTMPX_FILE in the file config.h
-#endif
+#error You must define UTMPX_FILE in the file config.h
#endif
#else
-#ifndef _PATH_UTMP
-#ifdef UTMP_FILE
-#define _PATH_UTMP UTMP_FILE
+#if defined(_PATH_UTMP)
+#define SH_PATH_UTMP _PATH_UTMP
+#elif defined(UTMP_FILE)
+#define SH_PATH_UTMP UTMP_FILE
#else
#error You must define UTMP_FILE in the file config.h
#endif
-#endif
-#ifndef _PATH_WTMP
-#ifdef WTMP_FILE
-#define _PATH_WTMP WTMP_FILE
-#else
-#error You must define WTMP_FILE in the file config.h
-#endif
-#endif
#endif
typedef struct log_user {
+ time_t last_checked;
char ut_tty[UT_LINESIZE+1];
char name[UT_NAMESIZE+1];
char ut_host[UT_HOSTSIZE+1];
@@ -183,18 +172,12 @@ typedef struct log_user {
struct log_user * next;
} blah_utmp;
-#ifdef HAVE_UTTYPE
-static char terminated_line[UT_HOSTSIZE];
-#endif
-
-static char * mode_path[] = { _PATH_WTMP, _PATH_WTMP, _PATH_UTMP };
-
-static struct SH_UTMP_S save_utmp;
+static char * utmp_path = SH_PATH_UTMP;
static void sh_utmp_logout_morechecks(struct log_user * user);
static void sh_utmp_login_morechecks(struct SH_UTMP_S * ut);
-static void sh_utmp_addlogin (struct SH_UTMP_S * ut);
-static void sh_utmp_check_internal(int mode);
+static void sh_utmp_checklogin (struct SH_UTMP_S * ut, time_t start_read);
+static void sh_utmp_check_internal();
static int ShUtmpLoginSolo = SH_ERR_INFO;
static int ShUtmpLoginMulti = SH_ERR_WARN;
@@ -257,12 +240,18 @@ static void set_defaults(void)
return;
}
+#if defined(HAVE_UTMPX_H) && defined(HAVE_GETUTXENT)
+#define USE_SETUTENT 1
+#elif defined(HAVE_GETUTENT)
+#define USE_SETUTENT 1
+#endif
-#if defined (HAVE_SETUTENT) && defined (USE_SETUTENT)
-#ifdef HAVE_UTMPX_H
+#if defined (USE_SETUTENT)
-#define sh_utmp_utmpname utmpxname
+#ifdef HAVE_UTMPX_H
+
+#define sh_utmp_utmpname(a) (void)(a)
#define sh_utmp_setutent setutxent
#define sh_utmp_endutent endutxent
#define sh_utmp_getutent getutxent
@@ -291,12 +280,8 @@ static void set_defaults(void)
*/
static FILE * sh_utmpfile = NULL;
-static char sh_utmppath[80] = _PATH_UTMP;
+static char sh_utmppath[80] = SH_PATH_UTMP;
-/* sh_utmp_feed_forward is for optimizing
- * (fseek instead of getutent loop)
- */
-static long sh_utmp_feed_forward = 0;
static void sh_utmp_utmpname(const char * str)
{
@@ -307,7 +292,7 @@ static void sh_utmp_utmpname(const char * str)
sh_utmpfile = NULL;
}
- (void) sl_strlcpy (sh_utmppath, str, 80);
+ (void) sl_strlcpy (sh_utmppath, str, sizeof(sh_utmppath));
SL_RET0(_("sh_utmp_utmpname"));
}
@@ -343,11 +328,6 @@ static void sh_utmp_setutent(void)
}
}
(void) fseek (sh_utmpfile, 0L, SEEK_SET);
- if (-1 == fseek (sh_utmpfile, sh_utmp_feed_forward, SEEK_CUR))
- {
- sh_utmp_feed_forward = 0; /* modified Apr 4, 2004 */
- (void) fseek (sh_utmpfile, 0L, SEEK_SET);
- }
clearerr (sh_utmpfile);
SL_RET0(_("sh_utmp_setutent"));
}
@@ -387,63 +367,6 @@ static struct SH_UTMP_S * sh_utmp_getutent(void)
SL_RETURN(&out, _("sh_utmp_getutent"));
}
-#ifdef USE_UNUSED
-
-static struct SH_UTMP_S * sh_utmp_getutline(struct SH_UTMP_S * ut)
-{
- struct SH_UTMP_S * out;
-
- while (1) {
- if ((out = sh_utmp_getutent()) == NULL) {
- return NULL;
- }
-#ifdef HAVE_UTTYPE
- if (out->ut_type == USER_PROCESS || out->ut_type == LOGIN_PROCESS)
- if (sl_strcmp(ut->ut_line, out->ut_line) == 0)
- return out;
-#else
- if ( 0 != sl_strncmp (out->ut_name, "reboot", 6) &&
- 0 != sl_strncmp (out->ut_name, "shutdown", 8) &&
- 0 != sl_strncmp (out->ut_name, "date", 4) )
- return out;
-#endif
- }
- return NULL;
-}
-
-static struct SH_UTMP_S * sh_utmp_getutid(struct SH_UTMP_S * ut)
-{
-#ifdef HAVE_UTTYPE
- struct SH_UTMP_S * out;
-
- if (ut->ut_type == RUN_LVL || ut->ut_type == BOOT_TIME ||
- ut->ut_type == NEW_TIME || ut->ut_type == OLD_TIME)
- {
- while (1) {
- if ((out = sh_utmp_getutent()) == NULL) {
- return NULL;
- }
- if (out->ut_type == ut->ut_type)
- return out;
- }
- }
- else if (ut->ut_type == INIT_PROCESS || ut->ut_type == LOGIN_PROCESS ||
- ut->ut_type == USER_PROCESS || ut->ut_type == DEAD_PROCESS )
- {
- while (1) {
- if ((out = sh_utmp_getutent()) == NULL) {
- return NULL;
- }
- if (sl_strcmp(ut->ut_id, out->ut_id) == 0)
- return out;
- }
- }
-#endif
- return NULL;
-}
-/* #ifdef USE_UNUSED */
-#endif
-
/* #ifdef HAVE_SETUTENT */
#endif
@@ -510,9 +433,7 @@ static int sh_utmp_init_internal (void)
}
lastcheck = time (NULL);
userlist = NULL;
- memset (&save_utmp, 0, sizeof(struct SH_UTMP_S));
- sh_utmp_check_internal (2); /* current logins */
- sh_utmp_check_internal (0);
+ sh_utmp_check_internal (); /* current logins */
init_done = 1;
SL_RETURN( (0), _("sh_utmp_init"));
}
@@ -617,7 +538,7 @@ int sh_utmp_timer (time_t tcurrent)
if ( (sh.flag.isdaemon == S_TRUE || sh.flag.loop == S_TRUE) &&
sh.flag.checkSum != SH_CHECK_INIT )
{
- sh_inotify_wait_for_change(mode_path[1], &inotify_watch,
+ sh_inotify_wait_for_change(utmp_path, &inotify_watch,
&errnum, ShUtmpInterval);
}
@@ -656,7 +577,7 @@ int sh_utmp_check ()
SH_MUTEX_LOCK(mutex_thread_nolog);
sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_UT_CHECK);
SH_MUTEX_UNLOCK(mutex_thread_nolog);
- sh_utmp_check_internal (1);
+ sh_utmp_check_internal ();
SL_RETURN(0, _("sh_utmp_check"));
}
@@ -736,7 +657,7 @@ int sh_utmp_set_login_activate (const char * c)
SL_RETURN(i, _("sh_utmp_set_login_activate"));
}
-#ifdef HAVE_UTTYPE
+
struct login_ct {
char name[UT_NAMESIZE+1];
int nlogin;
@@ -816,7 +737,6 @@ static int sh_utmp_login_r(char * str)
return 0;
}
-#endif
/* for each login:
@@ -825,14 +745,14 @@ static int sh_utmp_login_r(char * str)
* - link user.ut_record -> log_record
*/
-#ifdef HAVE_UTTYPE
+#include <ctype.h>
static int sh_utmp_is_virtual (char * in_utline, char * in_uthost)
{
if (in_uthost != NULL &&
in_utline != NULL &&
in_uthost[0] == ':' &&
- in_uthost[1] == '0' &&
+ isdigit((int) in_uthost[1]) &&
0 == sl_strncmp(in_utline, _("pts/"), 4))
{
return 1;
@@ -840,7 +760,139 @@ static int sh_utmp_is_virtual (char * in_utline, char * in_uthost)
return 0;
}
+
+
+static void sh_utmp_log_out(int sev, struct log_user * user, int n)
+{
+ char ttt[TIM_MAX];
+
+ SH_MUTEX_LOCK(mutex_thread_nolog);
+ (void) sh_unix_time (user->time, ttt, TIM_MAX);
+ sh_error_handle( sev, FIL__, __LINE__, 0,
+#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
+ MSG_UT_LG3X,
+#elif defined(HAVE_UTHOST)
+ MSG_UT_LG3A,
+#else
+ MSG_UT_LG3B,
+#endif
+ user->name,
+ user->ut_tty,
+#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
+ user->ut_host,
+ user->ut_ship,
+#elif defined(HAVE_UTHOST)
+ user->ut_host,
+#endif
+ ttt,
+ n
+ );
+ SH_MUTEX_UNLOCK(mutex_thread_nolog);
+}
+
+static void sh_utmp_log_multi(int sev, struct log_user * user, int n)
+{
+ char ttt[TIM_MAX];
+
+ SH_MUTEX_LOCK(mutex_thread_nolog);
+ (void) sh_unix_time (user->time, ttt, TIM_MAX);
+ sh_error_handle( sev, FIL__, __LINE__, 0,
+#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
+ MSG_UT_LG2X,
+#elif defined(HAVE_UTHOST)
+ MSG_UT_LG2A,
+#else
+ MSG_UT_LG2B,
+#endif
+ user->name,
+ user->ut_tty,
+#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
+ user->ut_host,
+ user->ut_ship,
+#elif defined(HAVE_UTHOST)
+ user->ut_host,
+#endif
+ ttt,
+ n
+ );
+ SH_MUTEX_UNLOCK(mutex_thread_nolog);
+}
+
+static void sh_utmp_log_one(int sev, struct log_user * user, int n)
+{
+ char ttt[TIM_MAX];
+
+ SH_MUTEX_LOCK(mutex_thread_nolog);
+ (void) sh_unix_time (user->time, ttt, TIM_MAX);
+ sh_error_handle( sev, FIL__, __LINE__, 0,
+#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
+ MSG_UT_LG1X,
+#elif defined(HAVE_UTHOST)
+ MSG_UT_LG1A,
+#else
+ MSG_UT_LG1B,
+#endif
+ user->name,
+ user->ut_tty,
+#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
+ user->ut_host,
+ user->ut_ship,
+#elif defined(HAVE_UTHOST)
+ user->ut_host,
#endif
+ ttt,
+ n
+ );
+ SH_MUTEX_UNLOCK(mutex_thread_nolog);
+}
+
+static void sh_utmp_purge_old (time_t start_read)
+{
+ struct log_user * user = userlist;
+ struct log_user * userold = userlist;
+ volatile int status;
+
+ /* ------- find old entries --------
+ */
+ while (user != NULL)
+ {
+ if (user->last_checked < start_read)
+ {
+ /* report logout */
+ if (0 == sh_utmp_is_virtual(user->ut_tty, user->ut_host))
+ {
+ /* reference count down on list of logged in users */
+ status = sh_utmp_login_r(user->name);
+
+ sh_utmp_log_out(ShUtmpLogout, user, status);
+ sh_utmp_logout_morechecks((struct log_user *)user);
+ }
+
+ /* remove entry */
+ if (userold == user && userold == userlist)
+ {
+ /* first element in userlist, advance userlist & userold */
+ userold = user->next;
+ userlist = user->next;
+ SH_FREE((struct log_user *)user);
+ user = userlist;
+ }
+ else
+ {
+ /* other element in userlist, cut it out */
+ userold->next = user->next;
+ SH_FREE((struct log_user *)user);
+ user = userold->next;
+ }
+ }
+ else
+ {
+ userold = user;
+ user = user->next;
+ }
+ }
+ return;
+}
/* These variables are not used anywhere. They only exist
* to assign &userold, &user to them, which keeps gcc from
@@ -851,33 +903,19 @@ void * sh_dummy_850_userold = NULL;
void * sh_dummy_851_user = NULL;
-static void sh_utmp_addlogin (struct SH_UTMP_S * ut)
+static void sh_utmp_checklogin (struct SH_UTMP_S * ut, time_t start_read)
{
struct log_user * user = userlist;
struct log_user * userold = userlist;
-#ifdef HAVE_UTTYPE
- struct log_user * username = userlist;
-#endif
- char ttt[TIM_MAX];
-#ifdef HAVE_UTTYPE
+ struct log_user * username = userlist;
volatile int status;
-#endif
- SL_ENTER(_("sh_utmp_addlogin"));
- if (ut->ut_line[0] == '\0')
- SL_RET0(_("sh_utmp_addlogin"));
+ SL_ENTER(_("sh_utmp_checklogin"));
- /* for some stupid reason, AIX repeats the wtmp entry for logouts
- * with ssh
- */
- if (memcmp (&save_utmp, ut, sizeof(struct SH_UTMP_S)) == 0)
- {
- memset(&save_utmp, (int) '\0', sizeof(struct SH_UTMP_S));
- SL_RET0(_("sh_utmp_addlogin"));
- }
- memcpy (&save_utmp, ut, sizeof(struct SH_UTMP_S));
+ if (ut->ut_line[0] == '\0')
+ SL_RET0(_("sh_utmp_checklogin"));
/* Take the address to keep gcc from putting them into registers.
* Avoids the 'clobbered by longjmp' warning.
@@ -889,273 +927,108 @@ static void sh_utmp_addlogin (struct SH_UTMP_S * ut)
*/
while (user != NULL)
{
- if (0 == sl_strncmp((char*)(user->ut_tty), ut->ut_line, UT_LINESIZE) )
+ if (0 == sl_strncmp(user->ut_tty, ut->ut_line, UT_LINESIZE) &&
+ 0 == sl_strncmp(user->name, ut->ut_name, UT_NAMESIZE))
break;
userold = user;
user = user->next;
}
-#ifdef HAVE_UTTYPE
+
while (username != NULL)
{
if (0 == sl_strncmp(username->name, ut->ut_name, UT_NAMESIZE) )
break;
username = username->next;
}
-#endif
+
-#ifdef HAVE_UTTYPE
- /* ---------- LOGIN -------------- */
- if (ut->ut_type == USER_PROCESS)
+ if (user == NULL)
{
- if (user == NULL)
- {
- user = SH_ALLOC(sizeof(struct log_user));
- user->next = userlist;
- userlist = (struct log_user *) user;
- }
- (void) sl_strlcpy((char*)(user->ut_tty), ut->ut_line, UT_LINESIZE+1);
- (void) sl_strlcpy((char*)(user->name), ut->ut_name, UT_NAMESIZE+1);
-#ifdef HAVE_UTHOST
- (void) sl_strlcpy((char*)(user->ut_host), ut->ut_host, UT_HOSTSIZE+1);
-#else
- user->ut_host[0] = '\0';
-#endif
-#ifdef HAVE_UTADDR
-#ifdef HAVE_UTADDR_V6
- my_inet_ntoa(ut->ut_addr_v6, user->ut_ship, SH_IP_BUF);
-#else
- my_inet_ntoa(ut->ut_addr, user->ut_ship, SH_IP_BUF);
-#endif
-#endif
- user->time = ut->ut_time;
-
- if (username == NULL /* not yet logged in */
- || 0 == sl_strncmp(ut->ut_line, _("ttyp"), 4) /* in virt. console */
- || 0 == sl_strncmp(ut->ut_line, _("ttyq"), 4) /* in virt. console */
- ) {
- status = sh_utmp_login_a((char*)user->name);
- SH_MUTEX_LOCK(mutex_thread_nolog);
- (void) sh_unix_time (user->time, ttt, TIM_MAX);
- sh_error_handle( ShUtmpLoginSolo, FIL__, __LINE__, 0,
-#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
- MSG_UT_LG1X,
-#elif defined(HAVE_UTHOST)
- MSG_UT_LG1A,
-#else
- MSG_UT_LG1B,
-#endif
- user->name,
- user->ut_tty,
-#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
- user->ut_host,
- user->ut_ship,
-#elif defined(HAVE_UTHOST)
- user->ut_host,
-#endif
- ttt,
- status
- );
- SH_MUTEX_UNLOCK(mutex_thread_nolog);
- } else
- if (0 == sh_utmp_is_virtual(ut->ut_line, (char*)user->ut_host))
- {
- status = sh_utmp_login_a((char*)user->name);
- SH_MUTEX_LOCK(mutex_thread_nolog);
- (void) sh_unix_time (user->time, ttt, TIM_MAX);
- sh_error_handle( ShUtmpLoginMulti, FIL__, __LINE__, 0,
-#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
- MSG_UT_LG2X,
-#elif defined(HAVE_UTHOST)
- MSG_UT_LG2A,
-#else
- MSG_UT_LG2B,
-#endif
- user->name,
- user->ut_tty,
-#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
- user->ut_host,
- user->ut_ship,
-#elif defined(HAVE_UTHOST)
- user->ut_host,
-#endif
- ttt,
- status
- );
- SH_MUTEX_UNLOCK(mutex_thread_nolog);
- }
-
- sh_utmp_login_morechecks(ut);
+ user = SH_ALLOC(sizeof(struct log_user));
+ user->next = userlist;
+ userlist = (struct log_user *) user;
+ }
+ else if ( (user->time == ut->ut_time) &&
+ 0 == sl_strcmp (user->name, ut->ut_name))
+ {
+ /* we have it on record and nothing has changed */
+ user->last_checked = start_read;
goto out;
}
-
-
- /* --------- LOGOUT ---------------- */
- else if (ut->ut_name[0] == '\0'
- || ut->ut_type == DEAD_PROCESS /* solaris does not clear ut_name */
- )
+ else
{
- if (user != NULL)
- {
-#if defined(__linux__)
- if (0 == sh_utmp_is_virtual(ut->ut_line, (char*)user->ut_host)) {
-#endif
- status = sh_utmp_login_r((char*)user->name);
- SH_MUTEX_LOCK(mutex_thread_nolog);
- (void) sh_unix_time (ut->ut_time, ttt, TIM_MAX);
- sh_error_handle( ShUtmpLogout, FIL__, __LINE__, 0,
-#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
- MSG_UT_LG3X,
-#elif defined(HAVE_UTHOST)
- MSG_UT_LG3A,
-#else
- MSG_UT_LG3B,
-#endif
- user->name,
- user->ut_tty,
-#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
- user->ut_host,
- user->ut_ship,
-#elif defined(HAVE_UTHOST)
- user->ut_host,
-#endif
- ttt,
- status
- );
- SH_MUTEX_UNLOCK(mutex_thread_nolog);
- userold->next = user->next;
- if (user == userlist)
- userlist = user->next;
- sh_utmp_logout_morechecks((struct log_user *)user);
- SH_FREE((struct log_user *)user);
- user = NULL;
-#if defined(__linux__)
- }
-#endif
- }
- else
+ /* we have it on record and something has changed */
+ if (0 == sh_utmp_is_virtual(user->ut_tty, user->ut_host))
{
- (void) sl_strlcpy(terminated_line, ut->ut_line, UT_HOSTSIZE);
- SH_MUTEX_LOCK(mutex_thread_nolog);
- (void) sh_unix_time (ut->ut_time, ttt, TIM_MAX);
- sh_error_handle( ShUtmpLogout, FIL__, __LINE__, 0,
- MSG_UT_LG3C,
- terminated_line,
- ttt, 0
- );
- SH_MUTEX_UNLOCK(mutex_thread_nolog);
+ /* reference count down on list of logged in users */
+ status = sh_utmp_login_r(user->name);
+
+ sh_utmp_log_out(ShUtmpLogout, user, status);
+ sh_utmp_logout_morechecks((struct log_user *)user);
}
- goto out;
}
- /* default */
- goto out;
-
- /* #ifdef HAVE_UTTYPE */
-#else
-
- if (user == NULL) /* probably a login */
- {
- user = SH_ALLOC(sizeof(struct log_user));
- sl_strlcpy(user->ut_tty, ut->ut_line, UT_LINESIZE+1);
- sl_strlcpy(user->name, ut->ut_name, UT_NAMESIZE+1);
+ user->last_checked = start_read;
+
+ (void) sl_strlcpy(user->ut_tty, ut->ut_line, UT_LINESIZE+1);
+ (void) sl_strlcpy(user->name, ut->ut_name, UT_NAMESIZE+1);
#ifdef HAVE_UTHOST
- sl_strlcpy(user->ut_host, ut->ut_host, UT_HOSTSIZE+1);
+ (void) sl_strlcpy(user->ut_host, ut->ut_host, UT_HOSTSIZE+1);
+#else
+ user->ut_host[0] = '\0';
#endif
#ifdef HAVE_UTADDR
#ifdef HAVE_UTADDR_V6
- my_inet_ntoa(ut->ut_addr_v6, user->ut_ship, SH_IP_BUF);
-#else
- my_inet_ntoa(ut->ut_addr, user->ut_ship, SH_IP_BUF);
-#endif
-#endif
- user->time = ut->ut_time;
- user->next = userlist;
- userlist = user;
-
- SH_MUTEX_LOCK(mutex_thread_nolog);
- (void) sh_unix_time (user->time, ttt, TIM_MAX);
- sh_error_handle( ShUtmpLoginSolo, FIL__, __LINE__, 0,
-#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
- MSG_UT_LG1X,
-#elif defined(HAVE_UTHOST)
- MSG_UT_LG1A,
+ my_inet_ntoa(ut->ut_addr_v6, user->ut_ship, SH_IP_BUF);
#else
- MSG_UT_LG1B,
+ my_inet_ntoa(ut->ut_addr, user->ut_ship, SH_IP_BUF);
#endif
- user->name,
- user->ut_tty,
-#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
- user->ut_host,
- user->ut_ship,
-#elif defined(HAVE_UTHOST)
- user->ut_host,
#endif
- ttt,
- 1
- );
- SH_MUTEX_UNLOCK(mutex_thread_nolog);
- sh_utmp_login_morechecks(ut);
+ user->time = ut->ut_time;
+
+ if (username == NULL) /* not yet logged in */
+ {
+ /* add this username to the list of logged in users */
+ status = sh_utmp_login_a(user->name);
+
+ sh_utmp_log_one(ShUtmpLoginSolo, user, status);
+
}
- else /* probably a logout */
+ else if (0 == sh_utmp_is_virtual(user->ut_tty, (char*)user->ut_host))
{
- SH_MUTEX_LOCK(mutex_thread_nolog);
- (void) sh_unix_time (ut->ut_time, ttt, TIM_MAX);
- sh_error_handle( ShUtmpLogout, FIL__, __LINE__, 0,
-#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
- MSG_UT_LG2X,
-#elif defined(HAVE_UTHOST)
- MSG_UT_LG2A,
-#else
- MSG_UT_LG2B,
-#endif
- user->name,
- user->ut_tty,
-#if defined(HAVE_UTHOST) && defined(HAVE_UTADDR)
- user->ut_host,
- user->ut_ship,
-#elif defined(HAVE_UTHOST)
- user->ut_host,
-#endif
- ttt,
- 1
- );
- SH_MUTEX_UNLOCK(mutex_thread_nolog);
- sh_utmp_logout_morechecks(user);
- userold->next = user->next;
- if (user == userlist) /* inserted Apr 4, 2004 */
- userlist = user->next;
- SH_FREE(user);
- user = NULL;
+ /* add this username to the list of logged in users */
+ status = sh_utmp_login_a((char*)user->name);
+
+ sh_utmp_log_multi(ShUtmpLoginMulti, user, status);
}
+ sh_utmp_login_morechecks(ut);
+ goto out;
-#endif
out:
sh_dummy_851_user = NULL;
sh_dummy_850_userold = NULL;
- SL_RET0(_("sh_utmp_addlogin"));
+ SL_RET0(_("sh_utmp_checklogin"));
}
static time_t lastmod = 0;
-static off_t lastsize = 0;
-static unsigned long lastread = 0;
-static void sh_utmp_check_internal (int mode)
+static void sh_utmp_check_internal ()
{
struct stat buf;
int error;
struct SH_UTMP_S * ut;
- unsigned long this_read;
int val_retry;
+ time_t start_read;
SL_ENTER(_("sh_utmp_check_internal"));
/* error if no access
*/
do {
- val_retry = /*@-unrecog@*/lstat ( mode_path[mode], &buf)/*@+unrecog@*/;
+ val_retry = /*@-unrecog@*/lstat ( utmp_path, &buf)/*@+unrecog@*/;
} while (val_retry < 0 && errno == EINTR);
if (0 != val_retry)
@@ -1163,87 +1036,43 @@ static void sh_utmp_check_internal (int mode)
error = errno;
SH_MUTEX_LOCK(mutex_thread_nolog);
sh_error_handle((-1), FIL__, __LINE__, error, MSG_E_ACCESS,
- (long) sh.real.uid, mode_path[mode]);
+ (long) sh.real.uid, utmp_path);
SH_MUTEX_UNLOCK(mutex_thread_nolog);
SL_RET0(_("sh_utmp_check_internal"));
}
- /* modification time
- */
- if (mode < 2)
- {
- if (/*@-usedef@*/buf.st_mtime <= lastmod/*@+usedef@*/)
- {
- SL_RET0(_("sh_utmp_check_internal"));
- }
- else
- lastmod = buf.st_mtime;
- }
-
- /* file size
+ /* check modification time
*/
- if (/*@-usedef@*/buf.st_size < lastsize/*@+usedef@*/ && mode < 2)
+ if (/*@-usedef@*/buf.st_mtime <= lastmod/*@+usedef@*/)
{
- SH_MUTEX_LOCK(mutex_thread_nolog);
- sh_error_handle((-1), FIL__, __LINE__, 0, MSG_UT_ROT,
- mode_path[mode]);
- SH_MUTEX_UNLOCK(mutex_thread_nolog);
- lastread = 0;
-#ifndef USE_SETUTENT
- sh_utmp_feed_forward = 0L;
-#endif
+ SL_RET0(_("sh_utmp_check_internal"));
}
+ else
+ lastmod = buf.st_mtime;
- if (mode < 2)
- lastsize = buf.st_size;
-
- if (buf.st_size == 0)
- SL_RET0(_("sh_utmp_check_internal"));
-
- sh_utmp_utmpname(mode_path[mode]);
+ sh_utmp_utmpname(utmp_path);
sh_utmp_setutent();
- /*
- * feed forward if initializing
- * we need to do this here
- */
- this_read = 0;
-
- if (mode < 2)
- {
- while (this_read < lastread) {
- (void) sh_utmp_getutent();
- ++this_read;
- }
- }
-
/* start reading
*/
- this_read = 0;
+ start_read = time(NULL);
+
while (1 == 1) {
ut = sh_utmp_getutent();
if (ut == NULL)
break;
/* modified: ut_user --> ut_name */
- if (mode == 1 || (mode == 2 && ut->ut_name[0] != '\0'
+ if (ut->ut_name[0] != '\0'
#ifdef HAVE_UTTYPE
- && ut->ut_type != DEAD_PROCESS
+ && ut->ut_type == USER_PROCESS
#endif
- ))
- sh_utmp_addlogin (ut);
- ++this_read;
+ )
+ sh_utmp_checklogin (ut, start_read);
}
sh_utmp_endutent();
- if (mode < 2)
- {
- lastread += this_read;
-#ifndef USE_SETUTENT
- sh_utmp_feed_forward += (long) (this_read * sizeof(struct SH_UTMP_S));
- lastread = 0;
-#endif
- }
+ sh_utmp_purge_old (start_read);
SL_RET0(_("sh_utmp_check_internal"));
}
diff --git a/src/sh_xfer_client.c b/src/sh_xfer_client.c
index abc6504..aa4941c 100644
--- a/src/sh_xfer_client.c
+++ b/src/sh_xfer_client.c
@@ -96,7 +96,7 @@
#define FD_SETSIZE 32
#endif
#ifndef FD_ZERO
-#define FD_ZERO(p) memset((char *)(p), '\0', sizeof(*(p)))
+#define FD_ZERO(p) memset((char *)(p), 0, sizeof(*(p)))
#endif
#if defined(HAVE_MLOCK) && !defined(HAVE_BROKEN_MLOCK)
@@ -768,7 +768,7 @@ static int xfer_auth(int is_reinit, int * initialized,
/* verify random nonce v from server H(v, P)v
*/
sh_passwd (nounce, NULL, NULL, temp);
- if ( 0 != sl_strncmp(temp, answer, KEY_LEN))
+ if ( 0 != sl_ts_strncmp(temp, answer, KEY_LEN))
flag_err = (-1);
TPT(( 0, FIL__, __LINE__, _("msg=<c/r: vrfy nonce, flag_err = %d>\n"),
@@ -1002,7 +1002,7 @@ static int xfer_auth(int is_reinit, int * initialized,
M_buf, sizeof(M_buf)
);
if (M != NULL &&
- 0 == sl_strncmp (answer, M, KEY_LEN+1))
+ 0 == sl_ts_strncmp (answer, M, KEY_LEN+1))
{
sl_strlcpy (skey->session,
sh_tiger_hash(foo_Sc,
@@ -1050,7 +1050,7 @@ static int xfer_auth(int is_reinit, int * initialized,
{
xfer_timeout_val *= 2;
sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_NOAUTH);
- memset(answer, '\0', 512);
+ memset(answer, 0, 512);
MUNLOCK(answer, 512);
SH_FREE(answer);
return -1;
@@ -1082,7 +1082,7 @@ int xfer_check_server_cmd(char * answer, char * buffer)
(void) sl_strlcpy(buffer, &answer[KEY_LEN],
pos+1);
flag_err =
- sl_strncmp(&answer[KEY_LEN+pos],
+ sl_ts_strncmp(&answer[KEY_LEN+pos],
sh_util_siggen(skey->session,
buffer,
pos,
@@ -1201,12 +1201,12 @@ int xfer_send_message(char * errmsg, int sockfd, char * answer)
*/
(void) sl_strlcpy(buffer, errmsg, len);
(void) sl_strlcat(buffer, nsrv, len);
- flag_err = sl_strncmp(answer,
- sh_util_siggen(skey->session,
- buffer,
- sl_strlen(buffer),
- sigbuf, sizeof(sigbuf)),
- KEY_LEN);
+ flag_err = sl_ts_strncmp(answer,
+ sh_util_siggen(skey->session,
+ buffer,
+ sl_strlen(buffer),
+ sigbuf, sizeof(sigbuf)),
+ KEY_LEN);
TPT((0, FIL__, __LINE__, _("msg=<sign %s.>\n"),
sh_util_siggen(skey->session, buffer,
sl_strlen(buffer), sigbuf, sizeof(sigbuf))));
diff --git a/src/sh_xfer_server.c b/src/sh_xfer_server.c
index 0f7f1ab..fcc80fc 100644
--- a/src/sh_xfer_server.c
+++ b/src/sh_xfer_server.c
@@ -104,7 +104,7 @@
#define FD_SETSIZE 32
#endif
#ifndef FD_ZERO
-#define FD_ZERO(p) memset((char *)(p), '\0', sizeof(*(p)))
+#define FD_ZERO(p) memset((char *)(p), 0, sizeof(*(p)))
#endif
#if defined(HAVE_MLOCK) && !defined(HAVE_BROKEN_MLOCK)
@@ -418,6 +418,11 @@ char * clt_stat[] = {
* } client_t;
*/
+typedef struct client_alias {
+ char * alias;
+ char * hostname;
+} alias_t;
+
#include "zAVLTree.h"
static char * sh_tolower (char * s)
@@ -434,7 +439,7 @@ static char * sh_tolower (char * s)
}
/* Function to return the key for indexing
- * the argument
+ * the argument (for the client list)
*/
zAVLKey sh_avl_key (void const * arg)
{
@@ -444,6 +449,17 @@ zAVLKey sh_avl_key (void const * arg)
zAVLTree * all_clients = NULL;
+/* Function to return the key for indexing
+ * the argument (for the aliases list)
+ */
+zAVLKey sh_avl_alias (void const * arg)
+{
+ const alias_t * sa = (const alias_t *) arg;
+ return (zAVLKey) sa->alias;
+}
+
+zAVLTree * all_aliases = NULL;
+
void sh_xfer_html_write()
{
SL_ENTER(_("sh_xfer_html_write"));
@@ -469,7 +485,7 @@ int sh_xfer_use_clt_sev (const char * c)
}
-/* the destructor
+/* the destructor (client list item)
*/
void free_client(void * inptr)
{
@@ -491,6 +507,100 @@ void free_client(void * inptr)
SL_RET0(_("free_client"));
}
+/* the destructor (alias list item)
+ */
+void free_alias(void * inptr)
+{
+ alias_t * here;
+
+ SL_ENTER(_("free_alias"));
+ if (inptr == NULL)
+ SL_RET0(_("free_alias"));
+ else
+ here = (alias_t *) inptr;
+
+ if (here->alias != NULL)
+ SH_FREE(here->alias);
+ if (here->hostname != NULL)
+ SH_FREE(here->hostname);
+ SH_FREE(here);
+ SL_RET0(_("free_alias"));
+}
+
+int sh_xfer_register_alias (const char * str)
+{
+ alias_t * newalias;
+ alias_t * testalias;
+
+ const char * ptr;
+ int sepnum = 0;
+ int sep = 0;
+ register int i = 0;
+ int siz_str = 0;
+
+ SL_ENTER(_("sh_xfer_register_alias"));
+
+ ptr = str;
+ while (*ptr) {
+ if (*ptr == '@' && sepnum < 1)
+ {
+ sep = i;
+ ++sepnum;
+ }
+ ++ptr; ++i;
+ }
+
+ if (all_aliases == NULL)
+ {
+ all_aliases = zAVLAllocTree (sh_avl_alias, zAVL_KEY_STRING);
+ if (all_aliases == NULL)
+ {
+ (void) safe_logger (0, 0, NULL);
+ aud__exit(FIL__, __LINE__, EXIT_FAILURE);
+ }
+ }
+
+ if ((sepnum == 1) && (sep > 0) && (i > (sep + 1)))
+ {
+ newalias = SH_ALLOC (sizeof(alias_t));
+ newalias->alias = SH_ALLOC (sep+1);
+ newalias->hostname = SH_ALLOC (sl_strlen(str)-sep);
+
+ /* truncate */
+ sl_strlcpy(newalias->alias, &str[0], sep+1);
+ sh_tolower(newalias->alias);
+
+ /* truncate */
+ sl_strlcpy(newalias->hostname, &str[sep+1], sl_strlen(str)-sep);
+ sh_tolower(newalias->hostname);
+
+ testalias = (alias_t *) zAVLSearch (all_aliases, newalias->alias);
+
+ if (testalias != NULL)
+ {
+ /* keep the alias but replace the hostname with the new one */
+ SH_FREE(testalias->hostname);
+ siz_str = strlen (newalias->hostname) + 1;
+ testalias->hostname = SH_ALLOC (siz_str);
+ sl_strlcpy(testalias->hostname, newalias->hostname, siz_str);
+
+ free_alias(newalias);
+ SL_RETURN( 0, _("sh_xfer_register_alias"));
+ }
+ else
+ {
+ if (0 == zAVLInsert (all_aliases, newalias))
+ {
+ sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_AREG,
+ newalias->alias,
+ newalias->hostname);
+ SL_RETURN( 0, _("sh_xfer_register_alias"));
+ }
+ }
+ }
+ SL_RETURN (-1, _("sh_xfer_register_alias"));
+}
+
int sh_xfer_register_client (const char * str)
{
@@ -1052,6 +1162,7 @@ int set_socket_peer (const char * c)
*/
client_t * search_register(sh_conn_t * conn, int pos)
{
+ alias_t * this_alias;
client_t * this_client;
char peer_ip[SH_IP_BUF];
char numerical[SH_IP_BUF];
@@ -1067,6 +1178,7 @@ client_t * search_register(sh_conn_t * conn, int pos)
{
memcpy(&peer_addr, &(conn->addr_peer), sizeof(struct sh_sockaddr));
sh_ipvx_ntoa (peer_ip, sizeof(peer_ip), &peer_addr);
+ peer_name[0] = '\0';
/* get canonical name of socket peer
*/
@@ -1085,6 +1197,14 @@ client_t * search_register(sh_conn_t * conn, int pos)
{
sl_strlcpy(peer_name, peer_ip, MAXHOSTNAMELEN + 1);
}
+ else
+ {
+ this_alias = zAVLSearch(all_aliases, peer_name);
+ if (this_alias)
+ {
+ sl_strlcpy(peer_name, this_alias->hostname, MAXHOSTNAMELEN + 1);
+ }
+ }
search_string = peer_name;
}
@@ -1196,7 +1316,7 @@ client_t * do_check_client(sh_conn_t * conn, int * retval)
sigbuf, sizeof(sigbuf)),
KEY_LEN+1);
- if (0 != sl_strncmp(conn->K, conn->buf, KEY_LEN))
+ if (0 != sl_ts_strncmp(conn->K, conn->buf, KEY_LEN))
{
TPT((0, FIL__, __LINE__, _("msg=<clt %s>\n"), conn->buf));
TPT((0, FIL__, __LINE__, _("msg=<srv %s>\n"), conn->K));
@@ -1228,11 +1348,6 @@ static void do_file_send_data(sh_conn_t * conn)
char * send_buf;
int bytes;
SL_TICKET sfd = -1;
-#ifdef SH_ENCRYPT
- int blkfac;
- int rem;
- int send_bytes;
-#endif
if (conn == NULL || conn->FileName == NULL)
{
@@ -1279,26 +1394,11 @@ static void do_file_send_data(sh_conn_t * conn)
if (bytes >= 0)
{
+ send_buf = hash_me(conn->K, read_buf, bytes);
#ifdef SH_ENCRYPT
- /* need to send N * B_SIZ bytes
- */
- blkfac = bytes / B_SIZ;
- rem = bytes - (blkfac * B_SIZ);
- if (rem != 0)
- {
- memset(&read_buf[bytes], '\n', (B_SIZ-rem));
- ++blkfac;
- send_bytes = blkfac * B_SIZ;
- }
- else
- send_bytes = bytes;
-
- send_buf = hash_me(conn->K, read_buf, send_bytes);
-
- sh_xfer_send_crypt (conn, send_buf, send_bytes+KEY_LEN, _("FILE"),
+ sh_xfer_send_crypt (conn, send_buf, bytes+KEY_LEN, _("FILE"),
SH_PROTO_BIG|conn->client_entry->encf_flag);
#else
- send_buf = hash_me(conn->K, read_buf, bytes);
sh_xfer_send_crypt (conn, send_buf, bytes+KEY_LEN, _("FILE"),
SH_PROTO_BIG);
#endif
@@ -1662,12 +1762,12 @@ static int do_message_transfer(sh_conn_t * conn, int state)
/* verify hash
*/
buffer = sh_util_strconcat(conn->buf, conn->challenge, NULL);
- i = sl_strncmp(hash,
- sh_util_siggen(conn->client_entry->session_key,
- buffer,
- sl_strlen(buffer),
- sigbuf, sizeof(sigbuf)),
- KEY_LEN);
+ i = sl_ts_strncmp(hash,
+ sh_util_siggen(conn->client_entry->session_key,
+ buffer,
+ sl_strlen(buffer),
+ sigbuf, sizeof(sigbuf)),
+ KEY_LEN);
TPT((0, FIL__, __LINE__, _("msg=<sign %s.>\n"),
sh_util_siggen(conn->client_entry->session_key,
buffer,
@@ -1787,7 +1887,7 @@ static int do_message_transfer(sh_conn_t * conn, int state)
SH_FREE(ptok);
clt_class = (-1);
}
- memset(buffer, '\0', sl_strlen(buffer));
+ memset(buffer, 0, sl_strlen(buffer));
SH_FREE(buffer);
/* SERVER CONF SEND
@@ -1845,7 +1945,7 @@ static int do_message_transfer(sh_conn_t * conn, int state)
SH_PROTO_MSG|SH_PROTO_END);
#endif
- memset(buffer, '\0', sl_strlen(buffer));
+ memset(buffer, 0, sl_strlen(buffer));
SH_FREE(buffer);
/* sh_xfer_do_free (conn); */
@@ -2086,7 +2186,7 @@ int do_auth(sh_conn_t * conn)
TPT((0, FIL__, __LINE__, _("msg=<c/r: H = %s>\n"), hash));
TPT((0, FIL__, __LINE__, _("msg=<c/r: P = %s>\n"), conn->M1));
- if ( 0 != sl_strncmp(conn->M1, conn->buf, KEY_LEN))
+ if ( 0 != sl_ts_strncmp(conn->M1, conn->buf, KEY_LEN))
{
sh_error_handle((-1), FIL__, __LINE__, 0, MSG_TCP_BADCONN,
_("Session key mismatch"), conn->peer);
@@ -2412,7 +2512,7 @@ int do_auth(sh_conn_t * conn)
* ----- send M2 = H(A, M1, K) -------
*/
if (conn->buf != NULL &&
- sl_strncmp(conn->buf, conn->M1, KEY_LEN) == 0)
+ sl_ts_strncmp(conn->buf, conn->M1, KEY_LEN) == 0)
{
/*
* send M2
@@ -2425,8 +2525,12 @@ int do_auth(sh_conn_t * conn)
_("PARP"),
(conn->head[0]|SH_PROTO_SRP));
- if (conn->A != NULL) SH_FREE(conn->A); conn->A = NULL;
- if (conn->M1 != NULL) SH_FREE(conn->M1); conn->M1 = NULL;
+ if (conn->A != NULL)
+ SH_FREE(conn->A);
+ conn->A = NULL;
+ if (conn->M1 != NULL)
+ SH_FREE(conn->M1);
+ conn->M1 = NULL;
sl_strlcpy(conn->client_entry->session_key,
conn->K, KEY_LEN+1);
TPT((0, FIL__, __LINE__, _("msg=<key %s>\n"),
@@ -2449,7 +2553,9 @@ int do_auth(sh_conn_t * conn)
_("sh_xfer_prep_send_int: makeKey"));
#endif
- if (conn->K != NULL) SH_FREE(conn->K); conn->K = NULL;
+ if (conn->K != NULL)
+ SH_FREE(conn->K);
+ conn->K = NULL;
conn->client_entry->last_connect = time (NULL);
@@ -3102,7 +3208,7 @@ int sh_create_tcp_socket (void)
#if defined(USE_IPVX)
if (use_server_interface == 0) /* INADDR_ANY, listen on all interfaces */
{
- memset (&hints, '\0', sizeof (hints));
+ memset (&hints, 0, sizeof (hints));
hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
hints.ai_socktype = SOCK_STREAM;
hints.ai_family = AF_UNSPEC;
@@ -3387,6 +3493,10 @@ void sh_xfer_start_server()
*/
sh_xfer_mark_dead ();
+ /* free the aliases list */
+ zAVLFreeTree (all_aliases, free_alias);
+ all_aliases = NULL;
+
reset_count_dev_console();
reset_count_dev_time();
sl_trust_purge_user();
diff --git a/src/sh_xfer_syslog.c b/src/sh_xfer_syslog.c
index ab516f5..8013e96 100644
--- a/src/sh_xfer_syslog.c
+++ b/src/sh_xfer_syslog.c
@@ -434,7 +434,7 @@ int sh_xfer_create_syslog_socket (int callerFlag)
}
#else
- memset (&hints, '\0', sizeof (hints));
+ memset (&hints, 0, sizeof (hints));
hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
hints.ai_socktype = SOCK_DGRAM;
if (getaddrinfo (NULL, "syslog", &hints, &ai) != 0)
diff --git a/src/slib.c b/src/slib.c
index b0e84f5..5d09ab8 100644
--- a/src/slib.c
+++ b/src/slib.c
@@ -1,7 +1,16 @@
#include "config_xor.h"
#if defined(HAVE_POSIX_FADVISE) && defined(HAVE_MINCORE)
+
+#if defined(__sun) || defined(__sun__) || defined(sun)
+#define _XOPEN_SOURCE 500
+#else
#define _XOPEN_SOURCE 600
+#endif
+
+#if defined(__GNUC__)
+#define _DEFAULT_SOURCE
+#endif
#define _BSD_SOURCE
#endif
@@ -247,9 +256,9 @@ int dlog (int flag, const char * file, int line, const char *fmt, ...)
if (flag == 1)
{
sl_snprintf (val, 81, _("\n--------- %10s "), file);
- sl_strlcpy (msg, val, 80);
+ sl_strlcpy (msg, val, sizeof(msg));
sl_snprintf (val, 81, _(" --- %6d ---------\n"), line);
- sl_strlcat (msg, val, 80);
+ sl_strlcat (msg, val, sizeof(msg));
sh_log_console (msg);
}
@@ -578,11 +587,37 @@ int sl_get_cap_qdel() { return 0; }
/*
* Have memset in a different translation unit (i.e. this) to prevent
- * it to get optimized away
+ * it to get optimized away ...not safe with link-time optimisation...
*/
-void *sl_memset(void *s, int c, size_t n)
+void * sl_memset(void *s, int c, size_t n)
{
- return memset(s, c,n);
+ /* See:
+ * https://www.usenix.org/sites/default/files/conference/protected-files/usenixsecurity17_slides_zhaomo_yang.pdf
+ */
+#if defined(HAVE_EXPLICIT_MEMSET)
+ return explicit_memset(s, c, n);
+#elif defined(HAVE_EXPLICIT_BZERO)
+ if (c == 0) {
+ explicit_bzero(s, n);
+ return s;
+ } else {
+ return memset(s, c, n);
+ }
+#elif defined(__GNUC__)
+ memset(s, c, n);
+ __asm__ __volatile__ ("" ::"r"(s): "memory"); /* compiler barrier */
+ return s;
+#else
+ if (c == 0) {
+ size_t i;
+ volatile unsigned char * t_s = (volatile unsigned char *)s;
+ for (i=0; i<n; ++i)
+ t_s[i] = 0;
+ return s;
+ } else {
+ return memset(s, c, n);
+ }
+#endif
}
@@ -1069,6 +1104,40 @@ int sl_strcmp(const char * a, const char * b)
return (-7); /* default to not equal */
}
+/* Does not report sign. */
+int sl_ts_strncmp(const char * a, const char * b, size_t n)
+{
+#ifdef SL_FAIL_ON_ERROR
+ SL_REQUIRE (a != NULL, _("a != NULL"));
+ SL_REQUIRE (b != NULL, _("b != NULL"));
+ SL_REQUIRE (n > 0, _("n > 0"));
+#endif
+
+ if (a != NULL && b != NULL)
+ {
+ const unsigned char *a1 = (const unsigned char *)a;
+ const unsigned char *b1 = (const unsigned char *)b;
+ size_t i;
+ int retval=0;
+ /* The simple index based access is optimized best by the
+ * compiler (tested with gcc 7.3.0). */
+ for (i = 0; i < n; ++i)
+ {
+ if (a1[i] == '\0' || b1[i] == '\0')
+ break;
+ retval |= (a1[i] ^ b1[i]);
+ }
+ /* if (retval == 0) --> false (0) */
+ return (retval != 0);
+ }
+ else if (a == NULL && b != NULL)
+ return (-1);
+ else if (a != NULL && b == NULL)
+ return (1);
+ else
+ return (-7); /* default to not equal */
+}
+
int sl_strncmp(const char * a, const char * b, size_t n)
{
#ifdef SL_FAIL_ON_ERROR
@@ -1767,6 +1836,7 @@ SL_TICKET sl_make_ticket (const char * ofile, int oline,
{
free (ofiles[fd]);
ofiles[fd] = NULL;
+ /* cppcheck-suppress memleak */
SL_IRETURN(SL_EMEM, _("sl_make_ticket"));
}
@@ -1779,6 +1849,7 @@ SL_TICKET sl_make_ticket (const char * ofile, int oline,
(void) free (ofiles[fd]->path);
(void) free (ofiles[fd]);
ofiles[fd] = NULL;
+ /* cppcheck-suppress memleak */
SL_IRETURN(ticket, _("sl_make_ticket"));
}
@@ -1792,6 +1863,7 @@ SL_TICKET sl_make_ticket (const char * ofile, int oline,
sl_strlcpy(ofiles[fd]->ofile, ofile, SL_OFILE_SIZE);
ofiles[fd]->oline = oline;
+ /* cppcheck-suppress memleak */
SL_IRETURN(ticket, _("sl_make_ticket"));
}
@@ -2376,6 +2448,7 @@ int sl_close (SL_TICKET ticket)
TPT((0, FIL__, __LINE__,
_("msg=<Error fclosing file.>, fd=<%d>, err=<%s>\n"),
fd, strerror(errno)));
+ SL_IRETURN(SL_ECLOSE, _("sl_close"));
}
}
else
@@ -2385,6 +2458,7 @@ int sl_close (SL_TICKET ticket)
TPT((0, FIL__, __LINE__,
_("msg=<Error closing file.>, fd=<%d>, err=<%s>\n"),
fd, strerror(errno)));
+ SL_IRETURN(SL_ECLOSE, _("sl_close"));
}
}
@@ -2559,8 +2633,8 @@ int sl_read_timeout_prep (SL_TICKET ticket)
}
-int sl_read_timeout_fd (int fd, void * buf_in, size_t count,
- int timeout, int is_nonblocking)
+static int sl_read_timeout_fd_int (int fd, void * buf_in, size_t count,
+ int timeout, int is_nonblocking, int once)
{
int sflags = 0;
fd_set readfds;
@@ -2609,7 +2683,7 @@ int sl_read_timeout_fd (int fd, void * buf_in, size_t count,
{
bytes += byteread; count -= byteread;
buf += byteread;
- if (count == 0)
+ if (count == 0 || once == S_TRUE)
break;
}
else if (byteread == 0)
@@ -2693,6 +2767,18 @@ int sl_read_timeout_fd (int fd, void * buf_in, size_t count,
return ((int) bytes);
}
+int sl_read_timeout_fd (int fd, void * buf_in, size_t count,
+ int timeout, int is_nonblocking)
+{
+ return sl_read_timeout_fd_int (fd, buf_in, count, timeout, is_nonblocking, S_FALSE);
+}
+
+int sl_read_timeout_fd_once (int fd, void * buf_in, size_t count,
+ int timeout, int is_nonblocking)
+{
+ return sl_read_timeout_fd_int (fd, buf_in, count, timeout, is_nonblocking, S_TRUE);
+}
+
int sl_read_timeout (SL_TICKET ticket, void * buf_in, size_t count,
int timeout, int is_nonblocking)
{
diff --git a/src/sstrip.c b/src/sstrip.c
deleted file mode 100644
index a296561..0000000
--- a/src/sstrip.c
+++ /dev/null
@@ -1,538 +0,0 @@
-/* sstrip, version 2.0: Copyright (C) 1999-2001 by Brian Raiter, under the
- * GNU General Public License. No warranty. See LICENSE for details.
- */
-
-/* Modified for portability and 64bit/32bit elf executables, Rainer Wichmann */
-
-#include "config.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-#if !defined(__ia64) && !defined(__ia64__) && !defined(__itanium__) && \
- !defined(__alpha) && !defined(__alpha__) && \
- (defined(HAVE_ELF_H) || defined(HAVE_LINUX_ELF_H)) && \
- (defined(__linux__) || defined(__FreeBSD__)) && \
- (defined(__i386__) || defined(__i386) || defined(i386))
-
-/* || defined(__sun) || defined(__sun__) || defined(sun) */
-
-
-#if defined(HAVE_ELF_H)
-#include <elf.h>
-#else
-#include <linux/elf.h>
-#endif
-
-#ifndef TRUE
-#define TRUE 1
-#define FALSE 0
-#endif
-
-#ifndef ELFCLASS32
-#define ELFCLASS32 1 /* 32-bit objects */
-#endif
-#ifndef ELFCLASS64
-#define ELFCLASS64 2 /* 64-bit objects */
-#endif
-
-
-
-/* The name of the program.
- */
-static char const *progname;
-
-/* The name of the current file.
- */
-static char const *filename;
-
-
-/* A simple error-handling function. FALSE is always returned for the
- * convenience of the caller.
- */
-static int err(char const *errmsg)
-{
- fprintf(stderr, "%s: %s: %s\n", progname, filename, errmsg);
- return FALSE;
-}
-
-/* A macro for I/O errors: The given error message is used only when
- * errno is not set.
- */
-#define ferr(msg) (err(errno ? strerror(errno) : (msg)))
-
-/* readelfheader() reads the ELF header into our global variable, and
- * checks to make sure that this is in fact a file that we should be
- * munging.
- */
-static int readelfheader_32(int fd, Elf32_Ehdr *ehdr)
-{
- errno = 0;
- if (read(fd, ehdr, sizeof *ehdr) != sizeof *ehdr)
- return ferr("missing or incomplete ELF header.");
-
- /* Check the ELF signature.
- */
- if (!(ehdr->e_ident[EI_MAG0] == ELFMAG0 &&
- ehdr->e_ident[EI_MAG1] == ELFMAG1 &&
- ehdr->e_ident[EI_MAG2] == ELFMAG2 &&
- ehdr->e_ident[EI_MAG3] == ELFMAG3))
- return err("missing ELF signature.");
-
- /* Compare the file's class and endianness with the program's.
- */
-#ifdef ELF_DATA
- if (ehdr->e_ident[EI_DATA] != ELF_DATA)
- return err("ELF file has different endianness.");
-#endif
-
- if (ehdr->e_ident[EI_CLASS] != ELFCLASS32)
- return FALSE;
-
- /* Check the target architecture.
- */
-#ifdef ELF_ARCH
- if (ehdr->e_machine != ELF_ARCH)
- return err("ELF file created for different architecture.");
-#endif
-
- /* Verify the sizes of the ELF header and the program segment
- * header table entries.
- */
- if (ehdr->e_ehsize != sizeof(Elf32_Ehdr))
- return err("unrecognized ELF header size.");
- if (ehdr->e_phentsize != sizeof(Elf32_Phdr))
- return err("unrecognized program segment header size.");
-
- /* Finally, check the file type.
- */
- if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN)
- return err("not an executable or shared-object library.");
-
- return TRUE;
-}
-
-static int readelfheader_64(int fd, Elf64_Ehdr *ehdr)
-{
- errno = 0;
-
- if (lseek(fd, 0, SEEK_SET))
- return ferr("could not rewind file");
-
- if (read(fd, ehdr, sizeof *ehdr) != sizeof *ehdr)
- return ferr("missing or incomplete ELF header.");
-
- /* Check the ELF signature.
- */
- if (!(ehdr->e_ident[EI_MAG0] == ELFMAG0 &&
- ehdr->e_ident[EI_MAG1] == ELFMAG1 &&
- ehdr->e_ident[EI_MAG2] == ELFMAG2 &&
- ehdr->e_ident[EI_MAG3] == ELFMAG3))
- return err("missing ELF signature.");
-
- /* Compare the file's class and endianness with the program's.
- */
-#ifdef ELF_DATA
- if (ehdr->e_ident[EI_DATA] != ELF_DATA)
- return err("ELF file has different endianness.");
-#endif
-
- if (ehdr->e_ident[EI_CLASS] != ELFCLASS64)
- return err("ELF file has different word size.");
-
- /* Check the target architecture.
- */
-#ifdef ELF_ARCH
- if (ehdr->e_machine != ELF_ARCH)
- return err("ELF file created for different architecture.");
-#endif
-
- /* Verify the sizes of the ELF header and the program segment
- * header table entries.
- */
- if (ehdr->e_ehsize != sizeof(Elf64_Ehdr))
- return err("unrecognized ELF header size.");
- if (ehdr->e_phentsize != sizeof(Elf64_Phdr))
- return err("unrecognized program segment header size.");
-
- /* Finally, check the file type.
- */
- if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN)
- return err("not an executable or shared-object library.");
-
- return TRUE;
-}
-
-/* readphdrtable() loads the program segment header table into memory.
- */
-static int readphdrtable_32(int fd, Elf32_Ehdr const *ehdr, Elf32_Phdr **phdrs)
-{
- size_t size;
-
- if (!ehdr->e_phoff || !ehdr->e_phnum)
- return err("ELF file has no program header table.");
-
- size = ehdr->e_phnum * sizeof **phdrs;
- if (!(*phdrs = calloc(1,size)))
- return err("Out of memory!");
-
- errno = 0;
- if (read(fd, *phdrs, size) != (ssize_t)size)
- return ferr("missing or incomplete program segment header table.");
-
- return TRUE;
-}
-
-static int readphdrtable_64(int fd, Elf64_Ehdr const *ehdr, Elf64_Phdr **phdrs)
-{
- size_t size;
-
- if (!ehdr->e_phoff || !ehdr->e_phnum)
- return err("ELF file has no program header table.");
-
- size = ehdr->e_phnum * sizeof **phdrs;
- if (!(*phdrs = calloc(1,size)))
- return err("Out of memory!");
-
- errno = 0;
- if (read(fd, *phdrs, size) != (ssize_t)size)
- return ferr("missing or incomplete program segment header table.");
-
- return TRUE;
-}
-
-/* getmemorysize() determines the offset of the last byte of the file
- * that is referenced by an entry in the program segment header table.
- * (Anything in the file after that point is not used when the program
- * is executing, and thus can be safely discarded.)
- */
-static int getmemorysize_32(Elf32_Ehdr const *ehdr, Elf32_Phdr const *phdrs,
- unsigned long *newsize)
-{
- Elf32_Phdr const *phdr;
- unsigned long size, n;
- unsigned int i;
-
- /* Start by setting the size to include the ELF header and the
- * complete program segment header table.
- */
- size = ehdr->e_phoff + ehdr->e_phnum * sizeof *phdrs;
- if (size < sizeof *ehdr)
- size = sizeof *ehdr;
-
- /* Then keep extending the size to include whatever data the
- * program segment header table references.
- */
- for (i = 0, phdr = phdrs ; i < ehdr->e_phnum ; ++i, ++phdr) {
- if (phdr->p_type != PT_NULL) {
- n = phdr->p_offset + phdr->p_filesz;
- if (n > size)
- size = n;
- }
- }
-
- *newsize = size;
- return TRUE;
-}
-
-static int getmemorysize_64(Elf64_Ehdr const *ehdr, Elf64_Phdr const *phdrs,
- unsigned long *newsize)
-{
- Elf64_Phdr const *phdr;
- unsigned long size, n;
- unsigned int i;
-
- /* Start by setting the size to include the ELF header and the
- * complete program segment header table.
- */
- size = ehdr->e_phoff + ehdr->e_phnum * sizeof *phdrs;
- if (size < sizeof *ehdr)
- size = sizeof *ehdr;
-
- /* Then keep extending the size to include whatever data the
- * program segment header table references.
- */
- for (i = 0, phdr = phdrs ; i < ehdr->e_phnum ; ++i, ++phdr) {
- if (phdr->p_type != PT_NULL) {
- n = phdr->p_offset + phdr->p_filesz;
- if (n > size)
- size = n;
- }
- }
-
- *newsize = size;
- return TRUE;
-}
-
-/* truncatezeros() examines the bytes at the end of the file's
- * size-to-be, and reduces the size to exclude any trailing zero
- * bytes.
- */
-static int truncatezeros(int fd, unsigned long *newsize)
-{
- unsigned char contents[1024];
- unsigned long size, n;
-
- size = *newsize;
- do {
- n = sizeof contents;
- if (n > size)
- n = size;
- if (lseek(fd, size - n, SEEK_SET) == (off_t)-1)
- return ferr("cannot seek in file.");
- if (read(fd, contents, n) != (ssize_t)n)
- return ferr("cannot read file contents");
- while (n && !contents[--n])
- --size;
- } while (size && !n);
-
- /* Sanity check.
- */
- if (!size)
- return err("ELF file is completely blank!");
-
- *newsize = size;
- return TRUE;
-}
-
-/* modifyheaders() removes references to the section header table if
- * it was stripped, and reduces program header table entries that
- * included truncated bytes at the end of the file.
- */
-static int modifyheaders_32(Elf32_Ehdr *ehdr, Elf32_Phdr *phdrs,
- unsigned long newsize)
-{
- Elf32_Phdr *phdr;
- unsigned int i;
-
- /* If the section header table is gone, then remove all references
- * to it in the ELF header.
- */
- if (ehdr->e_shoff >= newsize) {
- ehdr->e_shoff = 0;
- ehdr->e_shnum = 0;
- ehdr->e_shentsize = 0;
- ehdr->e_shstrndx = 0;
- }
-
- /* The program adjusts the file size of any segment that was
- * truncated. The case of a segment being completely stripped out
- * is handled separately.
- */
- for (i = 0, phdr = phdrs ; i < ehdr->e_phnum ; ++i, ++phdr) {
- if (phdr->p_offset >= newsize) {
- phdr->p_offset = newsize;
- phdr->p_filesz = 0;
- } else if (phdr->p_offset + phdr->p_filesz > newsize) {
- phdr->p_filesz = newsize - phdr->p_offset;
- }
- }
-
- return TRUE;
-}
-
-static int modifyheaders_64(Elf64_Ehdr *ehdr, Elf64_Phdr *phdrs,
- unsigned long newsize)
-{
- Elf64_Phdr *phdr;
- unsigned int i;
-
- /* If the section header table is gone, then remove all references
- * to it in the ELF header.
- */
- if (ehdr->e_shoff >= newsize) {
- ehdr->e_shoff = 0;
- ehdr->e_shnum = 0;
- ehdr->e_shentsize = 0;
- ehdr->e_shstrndx = 0;
- }
-
- /* The program adjusts the file size of any segment that was
- * truncated. The case of a segment being completely stripped out
- * is handled separately.
- */
- for (i = 0, phdr = phdrs ; i < ehdr->e_phnum ; ++i, ++phdr) {
- if (phdr->p_offset >= newsize) {
- phdr->p_offset = newsize;
- phdr->p_filesz = 0;
- } else if (phdr->p_offset + phdr->p_filesz > newsize) {
- phdr->p_filesz = newsize - phdr->p_offset;
- }
- }
-
- return TRUE;
-}
-
-/* commitchanges() writes the new headers back to the original file
- * and sets the file to its new size.
- */
-static int commitchanges_32(int fd, Elf32_Ehdr const *ehdr, Elf32_Phdr *phdrs,
- unsigned long newsize)
-{
- size_t n;
-
- /* Save the changes to the ELF header, if any.
- */
- if (lseek(fd, 0, SEEK_SET))
- return ferr("could not rewind file");
- errno = 0;
- if (write(fd, ehdr, sizeof *ehdr) != sizeof *ehdr)
- return err("could not modify file");
-
- /* Save the changes to the program segment header table, if any.
- */
- if (lseek(fd, ehdr->e_phoff, SEEK_SET) == (off_t)-1) {
- err("could not seek in file.");
- goto warning;
- }
- n = ehdr->e_phnum * sizeof *phdrs;
- if (write(fd, phdrs, n) != (ssize_t)n) {
- err("could not write to file");
- goto warning;
- }
-
- /* Eleventh-hour sanity check: don't truncate before the end of
- * the program segment header table.
- */
- if (newsize < ehdr->e_phoff + n)
- newsize = ehdr->e_phoff + n;
-
- /* Chop off the end of the file.
- */
- if (ftruncate(fd, newsize)) {
- err("could not resize file");
- goto warning;
- }
-
- return TRUE;
-
- warning:
- return err("ELF file may have been corrupted!");
-}
-
-static int commitchanges_64(int fd, Elf64_Ehdr const *ehdr, Elf64_Phdr *phdrs,
- unsigned long newsize)
-{
- size_t n;
-
- /* Save the changes to the ELF header, if any.
- */
- if (lseek(fd, 0, SEEK_SET))
- return ferr("could not rewind file");
- errno = 0;
- if (write(fd, ehdr, sizeof *ehdr) != sizeof *ehdr)
- return err("could not modify file");
-
- /* Save the changes to the program segment header table, if any.
- */
- if (lseek(fd, ehdr->e_phoff, SEEK_SET) == (off_t)-1) {
- err("could not seek in file.");
- goto warning;
- }
- n = ehdr->e_phnum * sizeof *phdrs;
- if (write(fd, phdrs, n) != (ssize_t)n) {
- err("could not write to file");
- goto warning;
- }
-
- /* Eleventh-hour sanity check: don't truncate before the end of
- * the program segment header table.
- */
- if (newsize < ehdr->e_phoff + n)
- newsize = ehdr->e_phoff + n;
-
- /* Chop off the end of the file.
- */
- if (ftruncate(fd, newsize)) {
- err("could not resize file");
- goto warning;
- }
-
- return TRUE;
-
- warning:
- return err("ELF file may have been corrupted!");
-}
-
-/* main() loops over the cmdline arguments, leaving all the real work
- * to the other functions.
- */
-int main(int argc, char *argv[])
-{
- int fd;
- int is_32bit_elf;
- Elf32_Ehdr ehdr32;
- Elf32_Phdr *phdrs32 = NULL;
- Elf64_Ehdr ehdr64;
- Elf64_Phdr *phdrs64 = NULL;
- unsigned long newsize;
- char **arg;
- int failures = 0;
-
- if (argc < 2 || argv[1][0] == '-') {
- printf("Usage: sstrip FILE...\n"
- "sstrip discards all nonessential bytes from an executable.\n\n"
- "Version 2.0 Copyright (C) 2000,2001 Brian Raiter.\n"
- "This program is free software, licensed under the GNU\n"
- "General Public License. There is absolutely no warranty.\n");
- return EXIT_SUCCESS;
- }
-
- progname = argv[0];
-
- for (arg = argv + 1 ; *arg != NULL ; ++arg) {
- filename = *arg;
-
- fd = open(*arg, O_RDWR);
- if (fd < 0) {
- ferr("can't open");
- ++failures;
- continue;
- }
-
- if (readelfheader_32(fd, &ehdr32)) {
- is_32bit_elf = TRUE;
- }
- else if (readelfheader_64(fd, &ehdr64)) {
- is_32bit_elf = FALSE;
- }
- else {
- close(fd);
- return EXIT_FAILURE;
- }
-
- if (is_32bit_elf) {
- if (!(readphdrtable_32(fd, &ehdr32, &phdrs32) &&
- getmemorysize_32(&ehdr32, phdrs32, &newsize) &&
- truncatezeros(fd, &newsize) &&
- modifyheaders_32(&ehdr32, phdrs32, newsize) &&
- commitchanges_32(fd, &ehdr32, phdrs32, newsize)))
- ++failures;
- }
- else {
- if (!(readphdrtable_64(fd, &ehdr64, &phdrs64) &&
- getmemorysize_64(&ehdr64, phdrs64, &newsize) &&
- truncatezeros(fd, &newsize) &&
- modifyheaders_64(&ehdr64, phdrs64, newsize) &&
- commitchanges_64(fd, &ehdr64, phdrs64, newsize)))
- ++failures;
- }
-
- close(fd);
- }
-
- return failures ? EXIT_FAILURE : EXIT_SUCCESS;
-}
-
-#else
-
-int main()
-{
- return (EXIT_SUCCESS);
-}
-
-#endif
diff --git a/src/t-test0.c b/src/t-test0.c
index ed03554..034ca6e 100644
--- a/src/t-test0.c
+++ b/src/t-test0.c
@@ -165,7 +165,7 @@ mem_init(unsigned char *ptr, unsigned long size)
if(size == 0) return;
#if TEST > 3
- memset(ptr, '\0', size);
+ memset(ptr, 0, size);
#endif
for(i=0; i<size; i+=2047) {
j = (unsigned long)ptr ^ i;
@@ -389,7 +389,7 @@ malloc_test(unsigned long size, int bins, int max)
#endif
actions = RANDOM(&ld, ACTIONS_MAX);
#if USE_MALLOC && MALLOC_DEBUG
- if(actions < 2) { mallinfo(); }
+ if(actions < 2) { mallinfo2(); }
#endif
for(j=0; j<actions; j++) {
b = RANDOM(&ld, p.bins);
diff --git a/src/t-test1.c b/src/t-test1.c
index 942f81d..9b3ebec 100644
--- a/src/t-test1.c
+++ b/src/t-test1.c
@@ -498,7 +498,7 @@ malloc_test(struct thread_st *st)
#endif
actions = RANDOM(&ld, ACTIONS_MAX);
#if USE_MALLOC && MALLOC_DEBUG
- if(actions < 2) { mallinfo(); }
+ if(actions < 2) { mallinfo2(); }
#endif
for(j=0; j<actions; j++) {
b = RANDOM(&ld, p.bins);
diff --git a/src/yulectl.c b/src/yulectl.c
index 50a837b..8948695 100644
--- a/src/yulectl.c
+++ b/src/yulectl.c
@@ -47,8 +47,10 @@
#define SH_REQ_PASSWORD 1
#endif
+#define SH_PW_SIZE 15
+
static int sock = -1;
-static char password[15] = "";
+static char password[SH_PW_SIZE] = "";
static int verbose = 0;
#ifdef SH_STEALTH
@@ -122,13 +124,10 @@ termination_handler (int signum)
static char * safe_copy(char * to, const char * from, size_t size)
{
- if (to && from)
+ if (to && from && (size > 0))
{
- strncpy (to, from, size);
- if (size > 0)
- to[size-1] = '\0';
- else
- *to = '\0';
+ strncpy (to, from, size-1);
+ to[size-1] = '\0';
}
return to;
}
@@ -143,7 +142,13 @@ static int send_to_server (char * serversock, char * message)
/* Initialize the server socket address.
*/
name.sun_family = AF_UNIX;
- strncpy (name.sun_path, serversock, sizeof(name.sun_path) - 1);
+ memcpy(name.sun_path, serversock, sizeof(name.sun_path));
+ name.sun_path[sizeof(name.sun_path)-1] = '\0';
+ if (strlen(serversock) > strlen(name.sun_path))
+ {
+ perror (_("ERROR: socket path too long"));
+ return -1;
+ }
size = (offsetof (struct sockaddr_un, sun_path)
+ strlen (name.sun_path) + 1);
@@ -400,7 +405,7 @@ static int get_passwd(char * message2, size_t size)
/* 1) Password from environment
*/
pw = getenv(_("YULECTL_PASSWORD"));
- if (pw && strlen(pw) < 15)
+ if (pw && strlen(pw) < SH_PW_SIZE)
{
strcpy(password, pw);
strcpy(message2, password);
@@ -412,7 +417,7 @@ static int get_passwd(char * message2, size_t size)
if (get_home(home, sizeof(home)) < 0)
return -1;
- if ( (strlen(home) + strlen(_("/.yulectl_cred")) + 1) > 4096)
+ if ( (strlen(home) + strlen(_("/.yulectl_cred")) + 1) > sizeof(home))
{
fprintf (stderr, "%s", _("ERROR: path for $HOME is too long.\n"));
return -1;
@@ -450,7 +455,7 @@ static int get_passwd(char * message2, size_t size)
(void) rtrim(message2);
- if (strlen(message2) > 14)
+ if (strlen(message2) > (SH_PW_SIZE -1))
{
fprintf (stderr, "%s",
_("ERROR: Password too long (max. 14 characters).\n"));