source: trunk/src/samhain.c@ 89

Last change on this file since 89 was 86, checked in by rainer, 18 years ago

More thorough fix for ticket #47, and corresponding regression test.

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