source: trunk/src/samhain.c @ 133

Last change on this file since 133 was 133, checked in by rainer, 12 years ago

Reentrant checksum/hash functions.

File size: 46.7 KB
Line 
1/* SAMHAIN file system integrity testing                                   */
2/* Copyright (C) 1999, 2000 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 <unistd.h>
27#include <fcntl.h>
28
29/* samhainctl */
30#include <sys/types.h>
31#include <sys/stat.h>
32#include <sys/wait.h>
33#include <signal.h>
34#include <errno.h>
35
36
37#if TIME_WITH_SYS_TIME
38#include <sys/time.h>
39#include <time.h>
40#else
41#if HAVE_SYS_TIME_H
42#include <sys/time.h>
43#else
44#include <time.h>
45#endif
46#endif
47
48#ifdef HAVE_MEMORY_H
49#include <memory.h>
50#endif
51
52#ifdef HAVE_SETPRIORITY
53#include <sys/resource.h>
54#endif
55
56#ifndef HAVE_LSTAT
57#define lstat stat
58#endif
59
60/* for FLT_EPSILON
61 */
62#include <float.h>
63
64#include "samhain.h"
65#include "sh_pthread.h"
66#include "sh_files.h"
67#include "sh_utils.h"
68#include "sh_error.h"
69#include "sh_unix.h"
70#include "sh_getopt.h"
71#include "sh_readconf.h"
72#include "sh_hash.h"
73
74#include "sh_mail.h"
75
76#include "sh_tiger.h"
77#include "sh_gpg.h"
78#include "sh_mem.h"
79#include "sh_forward.h"
80#include "sh_tools.h"
81#include "sh_hash.h"
82#if defined(WITH_EXTERNAL)
83#include "sh_extern.h"
84#endif
85#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
86#include "sh_modules.h"
87#include "sh_ignore.h"
88#include "sh_prelink.h"
89#endif
90
91#undef  FIL__
92#define FIL__  _("samhain.c")
93
94
95/**************************************************
96 *
97 * Needed to compile the key into the code.
98 *
99 **************************************************/
100
101extern UINT32  ErrFlag[2];
102#include "sh_MK.h"
103
104/**************************************************
105 *
106 * Variables for signal handling.
107 *
108 **************************************************/
109
110volatile  int      sig_raised;
111volatile  int      sig_urgent;
112volatile  int      sig_debug_switch;       /* SIGUSR1 */
113volatile  int      sig_suspend_switch;     /* SIGUSR2 */
114volatile  int      sh_global_suspend_flag;
115volatile  int      sig_fresh_trail;        /* SIGIOT  */
116volatile  int      sig_config_read_again;  /* SIGHUP  */
117volatile  int      sig_terminate;          /* SIGQUIT */
118volatile  int      sig_termfast;           /* SIGTERM */
119volatile  int      sig_force_check;        /* SIGTTOU */
120long int           eintr__result;
121char               sh_sig_msg[SH_MINIBUF];
122
123
124#ifdef SH_STEALTH
125/**************************************************
126 *
127 * The following set of functions is required for
128 * the 'stealth' mode.
129 *
130 **************************************************/
131
132#ifndef SH_MAX_GLOBS
133#define SH_MAX_GLOBS 16
134#endif
135
136#ifndef GLOB_LEN
137#define GLOB_LEN 511
138#endif
139
140char * globber(const char * str)
141{
142  size_t i;
143  size_t j;
144
145  static   size_t  items = 0;
146  static   size_t  count = 0;
147  static   char glob[SH_MAX_GLOBS * (GLOB_LEN+1)];
148
149  if (str == NULL)
150    return NULL;
151  else
152    j = strlen(str);
153
154  ++items;
155
156  ASSERT((j <= GLOB_LEN), _("j <= GLOB_LEN"))
157
158  if (j > GLOB_LEN) 
159    j = GLOB_LEN;
160
161  /* Overwrap the buffer.
162   */
163  if ( (count + j) >= (SH_MAX_GLOBS * (GLOB_LEN+1)))
164    {
165      count = 0;
166      items = 0;
167    }
168
169  for (i = 0; i < j; ++i)
170    {
171      if (str[i] != '\n' && str[i] != '\t' && str[i] != '\r' && str[i] != '"')
172        glob[count + i] = str[i] ^ XOR_CODE;
173      else
174        glob[count + i] = str[i];
175    }
176  glob[count + j] = '\0';
177
178  i     = count;
179  count = count + j + 1;
180  return &glob[i];
181}
182
183void sh_do_encode (char * str, int len)
184{
185  register          int i;
186
187  /* this is a symmetric operation
188   */
189  for (i = 0; i < len; ++i)
190    {
191      str[i] = str[i] ^ XOR_CODE;
192    }
193  return;
194}
195
196#endif
197
198/**************************************************
199 *
200 * Global variables.
201 *
202 **************************************************/
203
204sh_struct   sh;
205/*@null@*/ sh_key_t  * skey = NULL;
206
207extern unsigned char TcpFlag[8][PW_LEN+1];
208
209/**************************************************
210 *
211 * Initializing.
212 *
213 **************************************************/
214
215static int is_samhainctl_init = S_FALSE;
216
217static
218void sh_init (void)
219{
220  unsigned char * dez = NULL;
221  int             i;
222#if defined(SH_WITH_MAIL)
223  char          * p;
224  char            q[SH_PATHBUF];
225#endif
226
227  SL_ENTER(_("sh_init"));
228
229#ifdef MKA_09
230  ErrFlag[0] |= (1 << 8);
231#endif
232#ifdef MKA_10
233  ErrFlag[0] |= (1 << 9);
234#endif
235#ifdef MKA_11
236  ErrFlag[0] |= (1 << 10);
237#endif
238#ifdef MKA_12
239  ErrFlag[0] |= (1 << 11);
240#endif
241#ifdef MKA_13
242  ErrFlag[0] |= (1 << 12);
243#endif
244#ifdef MKA_14
245  ErrFlag[0] |= (1 << 13);
246#endif
247#ifdef MKA_15
248  ErrFlag[0] |= (1 << 14);
249#endif
250#ifdef MKA_16
251  ErrFlag[0] |= (1 << 15);
252#endif
253
254  /* Signal handling.
255   */
256  sig_raised             = 0;
257  sig_config_read_again  = 0;           /* SIGHUP  */
258  sig_debug_switch       = 0;           /* SIGUSR1 */
259  sig_suspend_switch     = 0;           /* SIGUSR2 */
260  sh_global_suspend_flag = 0;           /* SIGUSR2 */
261  sig_fresh_trail        = 0;           /* SIGIOT  */
262  sig_terminate          = 0;           /* SIGQUIT */
263  sig_termfast           = 0;           /* SIGTERM */
264  sig_force_check        = 0;           /* SIGTTOU */
265  strcpy ( sh_sig_msg, _("None"));
266
267#ifdef MKB_01
268  ErrFlag[1] |= (1 << 0);
269#endif
270#ifdef MKB_02
271  ErrFlag[1] |= (1 << 1);
272#endif
273#ifdef MKB_03
274  ErrFlag[1] |= (1 << 2);
275#endif
276#ifdef MKB_04
277  ErrFlag[1] |= (1 << 3);
278#endif
279#ifdef MKB_05
280  ErrFlag[1] |= (1 << 4);
281#endif
282#ifdef MKB_06
283  ErrFlag[1] |= (1 << 5);
284#endif
285#ifdef MKB_07
286  ErrFlag[1] |= (1 << 6);
287#endif
288#ifdef MKB_08
289  ErrFlag[1] |= (1 << 7);
290#endif
291
292#if defined(SH_WITH_SERVER) && !defined(SH_WITH_CLIENT)
293  strncpy(sh.prg_name, _("Yule"), 8);
294  sh.prg_name[4] = '\0';
295#else
296  strncpy(sh.prg_name, _("Samhain"), 8);
297  sh.prg_name[7] = '\0';
298#endif
299
300  /* The flags.
301   */
302  if (is_samhainctl_init == S_FALSE)
303    sh.flag.checkSum        = SH_CHECK_NONE;
304  sh.flag.update          = S_FALSE;
305  sh.flag.opts            = S_FALSE;
306  if (is_samhainctl_init == S_FALSE)
307    sh.flag.isdaemon        = S_FALSE;
308  sh.flag.isserver        = S_FALSE;
309  sh.flag.islocked        = S_FALSE;
310  sh.flag.smsg            = S_FALSE;
311  sh.flag.log_start       = S_TRUE;
312  sh.flag.reportonce      = S_TRUE;
313  sh.flag.fulldetail      = S_FALSE;
314  sh.flag.audit           = S_FALSE;
315  sh.flag.nice            = 0;
316  sh.flag.aud_mask        = 0xFFFFFFFFUL;
317  sh.flag.client_severity = S_FALSE;
318  sh.flag.client_class    = S_FALSE;
319  sh.flag.hidefile        = S_FALSE;
320  sh.flag.loop            = S_FALSE;
321
322#ifdef MKB_09
323  ErrFlag[1] |= (1 << 8);
324#endif
325#ifdef MKB_10
326  ErrFlag[1] |= (1 << 9);
327#endif
328#ifdef MKB_11
329  ErrFlag[1] |= (1 << 10);
330#endif
331#ifdef MKB_12
332  ErrFlag[1] |= (1 << 11);
333#endif
334#ifdef MKB_13
335  ErrFlag[1] |= (1 << 12);
336#endif
337#ifdef MKB_14
338  ErrFlag[1] |= (1 << 13);
339#endif
340#ifdef MKB_15
341  ErrFlag[1] |= (1 << 14);
342#endif
343#ifdef MKB_16
344  ErrFlag[1] |= (1 << 15);
345#endif
346
347  /* The stats.
348   */
349  sh.statistics.bytes_speed  = 0;
350  sh.statistics.bytes_hashed = 0;
351  sh.statistics.mail_success = 0;
352  sh.statistics.mail_failed  = 0;
353  sh.statistics.time_start   = time(NULL);
354  sh.statistics.time_check   = (time_t) 0;
355
356#ifdef MKC_01
357  ErrFlag[0] |= (1 << 16);
358#endif
359#ifdef MKC_02
360  ErrFlag[0] |= (1 << 17);
361#endif
362#ifdef MKC_03
363  ErrFlag[0] |= (1 << 18);
364#endif
365#ifdef MKC_04
366  ErrFlag[0] |= (1 << 19);
367#endif
368#ifdef MKC_05
369  ErrFlag[0] |= (1 << 20);
370#endif
371#ifdef MKC_06
372  ErrFlag[0] |= (1 << 21);
373#endif
374#ifdef MKC_07
375  ErrFlag[0] |= (1 << 22);
376#endif
377#ifdef MKC_08
378  ErrFlag[0] |= (1 << 23);
379#endif
380
381
382  /* The local host.
383   */
384  (void) sl_strlcpy (sh.host.name,  _("localhost"),  SH_MINIBUF);
385  sh.host.system[0]     = '\0'; /* flawfinder: ignore *//* ff bug */
386  sh.host.release[0]    = '\0';
387  sh.host.machine[0]    = '\0';
388
389#ifdef MKC_09
390  ErrFlag[0] |= (1 << 24);
391#endif
392#ifdef MKC_10
393  ErrFlag[0] |= (1 << 25);
394#endif
395#ifdef MKC_11
396  ErrFlag[0] |= (1 << 26);
397#endif
398#ifdef MKC_12
399  ErrFlag[0] |= (1 << 27);
400#endif
401#ifdef MKC_13
402  ErrFlag[0] |= (1 << 28);
403#endif
404#ifdef MKC_14
405  ErrFlag[0] |= (1 << 29);
406#endif
407#ifdef MKC_15
408  ErrFlag[0] |= (1 << 30);
409#endif
410#ifdef MKC_16
411  ErrFlag[0] |= (1UL << 31);
412#endif
413
414  /* The paths.
415   */
416  (void) sl_strlcpy (sh.conf.path,  DEFAULT_CONFIGFILE,    SH_PATHBUF);
417  sh.conf.hash[0] = '\0';
418  (void) sl_strlcpy (sh.data.path,  DEFAULT_DATA_FILE,     SH_PATHBUF);
419  sh.data.hash[0] = '\0';
420  sh.exec.path[0] = '\0';
421  sh.exec.hash[0] = '\0';
422
423#ifdef MKD_01
424  ErrFlag[1] |= (1 << 16);
425#endif
426#ifdef MKD_02
427  ErrFlag[1] |= (1 << 17);
428#endif
429#ifdef MKD_03
430  ErrFlag[1] |= (1 << 18);
431#endif
432#ifdef MKD_04
433  ErrFlag[1] |= (1 << 19);
434#endif
435#ifdef MKD_05
436  ErrFlag[1] |= (1 << 20);
437#endif
438#ifdef MKD_06
439  ErrFlag[1] |= (1 << 21);
440#endif
441#ifdef MKD_07
442  ErrFlag[1] |= (1 << 22);
443#endif
444#ifdef MKD_08
445  ErrFlag[1] |= (1 << 23);
446#endif
447
448  /* The addresses.
449   */
450#if defined(SH_WITH_MAIL)
451  if (0 == strcmp (DEFAULT_MAILADDRESS, _("NULL")))
452    {
453#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
454      char * saveptr;
455      (void) sl_strncpy(q, DEFAULT_MAILADDRESS, SH_PATHBUF);
456      p = strtok_r (q, ", \t", &saveptr);
457      if (p)
458        {
459          (void) sh_mail_setaddress_int (p);
460          while (NULL != (p = strtok_r (NULL, ", \t", &saveptr)))
461            (void) sh_mail_setaddress_int (p);
462        }
463#else
464      (void) sl_strncpy(q, DEFAULT_MAILADDRESS, SH_PATHBUF);
465      p = strtok (q, ", \t");
466      if (p)
467        {
468          (void) sh_mail_setaddress_int (p);
469          while (NULL != (p = strtok (NULL, ", \t")))
470            (void) sh_mail_setaddress_int (p);
471        }
472#endif
473    }
474#endif
475
476  if (0 == strcmp (ALT_TIMESERVER, _("NULL")))
477    sh.srvtime.alt[0] = '\0';
478  else
479    (void) sl_strlcpy (sh.srvtime.alt, ALT_TIMESERVER,        SH_PATHBUF);
480  if (0 == strcmp (DEFAULT_TIMESERVER, _("NULL")))
481    sh.srvtime.name[0] = '\0';
482  else
483    (void) sl_strlcpy (sh.srvtime.name, DEFAULT_TIMESERVER,   SH_PATHBUF);
484
485
486  if (0 == strcmp (ALT_LOGSERVER, _("NULL")))
487    sh.srvexport.alt[0] = '\0';
488  else
489    (void) sl_strlcpy (sh.srvexport.alt,  ALT_LOGSERVER,  SH_PATHBUF);
490  if (0 == strcmp (DEFAULT_LOGSERVER, _("NULL")))
491    sh.srvexport.name[0] = '\0';
492  else
493    (void) sl_strlcpy (sh.srvexport.name,  DEFAULT_LOGSERVER, SH_PATHBUF);
494
495
496  if (0 == strcmp (DEFAULT_ERRLOCK, _("NULL")))
497    sh.srvlog.alt[0] = '\0';
498  else
499    (void) sl_strlcpy (sh.srvlog.alt,  DEFAULT_ERRLOCK,       SH_PATHBUF);
500  if (0 == strcmp (DEFAULT_ERRFILE, _("NULL")))
501    sh.srvlog.name[0] = '\0';
502  else
503    (void) sl_strlcpy (sh.srvlog.name,  DEFAULT_ERRFILE,      SH_PATHBUF);
504
505  if (0 == strcmp (ALT_CONSOLE, _("NULL")))
506    sh.srvcons.alt[0] = '\0';
507  else
508    (void) sl_strlcpy (sh.srvcons.alt,  ALT_CONSOLE,          SH_PATHBUF);
509#ifndef DEFAULT_CONSOLE
510  (void) sl_strlcpy (sh.srvcons.name, _("/dev/console"),    SH_PATHBUF);
511#else
512  if (0 == strcmp (DEFAULT_CONSOLE, _("NULL")))
513    (void) sl_strlcpy (sh.srvcons.name, _("/dev/console"),    SH_PATHBUF);
514  else
515    (void) sl_strlcpy (sh.srvcons.name,  DEFAULT_CONSOLE,     SH_PATHBUF);
516#endif
517
518#ifdef MKD_09
519  ErrFlag[1] |= (1 << 24);
520#endif
521#ifdef MKD_10
522  ErrFlag[1] |= (1 << 25);
523#endif
524#ifdef MKD_11
525  ErrFlag[1] |= (1 << 26);
526#endif
527#ifdef MKD_12
528  ErrFlag[1] |= (1 << 27);
529#endif
530#ifdef MKD_13
531  ErrFlag[1] |= (1 << 28);
532#endif
533#ifdef MKD_14
534  ErrFlag[1] |= (1 << 29);
535#endif
536#ifdef MKD_15
537  ErrFlag[1] |= (1 << 30);
538#endif
539#ifdef MKD_16
540  ErrFlag[1] |= (1UL << 31);
541#endif
542
543
544  /* The timers.
545   */
546  sh.fileCheck.alarm_last     = 0;
547  sh.fileCheck.alarm_interval = 600; /* ten minutes */
548
549  sh.mailTime.alarm_last     = 0;
550  sh.mailTime.alarm_interval = 86400;
551
552  sh.mailNum.alarm_last      = 0;
553  sh.mailNum.alarm_interval  = 10;
554
555  sh.looptime     = 60;
556
557  /* The struct to hold privileged information.
558   */
559  skey = (sh_key_t *) malloc (sizeof(sh_key_t));
560  if (skey != NULL)
561    {
562
563      skey->mlock_failed = SL_FALSE;
564      skey->rngI         = BAD;
565      /* properly initialized later
566       */
567      skey->rng0[0] = 0x03; skey->rng0[1] = 0x09; skey->rng0[2] = 0x17;
568      skey->rng1[0] = 0x03; skey->rng1[1] = 0x09; skey->rng1[2] = 0x17;
569      skey->rng2[0] = 0x03; skey->rng2[1] = 0x09; skey->rng2[2] = 0x17;
570     
571      for (i = 0; i < KEY_BYT; ++i)
572        skey->poolv[i] = '\0';
573     
574      skey->poolc        = 0;
575     
576      skey->ErrFlag[0]   = ErrFlag[0];
577      ErrFlag[0]         = 0;
578      skey->ErrFlag[1]   = ErrFlag[1];
579      ErrFlag[1]         = 0;
580     
581      dez = &(TcpFlag[POS_TF-1][0]);
582      for (i = 0; i < PW_LEN; ++i)
583        { 
584          skey->pw[i] = (char) (*dez); 
585          (*dez)      = '\0';
586          ++dez; 
587        }
588     
589      skey->sh_sockpass[0]  = '\0';
590      skey->sigkey_old[0]   = '\0';
591      skey->sigkey_new[0]   = '\0';
592      skey->mailkey_old[0]  = '\0';
593      skey->mailkey_new[0]  = '\0';
594      skey->crypt[0]        = '\0'; /* flawfinder: ignore *//* ff bug */
595      skey->session[0]      = '\0';
596      skey->vernam[0]       = '\0';
597    }
598  else
599    {
600      perror(_("sh_init"));
601      _exit (EXIT_FAILURE);
602    }
603
604  sh_unix_memlock();
605  SL_RET0(_("sh_init"));
606}
607
608
609#if defined(HAVE_MLOCK) && !defined(HAVE_BROKEN_MLOCK)
610#include <sys/mman.h>
611#endif
612
613#if defined(SH_USE_XML)
614extern int    sh_log_file    (char * message, char * inet_peer);
615#endif
616
617/*******************************************************
618 *
619 * Exit Handler
620 *
621 *******************************************************/
622static void exit_handler(void)
623{
624  /* --- Clean up modules, if any. ---
625   */
626#if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE)
627  int modnum;
628#endif
629#if defined(SH_WITH_SERVER)
630  extern int sh_socket_remove ();
631#endif
632
633  SL_ENTER(_("exit_handler"));
634
635#if defined(SH_WITH_SERVER)
636  sh_socket_remove ();
637#endif
638
639#if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE)
640  for (modnum = 0; modList[modnum].name != NULL; ++modnum) 
641    {
642      if (modList[modnum].initval == GOOD)
643        (void) modList[modnum].mod_cleanup();
644    }
645#endif
646
647  /* --- Push out all pending messages. ---
648   */
649#if defined(SH_WITH_MAIL)
650  if (sh.mailNum.alarm_last > 0) 
651    {
652      (void) sh_mail_msg (NULL);
653    }
654#endif
655
656  /* --- Write the server stat. ---
657   */
658#if defined(SH_WITH_SERVER)
659  sh_forward_html_write();
660#endif
661
662  /* --- Clean up memory to check for problems. ---
663   */
664#ifdef MEM_DEBUG
665#if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE)
666  sh_files_deldirstack ();
667  sh_files_delfilestack ();
668  sh_hash_hashdelete();
669  sh_files_hle_reg (NULL);
670#endif
671#if defined(SH_WITH_SERVER)
672  sh_forward_free_all ();
673#endif
674  delete_cache();
675  sh_mem_stat();
676#endif
677
678#ifdef MEM_DEBUG
679  sh_unix_count_mlock();
680#endif
681
682  /* --- Checksum of executable. ---
683   */
684  (void) sh_unix_self_check();
685
686
687  /* --- Exit Message. ---
688   */
689  sh_error_handle ((-1), FIL__, __LINE__, sh.flag.exit, MSG_EXIT_NORMAL, 
690                   sh.prg_name, sh_sig_msg);
691#ifdef SH_USE_XML
692  (void) sh_log_file (NULL, NULL);
693#endif
694
695
696  /* --- Restrict error logging to stderr. ---
697   */
698#ifdef WITH_MESSAGE_QUEUE
699  close_ipc ();
700#endif
701  sh_error_only_stderr (S_TRUE);
702
703
704  /* --- Remove lock, delete critical information. ---
705   */
706  (void) sh_unix_rm_lock_file (sh.srvlog.name);
707  (void) sh_unix_rm_pid_file ();
708  if (skey != NULL)
709    memset (skey, (int) '\0', sizeof(sh_key_t));
710 
711  /* --- Exit. ---
712   */
713  SL_RET0(_("exit_handler"));
714}
715
716/***********************************************************
717 *
718 */
719#ifndef SIGHUP
720#define SIGHUP   1
721#endif
722#ifndef SIGTERM
723#define SIGTERM 15
724#endif
725#ifndef SIGKILL
726#define SIGKILL  9
727#endif
728
729#if defined(__linux__) || defined(sun) || defined(__sun) || defined(__sun__)
730#include <dirent.h>
731static pid_t * procdirSamhain ()
732{
733  pid_t        * pidlist = malloc(sizeof(pid_t) * 65535);
734  struct dirent * d;
735  DIR *        dp;
736  long         ino;
737  struct stat  buf;
738  int          i = 0;
739  pid_t        pid, mypid = getpid();
740  char       * tail;
741  char         exef[128];
742
743  if (!pidlist)
744    return NULL;
745
746  for (i = 0; i < 65535; ++i) pidlist[i] = 0;
747  i = 0;
748
749  if (0 != stat(SH_INSTALL_PATH, &buf))
750    {
751      free(pidlist);
752      return NULL;
753    }
754
755  ino = (long) buf.st_ino;
756   
757  if (NULL == (dp = opendir("/proc")))
758    {
759      free(pidlist);
760      return NULL;
761    }
762
763  SH_MUTEX_LOCK(readdir_lock);
764
765  while (NULL != (d = readdir(dp)) && i < 65535)
766    {
767      if (0 != strcmp(d->d_name, ".") && 0 != strcmp(d->d_name, ".."))
768        {
769          errno = 0;
770          pid = (pid_t) strtol (d->d_name, &tail, 0);
771          if (*tail != '\0' || errno != 0)
772            continue;
773          if (pid == mypid)
774            continue;
775#if defined(__linux__)
776          sprintf(exef, _("/proc/%d/exe"), (int) pid); /* known to fit  */
777#else
778          sprintf(exef, _("/proc/%d/object/a.out"),    /* known to fit  */
779                  (int) pid);
780#endif
781          if (0 == stat(exef, &buf) && ino == (long) buf.st_ino)
782            { pidlist[i] = (pid_t) pid; ++i; }
783        }
784    }
785
786  SH_MUTEX_UNLOCK(readdir_lock);
787
788  closedir(dp);
789  return pidlist;
790}
791#else
792static pid_t * procdirSamhain ()
793{
794  return NULL;
795}
796#endif
797
798static int killprocSamhain (pid_t pid)
799{
800  int i;
801
802  /* fprintf(stderr, "Killing %d\n", pid); */
803  if (pid > 0 && 0 == kill (pid, SIGTERM))
804    {
805      for (i = 0; i < 16; ++i)
806        {
807          (void) retry_msleep(1, 0);
808          if (0 != kill (pid, 0) && errno == ESRCH)
809            return (0);
810        }
811     
812      (void) kill (pid, SIGKILL);
813      return (0);
814    }
815  if (pid > 0)
816    {
817      if (errno == ESRCH)
818        return 7;
819      if (errno == EPERM)
820        return 4;
821      return 1;
822    }
823  else
824    return (7);
825}
826
827static pid_t pidofSamhain (int flag)
828{
829  FILE      * fp;
830  char        line[256];
831  char      * tail;
832  char      * p;
833  pid_t       pid;
834  long        inpid;
835  struct stat buf;
836 
837  fp = fopen (DEFAULT_ERRLOCK, "r");
838
839  if (!fp)
840    { if (errno != ENOENT) perror(_("fopen")); return 0; }
841  if (NULL == fgets(line, sizeof(line), fp))
842    { perror(_("fgets")); (void) fclose(fp); return 0; }
843  (void) fclose(fp); 
844  p = line; 
845  while (*p == ' '  || *p == '\f' || *p == '\n' || 
846         *p == '\r' || *p == '\t' || *p == '\v')
847    ++p;
848  errno = 0;
849  inpid = strtol (p, &tail, 0);
850  if (p == tail || errno != 0)
851    { perror(_("strtol")); return 0; }
852
853  pid = (pid_t) inpid;
854  if (inpid != (long) pid)
855    { perror(_("strtol")); return 0; }
856
857  /* remove stale pid file
858   */
859  if (flag == 1 && pid > 0 && 0 != kill(pid, 0) && errno == ESRCH)
860    {
861      if /*@-unrecog@*/ (0 == lstat (DEFAULT_ERRLOCK, &buf))/*@+unrecog@*/
862        {
863          if /*@-usedef@*/(S_ISREG(buf.st_mode))/*@+usedef@*/ 
864            {
865              (void) unlink(DEFAULT_ERRLOCK);
866            }
867        }
868      else 
869        {
870          perror(_("lstat")); return 0;
871        }
872      pid = 0;
873    }
874  return pid;
875}
876
877/* 1: start 2:stop 3:reload 4:status
878 */
879/*@-exitarg@*/
880static int samhainctl(int ctl, int * argc, char * argv[])
881{
882  char * fullpath;
883  pid_t  pid;
884  int    status;
885  int    res;
886  pid_t  respid;
887  int    times;
888  char * argp[32];
889  pid_t       * pidlist;
890  int         i;
891
892
893  fullpath = strdup (SH_INSTALL_PATH);
894  if (fullpath == NULL)
895    { perror(_("strdup")); exit (1); }
896
897  argp[0]  = strdup (SH_INSTALL_PATH);
898  if (argp[0] == NULL)
899    { perror(_("strdup")); exit (1); }
900
901  for (times = 1; times < 32; ++times)  argp[times] = NULL;
902
903  res = (*argc > 32) ? 32 : *argc;
904
905  for (times = 2; times < res; ++times) 
906    {
907      argp[times-1] = strdup (argv[times]);
908      if (argp[times-1] == NULL)
909        { perror(_("strdup")); exit (1); }
910    }
911
912  if (ctl == 1)
913    {
914      pid = pidofSamhain(1);
915
916      if (pid != 0 && 0 == kill (pid, 0)) /* already started */
917        exit (0);
918
919      pid = fork();
920      switch (pid) {
921      case ((pid_t) -1):
922        perror(_("fork"));
923        exit (1);
924      case  0:
925        if (0 != close (0))
926          {
927            _exit(4);
928          }
929        (void) execv(fullpath, argp); /* flawfinder: ignore *//* wtf? */
930        if (errno == EPERM)
931          _exit(4);
932        else if (errno == ENOENT)
933          _exit(5);
934        _exit (1);
935      default:
936        times = 0;
937        while (times < 300) {
938          respid = waitpid(pid, &status, WNOHANG|WUNTRACED);
939          if ((pid_t)-1 == respid)
940            {
941              perror(_("waitpid"));
942              exit (1);
943            }
944          else if (pid == respid)
945            {
946#ifndef USE_UNO
947              if (0 != WIFEXITED(status))
948                {
949                  res = WEXITSTATUS(status);
950                  exit (res == 0 ? 0 : res );
951                }
952              else
953                exit (1);
954#else
955              exit (1);
956#endif
957            }
958          ++times;
959          (void) retry_msleep(1, 0);
960        }
961        exit (0); /* assume that it runs ok */
962      }
963    }
964
965  pid = pidofSamhain(0);
966
967  if (ctl == 2)  /* stop */
968    {
969      pidlist = procdirSamhain ();
970      if (pid == 0 && NULL == pidlist) /* pid file not found */ 
971        {
972          free(fullpath);
973          return (0);
974        }
975         
976      status = 0;
977      if (pid != 0)
978         status = killprocSamhain(pid);
979      if (pidlist != NULL)
980        {
981          i = 0; 
982          while (i < 65535 && pidlist[i] != 0)
983            { 
984              if (pidlist[i] != pid) 
985                status = killprocSamhain(pidlist[i]);
986              ++i;
987            }
988        }
989      free(fullpath);
990      if (status == 7)
991        return 0;
992      else
993        return status;
994    }
995       
996  if (ctl == 3)  /* reload */
997    {
998      if (pid == 0)
999        exit (7);
1000      if (0 == kill (pid, SIGHUP))
1001        exit (0);
1002      else
1003        {
1004          if (errno == EPERM)
1005            exit (4);
1006          if (errno == ESRCH)
1007            exit (7);
1008          exit (1);
1009        }
1010    }
1011
1012  if (ctl == 4)  /* status */
1013    {
1014      if (pid == 0)
1015        exit (3);
1016      if (0 == kill (pid, 0))
1017        exit (0);
1018      else
1019        {
1020          if (errno == EPERM)
1021            exit (4);
1022          if (errno == ESRCH)
1023            exit (1);
1024        }
1025    }
1026  free(fullpath); /* silence smatch false positive */
1027  exit (1); /* no exit handler installed yet */
1028  /*@notreached@*/
1029  return (0);
1030}
1031/*@+exitarg@*/
1032
1033#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
1034#include "sh_schedule.h"
1035static sh_schedule_t * FileSchedOne = NULL;
1036static sh_schedule_t * FileSchedTwo = NULL;
1037
1038/* free a linked list of schedules
1039 */
1040static sh_schedule_t *  free_sched (sh_schedule_t * isched)
1041{
1042  sh_schedule_t * current = isched;
1043  sh_schedule_t * next    = NULL;
1044
1045  while (current != NULL)
1046    {
1047      next = current->next;
1048      SH_FREE(current);
1049      current = next;
1050    }
1051  return NULL;
1052}
1053
1054/* Add a new schedule to the linked list of schedules
1055 */
1056static sh_schedule_t * sh_set_schedule_int (const char * str, 
1057                                            sh_schedule_t * FileSchedIn, 
1058                                            /*@out@*/ int * status)
1059{
1060  sh_schedule_t * FileSched;
1061
1062  SL_ENTER(_("sh_set_schedule_int"));
1063
1064  if (0 == sl_strncmp(str, _("NULL"), 4))
1065    {
1066      (void) free_sched(FileSchedIn);
1067      FileSchedIn = NULL;
1068      *status = 0;
1069      return 0;
1070    }
1071
1072  FileSched = SH_ALLOC(sizeof(sh_schedule_t));
1073  *status = create_sched(str, FileSched);
1074  if (*status != 0)
1075    {
1076      SH_FREE(FileSched);
1077      FileSched = NULL;
1078      SL_RETURN(FileSchedIn , _("sh_set_schedule_int"));
1079    }
1080  FileSched->next = FileSchedIn;
1081  SL_RETURN(FileSched , _("sh_set_schedule_int"));
1082}
1083
1084/* Add a new schedule to the linked list FileSchedOne
1085 */
1086int sh_set_schedule_one (const char * str)
1087{
1088  int status;
1089  FileSchedOne = sh_set_schedule_int (str, FileSchedOne, &status);
1090  return status;
1091}
1092
1093/* Add a new schedule to the linked list FileSchedTwo
1094 */
1095int sh_set_schedule_two (const char * str)
1096{
1097  int status;
1098  FileSchedTwo = sh_set_schedule_int (str, FileSchedTwo, &status);
1099  return status;
1100}
1101
1102#endif
1103
1104/*******************************************************
1105 *
1106 * Main program
1107 *
1108 *******************************************************/
1109#if !defined(SH_CUTEST)
1110int main(int argc, char * argv[])
1111#else
1112int undef_main(int argc, char * argv[])
1113#endif
1114{
1115#if defined(INET_SYSLOG)
1116  extern int    create_syslog_socket (int flag);
1117#endif
1118#if defined(SH_WITH_SERVER)
1119  extern int    sh_create_tcp_socket();
1120#endif
1121
1122#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
1123  int           modnum;
1124  time_t        runtim;
1125  float         st_1, st_2;
1126  int           status;
1127  long          cct = 0; /* main loop iterations */
1128
1129  int           flag_check_1 = 0;
1130  int           flag_check_2 = 0;
1131
1132  int           check_done   = 0;
1133#endif
1134
1135  time_t        told;
1136  time_t        tcurrent;
1137  size_t        tzlen;
1138  char *        tzptr;
1139  int           res;
1140
1141#if defined (SH_STEALTH_NOCL)
1142  char    command_line[256];
1143  int     my_argc = 0;
1144  char  * my_argv[32];
1145#endif
1146
1147  SL_ENTER(_("main"));
1148
1149  /* --- Close all but first three file descriptors. ---
1150   */
1151  sh_unix_closeall(3, -1); /* at program start */
1152
1153
1154  if (argc >= 2 && 0 != getuid() &&
1155      (0 == strcmp(argv[1], _("start")) ||
1156       0 == strcmp(argv[1], _("stop")) ||
1157       0 == strcmp(argv[1], _("reload")) ||
1158       0 == strcmp(argv[1], _("force-reload")) ||
1159       0 == strcmp(argv[1], _("status")) ||
1160       0 == strcmp(argv[1], _("restart"))))
1161    {
1162      return 4;
1163    }
1164       
1165  if (argc >= 2 && 0 == getuid())
1166    {
1167      /* return codes:
1168       * 0    Success
1169       * 1    Can not send signal / start program
1170       * 2    Pid file does not exist
1171       */
1172      if      (0 == strcmp(argv[1], _("start")))
1173        {
1174          (void) samhainctl (1, &argc, argv); /* does not return */
1175        }
1176      else if (0 == strcmp(argv[1], _("stop")))
1177        return (samhainctl (2, &argc, argv));
1178      else if (0 == strcmp(argv[1], _("reload")))
1179        (void) samhainctl (3, &argc, argv);   /* does not return */
1180      else if (0 == strcmp(argv[1], _("force-reload")))
1181        (void) samhainctl (3, &argc, argv);   /* does not return */
1182      else if (0 == strcmp(argv[1], _("status")))
1183        (void) samhainctl (4, &argc, argv);   /* does not return */
1184      else if (0 == strcmp(argv[1], _("restart")))
1185        {
1186          res = samhainctl (2, &argc, argv);
1187          if (res == 0 || res == 7)
1188            {
1189              (void) samhainctl (1, &argc, argv); /* does not return */
1190            }
1191          else
1192            return (res);
1193        }
1194    }
1195 
1196  /* if fd 0 is closed, presume that we want to be daemon and
1197   * run in check mode
1198   */
1199  if ((-1) == retry_fcntl(FIL__, __LINE__, 0, F_GETFL, 0) && 
1200           errno == EBADF)
1201    {
1202      sh.flag.opts = S_TRUE;
1203      (void) sh_unix_setdeamon(NULL);
1204#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
1205      sh.flag.checkSum = SH_CHECK_CHECK;
1206      /* (void) sh_util_setchecksum(_("check")); */
1207#endif
1208      is_samhainctl_init = S_TRUE;
1209      sh.flag.opts = S_FALSE;
1210    }
1211
1212
1213  /* --- Install the exit handler. ---
1214   */
1215  (void) atexit(exit_handler);
1216
1217  /* --- Zero the mailer key, and fill it. ---
1218   */
1219  memset (ErrFlag, 0, 2*sizeof(UINT32));
1220
1221#ifdef MKA_01
1222  ErrFlag[0] |= (1 << 0);
1223#endif
1224#ifdef MKA_02
1225  ErrFlag[0] |= (1 << 1);
1226#endif
1227#ifdef MKA_03
1228  ErrFlag[0] |= (1 << 2);
1229#endif
1230#ifdef MKA_04
1231  ErrFlag[0] |= (1 << 3);
1232#endif
1233#ifdef MKA_05
1234  ErrFlag[0] |= (1 << 4);
1235#endif
1236#ifdef MKA_06
1237  ErrFlag[0] |= (1 << 5);
1238#endif
1239#ifdef MKA_07
1240  ErrFlag[0] |= (1 << 6);
1241#endif
1242#ifdef MKA_08
1243  ErrFlag[0] |= (1 << 7);
1244#endif
1245
1246#if defined(SCREW_IT_UP)
1247  BREAKEXIT(sh_sigtrap_prepare);
1248  (void) sh_sigtrap_prepare();
1249#endif
1250
1251  /* Save the timezone.
1252   */
1253  if (NULL != (tzptr = getenv("TZ"))) /* flawfinder: ignore */
1254    {
1255      tzlen       = strlen(tzptr);
1256      if (tzlen < 1024)
1257        {
1258          sh.timezone = malloc (tzlen + 1);
1259          if (sh.timezone != NULL)
1260            (void) sl_strlcpy (sh.timezone, tzptr, tzlen + 1);
1261        }
1262      else
1263        sh.timezone = NULL;
1264    }
1265  else
1266     sh.timezone = NULL;
1267
1268
1269  /* --------  INIT  --------   
1270   */
1271
1272  /* Restrict error logging to stderr.
1273   */
1274  sh_error_only_stderr (S_TRUE);
1275
1276  BREAKEXIT(sh_derr);
1277  (void) sh_derr();
1278
1279  /* Check that first three descriptors are open.
1280   */
1281  if ( retry_fcntl(FIL__, __LINE__, 0, F_GETFL, 0) == (-1))
1282    (void) aud_open(FIL__, __LINE__, SL_NOPRIV, _("/dev/null"), O_RDWR, 0);
1283  if ( retry_fcntl(FIL__, __LINE__, 1, F_GETFL, 0) == (-1))
1284    (void) aud_open(FIL__, __LINE__, SL_NOPRIV, _("/dev/null"), O_RDWR, 1);
1285  if ( retry_fcntl(FIL__, __LINE__, 2, F_GETFL, 0) == (-1))
1286    (void) aud_open(FIL__, __LINE__, SL_NOPRIV, _("/dev/null"), O_RDWR, 2);
1287
1288  /* --- Set default values. ---
1289   */
1290  BREAKEXIT(sh_init);
1291  sh_init ();    /* we are still privileged here, so we can mlock skey */
1292#if (defined (SH_WITH_SERVER) && !defined (SH_WITH_CLIENT))
1293  sh.flag.isserver = S_TRUE;
1294#endif
1295
1296  /* --- Get local hostname. ---
1297   */
1298  BREAKEXIT(sh_unix_localhost);
1299  sh_unix_localhost();
1300
1301  /* --- Read the command line. ---
1302   */
1303  sh.flag.opts = S_TRUE;
1304
1305#if !defined(SH_STEALTH_NOCL)
1306  sh_argc_store = argc;
1307  sh_argv_store = argv;
1308  (void) sh_getopt_get (argc, argv);
1309#else
1310  if (argc > 1 && argv[1] != NULL && 
1311      strlen(argv[1]) > 0 && strlen(NOCL_CODE) > 0)
1312    {
1313      if ( 0 == strcmp(argv[1], NOCL_CODE) )
1314        {
1315#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
1316          char * saveptr;
1317#endif
1318          my_argv[0] = argv[0]; ++my_argc; 
1319          command_line[0] = '\0';
1320          (void*) fgets (command_line, sizeof(command_line), stdin);
1321          command_line[sizeof(command_line)-1] = '\0';
1322          do {
1323#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
1324            my_argv[my_argc] = 
1325              strtok_r( (my_argc == 1) ? command_line : NULL, " \n", &saveptr);
1326#else
1327            my_argv[my_argc] = 
1328              strtok( (my_argc == 1) ? command_line : NULL, " \n");
1329#endif
1330            if (my_argv[my_argc] != NULL) {
1331              ++my_argc;
1332            } else {
1333              break;
1334            }
1335          } while (my_argc < 32);
1336
1337          sh_argc_store = my_argc;
1338          sh_argv_store = my_argv;
1339
1340          (void) sh_getopt_get (my_argc, my_argv);
1341        }
1342      else
1343        {
1344          /* discard command line */
1345          /* _exit(EXIT_FAILURE)  */  ; 
1346        }
1347    }
1348#endif
1349  sh.flag.opts = S_FALSE;
1350 
1351
1352  /* --- Get user info. ---
1353   */
1354  TPT((0, FIL__, __LINE__, _("msg=<Get user name.>\n")))
1355  if (0 != sh_unix_getUser ())
1356    {
1357      sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_EXIT_ABORT1,
1358                       sh.prg_name);
1359      aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1360    }
1361
1362
1363  /* *****************************
1364   *
1365   *  Read the configuration file.
1366   *
1367   * *****************************/
1368
1369  TPT((0, FIL__, __LINE__, _("msg=<Read the configuration file.>\n")))
1370  BREAKEXIT(sh_readconf_read);
1371  (void) sh_readconf_read ();
1372
1373#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
1374  if (sh.flag.checkSum == SH_CHECK_NONE)
1375    {
1376      sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
1377                       _("No action specified: init, update, or check"), 
1378                       _("main"));
1379      sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_EXIT_ABORT1,
1380                       sh.prg_name);
1381      aud_exit (FIL__, __LINE__, EXIT_FAILURE);
1382    }
1383#endif
1384
1385  /* do not append to database if run SUID
1386   */
1387  if ((sh.flag.checkSum == SH_CHECK_INIT) && (0 != sl_is_suid())) 
1388    {
1389      (void) dlog(1, FIL__, __LINE__, 
1390           _("Cannot initialize database when running with SUID credentials.\nYou need to run this with the user ID %d.\nYour current user ID is %d."), 
1391           (int) geteuid(), (int) sh.real.uid);
1392      sh_error_handle ((-1), FIL__, __LINE__, EACCES, MSG_ACCESS,
1393                       (long) sh.real.uid, sh.data.path);
1394      aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1395    }
1396
1397  /* avoid daemon mode for initialization
1398   */
1399  if (sh.flag.checkSum == SH_CHECK_INIT)
1400    {
1401      sh.flag.isdaemon = S_FALSE;
1402      sh.flag.loop     = S_FALSE;
1403    }
1404
1405  /* --- load database; checksum of database
1406   */
1407#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
1408  TPT((0, FIL__, __LINE__, _("msg=<Get checksum of the database.>\n")))
1409  if (sh.flag.checkSum == SH_CHECK_CHECK) 
1410    {
1411      if (0 != sl_strcmp(file_path('D', 'R'), _("REQ_FROM_SERVER")))
1412        {
1413          char hashbuf[KEYBUF_SIZE];
1414          (void) sl_strlcpy(sh.data.hash,
1415                            sh_tiger_hash (file_path('D', 'R'), 
1416                                           TIGER_FILE, 0, 
1417                                           hashbuf, sizeof(hashbuf)), 
1418                            KEY_LEN+1);
1419        }
1420
1421      /* this eventually fetches the file from server to get checksum
1422       */
1423      sh_hash_init ();
1424    }
1425#endif
1426
1427  /* --- initialize signal handling etc.; fork daemon
1428   */
1429  if (sh_unix_init(sh.flag.isdaemon) == -1) 
1430    {
1431      sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_EXIT_ABORT1,
1432                       sh.prg_name);
1433      aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1434    }
1435
1436  /* --- drop privileges eventually ---
1437   */
1438#if defined(SH_WITH_SERVER)
1439  sh_create_tcp_socket ();
1440#if defined(INET_SYSLOG)
1441  create_syslog_socket (S_TRUE);
1442#endif
1443  SL_REQUIRE(sl_policy_get_real(DEFAULT_IDENT) == SL_ENONE, 
1444             _("sl_policy_get_real(DEFAULT_IDENT) == SL_ENONE"));
1445#else
1446  SL_REQUIRE(sl_policy_get_user(DEFAULT_IDENT) == SL_ENONE, 
1447             _("sl_policy_get_user(DEFAULT_IDENT) == SL_ENONE"));
1448#endif
1449
1450  /* --- Get user info (again). ---
1451   */
1452  TPT((0, FIL__, __LINE__, _("msg=<Get user name.>\n")))
1453  if (0 != sh_unix_getUser ())
1454    {
1455      sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_EXIT_ABORT1,
1456                       sh.prg_name);
1457      aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1458    }
1459
1460  /* --- now check whether we really wanted it; if not, close ---
1461   */
1462#if defined(INET_SYSLOG) && defined(SH_WITH_SERVER)
1463  create_syslog_socket (S_FALSE);
1464#endif
1465
1466
1467  /* --- Enable full error logging ---
1468   */
1469  sh_error_only_stderr (S_FALSE);
1470
1471  /****************************************************
1472   *
1473   *   SERVER
1474   *
1475   ****************************************************/
1476
1477#if defined(SH_WITH_SERVER) && !defined(SH_WITH_CLIENT)
1478
1479#if (defined(WITH_GPG) || defined(WITH_PGP))
1480  /* log startup */
1481  sh_gpg_log_startup ();
1482#else
1483  sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_START_1H,
1484                   sh.prg_name, (long) sh.real.uid, 
1485                   (sh.flag.hidefile == S_TRUE) ? 
1486                   _("(hidden)") : file_path('C','R'), 
1487                   sh.conf.hash);
1488#endif
1489
1490#else
1491
1492  /****************************************************
1493   *
1494   *   CLIENT/STANDALONE
1495   *
1496   ****************************************************/
1497
1498  BREAKEXIT(sh_error_handle);
1499
1500  if (sh.flag.checkSum == SH_CHECK_CHECK) 
1501    {
1502#if (defined(WITH_GPG) || defined(WITH_PGP))
1503      /* log startup */
1504      sh_gpg_log_startup ();
1505#else
1506      sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_START_2H,
1507                       sh.prg_name, (long) sh.real.uid,
1508                       (sh.flag.hidefile == S_TRUE) ? _("(hidden)") : file_path('C', 'R'), sh.conf.hash,
1509                       (sh.flag.hidefile == S_TRUE) ? _("(hidden)") : file_path('D', 'R'), sh.data.hash);
1510#endif
1511    }
1512  else
1513    {
1514#if (defined(WITH_GPG) || defined(WITH_PGP))
1515      /* log startup */
1516      sh_gpg_log_startup ();
1517#else
1518      sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_START_1H,
1519                       sh.prg_name, (long) sh.real.uid,
1520                       (sh.flag.hidefile == S_TRUE) ? _("(hidden)") : file_path('C', 'R'), sh.conf.hash);
1521#endif
1522    }
1523#endif
1524
1525 
1526  if ((skey == NULL) || (skey->mlock_failed == SL_TRUE))
1527    sh_error_handle ((-1), FIL__, __LINE__, EPERM, MSG_MLOCK);
1528
1529  /* timer
1530   */
1531  tcurrent                   = time (NULL);
1532  told                       = tcurrent;
1533  sh.mailTime.alarm_last     = told;
1534
1535
1536  /****************************************************
1537   *
1538   *   SERVER
1539   *
1540   ****************************************************/
1541
1542#if defined(SH_WITH_SERVER)
1543  TPT((0, FIL__, __LINE__, _("msg=<Start server.>\n")))
1544
1545#if defined (SH_WITH_CLIENT)
1546  if (sh.flag.isserver == S_TRUE)
1547    { 
1548      sh_receive();
1549      TPT((0, FIL__, __LINE__, _("msg=<End server.>\n")))
1550      aud_exit (FIL__, __LINE__, EXIT_SUCCESS);
1551    }
1552#else
1553  sh_receive();
1554  TPT((0, FIL__, __LINE__, _("msg=<End server.>\n")))
1555  aud_exit (FIL__, __LINE__, EXIT_SUCCESS);
1556#endif
1557
1558#endif
1559
1560  /****************************************************
1561   *
1562   *   CLIENT/STANDALONE
1563   *
1564   ****************************************************/
1565#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
1566
1567
1568  /* --- Initialize modules. ---
1569   */
1570  TPT((0, FIL__, __LINE__, _("msg=<Initialize modules.>\n")))
1571  for (modnum = 0; modList[modnum].name != NULL; ++modnum) 
1572    {
1573      if (0 != (status = modList[modnum].mod_init()))
1574        {
1575          if (status == (-1)) {
1576            sh_error_handle (SH_ERR_NOTICE, FIL__, __LINE__, status, 
1577                             MSG_MOD_FAIL,
1578                             _(modList[modnum].name),
1579                             status);
1580          } else {
1581            sh_error_handle ((-1), FIL__, __LINE__, status, MSG_MOD_FAIL,
1582                             _(modList[modnum].name),
1583                             status);
1584          }
1585          modList[modnum].initval = S_FALSE;
1586        }
1587      else
1588        {
1589          sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_MOD_OK,
1590                           _(modList[modnum].name));
1591          modList[modnum].initval = S_TRUE;
1592        }
1593    }
1594   
1595  /*  --------  TEST SETUP  ---------
1596   */
1597  (void) sh_files_setrec();
1598  (void) sh_files_test_setup();
1599
1600
1601  /* --------  NICE LEVEL   ---------
1602   */
1603  if (0 != sh.flag.nice)
1604    {
1605#ifdef HAVE_SETPRIORITY
1606      /*@-unrecog@*/
1607      (void) setpriority(PRIO_PROCESS, 0, sh.flag.nice);
1608      /*@+unrecog@*/
1609#else
1610      (void) nice(sh.flag.nice);
1611#endif
1612    }
1613
1614  /*  --------  MAIN LOOP  ---------
1615   */
1616  sh.statistics.bytes_speed  = 0;
1617  sh.statistics.bytes_hashed = 0;
1618
1619  while (1 == 1) 
1620    {
1621      ++cct;
1622
1623      BREAKEXIT(sh_error_handle);
1624
1625      TPT((0, FIL__, __LINE__, _("msg=<Start main loop.>, iter=<%ld>\n"), cct))
1626
1627      tcurrent = time (NULL);
1628
1629      if (sig_raised > 0) 
1630        {
1631
1632          TPT((0, FIL__, __LINE__, _("msg=<Process a signal.>\n")))
1633
1634          if (sig_termfast == 1)  /* SIGTERM */
1635            {
1636              TPT((0, FIL__, __LINE__, _("msg=<Terminate.>\n")));
1637              /* strncpy (sh_sig_msg, _("SIGTERM"), 20); */
1638              --sig_raised; --sig_urgent;
1639              aud_exit (FIL__, __LINE__, EXIT_SUCCESS);
1640            }
1641
1642          if (sig_force_check == 1) /* SIGTTOU */
1643            {
1644              TPT((0, FIL__, __LINE__, _("msg=<Check run triggered.>\n")));
1645              flag_check_1 = 1;
1646              flag_check_2 = 1;
1647              sig_force_check = 0;
1648              --sig_raised; 
1649            }
1650         
1651          if (sig_config_read_again == 1) /* SIGHUP */
1652            {
1653              TPT((0, FIL__, __LINE__, _("msg=<Re-read configuration.>\n")))
1654              sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_RECONF);
1655
1656#if defined(WITH_EXTERNAL)
1657              /* delete list of external tasks
1658               */
1659              (void) sh_ext_cleanup();
1660#endif
1661              /* delete the file list, make all database
1662               * entries visible (allignore = FALSE)
1663               */
1664              (void) sh_files_deldirstack ();
1665              (void) sh_files_delfilestack ();
1666              (void) sh_ignore_clean ();
1667              (void) hash_full_tree ();
1668
1669#if defined(SH_WITH_CLIENT)
1670              reset_count_dev_server();
1671#endif
1672#if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE)
1673
1674
1675              FileSchedOne = free_sched(FileSchedOne);
1676              FileSchedTwo = free_sched(FileSchedTwo);
1677
1678              for (modnum = 0; modList[modnum].name != NULL; ++modnum) 
1679                {
1680                  if (modList[modnum].initval == GOOD)
1681                    (void) modList[modnum].mod_reconf();
1682                }
1683#endif
1684
1685#if defined(SH_WITH_MAIL)
1686              reset_count_dev_mail();
1687#endif
1688              reset_count_dev_console();
1689              reset_count_dev_time();
1690
1691              (void) sh_unix_maskreset();
1692 
1693              /* Should this be included ???
1694               * (i.e. should we reload the database ?)
1695               */
1696#ifdef RELOAD_DATABASE
1697              sh_hash_hashdelete();
1698#endif
1699              (void) sl_trust_purge_user();
1700              (void) sh_files_hle_reg (NULL);
1701              (void) sh_prelink_run (NULL, NULL, 0);
1702
1703              /* --------------------------
1704               * --- READ CONFIGURATION ---
1705               * --------------------------
1706               */
1707              (void) sh_readconf_read ();
1708              sig_config_read_again = 0;
1709              (void) sh_files_setrec();
1710              (void) sh_files_test_setup();
1711              if (0 != sh.flag.nice)
1712                {
1713#ifdef HAVE_SETPRIORITY
1714                  setpriority(PRIO_PROCESS, 0, sh.flag.nice);
1715#else
1716                  nice(sh.flag.nice);
1717#endif
1718                }
1719
1720              if (sh.flag.checkSum == SH_CHECK_INIT)
1721                {
1722                  sh.flag.isdaemon = S_FALSE;
1723                  sh.flag.loop     = S_FALSE;
1724                }
1725
1726              /* --- Initialize modules. ---
1727               */
1728              TPT((0, FIL__, __LINE__, _("msg=<Initialize modules.>\n")));
1729              for (modnum = 0; modList[modnum].name != NULL; ++modnum) 
1730                {
1731                  if (0 != (status = modList[modnum].mod_init()))
1732                    {
1733                      if (status == (-1)) {
1734                        sh_error_handle (SH_ERR_NOTICE, FIL__, __LINE__, 
1735                                         status, MSG_MOD_FAIL,
1736                                         _(modList[modnum].name),
1737                                         status);
1738                      } else {
1739                        sh_error_handle ((-1), FIL__, __LINE__, 
1740                                         status, MSG_MOD_FAIL,
1741                                         _(modList[modnum].name),
1742                                         status);
1743                      }
1744                      modList[modnum].initval = S_FALSE;
1745                    }
1746                  else
1747                    {
1748                      sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_MOD_OK,
1749                                       _(modList[modnum].name));
1750                      modList[modnum].initval = S_TRUE;
1751                    }
1752                }
1753             
1754              --sig_raised;
1755            }
1756         
1757          if (sig_fresh_trail == 1) /* SIGIOT */
1758            {
1759              /* Logfile access
1760               */
1761#ifdef SH_USE_XML
1762              (void) sh_log_file (NULL, NULL);
1763#endif
1764              TPT((0, FIL__, __LINE__, _("msg=<Logfile stop/restart.>\n")));
1765              sh_error_only_stderr (S_TRUE);
1766              (void) sh_unix_rm_lock_file(sh.srvlog.name);
1767              (void) retry_msleep(3, 0);
1768              sh.flag.log_start = S_TRUE;
1769              sh_error_only_stderr (S_FALSE);
1770              sig_fresh_trail       = 0;
1771              --sig_raised;
1772            }
1773         
1774          if (sig_terminate == 1)  /* SIGQUIT */
1775            {
1776              TPT((0, FIL__, __LINE__, _("msg=<Terminate.>\n")));
1777              strncpy (sh_sig_msg, _("Quit"), 20);
1778              --sig_raised; --sig_urgent;
1779              aud_exit (FIL__, __LINE__, EXIT_SUCCESS);
1780            }
1781         
1782          if (sig_debug_switch == 1)  /* SIGUSR1 */
1783            {
1784              TPT((0, FIL__, __LINE__, _("msg=<Debug switch.>\n")));
1785              sh_error_dbg_switch();
1786              sig_debug_switch = 0;
1787              --sig_raised;
1788            }
1789         
1790          if (sig_suspend_switch > 0)  /* SIGUSR2 */
1791            {
1792              TPT((0, FIL__, __LINE__, _("msg=<Suspend switch.>\n")));
1793              if (sh_global_suspend_flag == 1) {
1794                sh_global_suspend_flag = 0;
1795              } else {
1796                sh_error_handle((-1), FIL__, __LINE__, 0, MSG_SUSPEND, 
1797                                sh.prg_name);
1798                sh_global_suspend_flag = 1;
1799              }
1800              --sig_suspend_switch;
1801              --sig_raised; --sig_urgent;
1802            }
1803          sig_raised = (sig_raised < 0) ? 0 : sig_raised;
1804          sig_urgent = (sig_urgent < 0) ? 0 : sig_urgent;
1805          TPT((0, FIL__, __LINE__, _("msg=<End signal processing.>\n")));
1806        }
1807     
1808      if (sh_global_suspend_flag == 1)
1809        {
1810          (void) retry_msleep (1, 0);
1811          continue;
1812        }
1813     
1814      /* see whether its time to check files
1815       */
1816      if      (sh.flag.checkSum == SH_CHECK_INIT ||
1817               (sh.flag.checkSum == SH_CHECK_CHECK &&
1818                (sh.flag.isdaemon == S_FALSE && sh.flag.loop == S_FALSE)))
1819        {
1820          flag_check_1 = 1;
1821          if (FileSchedTwo != NULL) 
1822            flag_check_2 = 1;
1823        }
1824      else if (sh.flag.checkSum == SH_CHECK_CHECK || 
1825               (sh.flag.update == S_TRUE && 
1826                (sh.flag.isdaemon == S_TRUE || sh.flag.loop == S_TRUE)))
1827        {
1828          if (FileSchedOne == NULL)
1829            {
1830              /* use interval if we have no schedule
1831               */
1832              if (tcurrent - sh.fileCheck.alarm_last >= 
1833                  sh.fileCheck.alarm_interval)
1834                flag_check_1 = 1;
1835            }
1836          else
1837            {
1838              flag_check_1 = test_sched(FileSchedOne);
1839              if (FileSchedTwo != NULL) 
1840                flag_check_2 = test_sched(FileSchedTwo);
1841              if (flag_check_2 == 1) 
1842                flag_check_1 = 1;
1843            }
1844        }
1845
1846      check_done = 0;
1847
1848      if (sh.flag.checkSum != SH_CHECK_NONE &&
1849          (flag_check_1 == 1 || flag_check_2 == 1))
1850        {
1851          /*
1852           * check directories and files
1853           * ORDER IS IMPORTANT -- DIRZ FIRST
1854           */
1855          sh.statistics.bytes_hashed   = 0;
1856          sh.statistics.time_start     = time (NULL);
1857          sh.statistics.dirs_checked   = 0;
1858          sh.statistics.files_checked  = 0;
1859
1860          TPT((0, FIL__, __LINE__, _("msg=<Check directories.>\n")))
1861          BREAKEXIT(sh_dirs_chk);
1862          if (flag_check_1 == 1)
1863            {
1864              (void) sh_dirs_chk  (1);
1865#ifndef SH_PROFILE
1866              (void) chdir ("/");
1867#endif
1868            }
1869          if (flag_check_2 == 1)
1870            {
1871              (void) sh_dirs_chk  (2); 
1872#ifndef SH_PROFILE
1873              (void) chdir ("/");
1874#endif
1875            }
1876          TPT((0, FIL__, __LINE__, _("msg=<Check files.>\n")))
1877          BREAKEXIT(sh_files_chk);
1878          if (flag_check_1 == 1)
1879            (void) sh_files_chk ();
1880
1881          if (sig_urgent > 0)
1882            continue;
1883
1884          /*
1885           * check for files not visited
1886           */
1887          if (flag_check_2 == 1 || FileSchedTwo == NULL)
1888            {
1889              TPT((0, FIL__, __LINE__, _("msg=<Check for missing files.>\n")))
1890              sh_hash_unvisited (ShDFLevel[SH_ERR_T_FILE]);
1891            }
1892
1893          if (sig_urgent > 0)
1894            continue;
1895
1896          /* reset
1897           */
1898          TPT((0, FIL__, __LINE__, _("msg=<Reset status.>\n")))
1899          sh_dirs_reset  ();
1900          if (sig_urgent > 0)
1901            continue;
1902
1903          sh_files_reset ();
1904          flag_check_1 = 0;
1905          flag_check_2 = 0;
1906          check_done   = 1;
1907
1908          (void) sh_prelink_run (NULL, NULL, 0);
1909
1910          if (sig_urgent > 0)
1911            continue;
1912
1913          runtim = time(NULL) - sh.statistics.time_start;
1914          sh.statistics.time_check = runtim;
1915       
1916          if ((sh.statistics.dirs_checked == 0) && 
1917              (sh.statistics.files_checked == 0))
1918            sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_CHECK_0);
1919
1920          else
1921            {
1922              st_1 = (float) sh.statistics.bytes_hashed;
1923              st_2 = (float) runtim;
1924
1925
1926              if (st_1 > FLT_EPSILON && st_2 > FLT_EPSILON) 
1927                st_1 = st_1/st_2;
1928              else if (st_1 > FLT_EPSILON)
1929                st_1 = (float) (st_1 * 1.0);
1930              else
1931                st_1 = 0.0;
1932
1933              sh.statistics.bytes_speed = (unsigned long) st_1;
1934
1935              sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_CHECK_1,
1936                               (long) runtim, 
1937                               0.001 * st_1);
1938            }
1939          sh.fileCheck.alarm_last = time (NULL);
1940
1941          if (sig_urgent > 0)
1942            continue;
1943
1944          /*
1945           * flush mail queue
1946           */
1947#if defined(SH_WITH_MAIL)
1948          TPT((0, FIL__, __LINE__, _("msg=<Flush mail queue.>\n")))
1949          (void) sh_mail_msg (NULL);
1950#endif
1951        }
1952     
1953      if (sig_urgent > 0)
1954        continue;
1955     
1956      /* execute modules
1957       */
1958      TPT((0, FIL__, __LINE__, _("msg=<Execute modules.>\n")))
1959      for (modnum = 0; modList[modnum].name != NULL; ++modnum) 
1960        {
1961          if (modList[modnum].initval == GOOD &&
1962              0 != modList[modnum].mod_timer(tcurrent))
1963            if (0 != (status = modList[modnum].mod_check()))
1964              sh_error_handle ((-1), FIL__, __LINE__, status, MSG_MOD_EXEC,
1965                               _(modList[modnum].name), (long) status);
1966        }
1967     
1968      /* 27.05.2002 avoid empty database
1969       * 22.10.2002 moved here b/o suid check initialization
1970       */ 
1971      if      (sh.flag.checkSum == SH_CHECK_INIT)
1972        sh_hash_pushdata (NULL, NULL);
1973
1974      /* write out database
1975       */
1976      if (sh.flag.checkSum == SH_CHECK_CHECK && 
1977          sh.flag.update == S_TRUE && 
1978          check_done == 1)
1979        sh_hash_writeout ();
1980
1981      /* no loop if not daemon
1982       */
1983      if (sh.flag.isdaemon != S_TRUE && sh.flag.loop == S_FALSE)
1984        break; 
1985      if (sig_urgent > 0)
1986        continue;
1987
1988      /* see whether its time to send mail
1989       */
1990#if defined(SH_WITH_MAIL)
1991      if (tcurrent - sh.mailTime.alarm_last >= sh.mailTime.alarm_interval) 
1992        {
1993          TPT((0, FIL__, __LINE__, _("msg=<Flush mail queue.>\n")))
1994          (void) sh_mail_msg (NULL);
1995          sh.mailTime.alarm_last = time (NULL);
1996        }
1997#endif
1998      if (sig_urgent > 0)
1999        continue;
2000           
2001      /* log the timestamp
2002       */
2003      if ((int)(tcurrent - told) >= sh.looptime )
2004        {
2005          TPT((0, FIL__, __LINE__, _("msg=<Log the timestamp.>\n")))
2006          told = tcurrent;
2007#ifdef MEM_DEBUG
2008          sh_mem_check();
2009          sh_unix_count_mlock();
2010#else
2011          sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_STAMP);
2012#endif
2013        }
2014   
2015      /* seed / re-seed the PRNG if required
2016       */
2017      (void) taus_seed();
2018     
2019      if (sig_urgent > 0)
2020        continue;
2021     
2022      /* go to sleep
2023       */
2024      (void) retry_msleep (1, 0);
2025
2026      BREAKEXIT(sh_derr);
2027      (void) sh_derr();
2028    }
2029 
2030  /*   ------  END  -----------
2031   */
2032
2033
2034
2035  /*
2036   * cleanup
2037   */
2038  TPT((0, FIL__, __LINE__, _("msg=<Cleanup.>\n")));
2039  sh_hash_hashdelete(); 
2040
2041#if defined(SH_WITH_MAIL)
2042  if (sh.mailNum.alarm_last > 0) 
2043    (void)sh_mail_msg (NULL);
2044#endif
2045
2046  /* #if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE) */
2047#endif
2048
2049  aud_exit (FIL__, __LINE__, EXIT_SUCCESS);
2050  SL_RETURN(0, _("main"));
2051}
Note: See TracBrowser for help on using the repository browser.