source: trunk/src/sh_unix.c @ 227

Last change on this file since 227 was 227, checked in by katerina, 13 years ago

Fix warnings with -fstack-check

File size: 118.3 KB
Line 
1/* SAMHAIN file system integrity testing                                   */
2/* Copyright (C) 1999 Rainer Wichmann                                      */
3/*                                                                         */
4/*  This program is free software; you can redistribute it                 */
5/*  and/or modify                                                          */
6/*  it under the terms of the GNU General Public License as                */
7/*  published by                                                           */
8/*  the Free Software Foundation; either version 2 of the License, or      */
9/*  (at your option) any later version.                                    */
10/*                                                                         */
11/*  This program is distributed in the hope that it will be useful,        */
12/*  but WITHOUT ANY WARRANTY; without even the implied warranty of         */
13/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
14/*  GNU General Public License for more details.                           */
15/*                                                                         */
16/*  You should have received a copy of the GNU General Public License      */
17/*  along with this program; if not, write to the Free Software            */
18/*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
19
20#include "config_xor.h"
21
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <ctype.h>
27#ifdef HAVE_LINUX_FS_H
28#include <linux/fs.h>
29#endif
30
31#ifdef HAVE_MEMORY_H
32#include <memory.h>
33#endif
34
35#ifdef  HAVE_UNISTD_H
36#include <errno.h>
37#include <signal.h>
38#include <pwd.h>
39#include <grp.h>
40#include <sys/types.h>
41#include <sys/stat.h>
42#include <sys/resource.h>
43#include <fcntl.h>
44#include <unistd.h>
45/* need to undef these, since the #define's may be picked up from
46 * linux/wait.h, and will clash with a typedef in sys/wait.h
47 */
48#undef P_ALL
49#undef P_PID
50#undef P_PGID
51#include <sys/wait.h>
52
53/*********************
54#ifdef HAVE_SYS_VFS_H
55#include <sys/vfs.h>
56#endif
57**********************/
58#endif
59
60#if TIME_WITH_SYS_TIME
61#include <sys/time.h>
62#include <time.h>
63#else
64#if HAVE_SYS_TIME_H
65#include <sys/time.h>
66#else
67#include <time.h>
68#endif
69#endif
70
71#ifdef HAVE_SYS_SELECT_H
72#include <sys/select.h>
73#endif
74
75#ifndef FD_SET
76#define NFDBITS         32
77#define FD_SET(n, p)    ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
78#define FD_CLR(n, p)    ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
79#define FD_ISSET(n, p)  ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
80#endif /* !FD_SET */
81#ifndef FD_SETSIZE
82#define FD_SETSIZE      32
83#endif
84#ifndef FD_ZERO
85#define FD_ZERO(p)      memset((char *)(p), '\0', sizeof(*(p)))
86#endif
87
88
89#if defined(HAVE_MLOCK) && !defined(HAVE_BROKEN_MLOCK)
90#include <sys/mman.h>
91#endif
92
93#include "samhain.h"
94#include "sh_error.h"
95#include "sh_unix.h"
96#include "sh_utils.h"
97#include "sh_mem.h"
98#include "sh_hash.h"
99#include "sh_tools.h"
100#include "sh_tiger.h"
101#include "sh_prelink.h"
102#include "sh_pthread.h"
103
104/* moved here from far below
105 */
106#include <netdb.h>
107
108#define SH_NEED_PWD_GRP
109#define SH_NEED_GETHOSTBYXXX
110#include "sh_static.h"
111
112#ifndef HAVE_LSTAT
113#define lstat   stat
114#endif
115 
116#if defined(S_IFLNK) && !defined(S_ISLNK)
117#define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
118#else
119#if !defined(S_ISLNK)
120#define S_ISLNK(mode) (0)
121#endif
122#endif
123
124#if defined(S_IFSOCK) && !defined(S_ISSOCK)
125#define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
126#else
127#if !defined(S_ISSOCK)
128#define S_ISSOCK(mode) (0)
129#endif
130#endif
131
132#if defined(S_IFDOOR) && !defined(S_ISDOOR)
133#define S_ISDOOR(mode) (((mode) & S_IFMT) == S_IFDOOR)
134#else
135#if !defined(S_ISDOOR)
136#define S_ISDOOR(mode) (0)
137#endif
138#endif
139
140#if defined(S_IFPORT) && !defined(S_ISPORT)
141#define S_ISPORT(mode) (((mode) & S_IFMT) == S_IFPORT)
142#else
143#if !defined(S_ISPORT)
144#define S_ISPORT(mode) (0)
145#endif
146#endif
147
148#define SH_KEY_NULL _("000000000000000000000000000000000000000000000000")
149
150#undef  FIL__
151#define FIL__  _("sh_unix.c")
152
153unsigned long mask_PRELINK      = MASK_PRELINK_;
154unsigned long mask_USER0        = MASK_USER_;
155unsigned long mask_USER1        = MASK_USER_;
156unsigned long mask_USER2        = MASK_USER_;
157unsigned long mask_USER3        = MASK_USER_;
158unsigned long mask_USER4        = MASK_USER_;
159unsigned long mask_ALLIGNORE    = MASK_ALLIGNORE_;
160unsigned long mask_ATTRIBUTES   = MASK_ATTRIBUTES_;
161unsigned long mask_LOGFILES     = MASK_LOGFILES_;
162unsigned long mask_LOGGROW      = MASK_LOGGROW_;
163unsigned long mask_READONLY     = MASK_READONLY_;
164unsigned long mask_NOIGNORE     = MASK_NOIGNORE_;
165
166
167extern char **environ;
168
169int sh_unix_maskreset()
170{
171  mask_PRELINK      = MASK_PRELINK_;
172  mask_USER0        = MASK_USER_;
173  mask_USER1        = MASK_USER_;
174  mask_USER2        = MASK_USER_;
175  mask_USER3        = MASK_USER_;
176  mask_USER4        = MASK_USER_;
177  mask_ALLIGNORE    = MASK_ALLIGNORE_;
178  mask_ATTRIBUTES   = MASK_ATTRIBUTES_;
179  mask_LOGFILES     = MASK_LOGFILES_;
180  mask_LOGGROW      = MASK_LOGGROW_;
181  mask_READONLY     = MASK_READONLY_;
182  mask_NOIGNORE     = MASK_NOIGNORE_;
183  return 0;
184}
185
186
187#ifdef SYS_SIGLIST_DECLARED
188/* extern const char * const sys_siglist[]; */
189#else
190char * sh_unix_siglist (int signum)
191{
192  switch (signum)
193    {
194#ifdef SIGHUP
195    case SIGHUP: 
196      return _("Hangup");
197#endif
198#ifdef SIGINT
199    case SIGINT: 
200      return _("Interrupt");
201#endif
202#ifdef SIGQUIT
203    case SIGQUIT: 
204      return _("Quit");
205#endif
206#ifdef SIGILL
207    case SIGILL: 
208      return _("Illegal instruction");
209#endif
210#ifdef SIGTRAP
211    case SIGTRAP: 
212      return _("Trace/breakpoint trap");
213#endif
214#ifdef SIGABRT
215    case SIGABRT: 
216      return _("IOT trap/Abort");
217#endif
218#ifdef SIGBUS
219    case SIGBUS: 
220      return _("Bus error");
221#endif
222#ifdef SIGFPE
223    case SIGFPE: 
224      return _("Floating point exception");
225#endif
226#ifdef SIGUSR1
227    case SIGUSR1: 
228      return _("User defined signal 1");
229#endif
230#ifdef SIGSEGV
231    case SIGSEGV: 
232      return _("Segmentation fault");
233#endif
234#ifdef SIGUSR2
235    case SIGUSR2: 
236      return _("User defined signal 2");
237#endif
238#ifdef SIGPIPE
239    case SIGPIPE: 
240      return _("Broken pipe");
241#endif
242#ifdef SIGALRM
243    case SIGALRM: 
244      return _("Alarm clock");
245#endif
246#ifdef SIGTERM
247    case SIGTERM: 
248      return _("Terminated");
249#endif
250#ifdef SIGSTKFLT
251    case SIGSTKFLT: 
252      return _("Stack fault");
253#endif
254#ifdef SIGCHLD
255    case SIGCHLD: 
256      return _("Child exited");
257#endif
258#ifdef SIGCONT
259    case SIGCONT: 
260      return _("Continued");
261#endif
262#ifdef SIGSTOP
263    case SIGSTOP: 
264      return _("Stopped");
265#endif
266#ifdef SIGTSTP
267    case SIGTSTP: 
268      return _("Stop typed at tty");
269#endif
270#ifdef SIGTTIN
271    case SIGTTIN: 
272      return _("Stopped (tty input)");
273#endif
274#ifdef SIGTTOU
275    case SIGTTOU: 
276      return _("Stopped (tty output)");
277#endif
278#ifdef SIGURG
279    case SIGURG: 
280      return _("Urgent condition");
281#endif
282#ifdef SIGXCPU
283    case SIGXCPU: 
284      return _("CPU time limit exceeded");
285#endif
286#ifdef SIGXFSZ
287    case SIGXFSZ: 
288      return _("File size limit exceeded");
289#endif
290#ifdef SIGVTALRM
291    case SIGVTALRM: 
292      return _("Virtual time alarm");
293#endif
294#ifdef SIGPROF
295    case SIGPROF: 
296      return _("Profile signal");
297#endif
298#ifdef SIGWINCH
299    case SIGWINCH: 
300      return _("Window size changed");
301#endif
302#ifdef SIGIO
303    case SIGIO: 
304      return _("Possible I/O");
305#endif
306#ifdef SIGPWR
307    case SIGPWR: 
308      return _("Power failure");
309#endif
310#ifdef SIGUNUSED
311    case SIGUNUSED: 
312      return _("Unused signal");
313#endif
314    }
315  return _("Unknown");
316}
317#endif
318
319
320/* Log from within a signal handler without using any
321 * functions that are not async signal safe.
322 *
323 * This is the safe_itoa helper function.
324 */
325char * safe_itoa(int i, char * str, int size)
326{
327  unsigned int u;
328  int iisneg = 0;
329  char *p = &str[size-1];
330 
331  *p = '\0';
332  if (i < 0) {
333    iisneg = 1;
334    u = ((unsigned int)(-(1+i))) + 1;
335  } else {
336    u = i;
337  }
338  do {
339    --p;
340    *p = '0' + (u % 10);
341    u /= 10;
342  } while (u && (p != str));
343  if ((iisneg == 1) && (p != str)) {
344    --p;
345    *p = '-';
346  }
347  return p;
348}
349
350/* Log from within a signal handler without using any
351 * functions that are not async signal safe.
352 *
353 * This is the safe_logger function.
354 * Arguments: signal (signal number), method (0=logger, 1=stderr), thepid (pid)
355 */
356extern int OnlyStderr; 
357
358int safe_logger (int thesignal, int method, char * details)
359{
360  unsigned int i = 0;
361  int status = -1;
362  struct stat buf;
363  pid_t  newpid;
364  char  str[128];
365  char  * p;
366 
367  char l0[64], l1[64], l2[64], l3[64];
368  char a0[32], a1[32], a2[32];
369  char e0[128];
370  char msg[128];
371 
372  char * locations[] = { NULL, NULL, NULL, NULL, NULL };
373  char * envp[]      = { NULL, NULL };
374  char * argp[]      = { NULL, NULL, NULL, NULL, NULL };
375 
376  pid_t  thepid = getpid();
377 
378  if ((sh.flag.isdaemon == S_FALSE) || (OnlyStderr == S_TRUE))
379    method = 1;
380 
381  /* seems that solaris cc needs this way of initializing ...
382   */
383  locations[0] = l0;
384  locations[1] = l1;
385  locations[2] = l2;
386  locations[3] = l3;
387 
388  envp[0] = e0;
389 
390  argp[0] = a0;
391  argp[1] = a1;
392  argp[2] = a2;
393 
394  sl_strlcpy(msg, _("samhain["), 128);
395  p = safe_itoa((int) thepid, str, 128);
396  if (p && *p)
397    sl_strlcat(msg, p, 128);
398  if (thesignal == 0)
399    {
400      if (details == NULL) {
401        sl_strlcat(msg, _("]: out of memory"), 128);
402      } else {
403        sl_strlcat(msg, _("]: "), 128);
404        sl_strlcat(msg, details, 128);
405      }
406    }
407  else 
408    {
409      sl_strlcat(msg, _("]: exit on signal "), 128);
410      p = safe_itoa(thesignal, str, 128);
411      if (p && *p)
412        sl_strlcat(msg, p, 128);
413    }
414
415  if (method == 1) {
416#ifndef STDERR_FILENO
417#define STDERR_FILENO 2
418#endif
419    int retval = 0;
420    do {
421      retval = write(STDERR_FILENO,  msg, strlen(msg));
422    } while (retval < 0 && errno == EINTR);
423    do {
424      retval = write(STDERR_FILENO, "\n", 1);
425    } while (retval < 0 && errno == EINTR);
426    return 0;
427  }
428
429  sl_strlcpy (l0, _("/usr/bin/logger"), 64);
430  sl_strlcpy (l1, _("/usr/sbin/logger"), 64);
431  sl_strlcpy (l2, _("/usr/ucb/logger"), 64);
432  sl_strlcpy (l3, _("/bin/logger"), 64);
433
434  sl_strlcpy (a0, _("logger"), 32);
435  sl_strlcpy (a1, _("-p"), 32);
436  sl_strlcpy (a2, _("daemon.alert"), 32);
437
438  sl_strlcpy (e0,
439              _("PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/ucb:/usr/local/bin"),
440              128);
441
442  while (locations[i] != NULL) {
443    status = stat(locations[i], &buf);
444    if (status == 0)
445      break;
446    ++i;
447  }
448
449  if (locations[i] != NULL) {
450    argp[3] = msg;
451    newpid = fork();
452    if (newpid == 0) {
453      execve(locations[i], argp, envp);
454      _exit(1);
455    }
456    else if (newpid > 0) {
457      waitpid(newpid, &status, WUNTRACED);
458    }
459  }
460  return 0;
461}
462
463void safe_fatal (const char * details, 
464                 const char * file, int line)
465{
466  char msg[128];
467  char str[128];
468  char * p;
469  int  thesignal = 0;
470  int  method = 0;
471
472  p = safe_itoa((int) line, str, 128);
473  sl_strlcpy(msg, _("FATAL: "), 128);
474  sl_strlcat(msg, file, 128);
475  sl_strlcat(msg, ": ", 128);
476  if (p && (*p)) {
477    sl_strlcat(msg, p   , 128);
478    sl_strlcat(msg, ": ", 128);
479  }
480  sl_strlcat(msg, details, 128);
481  (void) safe_logger (thesignal, method, msg);
482  raise(SIGKILL);
483}
484
485extern char sh_sig_msg[64];
486
487volatile int immediate_exit_normal = 0;
488
489#if defined(SA_SIGACTION_WORKS)
490static
491void sh_unix_sigexit (int mysignal, siginfo_t * signal_info, void * signal_add)
492#else
493static
494void sh_unix_sigexit (int mysignal)
495#endif
496{
497
498#if defined(SA_SIGACTION_WORKS)
499  if (signal_info != NULL && signal_info->si_code == SI_USER && 
500      mysignal != SIGTERM && mysignal != SIGINT) 
501    {
502      return;
503    }
504
505  /* avoid compiler warning (unused var)
506   */
507  (void) signal_add;
508#endif
509
510  /*
511   * Block re-entry
512   */
513  if (immediate_exit_normal > 0)
514    {
515      ++immediate_exit_normal;
516      if ((skey != NULL) && (immediate_exit_normal == 2))
517        memset (skey, '\0', sizeof(sh_key_t));
518      if (immediate_exit_normal == 2)
519        {
520          int val_return;
521
522          do {
523            val_return = chdir ("/");
524          } while (val_return < 0 && errno == EINTR);
525
526          safe_logger (mysignal, 0, NULL);
527        }
528      raise(SIGKILL);
529    }
530  else
531    {
532      immediate_exit_normal = 1;
533    }
534
535#ifdef SYS_SIGLIST_DECLARED
536  strncpy (sh_sig_msg, sys_siglist[mysignal],     40);
537#else
538  strncpy (sh_sig_msg, sh_unix_siglist(mysignal), 40);
539#endif
540  sh_sig_msg[63] = '\0';
541
542  ++sig_raised;
543  ++sig_urgent;
544  sig_termfast   = 1;
545  return;
546}
547
548volatile int immediate_exit_fast = 0;
549
550#if defined(SA_SIGACTION_WORKS)
551static
552void sh_unix_sigexit_fast (int mysignal, siginfo_t * signal_info, 
553                           void * signal_add)
554#else
555static
556void sh_unix_sigexit_fast (int mysignal)
557#endif
558{
559#if defined(SL_DEBUG) && (defined(USE_SYSTEM_MALLOC) || !defined(USE_MALLOC_LOCK))
560  int retval;
561#endif
562
563#if defined(SA_SIGACTION_WORKS)
564  if (signal_info != NULL && signal_info->si_code == SI_USER)
565    {
566      return;
567    }
568#endif
569
570  /* avoid compiler warning (unused var)
571   */
572#if defined(SA_SIGACTION_WORKS)
573  (void) signal_add;
574#endif
575
576  /* Check whether the heap is ok; otherwise _exit
577   */
578#if !defined(SL_DEBUG) || (!defined(USE_SYSTEM_MALLOC) && defined(USE_MALLOC_LOCK))
579  ++immediate_exit_fast;
580  if (skey != NULL && immediate_exit_fast < 2)
581    memset (skey, '\0', sizeof(sh_key_t));
582  if (immediate_exit_fast < 2)
583    safe_logger (mysignal, 0, NULL);
584  raise(SIGKILL);
585#else
586
587  /* debug code
588   */
589  if (immediate_exit_fast == 1)
590    {
591      ++immediate_exit_fast;
592      if (skey != NULL)
593        memset (skey, '\0', sizeof(sh_key_t));
594#ifdef WITH_MESSAGE_QUEUE
595      close_ipc ();
596#endif
597      safe_logger (mysignal, 0, NULL);
598      do {
599        retval = chdir ("/");
600      } while (retval < 0 && errno == EINTR);
601      raise(SIGFPE);
602    }
603  else if (immediate_exit_fast == 2)
604    {
605      do {
606        retval = chdir ("/");
607      } while (retval < 0 && errno == EINTR);
608      raise(SIGFPE);
609    }
610  else if (immediate_exit_fast != 0)
611    {
612      raise(SIGKILL);
613    }
614
615  ++immediate_exit_fast;
616 
617  /* The FPE|BUS|SEGV|ILL signals leave the system in an undefined
618   * state, thus it is best to exit immediately.
619   */
620#ifdef SYS_SIGLIST_DECLARED
621  strncpy (sh_sig_msg, sys_siglist[mysignal],     40);
622#else
623  strncpy (sh_sig_msg, sh_unix_siglist(mysignal), 40);
624#endif
625  sh_sig_msg[63] = '\0';
626
627  sl_stack_print();
628
629  /* Try to push out an error message.
630   */
631  sh_error_handle ((-1), FIL__, __LINE__, mysignal, MSG_EXIT_NORMAL, 
632                   sh.prg_name, sh_sig_msg);
633
634  if (skey != NULL)
635    memset (skey, '\0', sizeof(sh_key_t));
636#ifdef WITH_MESSAGE_QUEUE
637  close_ipc ();
638#endif
639
640  do {
641    retval = chdir ("/");
642  } while (retval < 0 && errno == EINTR);
643
644  raise(SIGFPE);
645#endif
646}
647
648
649static
650void sh_unix_sigaction (int mysignal)
651{
652  ++sig_raised;
653#ifdef SIGUSR1
654  if (mysignal == SIGUSR1)
655    sig_debug_switch       = 1;
656#endif
657#ifdef SIGUSR2
658  if (mysignal == SIGUSR2)
659    {
660      ++sig_suspend_switch;
661      ++sig_urgent;
662    }
663#endif
664#ifdef SIGHUP
665  if (mysignal == SIGHUP)
666    sig_config_read_again = 1;
667#endif
668#ifdef SIGTTOU
669  if (mysignal == SIGTTOU)
670    sig_force_check = 1;
671#endif
672#ifdef SIGABRT
673  if (mysignal == SIGABRT)
674    sig_fresh_trail       = 1;
675#endif
676#ifdef SIGQUIT
677  if (mysignal == SIGQUIT)
678    {
679      sig_terminate       = 1;
680      ++sig_urgent;
681    }
682#endif
683#ifdef SIGTERM
684  if (mysignal == SIGTERM)
685    {
686      strncpy (sh_sig_msg, _("Terminated"), 40);
687      sig_termfast          = 1;
688      ++sig_urgent;
689    }
690#endif
691
692  return;
693}
694
695static
696void sh_unix_siginstall (int goDaemon)
697{
698  struct sigaction act, act_fast, act2, oldact, ignact;
699#if defined (SH_WITH_SERVER)
700  (void) goDaemon;
701#endif
702
703  SL_ENTER(_("sh_unix_siginstall"));
704
705  ignact.sa_handler = SIG_IGN;            /* signal action           */
706  sigemptyset( &ignact.sa_mask );         /* set an empty mask       */
707  ignact.sa_flags = 0;                    /* init sa_flags           */
708
709#if defined(SA_SIGACTION_WORKS)
710  act.sa_sigaction = &sh_unix_sigexit;    /* signal action           */
711#else
712  act.sa_handler   = &sh_unix_sigexit;    /* signal action           */
713#endif
714
715  sigfillset ( &act.sa_mask );            /* set a  full mask        */
716
717
718  /* Block all but deadly signals.
719   */
720#ifdef SIGILL
721  sigdelset  ( &act.sa_mask, SIGILL  );
722#endif
723#ifndef SL_DEBUG
724#ifdef SIGFPE
725  sigdelset  ( &act.sa_mask, SIGFPE  );
726#endif
727#endif
728#ifdef SIGSEGV
729  sigdelset  ( &act.sa_mask, SIGSEGV );
730#endif
731#ifdef SIGBUS
732  sigdelset  ( &act.sa_mask, SIGBUS  );
733#endif
734
735#if defined(SA_SIGACTION_WORKS)
736  act_fast.sa_sigaction = &sh_unix_sigexit_fast;  /* signal action           */
737#else
738  act_fast.sa_handler   = &sh_unix_sigexit_fast;  /* signal action           */
739#endif
740
741  sigfillset ( &act_fast.sa_mask );               /* set a full mask         */
742
743#ifdef SIGILL
744  sigdelset  ( &act_fast.sa_mask, SIGILL  );
745#endif
746#ifndef SL_DEBUG
747#ifdef SIGFPE
748  sigdelset  ( &act_fast.sa_mask, SIGFPE  );
749#endif
750#endif
751#ifdef SIGSEGV
752  sigdelset  ( &act_fast.sa_mask, SIGSEGV );
753#endif
754#ifdef SIGBUS
755  sigdelset  ( &act_fast.sa_mask, SIGBUS  );
756#endif
757
758
759  /* Use siginfo to verify origin of signal, if possible.
760   */
761#if defined(SA_SIGACTION_WORKS)
762  act.sa_flags      = SA_SIGINFO;
763  act_fast.sa_flags = SA_SIGINFO;
764#else
765  act.sa_flags      = 0;
766  act_fast.sa_flags = 0;
767#endif
768
769  /* Do not block the signal from being received in its handler ...
770   * (is this a good or a bad idea ??).
771   */
772#if   defined(SA_NOMASK)
773  act_fast.sa_flags |= SA_NOMASK;
774#elif defined(SA_NODEFER)
775  act_fast.sa_flags |= SA_NODEFER;
776#endif
777
778
779  act2.sa_handler = &sh_unix_sigaction;  /* signal action           */
780  sigemptyset( &act2.sa_mask );          /* set an empty mask       */
781  act2.sa_flags = 0;                     /* init sa_flags           */
782
783  /* signals to control the daemon */
784
785#ifdef SIGHUP
786  retry_sigaction(FIL__, __LINE__, SIGHUP,     &act2, &oldact);
787#endif
788#ifdef SIGABRT
789  retry_sigaction(FIL__, __LINE__, SIGABRT,    &act2, &oldact);
790#endif
791#ifdef SIGUSR1
792  retry_sigaction(FIL__, __LINE__, SIGUSR1,    &act2, &oldact);
793#endif
794#ifdef SIGUSR2
795  retry_sigaction(FIL__, __LINE__, SIGUSR2,    &act2, &oldact);
796#endif
797#ifdef SIGQUIT
798  retry_sigaction(FIL__, __LINE__, SIGQUIT,    &act2, &oldact);
799#endif
800#ifdef SIGTERM
801  retry_sigaction(FIL__, __LINE__, SIGTERM,    &act,  &oldact);
802#endif
803
804  /* fatal signals that may cause termination */
805
806#ifdef SIGILL
807  retry_sigaction(FIL__, __LINE__, SIGILL,  &act_fast, &oldact);
808#endif
809#ifndef SL_DEBUG
810#ifdef SIGFPE
811  retry_sigaction(FIL__, __LINE__, SIGFPE,  &act_fast, &oldact);
812#endif
813#endif
814#ifdef SIGSEGV
815  retry_sigaction(FIL__, __LINE__, SIGSEGV, &act_fast, &oldact);
816#endif
817#ifdef SIGBUS
818  retry_sigaction(FIL__, __LINE__, SIGBUS,  &act_fast, &oldact);
819#endif
820
821  /* other signals  */
822
823#ifdef SIGINT
824  retry_sigaction(FIL__, __LINE__, SIGINT,       &act, &oldact);
825#endif
826#ifdef SIGPIPE
827#ifdef HAVE_PTHREAD
828  retry_sigaction(FIL__, __LINE__, SIGPIPE,   &ignact, &oldact);
829#else
830  retry_sigaction(FIL__, __LINE__, SIGPIPE,      &act, &oldact);
831#endif
832#endif
833#ifdef SIGALRM
834  retry_sigaction(FIL__, __LINE__, SIGALRM,   &ignact, &oldact);
835#endif
836#ifdef SIGTSTP
837  retry_sigaction(FIL__, __LINE__, SIGTSTP,   &ignact, &oldact);
838#endif
839#ifdef SIGTTIN
840  retry_sigaction(FIL__, __LINE__, SIGTTIN,   &ignact, &oldact);
841#endif
842#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
843#ifdef SIGTTOU
844  if (goDaemon == 1)
845    retry_sigaction(FIL__, __LINE__, SIGTTOU,     &act2, &oldact);
846  else
847    retry_sigaction(FIL__, __LINE__, SIGTTOU,   &ignact, &oldact);
848#endif
849#else
850#ifdef SIGTTOU
851  retry_sigaction(FIL__, __LINE__, SIGTTOU,   &ignact, &oldact);
852#endif
853#endif
854
855#ifdef SIGTRAP
856#if !defined(SCREW_IT_UP)
857  retry_sigaction(FIL__, __LINE__, SIGTRAP,      &act, &oldact);
858#endif
859#endif
860
861#ifdef SIGPOLL
862  retry_sigaction(FIL__, __LINE__, SIGPOLL,   &ignact, &oldact);
863#endif
864#if defined(SIGPROF) && !defined(SH_PROFILE)
865  retry_sigaction(FIL__, __LINE__, SIGPROF,   &ignact, &oldact);
866#endif
867#ifdef SIGSYS
868  retry_sigaction(FIL__, __LINE__, SIGSYS,       &act, &oldact);
869#endif
870#ifdef SIGURG
871  retry_sigaction(FIL__, __LINE__, SIGURG,    &ignact, &oldact);
872#endif
873#if defined(SIGVTALRM) && !defined(SH_PROFILE)
874  retry_sigaction(FIL__, __LINE__, SIGVTALRM, &ignact, &oldact);
875#endif
876#ifdef SIGXCPU
877  retry_sigaction(FIL__, __LINE__, SIGXCPU,      &act, &oldact);
878#endif
879#ifdef SIGXFSZ
880  retry_sigaction(FIL__, __LINE__, SIGXFSZ,      &act, &oldact);
881#endif
882
883#ifdef SIGEMT
884  retry_sigaction(FIL__, __LINE__, SIGEMT,    &ignact, &oldact);
885#endif
886#ifdef SIGSTKFLT
887  retry_sigaction(FIL__, __LINE__, SIGSTKFLT,    &act, &oldact);
888#endif
889#ifdef SIGIO
890  retry_sigaction(FIL__, __LINE__, SIGIO,     &ignact, &oldact);
891#endif
892#ifdef SIGPWR
893  retry_sigaction(FIL__, __LINE__, SIGPWR,       &act, &oldact);
894#endif
895
896#ifdef SIGLOST
897  retry_sigaction(FIL__, __LINE__, SIGLOST,   &ignact, &oldact);
898#endif
899#ifdef SIGUNUSED
900  retry_sigaction(FIL__, __LINE__, SIGUNUSED, &ignact, &oldact);
901#endif
902
903  SL_RET0(_("sh_unix_siginstall"));
904}
905
906/* ---------------------------------------------------------------- */
907
908/* checksum the own binary
909 */
910int sh_unix_self_hash (const char * c)
911{
912  char message[512];
913  char hashbuf[KEYBUF_SIZE];
914
915  SL_ENTER(_("sh_unix_self_hash"));
916
917  if (c == NULL)
918    {
919      sh.exec.path[0] = '\0';
920      SL_RETURN((0), _("sh_unix_self_hash"));
921    }
922  sl_strlcpy(sh.exec.path, c, SH_PATHBUF);
923
924  sl_strlcpy(sh.exec.hash,
925             sh_tiger_hash (c, TIGER_FILE, TIGER_NOLIM, hashbuf, sizeof(hashbuf)), 
926             KEY_LEN+1);
927  sl_snprintf(message, 512, _("%s has checksum: %s"),
928              sh.exec.path, sh.exec.hash);
929  message[511] = '\0';
930  sh_error_handle(SH_ERR_INFO, FIL__, __LINE__, 0, MSG_E_SUBGEN,
931                  message, _("sh_unix_self_hash"));
932  if (0 == sl_strcmp(sh.exec.hash, SH_KEY_NULL ))
933    {
934      dlog(1, FIL__, __LINE__, 
935           _("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"), 
936           sh.exec.path, sl_get_errmsg(), (int) sl_ret_euid());
937      sh_error_handle ((-1), FIL__, __LINE__, EACCES, MSG_NOACCESS,
938                       (long) sh.real.uid, c);
939      aud_exit (FIL__, __LINE__, EXIT_FAILURE);
940    }
941  SL_RETURN((0), _("sh_unix_self_hash"));
942}
943
944int sh_unix_self_check ()
945{
946  char newhash[KEY_LEN+1];
947  char message[512];
948  char hashbuf[KEYBUF_SIZE];
949
950  SL_ENTER(_("sh_unix_self_check"));
951  if (sh.exec.path == NULL || sh.exec.path[0] == '\0')
952    SL_RETURN((0), _("sh_unix_self_check"));
953
954  sl_strlcpy(newhash, 
955             sh_tiger_hash (sh.exec.path, TIGER_FILE, TIGER_NOLIM, hashbuf, sizeof(hashbuf)), 
956             KEY_LEN+1);
957  if (0 == sl_strncmp(sh.exec.hash, 
958                      newhash,
959                      KEY_LEN))
960    SL_RETURN((0), _("sh_unix_self_check"));
961
962 
963  dlog(1, FIL__, __LINE__, 
964       _("The checksum of the executable: %s has changed since startup (%s -> %s).\n"),
965       sh.exec.path, sh.exec.hash, newhash);
966
967  sl_snprintf(message, 512, 
968              _("The checksum of %s has changed since startup (%s -> %s)"),
969              sh.exec.path, sh.exec.hash, newhash);
970  message[511] = '\0';
971
972  sh_error_handle(SH_ERR_INFO, FIL__, __LINE__, 0, MSG_E_SUBGEN,
973                  message, _("sh_unix_self_check"));
974  sh_error_handle ((-1), FIL__, __LINE__, EACCES, MSG_E_AUTH,
975                   sh.exec.path);
976  SL_RETURN((-1), _("sh_unix_self_check"));
977}
978
979
980/* ---------------------------------------------------------------- */
981
982
983/* added    Tue Feb 22 10:36:44 NFT 2000 Rainer Wichmann            */
984static int tf_add_trusted_user_int(const char * c)
985{
986  struct passwd *          w;
987  int                           count;
988  uid_t                     pwid  = (uid_t)-1;
989
990#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
991  struct passwd    pwd;
992  char           * buffer;
993#endif
994 
995  SL_ENTER(_("tf_add_trusted_user_int"));
996
997  /* First check for a user name.
998   */
999#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
1000  buffer = SH_ALLOC(SH_PWBUF_SIZE);
1001  sh_getpwnam_r(c, &pwd, buffer, SH_PWBUF_SIZE, &w);
1002#else
1003  w = sh_getpwnam(c);
1004#endif
1005
1006  if ((w != NULL) && ((pwid = w->pw_uid) > 0))
1007    goto succe;
1008       
1009  /* Failed, so check for a numerical value.
1010   */
1011  pwid = strtol(c, (char **)NULL, 10);
1012  if (pwid > 0 && pwid < 65535)
1013    goto succe;
1014     
1015  sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS, 
1016                   _("add trusted user"), c);
1017#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
1018  SH_FREE(buffer);
1019#endif
1020  SL_RETURN((-1), _("tf_add_trusted_user_int"));
1021
1022 succe:
1023  count = sl_trust_add_user(pwid);
1024#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
1025  SH_FREE(buffer);
1026#endif
1027  SL_RETURN((count), _("tf_add_trusted_user_int"));
1028}
1029
1030int tf_add_trusted_user(const char * c)
1031{
1032  int    i;
1033  char * q;
1034  char * p = sh_util_strdup (c);
1035#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
1036  char * saveptr;
1037#endif
1038
1039  SL_ENTER(_("tf_add_trusted_user"));
1040
1041#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
1042  q = strtok_r(p, ", \t", &saveptr);
1043#else
1044  q = strtok(p, ", \t");
1045#endif
1046  if (!q)
1047    {
1048      SH_FREE(p);
1049      SL_RETURN((-1), _("tf_add_trusted_user"));
1050    }
1051  while (q)
1052    {
1053      i = tf_add_trusted_user_int(q);
1054      if (SL_ISERROR(i))
1055        {
1056          SH_FREE(p);
1057          SL_RETURN((i), _("tf_add_trusted_user"));
1058        }
1059#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
1060      q = strtok_r(NULL, ", \t", &saveptr);
1061#else
1062      q = strtok(NULL, ", \t");
1063#endif
1064    }
1065  SH_FREE(p);
1066  SL_RETURN((0), _("tf_add_trusted_user"));
1067}
1068
1069extern uid_t   sl_trust_baduid(void);
1070extern gid_t   sl_trust_badgid(void);
1071
1072#if defined(HOST_IS_CYGWIN) || defined(__cygwin__) || defined(__CYGWIN32__) || defined(__CYGWIN__)
1073int tf_trust_check (const char * file, int mode)
1074{
1075  (void) file;
1076  (void) mode;
1077  return 0;
1078}
1079#else
1080int tf_trust_check (const char * file, int mode)
1081{
1082  char * tmp;
1083  char * tmp2;
1084  char * p;
1085  int    status;
1086  int    level;
1087  uid_t  ff_euid;
1088
1089  SL_ENTER(_("tf_trust_check"));
1090
1091  if (mode == SL_YESPRIV)
1092    sl_get_euid(&ff_euid);
1093  else
1094    sl_get_ruid(&ff_euid);
1095
1096#if defined(SH_WITH_SERVER)
1097  if (0 == sl_ret_euid())   /* privileges not dropped yet */
1098    {
1099#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
1100      struct passwd    pwd;
1101      char          *  buffer = SH_ALLOC(SH_PWBUF_SIZE);
1102      struct passwd *  tempres;
1103      sh_getpwnam_r(DEFAULT_IDENT, &pwd, buffer, SH_PWBUF_SIZE, &tempres);
1104#else
1105      struct passwd * tempres = sh_getpwnam(DEFAULT_IDENT);
1106#endif
1107
1108      if (!tempres)
1109        {
1110          dlog(1, FIL__, __LINE__, 
1111               _("User %s does not exist. Please add the user to your system.\n"), 
1112               DEFAULT_IDENT);
1113          aud_exit (FIL__, __LINE__, EXIT_FAILURE);
1114        }
1115      ff_euid = tempres->pw_uid;
1116#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
1117      SH_FREE(buffer);
1118#endif
1119    }
1120#endif
1121
1122  status = sl_trustfile_euid(file, ff_euid);
1123
1124  if ( SL_ENONE != status) 
1125    {
1126      if (status == SL_ESTAT) 
1127        level = SH_ERR_ALL;
1128      else
1129        level = SH_ERR_ERR;
1130
1131      tmp  = sh_util_safe_name (file);
1132      p    = sl_trust_errfile();
1133      if (p && *p != '\0')
1134        {
1135          tmp2  = sh_util_safe_name (sl_trust_errfile());
1136          sh_error_handle(level, FIL__, __LINE__, status, MSG_E_TRUST2,
1137                          sl_error_string(status), tmp, tmp2);
1138          SH_FREE(tmp2); 
1139        }
1140      else
1141        {
1142          sh_error_handle(level, FIL__, __LINE__, status, MSG_E_TRUST1,
1143                          sl_error_string(status), tmp);
1144        }
1145      SH_FREE(tmp);
1146
1147      if (status == SL_EBADUID   || status == SL_EBADGID || 
1148          status == SL_EBADOTH   || status == SL_ETRUNC  || 
1149          status == SL_EINTERNAL )
1150        {
1151          switch (status) {
1152          case SL_EINTERNAL:
1153            dlog(1, FIL__, __LINE__, 
1154                 _("An internal error occured in the trustfile function.\n"));
1155            break;
1156          case SL_ETRUNC:
1157            tmp  = sh_util_safe_name (file);
1158            dlog(1, FIL__, __LINE__, 
1159                 _("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"), 
1160                 tmp);
1161            SH_FREE(tmp);
1162            break;
1163          case SL_EBADOTH:
1164            tmp  = sh_util_safe_name (file);
1165            p    = sl_trust_errfile();
1166            dlog(1, FIL__, __LINE__, 
1167                 _("The path element: %s\nin the filename: %s is world writeable.\n"),
1168                 p, tmp);
1169            SH_FREE(tmp);
1170            break;
1171          case SL_EBADUID:
1172            tmp  = sh_util_safe_name (file);
1173            p    = sl_trust_errfile();
1174            dlog(1, FIL__, __LINE__, 
1175                 _("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"),
1176                 (UID_CAST)sl_trust_baduid(), p, tmp);
1177            SH_FREE(tmp);
1178            break;
1179          case SL_EBADGID:
1180            tmp  = sh_util_safe_name (file);
1181            p    = sl_trust_errfile();
1182            dlog(1, FIL__, __LINE__, 
1183                 _("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"),
1184                 p, tmp, (UID_CAST)sl_trust_badgid(), 
1185                 (UID_CAST)sl_trust_baduid());
1186            SH_FREE(tmp);
1187            break;
1188          default:
1189            break;
1190          }
1191           
1192          SL_RETURN((-1), _("tf_trust_check"));
1193        }
1194    }
1195
1196  SL_RETURN((0), _("tf_trust_check"));
1197}
1198#endif
1199
1200#ifdef HAVE_INITGROUPS
1201#ifdef HOST_IS_OSF
1202int  sh_unix_initgroups (      char * in_user, gid_t in_gid)
1203#else
1204int  sh_unix_initgroups (const char * in_user, gid_t in_gid)
1205#endif
1206{
1207  int status  = -1;
1208  status = sh_initgroups (in_user, in_gid);
1209  if (status < 0)
1210    {
1211      if (errno == EPERM)
1212        return 0;
1213      if (errno == EINVAL)
1214        return 0;
1215      return -1;
1216    }
1217  return 0;
1218}
1219#else
1220int  sh_unix_initgroups (const char * in_user, gid_t in_gid)
1221{
1222  (void) in_user;
1223  (void) in_gid;
1224  return 0;
1225}
1226#endif
1227
1228#ifdef HAVE_INITGROUPS
1229char *  sh_unix_getUIDname (int level, uid_t uid, char * out, size_t len);
1230int  sh_unix_initgroups2 (uid_t in_pid, gid_t in_gid)
1231{
1232  int status  = -1;
1233  char user[SH_MINIBUF];
1234
1235  SL_ENTER(_("sh_unix_initgroups2"));
1236
1237  if (NULL == sh_unix_getUIDname (SH_ERR_ERR, in_pid, user, sizeof(user)))
1238    SL_RETURN((-1), _("sh_unix_initgroups2"));
1239  status = sh_initgroups (user, in_gid);
1240  if (status < 0)
1241    {
1242      if (errno == EPERM)
1243        status = 0;
1244      if (errno == EINVAL)
1245        status = 0;
1246    }
1247  SL_RETURN((status), _("sh_unix_initgroups2"));
1248}
1249#else
1250int  sh_unix_initgroups2 (uid_t in_pid, gid_t in_gid)
1251{
1252  (void) in_pid;
1253  (void) in_gid;
1254  return 0;
1255}
1256#endif
1257
1258void sh_unix_closeall (int fd, int except, int inchild)
1259{
1260  int fdx = fd;
1261#ifdef _SC_OPEN_MAX
1262  int fdlimit = sysconf (_SC_OPEN_MAX);
1263#else
1264#ifdef OPEN_MAX
1265  int fdlimit = OPEN_MAX;
1266#else
1267  int fdlimit = _POSIX_OPEN_MAX;
1268#endif
1269#endif
1270
1271  SL_ENTER(_("sh_unix_closeall"));
1272
1273  /* can't happen - so fix it :-(
1274   */
1275  if (fdlimit < 0)
1276    fdlimit = 20;  /* POSIX lower limit */
1277
1278  if (fdlimit > 65536)
1279    fdlimit = 65536;
1280
1281  /* Close everything from fd (inclusive) up to fdlimit (exclusive).
1282   */
1283  while (fd < fdlimit)
1284    {
1285      if (fd == except)
1286        fd++;
1287      else if (slib_do_trace != 0 && fd == slib_trace_fd)
1288        fd++;
1289      else
1290        close(fd++);
1291    }
1292
1293  if (!inchild)
1294    sl_dropall (fdx, except);
1295  else
1296    sl_dropall_dirty (fdx, except);
1297
1298  SL_RET0(_("sh_unix_closeall"));
1299}
1300
1301static void sh_unix_setlimits(void)
1302{
1303  struct rlimit limits;
1304
1305  SL_ENTER(_("sh_unix_setlimits"));
1306
1307  limits.rlim_cur = RLIM_INFINITY;
1308  limits.rlim_max = RLIM_INFINITY;
1309
1310#ifdef RLIMIT_CPU
1311  setrlimit (RLIMIT_CPU,     &limits);
1312#endif
1313#ifdef RLIMIT_FSIZE
1314  setrlimit (RLIMIT_FSIZE,   &limits);
1315#endif
1316#ifdef RLIMIT_DATA
1317  setrlimit (RLIMIT_DATA,    &limits);
1318#endif
1319#ifdef RLIMIT_STACK
1320  setrlimit (RLIMIT_STACK,   &limits);
1321#endif
1322#ifdef RLIMIT_RSS
1323  setrlimit (RLIMIT_RSS,     &limits);
1324#endif
1325#ifdef RLIMIT_NPROC
1326  setrlimit (RLIMIT_NPROC,   &limits);
1327#endif
1328#ifdef RLIMIT_MEMLOCK
1329  setrlimit (RLIMIT_MEMLOCK, &limits);
1330#endif
1331
1332#if !defined(SL_DEBUG)
1333  /* no core dumps
1334   */
1335  limits.rlim_cur = 0;
1336  limits.rlim_max = 0;
1337#ifdef RLIMIT_CORE
1338  setrlimit (RLIMIT_CORE,    &limits);
1339#endif
1340#else
1341#ifdef RLIMIT_CORE
1342  setrlimit (RLIMIT_CORE,    &limits);
1343#endif
1344#endif
1345
1346  limits.rlim_cur = 1024;
1347  limits.rlim_max = 1024;
1348
1349#if defined(RLIMIT_NOFILE)
1350  setrlimit (RLIMIT_NOFILE,  &limits);
1351#elif defined(RLIMIT_OFILE)
1352  setrlimit (RLIMIT_OFILE,   &limits);
1353#endif
1354
1355  SL_RET0(_("sh_unix_setlimits"));
1356}
1357
1358static void sh_unix_copyenv(void)
1359{
1360  char ** env0 = environ; 
1361  char ** env1;
1362  int   envlen = 0;
1363  size_t len;
1364
1365  SL_ENTER(_("sh_unix_copyenv"));
1366
1367  while (env0 != NULL && env0[envlen] != NULL) { 
1368    /* printf("%2d: %s\n", envlen, env0[envlen]); */
1369    ++envlen; 
1370  }
1371  ++envlen;
1372
1373  /* printf("-> %2d: slots allocated\n", envlen); */
1374  env1 = malloc (sizeof(char *) * envlen);      /* only once */
1375  if (env1 == NULL)
1376    {
1377      fprintf(stderr, _("%s: %d: Out of memory\n"), FIL__, __LINE__);
1378      SL_RET0(_("sh_unix_copyenv"));
1379    }
1380  env0   = environ;
1381  envlen = 0;
1382
1383  while (env0 != NULL && env0[envlen] != NULL) {
1384    len = strlen(env0[envlen]) + 1;
1385    env1[envlen] = malloc (len); /* only once */
1386    if (env1[envlen] == NULL)
1387      {
1388        fprintf(stderr, _("%s: %d: Out of memory\n"), FIL__, __LINE__);
1389        SL_RET0(_("sh_unix_copyenv"));
1390      }
1391    sl_strlcpy(env1[envlen], env0[envlen], len);
1392    ++envlen;
1393  }
1394  env1[envlen] = NULL;
1395
1396  environ = env1;
1397  SL_RET0(_("sh_unix_copyenv"));
1398}
1399
1400/* delete all environment variables
1401 */
1402static void sh_unix_zeroenv(void)
1403{
1404  char * c;
1405  char ** env;
1406
1407  SL_ENTER(_("sh_unix_zeroenv"));
1408
1409  sh_unix_copyenv();
1410  env = environ;
1411
1412  while (env != NULL && *env != NULL) {
1413    c = strchr ((*env), '=');
1414#ifdef WITH_MYSQL
1415    /*
1416     * Skip the MYSQL_UNIX_PORT environment variable; MySQL may need it.
1417     */
1418    if (0 == sl_strncmp((*env), _("MYSQL_UNIX_PORT="), 16))
1419      {
1420        ++(env);
1421        continue;
1422      }
1423    if (0 == sl_strncmp((*env), _("MYSQL_TCP_PORT="), 15))
1424      {
1425        ++(env);
1426        continue;
1427      }
1428    if (0 == sl_strncmp((*env), _("MYSQL_HOME="), 11))
1429      {
1430        ++(env);
1431        continue;
1432      }
1433#endif
1434#ifdef WITH_ORACLE
1435    /*
1436     * Skip the ORACLE_HOME environment variable; Oracle may need it.
1437     */
1438    if (0 == sl_strncmp((*env), _("ORACLE_HOME="), 12))
1439      {
1440        ++(env);
1441        continue;
1442      }
1443#endif
1444    /*
1445     * Skip the TZ environment variable.
1446     */
1447    if (0 == sl_strncmp((*env), _("TZ="), 3))
1448      {
1449        ++(env);
1450        continue;
1451      }
1452    ++(env);
1453    if (c != NULL)
1454      {
1455        ++c;
1456        while ((*c) != '\0') {
1457          (*c) = '\0';
1458          ++c;
1459        }
1460      }
1461  }
1462
1463#ifdef HAVE_TZSET
1464  tzset();
1465#endif
1466
1467  SL_RET0(_("sh_unix_zeroenv"));
1468}
1469
1470
1471static void  sh_unix_resettimer(void)
1472{
1473  struct itimerval this_timer;
1474
1475  SL_ENTER(_("sh_unix_resettimer"));
1476
1477  this_timer.it_value.tv_sec  = 0;
1478  this_timer.it_value.tv_usec = 0;
1479
1480  this_timer.it_interval.tv_sec  = 0;
1481  this_timer.it_interval.tv_usec = 0;
1482
1483  setitimer(ITIMER_REAL,    &this_timer, NULL);
1484#if !defined(SH_PROFILE)
1485  setitimer(ITIMER_VIRTUAL, &this_timer, NULL);
1486  setitimer(ITIMER_PROF,    &this_timer, NULL);
1487#endif
1488
1489  SL_RET0(_("sh_unix_resettimer"));
1490}
1491
1492static void  sh_unix_resetsignals(void)
1493{
1494  int  sig_num;
1495#ifdef NSIG
1496  int  max_sig = NSIG; 
1497#else
1498  int  max_sig = 255;
1499#endif
1500  int  test;
1501  struct sigaction act, oldact;
1502  int  status;
1503
1504  sigset_t set_proc;
1505
1506  SL_ENTER(_("sh_unix_resetsignals"));
1507  /*
1508   * Reset the current signal mask (inherited from parent process).
1509   */
1510
1511  sigfillset(&set_proc);
1512
1513  do {
1514    errno = 0;
1515    test  = sigprocmask(SIG_UNBLOCK, &set_proc, NULL);
1516  } while (test < 0 && errno == EINTR);
1517
1518  /*
1519   * Reset signal handling.
1520   */
1521 
1522  act.sa_handler = SIG_DFL;         /* signal action           */
1523  sigemptyset( &act.sa_mask );      /* set an empty mask       */
1524  act.sa_flags = 0;                 /* init sa_flags           */
1525
1526  for (sig_num = 1; sig_num <= max_sig; ++sig_num) 
1527    {
1528#if !defined(SH_PROFILE)
1529      test = retry_sigaction(FIL__, __LINE__, sig_num,  &act, &oldact);
1530#else
1531      test = 0;
1532#endif
1533      if ((test == -1) && (errno != EINVAL)) 
1534        {
1535          char errbuf[SH_ERRBUF_SIZE];
1536          status = errno;
1537          sh_error_handle ((-1), FIL__, __LINE__, status, MSG_W_SIG,
1538                           sh_error_message (status, errbuf, sizeof(errbuf)), sig_num);
1539        }
1540    }
1541
1542  SL_RET0(_("sh_unix_resetsignals"));
1543}
1544
1545/* Get the local hostname (FQDN)
1546 */
1547#include <sys/socket.h> 
1548
1549/* Required for BSD
1550 */
1551#ifdef HAVE_NETINET_IN_H
1552#include <netinet/in.h>
1553#endif
1554
1555#include <arpa/inet.h>
1556
1557char * sh_unix_h_name (struct hostent * host_entry)
1558{
1559        char ** p;
1560        if (strchr(host_entry->h_name, '.')) {
1561                return host_entry->h_name;
1562        } else {
1563                for (p = host_entry->h_aliases; *p; ++p) {
1564                        if (strchr(*p, '.'))
1565                                return *p;
1566                }
1567        }
1568        return host_entry->h_name;
1569}
1570
1571/* uname() on FreeBSD is broken, because the 'nodename' buf is too small
1572 * to hold a valid (leftmost) domain label.
1573 */
1574#if defined(HAVE_UNAME) && !defined(HOST_IS_FREEBSD)
1575#include <sys/utsname.h>
1576void sh_unix_localhost()
1577{
1578  struct utsname   buf;
1579  struct hostent * he1;
1580  int              i;
1581  int              ddot;
1582  int              len;
1583  char           * p;
1584  char             hostname[256];
1585
1586
1587  SL_ENTER(_("sh_unix_localhost"));
1588
1589  (void) uname (&buf);
1590  /* flawfinder: ignore */ /* ff bug, ff sees system() */
1591  sl_strlcpy (sh.host.system,  buf.sysname, SH_MINIBUF);
1592  sl_strlcpy (sh.host.release, buf.release, SH_MINIBUF);
1593  sl_strlcpy (sh.host.machine, buf.machine, SH_MINIBUF);
1594
1595  /* Workaround for cases where nodename could be
1596   * a truncated FQDN.
1597   */
1598  if (strlen(buf.nodename) == (sizeof(buf.nodename)-1))
1599    {
1600      p = strchr(buf.nodename, '.');
1601      if (NULL != p) {
1602        *p = '\0';
1603        sl_strlcpy(hostname, buf.nodename, 256);
1604      } else {
1605#ifdef HAVE_GETHOSTNAME
1606        if (0 != gethostname(hostname, 256))
1607          {
1608            sh_error_handle(SH_ERR_WARN, FIL__, __LINE__, 0, MSG_E_SUBGEN,
1609                            _("nodename returned by uname may be truncated"), 
1610                            _("sh_unix_localhost"));
1611            sl_strlcpy (hostname, buf.nodename, 256);
1612          }
1613        else
1614          {
1615            hostname[255] = '\0';
1616          }
1617#else
1618        sh_error_handle(SH_ERR_WARN, FIL__, __LINE__, 0, MSG_E_SUBGEN,
1619                        _("nodename returned by uname may be truncated"), 
1620                        _("sh_unix_localhost"));
1621        sl_strlcpy(hostname, buf.nodename, 256);
1622#endif
1623      }
1624    }
1625  else
1626    {
1627      sl_strlcpy(hostname, buf.nodename, 256);
1628    }
1629
1630  SH_MUTEX_LOCK(mutex_resolv);
1631  he1 = sh_gethostbyname(hostname);
1632
1633  if (he1 != NULL)
1634    {
1635      sl_strlcpy (sh.host.name, sh_unix_h_name(he1), SH_PATHBUF);
1636    }
1637  SH_MUTEX_UNLOCK(mutex_resolv);
1638
1639  if (he1 == NULL)
1640    {
1641      dlog(1, FIL__, __LINE__, 
1642           _("According to uname, your nodename is %s, but your resolver\nlibrary cannot resolve this nodename to a FQDN. For more information, see the entry about self-resolving under 'Most frequently' in the FAQ that you will find in the docs/ subdirectory.\n"),
1643           hostname);
1644      sl_strlcpy (sh.host.name, hostname,    SH_PATHBUF);
1645    }
1646 
1647
1648  /* check whether it looks like a FQDN
1649   */
1650  len = sl_strlen(sh.host.name);
1651  ddot = 0;
1652  for (i = 0; i < len; ++i) 
1653    if (sh.host.name[i] == '.') ++ddot; 
1654
1655  if (ddot == 0 && he1 != NULL)
1656    { 
1657      dlog(1, FIL__, __LINE__, 
1658           _("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"),
1659           hostname, sh.host.name);
1660      sl_strlcpy (sh.host.name, 
1661                  inet_ntoa (*(struct in_addr *) he1->h_addr), 
1662                  SH_PATHBUF);
1663      SL_RET0(_("sh_unix_localhost"));
1664    } 
1665
1666  if (is_numeric(sh.host.name)) 
1667    {
1668      dlog(1, FIL__, __LINE__, 
1669           _("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"),
1670           hostname, sh.host.name);
1671    }
1672
1673  SL_RET0(_("sh_unix_localhost"));
1674}
1675
1676#else
1677
1678/*
1679 * --FreeBSD code
1680 */
1681#if defined(HAVE_UNAME)
1682#include <sys/utsname.h>
1683#endif
1684void sh_unix_localhost()
1685{
1686#if defined(HAVE_UNAME)
1687  struct utsname   buf;
1688#endif
1689  struct hostent * he1;
1690  int              i;
1691  int              ddot;
1692  int              len;
1693  char             hostname[1024];
1694
1695
1696  SL_ENTER(_("sh_unix_localhost"));
1697
1698#if defined(HAVE_UNAME)
1699  (void) uname (&buf);
1700  /* flawfinder: ignore */ /* ff bug, ff sees system() */
1701  sl_strlcpy (sh.host.system,  buf.sysname, SH_MINIBUF);
1702  sl_strlcpy (sh.host.release, buf.release, SH_MINIBUF);
1703  sl_strlcpy (sh.host.machine, buf.machine, SH_MINIBUF);
1704#endif
1705
1706  (void) gethostname (hostname, 1024);
1707  hostname[1023] = '\0';
1708
1709  SH_MUTEX_LOCK(mutex_resolv);
1710  he1 = sh_gethostbyname(hostname);
1711
1712  if (he1 != NULL)
1713    {
1714      sl_strlcpy (sh.host.name, sh_unix_h_name(he1), SH_PATHBUF);
1715    }
1716  SH_MUTEX_UNLOCK(mutex_resolv);
1717
1718  if (he1 == NULL)
1719    {
1720      dlog(1, FIL__, __LINE__, 
1721           _("According to gethostname, your nodename is %s, but your resolver\nlibrary cannot resolve this nodename to a FQDN.\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"),
1722           hostname);
1723      sl_strlcpy (sh.host.name, _("localhost"), SH_PATHBUF);
1724      SL_RET0(_("sh_unix_localhost"));
1725    }
1726
1727  /* check whether it looks like a FQDN
1728   */
1729  len = sl_strlen(sh.host.name);
1730  ddot = 0;
1731  for (i = 0; i < len; ++i) 
1732    if (sh.host.name[i] == '.') ++ddot; 
1733  if (ddot == 0) 
1734    {
1735      dlog(1, FIL__, __LINE__, 
1736           _("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"),
1737           hostname, sh.host.name);
1738      sl_strlcpy (sh.host.name, 
1739                  inet_ntoa (*(struct in_addr *) he1->h_addr), 
1740                  SH_PATHBUF);
1741      SL_RET0(_("sh_unix_localhost"));
1742    }
1743
1744  if (is_numeric(sh.host.name)) 
1745    {
1746      dlog(1, FIL__, __LINE__, 
1747           _("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"),
1748           hostname, sh.host.name);
1749    }
1750
1751  SL_RET0(_("sh_unix_localhost"));
1752}
1753#endif
1754
1755
1756void sh_unix_memlock()
1757{
1758  SL_ENTER(_("sh_unix_memlock"));
1759
1760  /* do this before dropping privileges
1761   */
1762#if defined(HAVE_MLOCK) && !defined(HAVE_BROKEN_MLOCK)
1763  if (skey->mlock_failed == SL_FALSE)
1764    {
1765      if ( (-1) == sh_unix_mlock( FIL__, __LINE__, 
1766                                  (char *) skey, sizeof (sh_key_t)) ) 
1767        {
1768          SH_MUTEX_LOCK_UNSAFE(mutex_skey);
1769          skey->mlock_failed = SL_TRUE;
1770          SH_MUTEX_UNLOCK_UNSAFE(mutex_skey);
1771        }
1772    }
1773#else
1774  if (skey->mlock_failed == SL_FALSE)
1775    {
1776      SH_MUTEX_LOCK_UNSAFE(mutex_skey);
1777      skey->mlock_failed = SL_TRUE;
1778      SH_MUTEX_UNLOCK_UNSAFE(mutex_skey);
1779    }
1780#endif
1781
1782  SL_RET0(_("sh_unix_memlock"));
1783}
1784
1785#ifdef SH_WITH_SERVER
1786char * chroot_dir = NULL;
1787
1788int sh_unix_set_chroot(const char * str)
1789{
1790  size_t len;
1791  static int block = 0;
1792
1793  if (block == 1)
1794    return 0;
1795
1796  if (str && *str == '/')
1797    {
1798      len = strlen(str) + 1;
1799      chroot_dir = malloc(strlen(str) + 1);  /* only once */
1800      if (!chroot_dir)
1801        {
1802          fprintf(stderr, _("%s: %d: Out of memory\n"), FIL__, __LINE__);
1803          return 1;
1804        }
1805      sl_strlcpy(chroot_dir, str, len);
1806      block = 1;
1807      return 0;
1808    }
1809  return 1;
1810}
1811
1812int sh_unix_chroot(void)
1813{
1814  int status;
1815
1816  if (chroot_dir != NULL)
1817    {
1818      status = retry_aud_chdir(FIL__, __LINE__, chroot_dir);
1819      if ( (-1) == status ) 
1820        {
1821          char errbuf[SH_ERRBUF_SIZE];
1822          status = errno;
1823          sh_error_handle ((-1), FIL__, __LINE__, status, MSG_W_CHDIR,
1824                           sh_error_message (status, errbuf, sizeof(errbuf)), chroot_dir);
1825          aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1826        }
1827      /* flawfinder: ignore */
1828      return (chroot(chroot_dir));
1829    }
1830  return 0;
1831}
1832/* #ifdef SH_WITH_SERVER */
1833#else
1834int sh_unix_chroot(void) { return 0; }
1835#endif
1836
1837/* daemon mode
1838 */
1839static int block_setdeamon = 0;
1840
1841int sh_unix_setdeamon(const char * dummy)
1842{
1843  int    res = 0;
1844
1845  SL_ENTER(_("sh_unix_setdeamon"));
1846
1847  if (block_setdeamon != 0)
1848    SL_RETURN((0),_("sh_unix_setdeamon"));
1849
1850  if (dummy == NULL)
1851    sh.flag.isdaemon = ON;
1852  else 
1853    res = sh_util_flagval (dummy, &sh.flag.isdaemon);
1854
1855  if (sh.flag.opts == S_TRUE) 
1856    block_setdeamon = 1;
1857           
1858  SL_RETURN(res, _("sh_unix_setdeamon"));
1859}
1860#if defined(HAVE_LIBPRELUDE)
1861#include "sh_prelude.h"
1862#endif
1863
1864int sh_unix_setnodeamon(const char * dummy)
1865{
1866  int    res = 0;
1867 
1868  SL_ENTER(_("sh_unix_setnodeamon"));
1869
1870  if (block_setdeamon != 0)
1871    SL_RETURN((0),_("sh_unix_setmodeamon"));
1872
1873  if (dummy == NULL)
1874    sh.flag.isdaemon = OFF;
1875  else 
1876    res = sh_util_flagval (dummy, &sh.flag.isdaemon);
1877
1878  if (sh.flag.opts == S_TRUE) 
1879    block_setdeamon = 1;
1880           
1881  SL_RETURN(res, _("sh_unix_setnodeamon"));
1882}
1883
1884int sh_unix_init(int goDaemon)
1885{
1886  int    status;
1887  uid_t  uid;
1888  pid_t  oldpid = getpid();
1889#if defined(SH_WITH_SERVER)
1890  extern int sh_socket_open_int (void);
1891#endif
1892  char errbuf[SH_ERRBUF_SIZE];
1893
1894  SL_ENTER(_("sh_unix_init"));
1895
1896  /* fork twice, exit the parent process
1897   */
1898  if (goDaemon == 1) {
1899   
1900    switch (aud_fork(FIL__, __LINE__)) {
1901    case 0:  break;                             /* child process continues */
1902    case -1: SL_RETURN((-1),_("sh_unix_init")); /* error                   */
1903    default: aud__exit(FIL__, __LINE__, 0);     /* parent process exits    */
1904    }
1905
1906    /* Child processes do not inherit page locks across a fork.
1907     * Error in next fork would return in this (?) thread of execution.
1908     */
1909    sh_unix_memlock();
1910
1911    setsid();            /* should not fail         */
1912    sh.pid = (UINT64) getpid();
1913
1914    switch (aud_fork(FIL__, __LINE__)) {
1915    case 0:  break;                             /* child process continues */
1916    case -1: SL_RETURN((-1),_("sh_unix_init")); /* error                   */
1917    default: aud__exit(FIL__, __LINE__, 0);     /* parent process exits    */
1918    }
1919
1920    /* Child processes do not inherit page locks across a fork.
1921     */
1922    sh_unix_memlock();
1923    sh.pid = (UINT64) getpid();
1924
1925  } else {
1926    setsid();            /* should not fail         */
1927  } 
1928
1929  /* set working directory   
1930   */
1931#ifdef SH_PROFILE
1932  status = 0;
1933#else
1934  status = retry_aud_chdir(FIL__, __LINE__, "/");
1935#endif
1936  if ( (-1) == status ) 
1937    {
1938      status = errno;
1939      sh_error_handle ((-1), FIL__, __LINE__, status, MSG_W_CHDIR,
1940                       sh_error_message (status, errbuf, sizeof(errbuf)), "/");
1941      aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1942    }
1943
1944  /* reset timers
1945   */
1946  sh_unix_resettimer();
1947
1948  /* signal handlers
1949   */
1950  sh_unix_resetsignals();
1951#if defined(SCREW_IT_UP)
1952  sh_sigtrap_prepare();
1953#endif
1954  sh_unix_siginstall  (goDaemon);
1955
1956  /* set file creation mask
1957   */
1958  (void) umask (0); /* should not fail */
1959
1960  /* set resource limits to maximum, and
1961   * core dump size to zero
1962   */
1963  sh_unix_setlimits();
1964
1965  /* zero out the environment (like PATH='\0') 
1966   */
1967  sh_unix_zeroenv();
1968
1969  if (goDaemon == 1)
1970    {
1971      /* Close first tree file descriptors
1972       */ 
1973      close (0);  /* if running as daemon */
1974      close (1);  /* if running as daemon */
1975      close (2);  /* if running as daemon */
1976
1977      /* Enable full error logging
1978       */
1979      sh_error_only_stderr (S_FALSE);
1980
1981      /* open first three streams to /dev/null
1982       */
1983      status = aud_open(FIL__, __LINE__, SL_NOPRIV, _("/dev/null"), O_RDWR, 0);
1984      if (status < 0)
1985        {
1986          status = errno;
1987          sh_error_handle((-1), FIL__, __LINE__, status, MSG_E_SUBGEN, 
1988                          sh_error_message(status, errbuf, sizeof(errbuf)), _("open"));
1989          aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1990        }
1991
1992      status = retry_aud_dup(FIL__, __LINE__, 0); 
1993      if (status >= 0)
1994        retry_aud_dup(FIL__, __LINE__, 0);
1995
1996      if (status < 0)
1997        {
1998          status = errno;
1999          sh_error_handle((-1), FIL__, __LINE__, status, MSG_E_SUBGEN, 
2000                          sh_error_message(status, errbuf, sizeof(errbuf)), _("dup"));
2001          aud_exit(FIL__, __LINE__, EXIT_FAILURE);
2002        }
2003
2004      sh_error_enable_unsafe (S_TRUE);
2005#if defined(HAVE_LIBPRELUDE)
2006      sh_prelude_reset ();
2007#endif
2008
2009      /* --- wait until parent has exited ---
2010       */
2011      while (1 == 1)
2012        {
2013          errno = 0;
2014          if (0 > aud_kill (FIL__, __LINE__, oldpid, 0) && errno == ESRCH)
2015            {
2016              break;
2017            }
2018          retry_msleep(0, 1);
2019        }
2020
2021      /* write PID file
2022       */
2023      status = sh_unix_write_pid_file();
2024      if (status < 0)
2025        {
2026          sl_get_euid(&uid);
2027          sh_error_handle ((-1), FIL__, __LINE__, status, MSG_PIDFILE,
2028                           (long) uid, sh.srvlog.alt);
2029          aud_exit(FIL__, __LINE__, EXIT_FAILURE);
2030        }
2031#if defined(SH_WITH_SERVER)
2032      sh_socket_open_int ();
2033#endif
2034    }
2035  else
2036    {
2037      sh_error_enable_unsafe (S_TRUE);
2038#if defined(HAVE_LIBPRELUDE)
2039      sh_prelude_reset ();
2040#endif
2041#if defined(SH_WITH_SERVER)
2042      sh_socket_open_int ();
2043#endif
2044    }
2045
2046  /* chroot (this is a no-op if no chroot dir is specified
2047   */
2048  status = sh_unix_chroot();
2049  if (status < 0)
2050    {
2051      status = errno;
2052      sh_error_handle((-1), FIL__, __LINE__, status, MSG_E_SUBGEN, 
2053                          sh_error_message(status, errbuf, sizeof(errbuf)), _("chroot"));
2054      aud_exit(FIL__, __LINE__, EXIT_FAILURE);
2055    }
2056
2057  /* drop capabilities
2058   */
2059  sl_drop_cap();
2060
2061  SL_RETURN((0),_("sh_unix_init"));
2062}
2063
2064/* --- run a command, securely --- */
2065
2066int sh_unix_run_command (const char * str)
2067{
2068  pid_t  pid;
2069  char * arg[4];
2070  char * env[5];
2071  char * path = sh_util_strdup(_("/bin/sh"));
2072
2073  int  status = -1;
2074
2075  arg[0] = sh_util_strdup(_("/bin/sh"));
2076  arg[1] = sh_util_strdup(_("-c"));
2077  arg[2] = sh_util_strdup(str);
2078  arg[3] = NULL;
2079
2080  env[0] = sh_util_strdup(_("PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/ucb"));
2081  env[1] = sh_util_strdup(_("SHELL=/bin/sh"));
2082  env[2] = sh_util_strdup(_("IFS= \t\n"));
2083  if (getenv("TZ")) {                         /* flawfinder: ignore */
2084    char * tz = sh_util_strdup(getenv("TZ")); /* flawfinder: ignore */
2085    size_t tzlen = strlen(tz);
2086    if (SL_TRUE == sl_ok_adds (4, tzlen)) {
2087        env[3] = SH_ALLOC(4+tzlen);
2088        sl_strlcpy(env[3], "TZ=", 4);
2089        sl_strlcat(env[3], tz   , 4+tzlen);
2090    } else {
2091      env[3] = NULL;
2092    }
2093  } else {
2094    env[3] = NULL;
2095  }
2096  env[4] = NULL;
2097
2098  pid = fork();
2099
2100  if (pid == (pid_t)(-1))
2101    {
2102      return -1;
2103    }
2104
2105  else if (pid == 0) /* child */
2106    {
2107      memset(skey, 0, sizeof(sh_key_t));
2108      (void) umask(S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH);
2109      sh_unix_closeall (3, -1, SL_TRUE); /* in child process */
2110      execve(path, arg, env);
2111      _exit(EXIT_FAILURE);
2112    }
2113
2114  else /* parent */
2115    {
2116      int r;
2117
2118      while((r = waitpid(pid, &status, WUNTRACED)) != pid && r != -1) ;
2119
2120#if !defined(USE_UNO)
2121      if (r == -1 || !WIFEXITED(status)) 
2122        {
2123          status = -1;
2124        }
2125      else
2126        {
2127          status = WEXITSTATUS(status);
2128        }
2129#endif
2130     }
2131
2132  return status;
2133}
2134
2135/********************************************************
2136 *
2137 *  TIME
2138 *
2139 ********************************************************/
2140
2141/* Figure out the time offset of the current timezone
2142 * in a portable way.
2143 */
2144char * t_zone(const time_t * xx)
2145{
2146  struct tm   aa;
2147  struct tm   bb;
2148  struct tm * cc;
2149  int  sign =  0;
2150  int  diff =  0;
2151  int  hh, mm;
2152  static char tz[64];
2153
2154  SL_ENTER(_("t_zone"));
2155
2156#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GMTIME_R)
2157  cc = gmtime_r (xx, &aa);
2158#else
2159  cc = gmtime (xx);
2160  memcpy (&aa, cc, sizeof(struct tm));
2161#endif
2162
2163#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_LOCALTIME_R)
2164  cc = localtime_r (xx, &bb);
2165#else
2166  cc = localtime (xx);
2167  memcpy (&bb, cc, sizeof(struct tm));
2168#endif
2169
2170  /* Check for datum wrap-around.
2171   */
2172  if      (aa.tm_year < bb.tm_year)
2173    sign = (-1);
2174  else if (aa.tm_mon  < bb.tm_mon)
2175    sign = (-1);
2176  else if (aa.tm_mday < bb.tm_mday)
2177    sign = (-1);
2178  else if (bb.tm_year < aa.tm_year)
2179    sign = ( 1);
2180  else if (bb.tm_mon  < aa.tm_mon)
2181    sign = ( 1);
2182  else if (bb.tm_mday < aa.tm_mday)
2183    sign = ( 1);
2184
2185  diff = aa.tm_hour * 60 + aa.tm_min;
2186  diff = (bb.tm_hour * 60 + bb.tm_min) - diff;
2187  diff = diff - (sign * 24 * 60);   /* datum wrap-around correction */
2188  hh = diff / 60;
2189  mm = diff - (hh * 60);
2190  sprintf (tz, _("%+03d%02d"), hh, mm);                /* known to fit  */
2191
2192  SL_RETURN(tz, _("t_zone"));
2193}
2194
2195unsigned long sh_unix_longtime ()
2196{
2197  return ((unsigned long)time(NULL));
2198} 
2199
2200#ifdef HAVE_GETTIMEOFDAY
2201unsigned long sh_unix_notime ()
2202{
2203  struct timeval  tv;
2204
2205  gettimeofday (&tv, NULL);
2206
2207  return ((unsigned long)(tv.tv_sec + tv.tv_usec * 10835 + getpid() + getppid()));
2208 
2209}
2210#endif
2211
2212static int count_dev_time = 0;
2213
2214void reset_count_dev_time(void)
2215{
2216  count_dev_time = 0;
2217  return;
2218}
2219
2220int sh_unix_settimeserver (const char * address)
2221{
2222
2223  SL_ENTER(_("sh_unix_settimeserver"));
2224
2225  if (address != NULL && count_dev_time < 2 
2226      && sl_strlen(address) < SH_PATHBUF) 
2227    {
2228      if (count_dev_time == 0)
2229        sl_strlcpy (sh.srvtime.name, address, SH_PATHBUF);
2230      else
2231        sl_strlcpy (sh.srvtime.alt,  address, SH_PATHBUF);
2232
2233      ++count_dev_time;
2234      SL_RETURN((0), _("sh_unix_settimeserver"));
2235    }
2236  SL_RETURN((-1), _("sh_unix_settimeserver"));
2237}
2238
2239
2240#ifdef HAVE_NTIME
2241#define UNIXEPOCH 2208988800UL  /* difference between Unix time and net time
2242                                 * The UNIX EPOCH starts in 1970.
2243                                 */
2244#include <sys/socket.h>
2245#include <netinet/in.h>
2246#include <arpa/inet.h>
2247#include <netdb.h>
2248#include <ctype.h>
2249#endif
2250
2251/* Timeserver service.               */
2252/* define is missing on HP-UX 10.20  */
2253#ifndef IPPORT_TIMESERVER
2254#define IPPORT_TIMESERVER 37
2255#endif
2256
2257char * sh_unix_time (time_t thetime, char * buffer, size_t len)
2258{
2259
2260  int           status;
2261  char          AsciiTime[81];                       /* local time   */
2262  time_t        time_now;
2263  struct tm   * time_ptr;
2264#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_LOCALTIME_R)
2265  struct tm     time_tm;
2266#endif
2267#ifdef SH_USE_XML
2268  static char   deftime[] = N_("0000-00-00T00:00:00"); /* default time */
2269#else
2270  static char   deftime[] = N_("[0000-00-00T00:00:00]"); /* default time */
2271#endif
2272
2273#ifdef HAVE_NTIME
2274  int    fd;                    /* network file descriptor                  */
2275  u_char net_time[4];           /* remote time in network format            */
2276  static int failerr = 0;       /* no net time                              */
2277  int    fail = 0;              /* no net time                              */
2278  int    errflag;
2279  char   errmsg[256];
2280  char   error_call[SH_MINIBUF];
2281  int    error_num;
2282#endif
2283 
2284  SL_ENTER(_("sh_unix_time"));
2285
2286#ifdef HAVE_NTIME
2287  if (thetime == 0) 
2288    {
2289      if (sh.srvtime.name[0] == '\0') 
2290        {
2291          fail = 1;
2292          (void) time (&time_now);
2293        } 
2294      else /* have a timeserver address */
2295        { 
2296          fd = connect_port_2 (sh.srvtime.name, sh.srvtime.alt, 
2297                               IPPORT_TIMESERVER, 
2298                               error_call, &error_num, errmsg, sizeof(errmsg));
2299          if (fd >= 0)
2300            {
2301              if (4 != read_port (fd, (char *) net_time, 4, &errflag, 2))
2302                {
2303                  fail = 1;
2304                  sh_error_handle ((-1), FIL__, __LINE__, errflag, 
2305                                   MSG_E_NLOST, 
2306                                   _("time"), sh.srvtime.name);
2307                }
2308              close(fd);
2309            }
2310          else
2311            {
2312              sh_error_handle ((-1), FIL__, __LINE__, error_num, 
2313                               MSG_E_NET, errmsg, error_call,
2314                               _("time"), sh.srvtime.name);
2315              fail = 1;
2316            }
2317         
2318          if (fail == 0) 
2319            { 
2320              time_now = ntohl(* (long *) net_time) - UNIXEPOCH;
2321              /* fprintf(stderr, "TIME IS %ld\n", time_now); */
2322              if (failerr == 1) {
2323                failerr = 0;
2324                sh_error_handle ((-1), FIL__, __LINE__, 0, 
2325                                 MSG_E_NEST, 
2326                                 _("time"), sh.srvtime.name);
2327              } 
2328            }
2329          else
2330            {
2331              (void) time (&time_now);
2332              if (failerr == 0)
2333                {
2334                  failerr = 1;
2335                  sh_error_handle ((-1), FIL__, __LINE__, errflag, 
2336                                   MSG_SRV_FAIL, 
2337                                   _("time"), sh.srvtime.name);
2338                }
2339            }
2340        }
2341    }
2342  else 
2343    {
2344      time_now = thetime;
2345    }
2346
2347  /* #ifdef HAVE_NTIME */
2348#else
2349
2350  if (thetime == 0) 
2351    {
2352      (void) time (&time_now);
2353    } 
2354  else 
2355    {
2356      time_now = thetime;
2357    }
2358
2359  /* #ifdef HAVE_NTIME */
2360#endif
2361
2362  if (time_now == (-1) )
2363    {
2364      sl_strlcpy(buffer, _(deftime), len);
2365      SL_RETURN(buffer, _("sh_unix_time"));
2366    }
2367  else
2368    {
2369#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_LOCALTIME_R)
2370      time_ptr   = localtime_r (&time_now, &time_tm);
2371#else
2372      time_ptr   = localtime (&time_now);
2373#endif
2374    }
2375  if (time_ptr != NULL) 
2376    {
2377      status = strftime (AsciiTime, sizeof(AsciiTime),
2378#ifdef SH_USE_XML
2379                         _("%Y-%m-%dT%H:%M:%S%%s"),
2380#else
2381                         _("[%Y-%m-%dT%H:%M:%S%%s]"),
2382#endif
2383                         time_ptr);
2384
2385      sl_snprintf(buffer, len, AsciiTime, t_zone(&time_now));
2386
2387      if ( (status == 0) || (status == sizeof(AsciiTime)) )
2388        {
2389          sl_strlcpy(buffer, _(deftime), len);
2390          SL_RETURN( buffer, _("sh_unix_time"));
2391        }
2392      else
2393        {
2394          SL_RETURN(buffer, _("sh_unix_time"));
2395        }
2396    }
2397
2398  /* last resort
2399   */
2400  sl_strlcpy(buffer, _(deftime), len);
2401  SL_RETURN( buffer, _("sh_unix_time"));
2402}
2403
2404static int sh_unix_use_localtime = S_FALSE;
2405
2406/* whether to use localtime for file timesatams in logs
2407 */
2408int sh_unix_uselocaltime (const char * c)
2409{
2410  int i;
2411  SL_ENTER(_("sh_unix_uselocaltime"));
2412  i = sh_util_flagval(c, &(sh_unix_use_localtime));
2413
2414  SL_RETURN(i, _("sh_unix_uselocaltime"));
2415}
2416   
2417char * sh_unix_gmttime (time_t thetime, char * buffer, size_t len)
2418{
2419
2420  int           status;
2421
2422  struct tm   * time_ptr;
2423#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS)
2424  struct tm     time_tm;
2425#endif
2426  char   AsciiTime[81];                       /* GMT time   */
2427#ifdef SH_USE_XML
2428  static char   deftime[] = N_("0000-00-00T00:00:00"); /* default time */
2429#else
2430  static char   deftime[] = N_("[0000-00-00T00:00:00]"); /* default time */
2431#endif
2432
2433  SL_ENTER(_("sh_unix_gmttime"));
2434
2435  if (sh_unix_use_localtime == S_FALSE)
2436    {
2437#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GMTIME_R)
2438      time_ptr   = gmtime_r (&thetime, &time_tm);
2439#else
2440      time_ptr   = gmtime (&thetime);
2441#endif
2442    }
2443  else
2444    {
2445#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_LOCALTIME_R)
2446      time_ptr   = localtime_r (&thetime, &time_tm);
2447#else
2448      time_ptr   = localtime (&thetime);
2449#endif
2450    }
2451  if (time_ptr != NULL) 
2452    {
2453      status = strftime (AsciiTime, 80,
2454#ifdef SH_USE_XML
2455                         _("%Y-%m-%dT%H:%M:%S"),
2456#else
2457                         _("[%Y-%m-%dT%H:%M:%S]"),
2458#endif
2459                         time_ptr);
2460
2461      if ( (status == 0) || (status == 80) )
2462        sl_strlcpy(buffer, _(deftime), len);
2463      else
2464        sl_strlcpy(buffer, AsciiTime, len);
2465      SL_RETURN( buffer, _("sh_unix_gmttime"));
2466    }
2467
2468  /* last resort
2469   */
2470  sl_strlcpy(buffer, _(deftime), len);
2471  SL_RETURN( buffer, _("sh_unix_gmttime"));
2472}
2473
2474
2475char *  sh_unix_getUIDdir (int level, uid_t uid, char * out, size_t len)
2476{
2477  struct passwd * tempres;
2478  int    status = 0;
2479#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWUID_R)
2480  struct passwd pwd;
2481  char   * buffer;
2482#endif
2483  char errbuf[SH_ERRBUF_SIZE];
2484
2485  SL_ENTER(_("sh_unix_getUIDdir"));
2486
2487#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWUID_R)
2488  buffer = SH_ALLOC(SH_PWBUF_SIZE);
2489  sh_getpwuid_r(uid, &pwd, buffer, SH_PWBUF_SIZE, &tempres);
2490#else
2491  errno = 0;
2492  tempres = sh_getpwuid(uid);
2493  status = errno;
2494#endif
2495
2496  if (tempres == NULL) {
2497    sh_error_handle (level, FIL__, __LINE__, EINVAL, MSG_E_PWNULL,
2498                     sh_error_message(status, errbuf, sizeof(errbuf)),
2499                     _("getpwuid"), (long) uid, _("completely missing"));
2500#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R)
2501    SH_FREE(buffer);
2502#endif
2503    SL_RETURN( NULL, _("sh_unix_getUIDdir"));
2504  }
2505
2506  if (tempres->pw_dir != NULL) {
2507    sl_strlcpy(out, tempres->pw_dir, len);
2508#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R)
2509    SH_FREE(buffer);
2510#endif
2511    SL_RETURN( out, _("sh_unix_getUIDdir"));
2512  } else {
2513    sh_error_handle (level, FIL__, __LINE__, EINVAL, MSG_E_PWNULL,
2514                     sh_error_message(status, errbuf, sizeof(errbuf)),
2515                     _("getpwuid"), (long) uid, _("pw_dir"));
2516#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R)
2517    SH_FREE(buffer);
2518#endif
2519    SL_RETURN( NULL, _("sh_unix_getUIDdir"));
2520  }
2521}
2522
2523SH_MUTEX_STATIC(mutex_getUIDname, PTHREAD_MUTEX_INITIALIZER);
2524
2525char *  sh_unix_getUIDname (int level, uid_t uid, char * out, size_t len)
2526{
2527  struct passwd * tempres;
2528#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWUID_R)
2529  struct passwd pwd;
2530  char   * buffer;
2531#endif
2532  int             status = 0;
2533  static uid_t    old_uid;
2534  static char     name[32] = { '\0' };
2535  char errbuf[SH_ERRBUF_SIZE];
2536
2537  SL_ENTER(_("sh_unix_getUIDname"));
2538
2539  if ((uid == old_uid) && (name[0] != '\0')) {
2540    out[0] = '\0';
2541    SH_MUTEX_LOCK_UNSAFE(mutex_getUIDname);
2542    if ((uid == old_uid) && (name[0] != '\0')) {
2543      sl_strlcpy(out, name, len);
2544    }
2545    SH_MUTEX_UNLOCK_UNSAFE(mutex_getUIDname);
2546    if (out[0] != '\0')
2547      SL_RETURN( out, _("sh_unix_getUIDname"));
2548  }
2549
2550#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWUID_R)
2551  buffer = SH_ALLOC(SH_PWBUF_SIZE);
2552  sh_getpwuid_r(uid, &pwd, buffer, SH_PWBUF_SIZE, &tempres);
2553#else
2554  errno = 0;
2555  tempres = sh_getpwuid(uid);
2556  status = errno;
2557#endif
2558 
2559  if (tempres == NULL) {
2560    sh_error_handle (level, FIL__, __LINE__, EINVAL, MSG_E_PWNULL,
2561                     sh_error_message(status, errbuf, sizeof(errbuf)),
2562                     _("getpwuid"), (long) uid, _("completely missing"));
2563#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R)
2564    SH_FREE(buffer);
2565#endif
2566    SL_RETURN( NULL, _("sh_unix_getUIDname"));
2567  }
2568
2569
2570  if (tempres->pw_name != NULL) {
2571    SH_MUTEX_LOCK_UNSAFE(mutex_getUIDname);
2572    sl_strlcpy(name, tempres->pw_name, sizeof(name));
2573    old_uid = uid;
2574    sl_strlcpy(out, name, len);
2575    SH_MUTEX_UNLOCK_UNSAFE(mutex_getUIDname);
2576#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R)
2577    SH_FREE(buffer);
2578#endif
2579    SL_RETURN( out, _("sh_unix_getUIDname"));
2580  } else {
2581    sh_error_handle (level, FIL__, __LINE__, EINVAL, MSG_E_PWNULL,
2582                     sh_error_message(status, errbuf, sizeof(errbuf)),
2583                     _("getpwuid"), (long) uid, _("pw_user"));
2584#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R)
2585    SH_FREE(buffer);
2586#endif
2587    SL_RETURN( NULL, _("sh_unix_getUIDname"));
2588  }
2589}
2590
2591SH_MUTEX_STATIC(mutex_getGIDname, PTHREAD_MUTEX_INITIALIZER);
2592
2593char *  sh_unix_getGIDname (int level, gid_t gid, char * out, size_t len)
2594{
2595  struct group  * tempres;
2596  int             status = 0;
2597  static gid_t    old_gid;
2598  static char     name[32] = { '\0' };
2599#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R)
2600  struct group    grp;
2601  char          * buffer;
2602#endif
2603  char errbuf[SH_ERRBUF_SIZE];
2604 
2605
2606  SL_ENTER(_("sh_unix_getGIDname"));
2607
2608  if ((gid == old_gid) && (name[0] != '\0')) {
2609    out[0] = '\0';
2610    SH_MUTEX_LOCK_UNSAFE(mutex_getGIDname);
2611    if ((gid == old_gid) && (name[0] != '\0')) {
2612      sl_strlcpy(out, name, len);
2613    }
2614    SH_MUTEX_UNLOCK_UNSAFE(mutex_getGIDname);
2615    if (out[0] != '\0')
2616      SL_RETURN( out, _("sh_unix_getGIDname"));
2617  }
2618
2619#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R)
2620  buffer = SH_ALLOC(SH_GRBUF_SIZE);
2621  status = sh_getgrgid_r(gid, &grp, buffer, SH_GRBUF_SIZE, &tempres);
2622#else
2623  errno = 0;
2624  tempres = sh_getgrgid(gid);
2625  status = errno;
2626#endif
2627
2628  if (tempres == NULL) {
2629    sh_error_handle (level, FIL__, __LINE__, EINVAL, MSG_E_GRNULL,
2630                     sh_error_message(status, errbuf, sizeof(errbuf)),
2631                     _("getgrgid"), (long) gid, _("completely missing"));
2632     
2633#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R)
2634    SH_FREE(buffer);
2635#endif
2636    SL_RETURN( NULL, _("sh_unix_getGIDname"));
2637  }
2638
2639  if (tempres->gr_name != NULL) {
2640    SH_MUTEX_LOCK_UNSAFE(mutex_getGIDname);
2641    sl_strlcpy(name, tempres->gr_name, sizeof(name));
2642    old_gid = gid;
2643    sl_strlcpy(out, name, len);
2644    SH_MUTEX_UNLOCK_UNSAFE(mutex_getGIDname);
2645#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R)
2646    SH_FREE(buffer);
2647#endif
2648    SL_RETURN( out, _("sh_unix_getGIDname"));
2649  } else {
2650    sh_error_handle (level, FIL__, __LINE__, EINVAL, MSG_E_GRNULL,
2651                     sh_error_message(status, errbuf, sizeof(errbuf)),
2652                     _("getgrgid"), (long) gid, _("gr_name"));
2653#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R)
2654    SH_FREE(buffer);
2655#endif
2656    SL_RETURN( NULL, _("sh_unix_getGIDname"));
2657  }
2658}
2659
2660int sh_unix_getUser ()
2661{
2662  char          * p;
2663  uid_t  seuid, sruid;
2664  char   user[USER_MAX];
2665  char   dir[SH_PATHBUF];
2666
2667  SL_ENTER(_("sh_unix_getUser"));
2668
2669  seuid =  geteuid();
2670
2671  sh.effective.uid = seuid;
2672
2673  p = sh_unix_getUIDdir (SH_ERR_ERR, seuid, dir, sizeof(dir));
2674
2675  if (p == NULL)
2676    SL_RETURN((-1), _("sh_unix_getUser"));
2677  else
2678    {
2679      if (sl_strlen(p) >= SH_PATHBUF) {
2680        sh_error_handle (SH_ERR_ERR, FIL__, __LINE__, EINVAL, MSG_E_PWLONG,
2681                         _("getpwuid"), (long) seuid, _("pw_home"));
2682        SL_RETURN((-1), _("sh_unix_getUser"));
2683      } else {
2684        sl_strlcpy ( sh.effective.home, p, SH_PATHBUF);
2685      }
2686    }
2687
2688  sruid = getuid();
2689
2690  sh.real.uid = sruid;
2691
2692  p = sh_unix_getUIDname (SH_ERR_ERR, sruid, user, sizeof(user));
2693  if (p == NULL)
2694    SL_RETURN((-1), _("sh_unix_getUser"));
2695  else
2696    {
2697      if (sl_strlen(p) >= USER_MAX) {
2698        sh_error_handle (SH_ERR_ERR, FIL__, __LINE__, EINVAL, MSG_E_PWLONG,
2699                         _("getpwuid"), (long) sruid, _("pw_user"));
2700        SL_RETURN((-1), _("sh_unix_getUser"));
2701      } else {
2702        sl_strlcpy ( sh.real.user, p, USER_MAX);
2703      }
2704    }
2705
2706  p = sh_unix_getUIDdir (SH_ERR_ERR, sruid, dir, sizeof(dir));
2707
2708  if (p == NULL)
2709    SL_RETURN((-1), _("sh_unix_getUser"));
2710  else
2711    {
2712      if (sl_strlen(p) >= SH_PATHBUF) {
2713        sh_error_handle (SH_ERR_ERR, FIL__, __LINE__, EINVAL, MSG_E_PWLONG,
2714                         _("getpwuid"), (long) sruid, _("pw_home"));
2715        SL_RETURN((-1), _("sh_unix_getUser"));
2716      } else {
2717        sl_strlcpy ( sh.real.home, p, SH_PATHBUF);
2718      }
2719    }
2720
2721  SL_RETURN((0), _("sh_unix_getUser"));
2722
2723  /* notreached */
2724}
2725
2726
2727int sh_unix_getline (SL_TICKET fd, char * line, int sizeofline)
2728{
2729  register int  count;
2730  register int  n = 0;
2731  char          c;
2732
2733  SL_ENTER(_("sh_unix_getline"));
2734
2735  if (sizeofline < 2) {
2736    line[0] = '\0';
2737    SL_RETURN((0), _("sh_unix_getline"));
2738  }
2739
2740  --sizeofline;
2741
2742  while (n < sizeofline) {
2743
2744    count = sl_read (fd, &c, 1);
2745
2746    /* end of file
2747     */
2748    if (count < 1) {
2749      line[n] = '\0';
2750      n = -1;
2751      break;
2752    } 
2753
2754    if (/* c != '\0' && */ c != '\n') {
2755      line[n] = c;
2756      ++n;
2757    } else if (c == '\n') {
2758      if (n > 0) {
2759        line[n] = '\0';
2760        break;
2761      } else {
2762        line[n] = '\n'; /* get newline only if only char on line */
2763        ++n;
2764        line[n] = '\0';
2765        break;
2766      }
2767    } else {
2768      line[n] = '\0';
2769      break;
2770    }
2771
2772  }
2773
2774
2775  line[sizeofline] = '\0';  /* make sure line is terminated */
2776  SL_RETURN((n), _("sh_unix_getline"));
2777}
2778
2779
2780#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
2781
2782/**************************************************************
2783 *
2784 * --- FILE INFO ---
2785 *
2786 **************************************************************/
2787
2788#if (defined(__linux__) && (defined(HAVE_LINUX_EXT2_FS_H) || defined(HAVE_EXT2FS_EXT2_FS_H))) || defined(HAVE_STAT_FLAGS)
2789
2790#if defined(__linux__)
2791
2792/* --- Determine ext2fs file attributes. ---
2793 */
2794#include <sys/ioctl.h>
2795#if defined(HAVE_EXT2FS_EXT2_FS_H)
2796#include <ext2fs/ext2_fs.h>
2797#else
2798#include <linux/ext2_fs.h>
2799#endif
2800
2801/* __linux__ includes */
2802#endif
2803
2804static 
2805int sh_unix_getinfo_attr (char * name, 
2806                          unsigned long * flags, 
2807                          char * c_attr,
2808                          int fd, struct stat * buf)
2809{
2810
2811/* TAKEN FROM:
2812 *
2813 * lsattr.c             - List file attributes on an ext2 file system
2814 *
2815 * Copyright (C) 1993, 1994  Remy Card <card@masi.ibp.fr>
2816 *                           Laboratoire MASI, Institut Blaise Pascal
2817 *                           Universite Pierre et Marie Curie (Paris VI)
2818 *
2819 * This file can be redistributed under the terms of the GNU General
2820 * Public License
2821 */
2822
2823#ifdef HAVE_STAT_FLAGS
2824
2825  SL_ENTER(_("sh_unix_getinfo_attr"));
2826
2827  *flags = 0;
2828
2829  /* cast to void to avoid compiler warning about unused parameters */
2830  (void) fd;
2831  (void) name;
2832
2833#ifdef UF_NODUMP
2834  if (buf->st_flags & UF_NODUMP) {
2835    *flags |= UF_NODUMP;
2836    c_attr[0] = 'd';
2837  }
2838#endif
2839#ifdef UF_IMMUTABLE
2840  if (buf->st_flags & UF_IMMUTABLE) {
2841    *flags |= UF_IMMUTABLE;
2842    c_attr[1] = 'i';
2843  }
2844#endif
2845#ifdef UF_APPEND
2846  if (buf->st_flags & UF_APPEND) {
2847    *flags |= UF_APPEND;
2848    c_attr[2] = 'a';
2849  }
2850#endif
2851#ifdef UF_NOUNLINK
2852  if (buf->st_flags & UF_NOUNLINK) {
2853    *flags |= UF_NOUNLINK;
2854    c_attr[3] = 'u';
2855  }
2856#endif
2857#ifdef UF_OPAQUE
2858  if (buf->st_flags & UF_OPAQUE) {
2859    *flags |= UF_OPAQUE;
2860    c_attr[4] = 'o';
2861  }
2862#endif
2863#ifdef SF_ARCHIVED
2864  if (buf->st_flags & SF_ARCHIVED) {
2865    *flags |= SF_ARCHIVED;
2866    c_attr[5] = 'R';
2867  }
2868   
2869#endif
2870#ifdef SF_IMMUTABLE
2871  if (buf->st_flags & SF_IMMUTABLE) {
2872    *flags |= SF_IMMUTABLE;
2873    c_attr[6] = 'I';
2874  }
2875#endif
2876#ifdef SF_APPEND
2877  if (buf->st_flags & SF_APPEND) {
2878    *flags |= SF_APPEND;
2879    c_attr[7] = 'A';
2880  }
2881#endif
2882#ifdef SF_NOUNLINK
2883  if (buf->st_flags & SF_NOUNLINK) {
2884    *flags |= SF_NOUNLINK;
2885    c_attr[8] = 'U';
2886  }
2887#endif
2888
2889  /* ! HAVE_STAT_FLAGS */
2890#else
2891
2892#ifdef HAVE_EXT2_IOCTLS
2893  int /* fd, */ r, f;
2894 
2895  SL_ENTER(_("sh_unix_getinfo_attr"));
2896
2897  *flags = 0;
2898  (void) buf;
2899
2900  /* open() -> aud_open() R.Wichmann
2901  fd = aud_open (FIL__, __LINE__, SL_YESPRIV, name, O_RDONLY|O_NONBLOCK, 0);
2902  */
2903
2904  if (fd == -1 || name == NULL)
2905    SL_RETURN(-1, _("sh_unix_getinfo_attr"));
2906
2907 
2908  r = ioctl (fd, EXT2_IOC_GETFLAGS, &f);
2909  /* close (fd); */
2910
2911  if (r == -1)
2912    SL_RETURN(-1, _("sh_unix_getinfo_attr"));
2913
2914  if (f == 0)
2915    SL_RETURN(0, _("sh_unix_getinfo_attr"));
2916
2917  *flags = f;
2918
2919/* ! HAVE_EXT2_IOCTLS */
2920#else
2921
2922  SL_ENTER(_("sh_unix_getinfo_attr"));
2923
2924  *flags = 0;                                     /* modified by R.Wichmann */
2925
2926/* ! HAVE_EXT2_IOCTLS */
2927#endif
2928/*
2929 * END
2930 *
2931 * lsattr.c             - List file attributes on an ext2 file system
2932 */
2933
2934  if (*flags == 0)
2935    goto theend;
2936
2937#ifdef EXT2_SECRM_FL
2938  if ( (*flags & EXT2_SECRM_FL) != 0  )   c_attr[0] = 's';
2939#endif
2940#ifdef EXT2_UNRM_FL
2941  if ( (*flags & EXT2_UNRM_FL) != 0   )   c_attr[1] = 'u';
2942#endif
2943#ifdef EXT2_SYNC_FL
2944  if ( (*flags & EXT2_SYNC_FL) != 0    )  c_attr[2] = 'S';
2945#endif
2946#ifdef EXT2_IMMUTABLE_FL
2947  if ( (*flags & EXT2_IMMUTABLE_FL) != 0) c_attr[3] = 'i';
2948#endif
2949#ifdef EXT2_APPEND_FL
2950  if ( (*flags & EXT2_APPEND_FL) != 0  )  c_attr[4] = 'a';
2951#endif
2952#ifdef EXT2_NODUMP_FL
2953  if ( (*flags & EXT2_NODUMP_FL) != 0  )  c_attr[5] = 'd';
2954#endif
2955#ifdef EXT2_NOATIME_FL
2956  if ( (*flags & EXT2_NOATIME_FL) != 0)   c_attr[6] = 'A';
2957#endif
2958#ifdef EXT2_COMPR_FL
2959  if ( (*flags & EXT2_COMPR_FL) != 0   )  c_attr[7] = 'c';
2960#endif
2961
2962#ifdef EXT2_TOPDIR_FL
2963  if ( (*flags & EXT2_TOPDIR_FL) != 0  )  c_attr[8] = 'T';
2964#endif
2965#ifdef EXT2_DIRSYNC_FL
2966  if ( (*flags & EXT2_DIRSYNC_FL) != 0 )  c_attr[9] = 'D';
2967#endif
2968#ifdef EXT2_NOTAIL_FL
2969  if ( (*flags & EXT2_NOTAIL_FL) != 0  )  c_attr[10] = 't';
2970#endif
2971#ifdef EXT2_JOURNAL_DATA_FL
2972  if ( (*flags & EXT2_JOURNAL_DATA_FL) != 0)  c_attr[11] = 'j';
2973#endif
2974
2975 theend:
2976  /* ext2 */
2977#endif
2978
2979  c_attr[12] = '\0';
2980
2981  SL_RETURN(0, _("sh_unix_getinfo_attr"));
2982}
2983#else
2984static 
2985int sh_unix_getinfo_attr (char * name, 
2986                          unsigned long * flags, 
2987                          char * c_attr,
2988                          int fd, struct stat * buf)
2989{
2990  return 0;
2991}
2992
2993/* defined(__linux__) || defined(HAVE_STAT_FLAGS) */
2994#endif
2995
2996/* determine file type
2997 */
2998static 
2999int sh_unix_getinfo_type (struct stat * buf, 
3000                          ShFileType * type, 
3001                          char * c_mode)
3002{
3003  SL_ENTER(_("sh_unix_getinfo_type"));
3004
3005  if      ( S_ISREG(buf->st_mode)  ) { 
3006    (*type)   = SH_FILE_REGULAR;
3007    c_mode[0] = '-';
3008  }
3009  else if ( S_ISLNK(buf->st_mode)  ) {
3010    (*type)   = SH_FILE_SYMLINK;
3011    c_mode[0] = 'l';
3012  }
3013  else if ( S_ISDIR(buf->st_mode)  ) {
3014    (*type)   = SH_FILE_DIRECTORY;
3015    c_mode[0] = 'd';
3016  }
3017  else if ( S_ISCHR(buf->st_mode)  ) {
3018    (*type)   = SH_FILE_CDEV;
3019    c_mode[0] = 'c';
3020  }
3021  else if ( S_ISBLK(buf->st_mode)  ) {
3022    (*type)   = SH_FILE_BDEV;
3023    c_mode[0] = 'b';
3024  }
3025  else if ( S_ISFIFO(buf->st_mode) ) {
3026    (*type)   = SH_FILE_FIFO;
3027    c_mode[0] = '|';
3028  }
3029  else if ( S_ISSOCK(buf->st_mode) ) {
3030    (*type)   = SH_FILE_SOCKET;
3031    c_mode[0] = 's';
3032  }
3033  else if ( S_ISDOOR(buf->st_mode) ) {
3034    (*type)   = SH_FILE_DOOR;
3035    c_mode[0] = 'D';
3036  }
3037  else if ( S_ISPORT(buf->st_mode) ) {
3038    (*type)   = SH_FILE_PORT;
3039    c_mode[0] = 'P';
3040  }
3041  else                              {
3042    (*type)   = SH_FILE_UNKNOWN;
3043    c_mode[0] = '?';
3044  }
3045
3046  SL_RETURN(0, _("sh_unix_getinfo_type"));
3047}
3048
3049int sh_unix_get_ftype(char * fullpath)
3050{
3051  char        c_mode[CMODE_SIZE];
3052  struct stat buf;
3053  ShFileType  type;
3054  int         res;
3055
3056  SL_ENTER(_("sh_unix_get_ftype"));
3057
3058  res = retry_lstat(FIL__, __LINE__, fullpath, &buf);
3059
3060  if (res < 0)
3061    SL_RETURN(SH_FILE_UNKNOWN, _("sh_unix_getinfo_type"));
3062
3063  sh_unix_getinfo_type (&buf, &type, c_mode);
3064
3065  SL_RETURN(type, _("sh_unix_get_ftype"));
3066}
3067
3068
3069static 
3070int  sh_unix_getinfo_mode (struct stat *buf, 
3071                           unsigned int * mode, 
3072                           char * c_mode)
3073{
3074
3075  SL_ENTER(_("sh_unix_getinfo_mode"));
3076
3077  (*mode) = buf->st_mode;
3078
3079  /* make 'ls'-like string */
3080 
3081  if ( (buf->st_mode & S_IRUSR) != 0 )  c_mode[1] = 'r'; 
3082  if ( (buf->st_mode & S_IWUSR) != 0 )  c_mode[2] = 'w'; 
3083  if ( (buf->st_mode & S_IXUSR) != 0 ) {
3084    if ((buf->st_mode & S_ISUID) != 0 ) c_mode[3] = 's';
3085    else                                c_mode[3] = 'x';
3086  } else {
3087    if ((buf->st_mode & S_ISUID) != 0 ) c_mode[3] = 'S';
3088  }
3089
3090  if ( (buf->st_mode & S_IRGRP) != 0 )  c_mode[4] = 'r'; 
3091  if ( (buf->st_mode & S_IWGRP) != 0 )  c_mode[5] = 'w'; 
3092  if ( (buf->st_mode & S_IXGRP) != 0 )  {
3093    if ((buf->st_mode & S_ISGID) != 0 ) c_mode[6] = 's';
3094    else                                c_mode[6] = 'x';
3095  } else {
3096    if ((buf->st_mode & S_ISGID) != 0 ) c_mode[6] = 'S';
3097  } 
3098
3099  if ( (buf->st_mode & S_IROTH) != 0 )  c_mode[7] = 'r'; 
3100  if ( (buf->st_mode & S_IWOTH) != 0 )  c_mode[8] = 'w';
3101#ifdef S_ISVTX  /* not POSIX */
3102  if ( (buf->st_mode & S_IXOTH) != 0 )  {
3103    if ((buf->st_mode & S_ISVTX) != 0 ) c_mode[9] = 't';
3104    else                                c_mode[9] = 'x';
3105  } else {
3106    if ((buf->st_mode & S_ISVTX) != 0 ) c_mode[9] = 'T';
3107  }
3108#else
3109  if ( (buf->st_mode & S_IXOTH) != 0 )  c_mode[9] = 'x';
3110#endif
3111
3112  SL_RETURN(0, _("sh_unix_getinfo_mode"));
3113}
3114
3115
3116long IO_Limit = 0;
3117
3118void sh_unix_io_pause ()
3119{
3120  long runtime;
3121  float          someval;
3122  unsigned long  sometime;
3123
3124  if (IO_Limit == 0)
3125    {
3126      return;
3127    }
3128  else
3129    {
3130      runtime = (long) (time(NULL) - sh.statistics.time_start);
3131     
3132      if (runtime > 0 && (long)(sh.statistics.bytes_hashed/runtime) > IO_Limit)
3133        {
3134          someval  = sh.statistics.bytes_hashed - (IO_Limit * runtime);
3135          someval /= (float) IO_Limit;
3136          if (someval < 1.0)
3137            {
3138              someval *= 1000;  /* milliseconds in a second */
3139              sometime = (unsigned long) someval;
3140              retry_msleep(0, sometime);
3141            }
3142          else
3143            {
3144              sometime = (unsigned long) someval;
3145              retry_msleep (sometime, 0);
3146            }
3147        }
3148    }
3149  return;
3150}
3151
3152int sh_unix_set_io_limit (const char * c)
3153{
3154  long val;
3155
3156  SL_ENTER(_("sh_unix_set_io_limit"));
3157
3158  val = strtol (c, (char **)NULL, 10);
3159  if (val < 0)
3160    sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS,
3161                      _("set I/O limit"), c);
3162
3163  val = (val < 0 ? 0 : val);
3164
3165  IO_Limit = val * 1024;
3166  SL_RETURN( 0, _("sh_unix_set_io_limit"));
3167}
3168
3169/* obtain file info
3170 */
3171extern int flag_err_debug;
3172
3173#include "sh_ignore.h"
3174
3175int sh_unix_checksum_size (char * filename, struct stat * fbuf, 
3176                           char * fileHash, int alert_timeout, SL_TICKET fd)
3177{
3178  file_type * tmpFile;
3179  int status;
3180
3181  SL_ENTER(_("sh_unix_checksum_size"));
3182
3183  tmpFile = SH_ALLOC(sizeof(file_type));
3184  tmpFile->link_path = NULL;
3185
3186  if (sh.flag.checkSum != SH_CHECK_INIT)
3187    {
3188      /* lookup file in database */
3189      status = sh_hash_get_it (filename, tmpFile);
3190      if (status != 0) {
3191        goto out;
3192      }
3193    }
3194  else
3195    {
3196      tmpFile->size = fbuf->st_size;
3197    }
3198
3199  /* if last < current get checksum */
3200  if (tmpFile->size < fbuf->st_size)
3201    {
3202      char hashbuf[KEYBUF_SIZE];
3203      UINT64 local_length = (UINT64) (tmpFile->size < 0 ? 0 : tmpFile->size);
3204      sl_strlcpy(fileHash,
3205                 sh_tiger_generic_hash (filename, fd, &(local_length), 
3206                                        alert_timeout, hashbuf, sizeof(hashbuf)),
3207                 KEY_LEN+1);
3208     
3209       /* return */
3210      if (tmpFile->link_path)   SH_FREE(tmpFile->link_path);
3211      SH_FREE(tmpFile);
3212      SL_RETURN( 0, _("sh_unix_checksum_size"));
3213    }
3214
3215 out:
3216  if (tmpFile->link_path)   SH_FREE(tmpFile->link_path);
3217  SH_FREE(tmpFile);
3218  sl_strlcpy(fileHash, SH_KEY_NULL, KEY_LEN+1);
3219  SL_RETURN( -1, _("sh_unix_checksum_size"));
3220}
3221
3222int sh_unix_check_selinux = S_FALSE;
3223int sh_unix_check_acl     = S_FALSE;
3224
3225#ifdef USE_ACL
3226
3227#include <sys/acl.h>
3228static char * sh_unix_getinfo_acl (char * path, int fd, struct stat * buf)
3229{
3230  /* system.posix_acl_access, system.posix_acl_default
3231   */
3232  char *  out  = NULL;
3233  char *  collect = NULL;
3234  char *  tmp;
3235  char *  out_compact;
3236  ssize_t len;
3237  acl_t   result;
3238
3239  SL_ENTER(_("sh_unix_getinfo_acl"));
3240
3241  result = (fd == -1) ? 
3242    acl_get_file (path, ACL_TYPE_ACCESS) :
3243    acl_get_fd   (fd);
3244
3245  if (result)
3246    {
3247      out = acl_to_text (result, &len);
3248      if (out && (len > 0)) {
3249        out_compact = sh_util_acl_compact (out, len);
3250        acl_free(out);
3251        if (out_compact) 
3252          {
3253            collect = sh_util_strconcat (_("acl_access:"), out_compact, NULL);
3254            SH_FREE(out_compact);
3255          }
3256      }
3257      acl_free(result);
3258    }
3259 
3260 
3261  if ( S_ISDIR(buf->st_mode) ) 
3262    {
3263      result = acl_get_file (path, ACL_TYPE_DEFAULT);
3264     
3265      if (result)
3266        {
3267          out = acl_to_text (result, &len);
3268          if (out && (len > 0)) {
3269            out_compact = sh_util_acl_compact (out, len);
3270            acl_free(out);
3271            if (out_compact) {
3272              if (collect) {
3273                tmp = sh_util_strconcat (_("acl_default:"), 
3274                                         out_compact, ":", collect, NULL);
3275                SH_FREE(collect);
3276              }
3277              else {
3278                tmp = sh_util_strconcat (_("acl_default:"), out_compact, NULL);
3279              }
3280              SH_FREE(out_compact);
3281              collect = tmp;
3282            }
3283          }
3284          acl_free(result);
3285        }
3286    }
3287 
3288  SL_RETURN((collect),_("sh_unix_getinfo_acl"));
3289}
3290#endif
3291
3292#ifdef USE_XATTR
3293
3294#include <attr/xattr.h>
3295static char * sh_unix_getinfo_xattr_int (char * path, int fd, char * name)
3296{
3297  char *  out   = NULL;
3298  char *  tmp   = NULL;
3299  size_t  size  = 256;
3300  ssize_t result;
3301
3302  SL_ENTER(_("sh_unix_getinfo_xattr_int"));
3303
3304  out = SH_ALLOC(size);
3305
3306  result = (fd == -1) ? 
3307    lgetxattr (path, name, out, size-1) :
3308    fgetxattr (fd,   name, out, size-1);
3309
3310  if (result == -1 && errno == ERANGE) 
3311    {
3312      SH_FREE(out);
3313      result = (fd == -1) ? 
3314        lgetxattr (path, name, NULL, 0) :
3315        fgetxattr (fd,   name, NULL, 0);
3316      size = result + 1;
3317      out  = SH_ALLOC(size);
3318      result = (fd == -1) ? 
3319        lgetxattr (path, name, out, size-1) :
3320        fgetxattr (fd,   name, out, size-1);
3321    }
3322
3323  if ((result > 0) && ((size_t)result < size))
3324    {
3325      out[size-1] = '\0';
3326      tmp = out;
3327    }
3328  else
3329    {
3330      SH_FREE(out);
3331    }
3332
3333  SL_RETURN((tmp),_("sh_unix_getinfo_xattr_int"));
3334}
3335
3336
3337static char * sh_unix_getinfo_xattr (char * path, int fd, struct stat * buf)
3338{
3339  /* system.posix_acl_access, system.posix_acl_default, security.selinux
3340   */
3341  char *  tmp;
3342  char *  out  = NULL;
3343  char *  collect = NULL;
3344
3345  SL_ENTER(_("sh_unix_getinfo_xattr"));
3346
3347#ifdef USE_ACL
3348  /*
3349   * we need the acl_get_fd/acl_get_file functions, getxattr will only
3350   * yield the raw bytes
3351   */
3352  if (sh_unix_check_acl == S_TRUE) 
3353    {
3354      out = sh_unix_getinfo_acl(path, fd, buf);
3355     
3356      if (out)
3357        {
3358          collect = out;
3359        }
3360  }
3361#endif
3362
3363  if (sh_unix_check_selinux == S_TRUE)
3364    {
3365      out = sh_unix_getinfo_xattr_int(path, fd, _("security.selinux"));
3366
3367      if (out)
3368        {
3369          if (collect) {
3370            tmp = sh_util_strconcat(_("selinux:"), out, ":", collect, NULL);
3371            SH_FREE(collect);
3372          }
3373          else {
3374            tmp = sh_util_strconcat(_("selinux:"), out, NULL);
3375          }
3376          SH_FREE(out);
3377          collect = tmp;
3378        }
3379    }
3380
3381  SL_RETURN((collect),_("sh_unix_getinfo_xattr"));
3382}
3383#endif
3384
3385#ifdef USE_XATTR
3386int sh_unix_setcheckselinux (const char * c)
3387{
3388  int i;
3389  SL_ENTER(_("sh_unix_setcheckselinux"));
3390  i = sh_util_flagval(c, &(sh_unix_check_selinux));
3391
3392  SL_RETURN(i, _("sh_unix_setcheckselinux"));
3393}
3394#endif
3395
3396#ifdef USE_ACL
3397int sh_unix_setcheckacl (const char * c)
3398{
3399  int i;
3400  SL_ENTER(_("sh_unix_setcheckacl"));
3401  i = sh_util_flagval(c, &(sh_unix_check_acl));
3402
3403  SL_RETURN(i, _("sh_unix_setcheckacl"));
3404}
3405#endif
3406
3407#ifdef HAVE_LIBZ
3408#include <zlib.h>
3409#endif   
3410
3411int sh_unix_getinfo (int level, char * filename, file_type * theFile, 
3412                     char * fileHash, int policy)
3413{
3414  char          timestr[81];
3415  long          runtim;
3416  struct stat   buf;
3417  struct stat   lbuf;
3418  struct stat   fbuf;
3419  int           stat_return;
3420  int           stat_errno = 0;
3421
3422  ShFileType    type;
3423  unsigned int  mode;
3424  char        * tmp;
3425  char        * tmp2;
3426
3427  char        * linknamebuf;
3428  int           linksize;
3429
3430  extern int get_the_fd (SL_TICKET ticket);
3431
3432  SL_TICKET     rval_open;
3433  int           err_open = 0;
3434
3435  int           fd;
3436  int           fstat_return;
3437  int           fstat_errno = 0;
3438
3439  sh_string   * content = NULL;
3440     
3441  time_t        tend;
3442  time_t        tstart;
3443
3444
3445  char * path = NULL;
3446
3447  int alert_timeout   = 120;
3448
3449  path = theFile->fullpath;
3450
3451  SL_ENTER(_("sh_unix_getinfo"));
3452
3453  /* --- Stat the file, and get checksum. ---
3454   */
3455  tstart = time(NULL);
3456
3457  stat_return = retry_lstat (FIL__, __LINE__, 
3458                             path /* theFile->fullpath */, &buf);
3459
3460  if (stat_return)
3461    stat_errno = errno;
3462
3463  fd           = -1;
3464  fstat_return = -1;
3465  rval_open    = -1;
3466
3467  theFile->link_path = NULL;
3468
3469  if (stat_return == 0 && S_ISREG(buf.st_mode)) 
3470    {
3471      rval_open = sl_open_fastread (path /* theFile->fullpath */, SL_YESPRIV);
3472      if (SL_ISERROR(rval_open))
3473        err_open = errno;
3474
3475      alert_timeout = 120; /* this is per 8K block now ! */
3476
3477      if (path[1] == 'p' && path[5] == '/' && path[2] == 'r' &&
3478          path[3] == 'o' && path[4] == 'c' && path[0] == '/')
3479        {
3480          /* seven is magic */
3481          alert_timeout = 7;
3482        }
3483
3484      fd = get_the_fd(rval_open);
3485    }
3486
3487  tend = time(NULL);
3488
3489  /* An unprivileged user may slow lstat/open to a crawl
3490   * with clever path/symlink setup
3491   */
3492  if ((tend - tstart) > (time_t) /* 60 */ 6)
3493    {
3494      tmp2 = sh_util_safe_name (theFile->fullpath);
3495      sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_TOOLATE,
3496                       (long)(tend - tstart), tmp2);
3497      SH_FREE(tmp2);
3498    }
3499
3500  if (fd >= 0) 
3501    {
3502      fstat_return = retry_fstat (FIL__, __LINE__, fd, &fbuf);
3503      if (fstat_return)
3504        fstat_errno = errno;
3505    }
3506  else
3507    {
3508      fd = -1;
3509    }
3510     
3511
3512  /* ---  case 1: lstat failed  ---
3513   */
3514  if (stat_return != 0) 
3515    {
3516      stat_return = errno;
3517      if (!SL_ISERROR(rval_open))
3518          sl_close(rval_open);
3519      if (sh.flag.checkSum == SH_CHECK_INIT || 
3520          (sh_hash_have_it (theFile->fullpath) >= 0 && 
3521           (!SH_FFLAG_REPORTED_SET(theFile->file_reported))))
3522        {
3523          if (S_FALSE == sh_ignore_chk_del(theFile->fullpath)) {
3524            char errbuf[SH_ERRBUF_SIZE];
3525            uid_t euid;
3526            (void) sl_get_euid(&euid);
3527            tmp2 = sh_util_safe_name (theFile->fullpath);
3528            sh_error_handle (level, FIL__, __LINE__, stat_return, MSG_FI_STAT,
3529                             _("lstat"),
3530                             sh_error_message (stat_errno, errbuf, sizeof(errbuf)),
3531                             (long) euid,
3532                             tmp2);
3533            SH_FREE(tmp2);
3534          }
3535        }
3536      SL_RETURN((-1),_("sh_unix_getinfo"));
3537    }
3538
3539  /* ---  case 2: not a regular file  ---
3540   */
3541  else if (! S_ISREG(buf.st_mode))
3542    {
3543      if (fileHash != NULL)
3544        sl_strlcpy(fileHash, SH_KEY_NULL, KEY_LEN+1);
3545    }
3546 
3547  /* ---  case 3a: a regular file, fstat ok ---
3548   */
3549  else if (fstat_return == 0 && 
3550           buf.st_mode == fbuf.st_mode &&
3551           buf.st_ino  == fbuf.st_ino  &&
3552           buf.st_uid  == fbuf.st_uid  &&
3553           buf.st_gid  == fbuf.st_gid  &&
3554           buf.st_dev  == fbuf.st_dev )
3555    {
3556      if (fileHash != NULL)
3557        {
3558          if ((theFile->check_mask & MODI_CHK) == 0)
3559            {
3560              sl_strlcpy(fileHash, SH_KEY_NULL, KEY_LEN+1);
3561            }
3562          else if ((theFile->check_mask & MODI_PREL) != 0 && 
3563                   S_TRUE == sh_prelink_iself(rval_open, fbuf.st_size, 
3564                                              alert_timeout, theFile->fullpath))
3565            {
3566              if (0 != sh_prelink_run (theFile->fullpath, 
3567                                       fileHash, alert_timeout))
3568                sl_strlcpy(fileHash, SH_KEY_NULL, KEY_LEN+1);
3569            }
3570          else
3571            {
3572              char hashbuf[KEYBUF_SIZE];
3573              UINT64 length_nolim = TIGER_NOLIM;
3574
3575              if (MODI_TXT_ENABLED(theFile->check_mask) && fbuf.st_size < (10 * SH_TXT_MAX))
3576                {
3577                  sl_init_content (rval_open, fbuf.st_size);
3578                }
3579
3580              sl_strlcpy(fileHash,
3581                         sh_tiger_generic_hash (theFile->fullpath, 
3582                                                rval_open, &length_nolim, 
3583                                                alert_timeout, 
3584                                                hashbuf, sizeof(hashbuf)),
3585                         KEY_LEN+1);
3586
3587              content = sl_get_content(rval_open);
3588              content = sh_string_copy(content);
3589
3590              if ((theFile->check_mask & MODI_SGROW) != 0)
3591                {
3592                  fbuf.st_size = (off_t) length_nolim;
3593                  buf.st_size  = fbuf.st_size;
3594                  sl_rewind(rval_open);
3595                  sh_unix_checksum_size (theFile->fullpath, &fbuf, 
3596                                         &fileHash[KEY_LEN + 1], 
3597                                         alert_timeout, rval_open);
3598                }
3599            }
3600        }
3601    }
3602
3603  /* ---  case 3b: a regular file, fstat ok, but different ---
3604   */
3605  else if (fstat_return == 0 && S_ISREG(fbuf.st_mode))
3606    {
3607      memcpy (&buf, &fbuf, sizeof( struct stat ));
3608
3609      if (fileHash != NULL)
3610        {
3611          if ((theFile->check_mask & MODI_CHK) == 0)
3612            {
3613              sl_strlcpy(fileHash, SH_KEY_NULL, KEY_LEN+1);
3614            }
3615          else if (policy == SH_LEVEL_PRELINK &&
3616                   S_TRUE == sh_prelink_iself(rval_open, fbuf.st_size, 
3617                                              alert_timeout, theFile->fullpath))
3618            {
3619              if (0 != sh_prelink_run (theFile->fullpath, 
3620                                       fileHash, alert_timeout))
3621                sl_strlcpy(fileHash, SH_KEY_NULL, KEY_LEN+1);
3622            }
3623          else
3624            {
3625              char hashbuf[KEYBUF_SIZE];
3626              UINT64 length_nolim = TIGER_NOLIM;
3627
3628              if (MODI_TXT_ENABLED(theFile->check_mask) && fbuf.st_size < (10 * SH_TXT_MAX))
3629                {
3630                  sl_init_content (rval_open, fbuf.st_size);
3631                }
3632
3633              sl_strlcpy(fileHash, 
3634                         sh_tiger_generic_hash (theFile->fullpath, rval_open, 
3635                                                &length_nolim,
3636                                                alert_timeout,
3637                                                hashbuf, sizeof(hashbuf)),
3638                         KEY_LEN + 1);
3639
3640              content = sl_get_content(rval_open);
3641              content = sh_string_copy(content);
3642
3643              if ((theFile->check_mask & MODI_SGROW) != 0) 
3644                {
3645                  fbuf.st_size = (off_t) length_nolim;
3646                  buf.st_size  = fbuf.st_size;
3647                  sl_rewind(rval_open);
3648                  sh_unix_checksum_size (theFile->fullpath, &fbuf, 
3649                                         &fileHash[KEY_LEN + 1], 
3650                                         alert_timeout, rval_open);
3651                }
3652            }
3653        }
3654    }
3655
3656  /* ---  case 4: a regular file, fstat failed ---
3657   */
3658
3659  else    /* fstat_return != 0 or !S_ISREG(fbuf.st_mode) or open() failed */
3660    {
3661      uid_t   euid;
3662
3663      if (fileHash != NULL)
3664        sl_strlcpy(fileHash, SH_KEY_NULL, KEY_LEN+1);
3665
3666      if ((theFile->check_mask & MODI_CHK) != 0)
3667        {
3668          tmp2 = sh_util_safe_name (theFile->fullpath);
3669
3670
3671          if (fd >= 0 && fstat_return != 0)
3672            {
3673              char errbuf[SH_ERRBUF_SIZE];
3674              (void) sl_get_euid(&euid);
3675
3676              sh_error_handle (level, FIL__, __LINE__, stat_return, MSG_FI_STAT,
3677                               _("fstat"),
3678                               sh_error_message (fstat_errno, errbuf, sizeof(errbuf)),
3679                               (long) euid,
3680                               tmp2);
3681            }
3682          else if (fd >= 0 && !S_ISREG(fbuf.st_mode))
3683            {
3684              sh_error_handle (level, FIL__, __LINE__, fstat_errno, 
3685                               MSG_E_NOTREG, tmp2);
3686            }
3687          else
3688            {
3689              char errbuf[SH_ERRBUF_SIZE];
3690              char errbuf2[SH_ERRBUF_SIZE];
3691              sl_strlcpy(errbuf, sl_error_string(rval_open), sizeof(errbuf));
3692              sh_error_message(err_open, errbuf2, sizeof(errbuf2));
3693              sh_error_handle (level, FIL__, __LINE__, err_open, 
3694                               MSG_E_READ, errbuf, errbuf2, tmp2);
3695            }
3696          SH_FREE(tmp2);
3697        }
3698    }     
3699
3700
3701  /* --- Determine file type. ---
3702   */
3703  memset (theFile->c_mode, '-', CMODE_SIZE-1);
3704  theFile->c_mode[CMODE_SIZE-1] = '\0';
3705
3706  memset (theFile->link_c_mode, '-', CMODE_SIZE-1);
3707  theFile->link_c_mode[CMODE_SIZE-1] = '\0';
3708
3709  sh_unix_getinfo_type (&buf, &type, theFile->c_mode);
3710  theFile->type = type;
3711
3712#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
3713
3714  /* --- Determine file attributes. ---
3715   */
3716  memset (theFile->c_attributes, '-', ATTRBUF_SIZE);
3717  theFile->c_attributes[ATTRBUF_USED] = '\0';
3718  theFile->attributes      =    0;
3719
3720  if (theFile->c_mode[0] != 'c' && theFile->c_mode[0] != 'b' &&
3721      theFile->c_mode[0] != 'l' )
3722    sh_unix_getinfo_attr(theFile->fullpath, 
3723                         &theFile->attributes, theFile->c_attributes, 
3724                         fd, &buf);
3725#endif
3726
3727#if defined(USE_XATTR) && defined(USE_ACL)
3728  if (sh_unix_check_selinux == S_TRUE || sh_unix_check_acl == S_TRUE)
3729    theFile->attr_string = sh_unix_getinfo_xattr (theFile->fullpath, fd, &buf);
3730#elif defined(USE_XATTR)
3731  if (sh_unix_check_selinux == S_TRUE)
3732    theFile->attr_string = sh_unix_getinfo_xattr (theFile->fullpath, fd, &buf);
3733#elif defined(USE_ACL)
3734  if (sh_unix_check_acl == S_TRUE)
3735    theFile->attr_string = sh_unix_getinfo_acl (theFile->fullpath, fd, &buf);
3736#else
3737  theFile->attr_string = NULL;
3738#endif
3739
3740  if (!SL_ISERROR(rval_open))
3741    sl_close(rval_open);
3742
3743
3744  /* --- I/O limit. ---
3745   */
3746  if (IO_Limit > 0)
3747    {
3748      runtim = (long) (time(NULL) - sh.statistics.time_start);
3749     
3750      if (runtim > 0 && (long)(sh.statistics.bytes_hashed/runtim) > IO_Limit)
3751        retry_msleep(1, 0);
3752    }
3753
3754  /* --- Determine permissions. ---
3755   */
3756  sh_unix_getinfo_mode (&buf, &mode, theFile->c_mode);
3757
3758  /* --- Trivia. ---
3759   */
3760  theFile->dev       = buf.st_dev;
3761  theFile->ino       = buf.st_ino;
3762  theFile->mode      = buf.st_mode;
3763  theFile->hardlinks = buf.st_nlink;
3764  theFile->owner     = buf.st_uid; 
3765  theFile->group     = buf.st_gid; 
3766  theFile->rdev      = buf.st_rdev;
3767  theFile->size      = buf.st_size;
3768  theFile->blksize   = (unsigned long) buf.st_blksize;
3769  theFile->blocks    = (unsigned long) buf.st_blocks;
3770  theFile->atime     = buf.st_atime;
3771  theFile->mtime     = buf.st_mtime;
3772  theFile->ctime     = buf.st_ctime;
3773
3774
3775  /* --- Owner and group. ---
3776   */
3777
3778  if (NULL == sh_unix_getGIDname(SH_ERR_ALL, buf.st_gid, theFile->c_group, GROUP_MAX+1)) {
3779
3780    tmp2 = sh_util_safe_name (theFile->fullpath);
3781
3782    if (policy == SH_LEVEL_ALLIGNORE)
3783      {
3784        sh_error_handle (SH_ERR_ALL, FIL__, __LINE__, ENOENT, 
3785                         MSG_FI_NOGRP,
3786                         (long) buf.st_gid, tmp2);
3787      }
3788    else
3789      {
3790        sh_error_handle (ShDFLevel[SH_ERR_T_NAME], FIL__, __LINE__, ENOENT, 
3791                         MSG_FI_NOGRP,
3792                         (long) buf.st_gid, tmp2);
3793      }
3794    SH_FREE(tmp2);
3795    sl_snprintf(theFile->c_group, GROUP_MAX+1, "%d", (long) buf.st_gid); 
3796  }
3797
3798 
3799  if (NULL == sh_unix_getUIDname(SH_ERR_ALL, buf.st_uid, theFile->c_owner, USER_MAX+1)) {
3800
3801    tmp2 = sh_util_safe_name (theFile->fullpath);
3802
3803    if (policy == SH_LEVEL_ALLIGNORE)
3804      {
3805        sh_error_handle (SH_ERR_ALL, FIL__, __LINE__, ENOENT, 
3806                         MSG_FI_NOUSR,
3807                         (long) buf.st_uid, tmp2);
3808      }
3809    else
3810      {
3811        sh_error_handle (ShDFLevel[SH_ERR_T_NAME], FIL__, __LINE__, ENOENT, 
3812                         MSG_FI_NOUSR,
3813                         (long) buf.st_uid, tmp2);
3814      }
3815    SH_FREE(tmp2);
3816    sl_snprintf(theFile->c_owner, USER_MAX+1, "%d", (long) buf.st_uid); 
3817  }
3818
3819  /* --- Output the file. ---
3820   */
3821  if (flag_err_debug == SL_TRUE)
3822    {
3823      tmp2 = sh_util_safe_name ((filename == NULL) ? 
3824                                theFile->fullpath : filename);
3825      (void) sh_unix_time(theFile->mtime, timestr, sizeof(timestr));
3826      sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_LIST,
3827                       theFile->c_mode,
3828                       theFile->hardlinks,
3829                       theFile->c_owner,
3830                       theFile->c_group,
3831                       (unsigned long) theFile->size,
3832                       timestr,
3833                       tmp2);
3834      SH_FREE(tmp2);
3835    }
3836
3837  /* --- Check for links. ---
3838   */
3839  if (theFile->c_mode[0] == 'l') 
3840    {
3841      linknamebuf = SH_ALLOC(PATH_MAX);
3842
3843      /* flawfinder: ignore */
3844      linksize    = readlink (theFile->fullpath, linknamebuf, PATH_MAX-1);
3845
3846      if (linksize < (PATH_MAX-1) && linksize >= 0) 
3847        linknamebuf[linksize] = '\0';
3848      else 
3849        linknamebuf[PATH_MAX-1] = '\0';
3850     
3851      if (linksize < 0) 
3852        {
3853          char errbuf[SH_ERRBUF_SIZE];
3854          linksize = errno;
3855          tmp2 = sh_util_safe_name (theFile->fullpath);
3856          sh_error_handle (level, FIL__, __LINE__, linksize, MSG_FI_RDLNK,
3857                           sh_error_message (linksize, errbuf, sizeof(errbuf)), tmp2);
3858          SH_FREE(tmp2);
3859          SH_FREE(linknamebuf);
3860          theFile->link_path = sh_util_strdup("-");
3861          SL_RETURN((-1),_("sh_unix_getinfo"));
3862        }
3863
3864      if (linknamebuf[0] == '/') 
3865        {
3866          theFile->link_path = sh_util_strdup (linknamebuf);
3867        } 
3868      else 
3869        {
3870          tmp = sh_util_dirname(theFile->fullpath);
3871          if (tmp) {
3872            theFile->link_path = SH_ALLOC(PATH_MAX);
3873            sl_strlcpy (theFile->link_path, tmp, PATH_MAX);
3874            SH_FREE(tmp);
3875          } else {
3876            theFile->link_path = SH_ALLOC(PATH_MAX);
3877            theFile->link_path[0] = '\0';
3878          }
3879          /*
3880           * Only attach '/' if not root directory. Handle "//", which
3881           * according to POSIX is implementation-defined, and may be
3882           * different from "/" (however, three or more '/' will collapse
3883           * to one).
3884           */
3885          tmp = theFile->link_path; while (*tmp == '/') ++tmp;
3886          if (*tmp != '\0')
3887            {
3888              sl_strlcat (theFile->link_path, "/", PATH_MAX);
3889            }
3890          sl_strlcat (theFile->link_path, linknamebuf, PATH_MAX);
3891        }
3892     
3893      /* stat the link
3894       */
3895      stat_return = retry_lstat (FIL__, __LINE__, theFile->link_path, &lbuf); 
3896     
3897      /* check for error
3898       */
3899      if (stat_return != 0) 
3900        { 
3901          stat_return = errno;
3902          tmp  = sh_util_safe_name (theFile->fullpath);
3903          tmp2 = sh_util_safe_name (theFile->link_path);
3904          if (stat_return != ENOENT)
3905            { 
3906              uid_t euid;
3907              char errbuf[SH_ERRBUF_SIZE];
3908
3909              (void) sl_get_euid(&euid);
3910              sh_error_handle (level, FIL__, __LINE__, stat_return, 
3911                               MSG_FI_STAT,
3912                               _("lstat"),
3913                               sh_error_message (stat_return,errbuf, sizeof(errbuf)), 
3914                               (long) euid,
3915                               tmp2);
3916            }
3917          else 
3918            {
3919              /* a dangling link -- everybody seems to have plenty of them
3920               */
3921              sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_DLNK,
3922                               tmp, tmp2);
3923            }
3924          theFile->linkisok = BAD;
3925          SH_FREE(tmp);
3926          SH_FREE(tmp2);
3927          SH_FREE(linknamebuf);
3928          /*
3929           * changed Tue Feb 10 16:16:13 CET 2004:
3930           *  add dangling symlinks into database
3931           * SL_RETURN((-1),_("sh_unix_getinfo"));
3932           */
3933          theFile->linkmode = 0;
3934          SL_RETURN((0),_("sh_unix_getinfo")); 
3935        }
3936     
3937      theFile->linkisok = GOOD;
3938     
3939     
3940      /* --- Determine file type. ---
3941       */
3942      sh_unix_getinfo_type (&lbuf, &type, theFile->link_c_mode);
3943      theFile->type = type;
3944     
3945      /* --- Determine permissions. ---
3946       */
3947      sh_unix_getinfo_mode (&lbuf, &mode, theFile->link_c_mode);
3948      theFile->linkmode = lbuf.st_mode;
3949     
3950      /* --- Output the link. ---
3951       */
3952      if (theFile->linkisok == GOOD) 
3953        {
3954          tmp2 = sh_util_safe_name (linknamebuf);     
3955          sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_LLNK,
3956                           theFile->link_c_mode, tmp2);
3957          SH_FREE(tmp2);
3958        }
3959      SH_FREE(linknamebuf);
3960    }
3961  else /* not a link */
3962    {
3963      if (content)
3964        {
3965#ifdef HAVE_LIBZ
3966          unsigned long   clen;
3967          unsigned char * compressed;
3968#ifdef HAVE_COMPRESSBOUND
3969          clen       = compressBound(sh_string_len(content));
3970#else
3971          if (sh_string_len(content) > 10*SH_TXT_MAX)
3972            clen = SH_TXT_MAX;
3973          else
3974            clen = 13 + (int)(1.0001*sh_string_len(content));
3975#endif
3976          compressed = SH_ALLOC(clen);
3977          if (Z_OK == compress(compressed, &clen, 
3978                               (unsigned char *) sh_string_str(content), 
3979                               sh_string_len(content)))
3980              {
3981                if (clen < SH_TXT_MAX)
3982                  {
3983                    sh_util_base64_enc_alloc (&(theFile->link_path), 
3984                                              (char *) compressed, clen);
3985                  }
3986                else
3987                  {
3988                    char tmsg[128];
3989                    char * tpath = sh_util_safe_name (theFile->fullpath);
3990                    sl_snprintf(tmsg, sizeof(tmsg), 
3991                                _("compressed file too large (%lu bytes)"),
3992                                clen);
3993                    sh_error_handle (SH_ERR_WARN, FIL__, __LINE__, -1, 
3994                                     MSG_E_SUBGPATH, tmsg, 
3995                                     _("sh_unix_getinfo"), tpath);
3996                    SH_FREE(tpath);
3997                  }
3998              }
3999          SH_FREE(compressed);
4000#endif
4001          sh_string_destroy(&content);
4002        }
4003    } 
4004  SL_RETURN((0),_("sh_unix_getinfo"));
4005}
4006
4007/*  #if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)  */
4008#endif
4009
4010int sh_unix_unlock(char * lockfile, char * flag)
4011{
4012  int         error = 0;
4013 
4014  SL_ENTER(_("sh_unix_unlock"));
4015
4016  if (sh.flag.isdaemon == S_FALSE && flag == NULL)
4017    SL_RETURN((0),_("sh_unix_unlock"));
4018
4019  /* --- Logfile is not locked to us. ---
4020   */
4021  if (sh.flag.islocked == BAD && flag != NULL) 
4022    SL_RETURN((-1),_("sh_unix_unlock"));
4023
4024  /* --- Check whether the directory is secure. ---
4025   */
4026  if (0 != tf_trust_check (lockfile, SL_YESPRIV))
4027    SL_RETURN((-1),_("sh_unix_unlock"));
4028
4029  /* --- Delete the lock file. ---
4030   */
4031  error = retry_aud_unlink (FIL__, __LINE__, lockfile);
4032 
4033  if (error == 0)
4034    {
4035      if (flag != NULL)
4036        sh.flag.islocked = BAD; /* not locked anymore */
4037    }
4038  else if (flag != NULL)
4039    {
4040      char errbuf[SH_ERRBUF_SIZE];
4041      error = errno;
4042      sh_error_handle ((-1), FIL__, __LINE__, error, MSG_E_UNLNK,
4043                       sh_error_message(error, errbuf, sizeof(errbuf)), 
4044                       lockfile);
4045      SL_RETURN((-1),_("sh_unix_unlock"));
4046    }
4047  SL_RETURN((0),_("sh_unix_unlock"));
4048}
4049
4050int sh_unix_lock (char * lockfile, char * flag)
4051{
4052  int filed;
4053  int errnum;
4054  char myPid[64];
4055  SL_TICKET  fd;
4056  extern int get_the_fd (SL_TICKET ticket);
4057
4058  SL_ENTER(_("sh_unix_lock"));
4059
4060  sprintf (myPid, "%ld\n", (long) sh.pid);             /* known to fit  */
4061
4062  fd = sl_open_safe_rdwr (lockfile, SL_YESPRIV);       /* fails if file exists */
4063
4064  if (!SL_ISERROR(fd))
4065    {
4066      errnum = sl_write (fd, myPid, sl_strlen(myPid));
4067      filed = get_the_fd(fd);
4068      fchmod (filed, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
4069      sl_close (fd);
4070
4071      if (!SL_ISERROR(errnum))
4072        {
4073          if (flag != NULL)
4074            sh.flag.islocked = GOOD;
4075          SL_RETURN((0),_("sh_unix_lock"));
4076        }
4077    }
4078
4079  TPT((0, FIL__, __LINE__, _("msg=<open pid file failed>\n")));
4080  if (flag != NULL)
4081    sh.flag.islocked       = BAD;
4082  SL_RETURN((-1),_("sh_unix_lock"));
4083
4084  /* notreached */
4085}
4086
4087
4088/* check whether file is locked
4089 */
4090int sh_unix_test_and_lock (char * filename, char * lockfile)
4091{
4092  static        struct stat   buf;
4093  int           status = 0;
4094
4095
4096  SL_TICKET     fd;
4097  char          line_in[128];
4098
4099  SL_ENTER(_("sh_unix_test_and_lock"));
4100
4101  status = retry_lstat (FIL__, __LINE__, lockfile, &buf);
4102
4103  /* --- No lock file found, try to lock. ---
4104   */
4105
4106  if (status < 0 && errno == ENOENT)
4107    {
4108      if (0 == sh_unix_lock (lockfile, filename))
4109        { 
4110          if (filename != NULL) 
4111            sh.flag.islocked = GOOD;
4112          SL_RETURN((0),_("sh_unix_test_and_lock"));
4113        }
4114      else
4115        {
4116          sh_error_handle ((-1), FIL__, __LINE__, status,
4117                           MSG_E_SUBGEN, 
4118                           (filename == NULL) ? _("Cannot create PID file") : _("Cannot create lock file"),
4119                           _("sh_unix_test_and_lock"));
4120          SL_RETURN((-1),_("sh_unix_test_and_lock"));
4121        }
4122    }
4123  else if (status == 0 && buf.st_size == 0)
4124    {
4125      if (filename != NULL)
4126        sh.flag.islocked = GOOD;
4127      sh_unix_unlock (lockfile, filename);
4128      if (filename != NULL)
4129        sh.flag.islocked = BAD;
4130      if (0 == sh_unix_lock (lockfile, filename))
4131        { 
4132          if (filename != NULL)
4133            sh.flag.islocked = GOOD;
4134          SL_RETURN((0),_("sh_unix_test_and_lock"));
4135        }
4136      else
4137        {
4138          sh_error_handle ((-1), FIL__, __LINE__, status,
4139                           MSG_E_SUBGEN, 
4140                           (filename == NULL) ? _("Cannot create PID file") : _("Cannot create lock file"),
4141                           _("sh_unix_test_and_lock"));
4142          SL_RETURN((-1),_("sh_unix_test_and_lock"));
4143        }
4144    }
4145
4146  /* --- Check on lock. ---
4147   */
4148 
4149  if (status >= 0)
4150    {
4151       fd = sl_open_read (lockfile, SL_YESPRIV);
4152       if (SL_ISERROR(fd))
4153         sh_error_handle ((-1), FIL__, __LINE__, fd,
4154                          MSG_E_SUBGEN, 
4155                          (filename == NULL) ? _("Cannot open PID file for read") : _("Cannot open lock file for read"),
4156                          _("sh_unix_test_and_lock"));
4157    }
4158  else
4159    fd = -1;
4160
4161  if (!SL_ISERROR(fd))
4162    {
4163      /* read the PID in the lock file
4164       */
4165      status = sl_read (fd, line_in, sizeof(line_in));
4166      line_in[sizeof(line_in)-1] = '\0';
4167
4168      /* convert to numeric
4169       */
4170      if (status > 0)
4171        {
4172          errno  = 0;
4173          status = strtol(line_in, (char **)NULL, 10);
4174          if (errno == ERANGE || status <= 0)
4175             {
4176                sh_error_handle ((-1), FIL__, __LINE__, status,
4177                                 MSG_E_SUBGEN, 
4178                                 (filename == NULL) ? _("Bad PID in PID file") : _("Bad PID in lock file"),
4179                                 _("sh_unix_test_and_lock"));
4180
4181                status = -1;
4182             }
4183        }
4184      else
4185        {
4186           sh_error_handle ((-1), FIL__, __LINE__, status,
4187                            MSG_E_SUBGEN, 
4188                            (filename == NULL) ? _("Cannot read PID file") : _("Cannot read lock file"),
4189                            _("sh_unix_test_and_lock"));
4190        }
4191      sl_close(fd);
4192
4193      if (status > 0 && (unsigned int) status == sh.pid)
4194        {
4195          if (filename != NULL)
4196            sh.flag.islocked = GOOD;
4197          SL_RETURN((0),_("sh_unix_test_and_lock"));
4198        }
4199
4200
4201      /* --- Check whether the process exists. ---
4202       */
4203      if (status > 0)
4204        {
4205          errno  = 0;
4206          status = aud_kill (FIL__, __LINE__, status, 0);
4207
4208          /* Does not exist, so remove the stale lock
4209           * and create a new one.
4210           */
4211          if (status < 0 && errno == ESRCH)
4212            {
4213              if (filename != NULL)
4214                sh.flag.islocked = GOOD;
4215              if (0 != sh_unix_unlock(lockfile, filename) && (filename !=NULL))
4216                sh.flag.islocked = BAD;
4217              else
4218                {
4219                  if (0 == sh_unix_lock  (lockfile, filename))
4220                    {
4221                      if (filename != NULL)
4222                        sh.flag.islocked = GOOD;
4223                      SL_RETURN((0),_("sh_unix_test_and_lock"));
4224                    }
4225                   else
4226                    {
4227                       sh_error_handle ((-1), FIL__, __LINE__, status,
4228                                        MSG_E_SUBGEN, 
4229                                        (filename == NULL) ? _("Cannot create PID file") : _("Cannot create lock file"),
4230                                        _("sh_unix_test_and_lock"));
4231                    }
4232                  if (filename != NULL)
4233                    sh.flag.islocked = BAD;
4234                }
4235            }
4236          else
4237            {
4238              sh_error_handle ((-1), FIL__, __LINE__, status,
4239                               MSG_E_SUBGEN, 
4240                               (filename == NULL) ? _("Cannot remove stale PID file, PID may be a running process") : _("Cannot remove stale lock file, PID may be a running process"),
4241                               _("sh_unix_test_and_lock"));
4242              if (filename != NULL)
4243                sh.flag.islocked = BAD;
4244            }
4245        }
4246    }
4247  SL_RETURN((-1),_("sh_unix_testlock"));
4248}
4249
4250/* write the PID file
4251 */
4252int sh_unix_write_pid_file()
4253{
4254  return sh_unix_test_and_lock(NULL, sh.srvlog.alt);
4255}
4256
4257/* write lock for filename
4258 */
4259int sh_unix_write_lock_file(char * filename)
4260{
4261  size_t len;
4262  int    res;
4263  char * lockfile;
4264
4265  if (filename == NULL)
4266    return (-1);
4267
4268  len = sl_strlen(filename);
4269  if (sl_ok_adds(len, 6))
4270    len += 6;
4271  lockfile = SH_ALLOC(len);
4272  sl_strlcpy(lockfile, filename,   len);
4273  sl_strlcat(lockfile, _(".lock"), len);
4274  res = sh_unix_test_and_lock(filename, lockfile);
4275  SH_FREE(lockfile);
4276  return res;
4277}
4278
4279/* rm lock for filename
4280 */
4281int sh_unix_rm_lock_file(char * filename)
4282{
4283  size_t len;
4284  int res;
4285  char * lockfile;
4286
4287  if (filename == NULL)
4288    return (-1);
4289
4290  len = sl_strlen(filename);
4291  if (sl_ok_adds(len, 6))
4292    len += 6;
4293  lockfile = SH_ALLOC(len);
4294  sl_strlcpy(lockfile, filename,   len);
4295  sl_strlcat(lockfile, _(".lock"), len);
4296
4297  res = sh_unix_unlock(lockfile, filename);
4298  SH_FREE(lockfile);
4299  return res;
4300}
4301
4302/* rm lock for filename
4303 */
4304int sh_unix_rm_pid_file()
4305{
4306  return sh_unix_unlock(sh.srvlog.alt, NULL);
4307}
4308
4309/* Test whether file exists
4310 */
4311int sh_unix_file_exists(char * path)
4312{
4313  struct stat buf;
4314
4315  SL_ENTER(_("sh_unix_file_exists"));
4316
4317  if (0 == retry_lstat(FIL__, __LINE__, path, &buf))
4318    SL_RETURN( S_TRUE,   _("sh_unix_file_exists"));
4319  else 
4320    SL_RETURN( S_FALSE,  _("sh_unix_file_exists"));
4321}
4322
4323
4324/* Test whether file exists, is a character device, and allows read
4325 * access.
4326 */
4327int sh_unix_device_readable(int fd)
4328{
4329  struct stat buf;
4330
4331  SL_ENTER(_("sh_unix_device_readable"));
4332
4333  if (retry_fstat(FIL__, __LINE__, fd, &buf) == -1)
4334    SL_RETURN( (-1), _("sh_unix_device_readable"));
4335  else if ( S_ISCHR(buf.st_mode) &&  0 != (S_IROTH & buf.st_mode) ) 
4336    SL_RETURN( (0), _("sh_unix_device_readable"));
4337  else 
4338    SL_RETURN( (-1), _("sh_unix_device_readable"));
4339}
4340
4341static char preq[16];
4342
4343/* return true if database is remote
4344 */
4345int file_is_remote ()
4346{
4347  static int init = 0;
4348  struct stat buf;
4349
4350  SL_ENTER(_("file_is_remote"));
4351
4352  if (init == 0)
4353    {
4354      sl_strlcpy(preq, _("REQ_FROM_SERVER"), 16);
4355      ++init;
4356    }
4357  if (0 == sl_strncmp (sh.data.path, preq, 15))
4358    {
4359      if (sh.data.path[15] != '\0') /* should be start of path */
4360        {
4361          if (0 == stat(&(sh.data.path[15]), &buf))
4362            {
4363              SL_RETURN( S_FALSE, _("file_is_remote"));
4364            }
4365        }
4366      SL_RETURN( S_TRUE, _("file_is_remote"));
4367    }
4368  SL_RETURN( S_FALSE, _("file_is_remote"));
4369}
4370
4371/* Return the path to the configuration/database file.
4372 */
4373char * file_path(char what, char flag)
4374{
4375  static int init = 0;
4376
4377  SL_ENTER(_("file_path"));
4378
4379  if (init == 0)
4380    {
4381      sl_strlcpy(preq, _("REQ_FROM_SERVER"), 16);
4382      ++init;
4383    }
4384
4385  switch (what)
4386    {
4387
4388    case 'C':
4389      if (0 == sl_strncmp (sh.conf.path, preq, 15))
4390        {
4391#if defined(SH_WITH_SERVER)
4392          if (sh.flag.isserver == S_TRUE && sl_strlen(sh.conf.path) == 15)
4393            SL_RETURN( NULL, _("file_path"));
4394          if (sh.flag.isserver == S_TRUE)
4395            SL_RETURN( &(sh.conf.path[15]), _("file_path"));
4396#endif
4397          if (flag == 'R')
4398            SL_RETURN( preq, _("file_path"));
4399          if (flag == 'I')
4400            {
4401              if (sl_strlen(sh.conf.path) == 15)
4402                SL_RETURN( NULL, _("file_path"));
4403              else
4404                SL_RETURN( &(sh.conf.path[15]), _("file_path"));
4405            }
4406          SL_RETURN ( preq, _("file_path"));
4407        }
4408      else
4409        SL_RETURN( sh.conf.path, _("file_path"));
4410      /* break; *//* unreachable */
4411
4412    case 'D':
4413      if (0 == sl_strncmp (sh.data.path, preq, 15))
4414        {
4415          if (flag == 'R')
4416            SL_RETURN( preq, _("file_path"));
4417          if (flag == 'W' && sl_strlen(sh.data.path) == 15)
4418            SL_RETURN (NULL, _("file_path"));
4419          if (flag == 'W')
4420            SL_RETURN( &(sh.data.path[15]), _("file_path"));
4421        }
4422      else
4423        SL_RETURN( sh.data.path, _("file_path"));
4424      break;
4425       
4426    default:
4427      SL_RETURN( NULL, _("file_path"));
4428    }
4429
4430  return NULL; /* notreached */
4431}
4432/************************************************/
4433/****   Mlock   Utilities                    ****/
4434/************************************************/
4435
4436#include <limits.h>
4437
4438int sh_unix_pagesize()
4439{
4440  int pagesize = 4096;
4441#if defined(_SC_PAGESIZE)
4442  pagesize = sysconf(_SC_PAGESIZE);
4443#elif defined(_SC_PAGE_SIZE)
4444  pagesize = sysconf(_SC_PAGE_SIZE);
4445#elif defined(HAVE_GETPAGESIZE)
4446  pagesize = getpagesize();
4447#elif defined(PAGESIZE)
4448  pagesize = PAGESIZE;
4449#endif
4450 
4451  return ((pagesize > 0) ? pagesize : 4096);
4452}
4453
4454typedef struct sh_page_lt {
4455  unsigned long  page_start;
4456  int            page_refcount;
4457  char           file[64];
4458  int            line;
4459  struct sh_page_lt * next;
4460} sh_page_l;
4461
4462sh_page_l * sh_page_locked = NULL;
4463volatile int page_locking = 0;
4464
4465unsigned long sh_unix_lookup_page (void * in_addr, size_t len, int * num_pages)
4466{
4467  int pagesize = sh_unix_pagesize();
4468  unsigned long  addr = (unsigned long) in_addr;
4469
4470  unsigned long pagebase;
4471  unsigned long pagediff;
4472  unsigned long pagenum   = addr / pagesize;
4473
4474  SL_ENTER(_("sh_unix_lookup_page"));
4475#if 0
4476  fprintf(stderr, "mlock: --> base %ld, pagenum: %ld\n",
4477          addr, pagenum);
4478#endif
4479
4480  /* address of first page
4481   */
4482  pagebase = pagenum * pagesize;
4483 
4484  /* number of pages
4485   */
4486  pagediff = (addr + len) - pagebase;
4487  pagenum  = pagediff / pagesize;
4488  if (pagenum * pagesize < pagediff)
4489    ++pagenum;
4490
4491#if 0
4492  fprintf(stderr, "mlock: --> pagebase %ld, pagediff %ld, (addr + len) %ld\n",
4493          pagebase, pagediff, (addr + len));
4494#endif
4495
4496  *num_pages = pagenum;
4497  SL_RETURN((pagebase), _("sh_unix_lookup_page"));
4498}
4499
4500
4501#if defined(HAVE_MLOCK) && !defined(HAVE_BROKEN_MLOCK)
4502
4503SH_MUTEX_STATIC(mutex_mlock,PTHREAD_MUTEX_INITIALIZER);
4504
4505int sh_unix_mlock (const char * file, int line, void * in_addr, size_t len)
4506{
4507  int         num_pages;
4508  int         status = 0;
4509  int         pagesize;
4510  sh_page_l * page_list = sh_page_locked;
4511  unsigned long addr;
4512#ifdef TEST_MLOCK
4513  int         i = 0;
4514#endif
4515
4516  SL_ENTER(_("sh_unix_mlock"));
4517
4518  /* There's no cancellation point here, except if tracing is on
4519   */
4520  SH_MUTEX_LOCK_UNSAFE(mutex_mlock);
4521
4522  if (0 != page_locking)
4523    {
4524      status = -1;
4525      goto exit_mlock;
4526    }
4527
4528  page_locking = 1;
4529
4530  pagesize = sh_unix_pagesize();
4531  addr = sh_unix_lookup_page (in_addr, len, &num_pages);
4532
4533#ifdef TEST_MLOCK
4534  fprintf(stderr, "mlock: addr %ld, base %ld, pages: %d, length %d\n", 
4535          (unsigned long) in_addr, addr, num_pages, len);
4536#endif
4537
4538  /* increase refcount of locked pages
4539   * addr is first page; num_pages is #(consecutive pages) to lock
4540   */
4541
4542  while ((page_list != NULL) && (num_pages > 0))
4543    {
4544#ifdef TEST_MLOCK
4545      fprintf(stderr, "mlock: check page %d: %ld [%d]\n", 
4546              i, page_list->page_start, page_list->page_refcount);
4547#endif
4548      if (page_list->page_start == addr)
4549        {
4550          page_list->page_refcount += 1;
4551          num_pages -= 1;
4552          addr += pagesize;
4553#ifdef TEST_MLOCK
4554          fprintf(stderr, "mlock: found page %d: %ld [%d], next page %ld\n", 
4555                  i, page_list->page_start, page_list->page_refcount, addr);
4556#endif
4557        }
4558#ifdef TEST_MLOCK
4559      ++i;
4560#endif
4561      page_list = page_list->next;
4562    }
4563
4564  /* mlock some more pages, if needed
4565   */
4566  while (num_pages > 0) 
4567    {
4568#ifdef TEST_MLOCK
4569      fprintf(stderr, "mlock: lock  page %d: mlock %ld [num_pages %d]\n", 
4570              i, addr, num_pages);
4571      ++i;
4572#endif
4573      page_list = SH_ALLOC(sizeof(sh_page_l));
4574      page_list->page_start = addr;
4575      page_list->page_refcount = 1;
4576      sl_strlcpy(page_list->file, file, 64);
4577      page_list->line = line;
4578      status = mlock( (void *) addr, pagesize);
4579      if (status != 0)
4580        {
4581#ifdef TEST_MLOCK
4582          char errbuf[SH_ERRBUF_SIZE];
4583          fprintf(stderr, "mlock: error: %s\n", 
4584                  sh_error_message(errno, errbuf, sizeof(errbuf)));
4585#endif
4586          SH_FREE(page_list);
4587          page_locking = 0;
4588          goto exit_mlock;
4589        }
4590      page_list->next = sh_page_locked;
4591      sh_page_locked  = page_list;
4592      num_pages -= 1;
4593      addr += pagesize;
4594    }
4595  page_locking = 0;
4596
4597 exit_mlock:
4598  SH_MUTEX_UNLOCK_UNSAFE(mutex_mlock);
4599
4600  SL_RETURN((status), _("sh_unix_mlock"));
4601}
4602#else
4603int sh_unix_mlock (const char * file, int line, void * in_addr, size_t len)
4604{
4605  (void) file;    (void) line;
4606  (void) in_addr; (void) len;
4607  return -1;
4608}
4609#endif
4610
4611#if defined(HAVE_MLOCK) && !defined(HAVE_BROKEN_MLOCK)
4612int sh_unix_munlock (void * in_addr, size_t len)
4613{
4614  int         num_pages;
4615  int         unlocked = 0;
4616  int         status   = 0;
4617  int         pagesize;
4618  sh_page_l * page_list = sh_page_locked;
4619  sh_page_l * page_last;
4620  unsigned long addr;
4621
4622  int           test_count;
4623  int           test_status;
4624  int           test_pages;
4625
4626#ifdef TEST_MLOCK
4627  int         i = 0;
4628#endif
4629
4630  SL_ENTER(_("sh_unix_munlock"));
4631
4632  /* There's no cancellation point here, except if tracing is on
4633   */
4634  SH_MUTEX_LOCK_UNSAFE(mutex_mlock);
4635
4636  if (0 != page_locking)
4637    {
4638      status = -1;
4639      goto exit_munlock;
4640    }
4641  page_locking = 1;
4642
4643  pagesize = sh_unix_pagesize();
4644  addr     = sh_unix_lookup_page (in_addr, len, &num_pages);
4645
4646#ifdef TEST_MLOCK
4647  fprintf(stderr, "munlock: in_addr %ld, addr %ld, pages: %d, length %d\n", 
4648          (unsigned long) in_addr, addr, num_pages, len);
4649#endif
4650
4651  test_pages = num_pages;
4652
4653  /* reduce refcount of locked pages
4654   * addr is first page; num_pages is #(consecutive pages) to lock
4655   */
4656  while ((page_list != NULL) && (num_pages > 0))
4657    {
4658#ifdef TEST_MLOCK
4659      fprintf(stderr, "munlock: page %d: %ld [%d]\n", 
4660              i, page_list->page_start, page_list->page_refcount);
4661#endif
4662
4663      test_status = 0;
4664      for (test_count = 0; test_count < test_pages; ++test_count)
4665        {
4666          if (page_list->page_start == (addr + (test_count * pagesize)))
4667            {
4668              test_status = 1;
4669              break;
4670            }
4671        }
4672
4673      if (test_status == 1)
4674        {
4675          page_list->page_refcount -= 1;
4676          if (page_list->page_refcount == 0)
4677            {
4678              status = munlock ( (void *) addr, pagesize);
4679              ++unlocked;
4680            }
4681          num_pages -= 1;
4682#ifdef TEST_MLOCK
4683          fprintf(stderr, 
4684                  "munlock: page %d: %ld [refcount %d], refcount reduced\n", 
4685                  i, page_list->page_start, page_list->page_refcount);
4686#endif
4687        }
4688#ifdef TEST_MLOCK
4689      ++i;
4690#endif
4691      page_list = page_list->next;
4692    }
4693
4694#ifdef TEST_MLOCK
4695      i = 0;
4696#endif
4697
4698  if (unlocked > 0)
4699    {
4700      page_list = sh_page_locked;
4701      page_last = sh_page_locked;
4702
4703      while ((page_list != NULL) && (unlocked > 0))
4704        {
4705          if (page_list->page_refcount == 0)
4706            {
4707#ifdef TEST_MLOCK
4708              fprintf(stderr, "munlock: remove page %d: %ld [refcount %d]\n", 
4709                      i, page_list->page_start, page_list->page_refcount);
4710#endif
4711              if (page_last != page_list)
4712                {
4713                  page_last->next = page_list->next;
4714                  SH_FREE(page_list);
4715                  page_list = page_last->next;
4716                }
4717              else
4718                {
4719                  page_last = page_list->next;
4720                  if (page_list == sh_page_locked)
4721                    sh_page_locked = page_list->next;
4722                  SH_FREE(page_list);
4723                  page_list = page_last;
4724                }
4725              --unlocked;
4726            }
4727          else
4728            {
4729#ifdef TEST_MLOCK
4730              fprintf(stderr, "munlock: skip   page %d: %ld [refcount %d]\n", 
4731                      i, page_list->page_start, page_list->page_refcount);
4732#endif
4733
4734              page_last = page_list;
4735              page_list = page_list->next;
4736            }
4737#ifdef TEST_MLOCK
4738          ++i;
4739#endif
4740        }
4741    }
4742
4743  page_locking = 0;
4744
4745 exit_munlock:
4746  SH_MUTEX_UNLOCK_UNSAFE(mutex_mlock);
4747  SL_RETURN((status), _("sh_unix_munlock"));
4748}
4749#else
4750int sh_unix_munlock (void * in_addr, size_t len)
4751{
4752  (void) in_addr; (void) len;
4753  return -1;
4754}
4755#endif
4756
4757int sh_unix_count_mlock()
4758{
4759  int i = 0;
4760  char str[128];
4761  sh_page_l * page_list = sh_page_locked;
4762
4763  SL_ENTER(_("sh_unix_count_mlock"));
4764  while (page_list != NULL)
4765    {
4766#ifdef WITH_TPT
4767      sl_snprintf(str, sizeof(str), _("file: %s line: %d page: %d"), 
4768                  page_list->file, page_list->line, i+1);
4769      sh_error_handle(SH_ERR_INFO, FIL__, __LINE__, i, MSG_E_SUBGEN,
4770                  str, _("sh_unix_count_mlock"));
4771#endif
4772      page_list = page_list->next;
4773      ++i;
4774    }
4775  sl_snprintf(str, sizeof(str), _("%d pages locked"), i);
4776  sh_error_handle(SH_ERR_INFO, FIL__, __LINE__, i, MSG_E_SUBGEN,
4777                  str, _("sh_unix_count_mlock"));
4778  SL_RETURN((i), _("sh_unix_count_mlock"));
4779}
4780
4781/************************************************/
4782/************************************************/
4783/****   Stealth Utilities                    ****/
4784/************************************************/
4785/************************************************/
4786#ifdef SH_STEALTH
4787
4788void sh_unix_xor_code (char * str, int len)
4789{
4790  register int i;
4791
4792  for (i = 0; i < len; ++i) str[i] ^= (char) XOR_CODE;
4793  return;
4794}
4795
4796#if  !defined(SH_STEALTH_MICRO)
4797
4798
4799int hideout_hex_block(SL_TICKET fd, unsigned char * str, int len,
4800                      unsigned long * bytes_read);
4801unsigned long first_hex_block(SL_TICKET fd, unsigned long * max);
4802
4803/*
4804 * --- Get hidden data from a block of hex data. ---
4805 */
4806int sh_unix_getline_stealth (SL_TICKET fd, char * str, int len)
4807{
4808  int                  add_off = 0, llen;
4809  static unsigned long off_data   = 0;
4810  static unsigned long max_data   = 0;
4811  static unsigned long bytes_read = 0;
4812  static int           stealth_init = BAD;
4813
4814  SL_ENTER(_("sh_unix_getline_stealth"));
4815
4816  if (str == NULL)
4817    {
4818      off_data   = 0;
4819      max_data   = 0;
4820      bytes_read = 0;
4821      stealth_init = BAD;
4822      SL_RETURN(0, _("sh_unix_getline_stealth"));
4823    }
4824
4825  /* --- Initialize. ---
4826   */
4827  if (stealth_init == BAD)
4828    {
4829      off_data = first_hex_block(fd, &max_data);
4830      if (off_data == 0)
4831        {
4832          dlog(1, FIL__, __LINE__, 
4833               _("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"));
4834          sh_error_handle ((-1), FIL__, __LINE__,  EIO, MSG_P_NODATA,
4835                           _("Stealth config file."));
4836          aud_exit (FIL__, __LINE__, EXIT_FAILURE);
4837        }
4838      stealth_init = GOOD;
4839      max_data += off_data;
4840    }
4841 
4842  /* --- Seek to proper position. ---
4843   */
4844  if (bytes_read >= max_data || add_off < 0)
4845    {
4846      dlog(1, FIL__, __LINE__, 
4847           _("The capacity of the container image file for the stealth config file seems to be too small. Your config file is likely truncated.\n"));
4848      sh_error_handle ((-1), FIL__, __LINE__,  EIO, MSG_P_NODATA,
4849                       _("Stealth config file."));
4850      aud_exit (FIL__, __LINE__, EXIT_FAILURE);
4851    }
4852  sl_seek(fd, off_data);
4853     
4854  /* --- Read one line. ---
4855   */
4856  add_off   = hideout_hex_block(fd, (unsigned char *) str, len, &bytes_read);
4857  off_data += add_off;
4858
4859  llen = sl_strlen(str);
4860  SL_RETURN(llen, _("sh_unix_getline_stealth"));
4861}
4862
4863int hideout_hex_block(SL_TICKET fd, unsigned char * str, int len, 
4864                      unsigned long * bytes_read)
4865{
4866
4867  register int  i, j, k;
4868  unsigned char c, e;
4869  register int  num;
4870  unsigned char mask[9] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
4871  unsigned long here   = 0;
4872  unsigned long retval = 0;
4873  unsigned long bread  = 0;
4874
4875  SL_ENTER(_("hideout_hex_block"));
4876
4877  ASSERT_RET((len > 1), _("len > 1"), (0));
4878
4879  --len;
4880
4881  i = 0;
4882  while (i < len)
4883    {
4884      for (j = 0; j < 8; ++j)
4885        {
4886
4887          /* --- Get a low byte, modify, read back. ---
4888           */
4889          for (k = 0; k < 2; ++k)
4890            {
4891              /* -- Skip whitespace. ---
4892               */
4893              c = ' ';
4894              do {
4895                do {
4896                  num = sl_read (fd, &c, 1);
4897                } while (num == 0 && errno == EINTR);
4898                if (num > 0)
4899                  ++here;
4900                else if (num == 0)
4901                  SL_RETURN((0), _("hideout_hex_block"));
4902                else 
4903                  SL_RETURN((-1), _("hideout_hex_block"));
4904              } while (c == '\n' || c == '\t' || c == '\r' || 
4905                       c == ' ');
4906            }
4907         
4908
4909          /* --- e is the value of the low byte. ---
4910           */
4911          e = (unsigned char) sh_util_hexchar( c );
4912          if ((e & mask[7]) != 0)  /* bit is set     */
4913            str[i] |= mask[j];
4914          else                     /* bit is not set */
4915            str[i] &= ~mask[j];
4916
4917          bread += 1;
4918        }
4919      if (str[i] == '\n') break;
4920      ++i;
4921    }
4922
4923  if (i != 0)
4924    str[i] = '\0';
4925  else
4926    str[i+1] = '\0'; /* keep newline and terminate */
4927  retval += here;
4928  *bytes_read += (bread/8);
4929
4930  SL_RETURN(retval, _("hideout_hex_block"));
4931}
4932
4933/* --- Get offset of first data block. ---
4934 */
4935unsigned long first_hex_block(SL_TICKET fd, unsigned long * max)
4936{
4937  unsigned int  i;
4938  long          num = 1;
4939  unsigned long lnum;
4940  char          c;
4941  int           nothex = 0;
4942  unsigned long retval = 0;
4943  unsigned int  this_line = 0;
4944  char          theline[SH_BUFSIZE];
4945
4946  SL_ENTER(_("first_hex_block"));
4947
4948  *max = 0;
4949
4950  while (1)
4951    {
4952      theline[0] = '\0';
4953      this_line  = 0;
4954      c          = '\0';
4955      while (c != '\n' && num > 0 && this_line < (sizeof(theline)-1))
4956        {
4957          do {
4958            num = sl_read (fd, &c, 1);
4959          } while (num == 0 && errno == EINTR);
4960          if (num > 0) 
4961            theline[this_line] = c;
4962          else           
4963            SL_RETURN((0), _("first_hex_block"));
4964          ++this_line;
4965        }
4966      theline[this_line] = '\0';
4967     
4968      /* not only 'newline' */ 
4969      if (this_line > 60)
4970        {
4971          nothex  = 0;
4972          i       = 0;
4973          while (nothex == 0 && i < (this_line-1))
4974            {
4975              if (! isxdigit((int)theline[i])) nothex = 1;
4976              ++i;
4977            }
4978          if (nothex == 1) retval += this_line;
4979        }
4980      else
4981        {
4982          nothex = 1;
4983          retval += this_line;
4984        }
4985
4986      if (nothex == 0)
4987        {
4988          *max = 0; 
4989          do {
4990            do {
4991              num = sl_read (fd, theline, SH_BUFSIZE);
4992            } while (num == 0 && errno == EINTR);
4993            if (num > 0)
4994              {
4995                lnum = (unsigned long) num;
4996                for (i = 0; i < lnum; ++i)
4997                  { 
4998                    c = theline[i];
4999                    if (c == '\n' || c == '\t' || c == '\r' || c == ' ') 
5000                      ;
5001                    else if (!isxdigit((int)c))
5002                      break;
5003                    else
5004                      *max += 1;
5005                  }
5006              }
5007          } while (num > 0);
5008
5009          *max /= 16;
5010          SL_RETURN((retval), _("first_hex_block"));
5011        }
5012
5013    }
5014  /* SL_RETURN((0), _("first_hex_block")); *//* unreachable */
5015}
5016
5017 /* if !defined(SH_STEALTH_MICRO) */
5018#endif
5019
5020 /* ifdef SH_STEALTH */
5021#endif
5022
5023/*
5024 * anti-debugger code
5025 */
5026#if defined(SCREW_IT_UP)
5027volatile int sh_not_traced = 0;
5028
5029#ifdef HAVE_GETTIMEOFDAY
5030struct timeval  save_tv;
5031#endif
5032
5033void sh_sigtrap_handler (int signum)
5034{
5035#ifdef HAVE_GETTIMEOFDAY
5036  struct timeval  tv;
5037  long   difftv;
5038 
5039  gettimeofday(&tv, NULL);
5040  difftv = (tv.tv_sec - save_tv.tv_sec) * 1000000 + 
5041    (tv.tv_usec - save_tv.tv_usec);
5042  if (difftv > 500000)
5043    raise(SIGKILL);
5044#endif
5045  sh_not_traced += signum;
5046  return;
5047}
5048#endif
Note: See TracBrowser for help on using the repository browser.