source: trunk/src/samhain.c@ 4

Last change on this file since 4 was 1, checked in by katerina, 19 years ago

Initial import

File size: 45.6 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';
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';
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#endif
655#if defined(SH_WITH_SERVER)
656 sh_forward_free_all ();
657#endif
658 delete_cache();
659 sh_mem_stat();
660#endif
661
662#ifdef MEM_DEBUG
663 sh_unix_count_mlock();
664#endif
665
666 /* --- Checksum of executable. ---
667 */
668 (void) sh_unix_self_check();
669
670
671 /* --- Exit Message. ---
672 */
673 sh_error_handle ((-1), FIL__, __LINE__, sh.flag.exit, MSG_EXIT_NORMAL,
674 sh.prg_name, sh_sig_msg);
675#ifdef SH_USE_XML
676 (void) sh_log_file (NULL, NULL);
677#endif
678
679
680 /* --- Restrict error logging to stderr. ---
681 */
682#ifdef WITH_MESSAGE_QUEUE
683 close_ipc ();
684#endif
685 sh_error_only_stderr (S_TRUE);
686
687
688 /* --- Remove lock, delete critical information. ---
689 */
690 (void) sh_unix_rm_lock_file (sh.srvlog.name);
691 (void) sh_unix_rm_pid_file ();
692 if (skey != NULL)
693 memset (skey, (int) '\0', sizeof(sh_key_t));
694
695 /* --- Exit. ---
696 */
697 SL_RET0(_("exit_handler"));
698}
699
700/***********************************************************
701 *
702 */
703#ifndef SIGHUP
704#define SIGHUP 1
705#endif
706#ifndef SIGTERM
707#define SIGTERM 15
708#endif
709#ifndef SIGKILL
710#define SIGKILL 9
711#endif
712
713#if defined(__linux__) || defined(sun) || defined(__sun) || defined(__sun__)
714#include <dirent.h>
715static pid_t * procdirSamhain ()
716{
717 pid_t * pidlist = malloc(sizeof(pid_t) * 65535);
718 struct dirent * d;
719 DIR * dp;
720 long ino;
721 struct stat buf;
722 int i = 0;
723 pid_t pid, mypid = getpid();
724 char * tail;
725 char exef[128];
726
727 for (i = 0; i < 65535; ++i) pidlist[i] = 0;
728 i = 0;
729
730 if (0 != stat(SH_INSTALL_PATH, &buf))
731 return NULL;
732
733 ino = (long) buf.st_ino;
734
735 if (NULL == (dp = opendir("/proc")))
736 return NULL;
737 while (NULL != (d = readdir(dp)) && i < 65535)
738 {
739 if (0 != strcmp(d->d_name, ".") && 0 != strcmp(d->d_name, ".."))
740 {
741 errno = 0;
742 pid = (pid_t) strtol (d->d_name, &tail, 0);
743 if (*tail != '\0' || errno != 0)
744 continue;
745 if (pid == mypid)
746 continue;
747#if defined(__linux__)
748 sprintf(exef, _("/proc/%d/exe"), (int) pid); /* known to fit */
749#else
750 sprintf(exef, _("/proc/%d/object/a.out"), /* known to fit */
751 (int) pid);
752#endif
753 if (0 == stat(exef, &buf) && ino == (long) buf.st_ino)
754 { pidlist[i] = (pid_t) pid; ++i; }
755 }
756 }
757 closedir(dp);
758 return pidlist;
759}
760#else
761static pid_t * procdirSamhain ()
762{
763 return NULL;
764}
765#endif
766
767static int killprocSamhain (pid_t pid)
768{
769 int i;
770
771 /* fprintf(stderr, "Killing %d\n", pid); */
772 if (pid > 0 && 0 == kill (pid, SIGTERM))
773 {
774 for (i = 0; i < 16; ++i)
775 {
776 (void) retry_msleep(1, 0);
777 if (0 != kill (pid, 0) && errno == ESRCH)
778 return (0);
779 }
780
781 (void) kill (pid, SIGKILL);
782 return (0);
783 }
784 if (pid > 0)
785 {
786 if (errno == ESRCH)
787 return 7;
788 if (errno == EPERM)
789 return 4;
790 return 1;
791 }
792 else
793 return (7);
794}
795
796static pid_t pidofSamhain (int flag)
797{
798 FILE * fp;
799 char line[256];
800 char * tail;
801 char * p;
802 pid_t pid;
803 long inpid;
804 struct stat buf;
805
806 fp = fopen (DEFAULT_ERRLOCK, "r");
807
808 if (!fp)
809 { if (errno != ENOENT) perror(_("fopen")); return 0; }
810 if (NULL == fgets(line, 255, fp))
811 { perror(_("fgets")); (void) fclose(fp); return 0; }
812 (void) fclose(fp);
813 p = line;
814 while (*p == ' ' || *p == '\f' || *p == '\n' ||
815 *p == '\r' || *p == '\t' || *p == '\v')
816 ++p;
817 errno = 0;
818 inpid = strtol (p, &tail, 0);
819 if (p == tail || errno != 0)
820 { perror(_("strtol")); return 0; }
821
822 pid = (pid_t) inpid;
823 if (inpid != (long) pid)
824 { perror(_("strtol")); return 0; }
825
826 /* remove stale pid file
827 */
828 if (flag == 1 && pid > 0 && 0 != kill(pid, 0) && errno == ESRCH)
829 {
830 if /*@-unrecog@*/ (0 == lstat (DEFAULT_ERRLOCK, &buf))/*@+unrecog@*/
831 {
832 if /*@-usedef@*/(S_ISREG(buf.st_mode))/*@+usedef@*/
833 {
834 (void) unlink(DEFAULT_ERRLOCK);
835 }
836 }
837 else
838 {
839 perror(_("lstat")); return 0;
840 }
841 pid = 0;
842 }
843 return pid;
844}
845
846/* 1: start 2:stop 3:reload 4:status
847 */
848/*@-exitarg@*/
849static int samhainctl(int ctl, int * argc, char * argv[])
850{
851 char * fullpath;
852 pid_t pid;
853 int status;
854 int res;
855 pid_t respid;
856 int times;
857 char * argp[32];
858 pid_t * pidlist;
859 int i;
860
861
862 fullpath = malloc(strlen(SH_INSTALL_PATH)+1);
863 if (fullpath == NULL)
864 { perror(_("malloc")); exit (1); }
865 else
866 strcpy(fullpath, SH_INSTALL_PATH); /* known to fit */
867
868 argp[0] = malloc(strlen(SH_INSTALL_PATH)+1);
869 if (argp[0] == NULL)
870 { perror(_("malloc")); exit (1); }
871 else
872 strcpy(argp[0], SH_INSTALL_PATH); /* known to fit */
873
874
875 for (times = 1; times < 32; ++times) argp[times] = NULL;
876
877 res = (*argc > 32) ? 32 : *argc;
878
879 for (times = 2; times < res; ++times)
880 {
881 argp[times-1] = malloc(strlen(argv[times])+1);
882 if (argp[times-1] == NULL)
883 { perror(_("malloc")); exit (1); }
884 else
885 strcpy(argp[times-1], argv[times]); /* known to fit */
886 }
887
888 if (ctl == 1)
889 {
890 pid = pidofSamhain(1);
891
892 if (pid != 0 && 0 == kill (pid, 0)) /* already started */
893 exit (0);
894
895 pid = fork();
896 switch (pid) {
897 case ((pid_t) -1):
898 perror(_("fork"));
899 exit (1);
900 case 0:
901 if (0 != close (0))
902 {
903 _exit(4);
904 }
905 (void) execv(fullpath, argp);
906 if (errno == EPERM)
907 _exit(4);
908 else if (errno == ENOENT)
909 _exit(5);
910 _exit (1);
911 default:
912 times = 0;
913 while (times < 64) {
914 respid = waitpid(pid, &status, WNOHANG|WUNTRACED);
915 if ((pid_t)-1 == respid)
916 {
917 perror(_("waitpid"));
918 exit (1);
919 }
920 else if (pid == respid)
921 {
922 if (0 != WIFEXITED(status))
923 {
924 res = WEXITSTATUS(status);
925 exit (res == 0 ? 0 : res );
926 }
927 else
928 exit (1);
929 }
930 ++times;
931 (void) retry_msleep(1, 0);
932 }
933 exit (1);
934 }
935 }
936
937 pid = pidofSamhain(0);
938
939 if (ctl == 2) /* stop */
940 {
941 pidlist = procdirSamhain ();
942 if (pid == 0 && NULL == pidlist) /* pid file not found */
943 return (0);
944
945 status = 0;
946 if (pid != 0)
947 status = killprocSamhain(pid);
948 if (pidlist != NULL)
949 {
950 i = 0;
951 while (i < 65535 && pidlist[i] != 0)
952 {
953 if (pidlist[i] != pid)
954 status = killprocSamhain(pidlist[i]);
955 ++i;
956 }
957 }
958 if (status == 7)
959 return 0;
960 else
961 return status;
962 }
963
964 if (ctl == 3) /* reload */
965 {
966 if (pid == 0)
967 exit (7);
968 if (0 == kill (pid, SIGHUP))
969 exit (0);
970 else
971 {
972 if (errno == EPERM)
973 exit (4);
974 if (errno == ESRCH)
975 exit (7);
976 exit (1);
977 }
978 }
979
980 if (ctl == 4) /* status */
981 {
982 if (pid == 0)
983 exit (3);
984 if (0 == kill (pid, 0))
985 exit (0);
986 else
987 {
988 if (errno == EPERM)
989 exit (4);
990 if (errno == ESRCH)
991 exit (1);
992 }
993 }
994
995 exit (1); /* no exit handler installed yet */
996 /*@notreached@*/
997 return (0);
998}
999/*@+exitarg@*/
1000
1001#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
1002#include "sh_schedule.h"
1003static sh_schedule_t * FileSchedOne = NULL;
1004static sh_schedule_t * FileSchedTwo = NULL;
1005
1006/* free a linked list of schedules
1007 */
1008static sh_schedule_t * free_sched (sh_schedule_t * isched)
1009{
1010 sh_schedule_t * current = isched;
1011 sh_schedule_t * next = NULL;
1012
1013 while (current != NULL)
1014 {
1015 next = current->next;
1016 SH_FREE(current);
1017 current = next;
1018 }
1019 return NULL;
1020}
1021
1022/* Add a new schedule to the linked list of schedules
1023 */
1024static sh_schedule_t * sh_set_schedule_int (char * str,
1025 sh_schedule_t * FileSchedIn,
1026 /*@out@*/ int * status)
1027{
1028 sh_schedule_t * FileSched;
1029
1030 SL_ENTER(_("sh_set_schedule_int"));
1031
1032 if (0 == sl_strncmp(str, _("NULL"), 4))
1033 {
1034 (void) free_sched(FileSchedIn);
1035 FileSchedIn = NULL;
1036 *status = 0;
1037 return 0;
1038 }
1039
1040 FileSched = SH_ALLOC(sizeof(sh_schedule_t));
1041 *status = create_sched(str, FileSched);
1042 if (*status != 0)
1043 {
1044 SH_FREE(FileSched);
1045 FileSched = NULL;
1046 SL_RETURN(FileSchedIn , _("sh_set_schedule_int"));
1047 }
1048 FileSched->next = FileSchedIn;
1049 SL_RETURN(FileSched , _("sh_set_schedule_int"));
1050}
1051
1052/* Add a new schedule to the linked list FileSchedOne
1053 */
1054int sh_set_schedule_one (char * str)
1055{
1056 int status;
1057 FileSchedOne = sh_set_schedule_int (str, FileSchedOne, &status);
1058 return status;
1059}
1060
1061/* Add a new schedule to the linked list FileSchedTwo
1062 */
1063int sh_set_schedule_two (char * str)
1064{
1065 int status;
1066 FileSchedTwo = sh_set_schedule_int (str, FileSchedTwo, &status);
1067 return status;
1068}
1069
1070#endif
1071
1072/*******************************************************
1073 *
1074 * Main program
1075 *
1076 *******************************************************/
1077int main(int argc, char * argv[])
1078{
1079#if defined(INET_SYSLOG)
1080 extern int create_syslog_socket (int flag);
1081#endif
1082#if defined(SH_WITH_SERVER)
1083 extern int sh_create_tcp_socket();
1084#endif
1085
1086#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
1087 int modnum;
1088 time_t runtim;
1089 float st_1, st_2;
1090 int status;
1091 long cct = 0; /* main loop iterations */
1092
1093 int flag_check_1 = 0;
1094 int flag_check_2 = 0;
1095
1096 int check_done = 0;
1097#endif
1098
1099 time_t told;
1100 time_t tcurrent;
1101 size_t tzlen;
1102 char * tzptr;
1103 int res;
1104
1105#if defined (SH_STEALTH_NOCL)
1106 char * command_line;
1107 int my_argc = 0;
1108 char * my_argv[32];
1109#endif
1110
1111 SL_ENTER(_("main"));
1112
1113 if (argc >= 2 && 0 != getuid() &&
1114 (0 == strcmp(argv[1], _("start")) ||
1115 0 == strcmp(argv[1], _("stop")) ||
1116 0 == strcmp(argv[1], _("reload")) ||
1117 0 == strcmp(argv[1], _("force-reload")) ||
1118 0 == strcmp(argv[1], _("status")) ||
1119 0 == strcmp(argv[1], _("restart"))))
1120 {
1121 return 4;
1122 }
1123
1124 if (argc >= 2 && 0 == getuid())
1125 {
1126 /* return codes:
1127 * 0 Success
1128 * 1 Can not send signal / start program
1129 * 2 Pid file does not exist
1130 */
1131 if (0 == strcmp(argv[1], _("start")))
1132 {
1133 (void) samhainctl (1, &argc, argv); /* does not return */
1134 }
1135 else if (0 == strcmp(argv[1], _("stop")))
1136 return (samhainctl (2, &argc, argv));
1137 else if (0 == strcmp(argv[1], _("reload")))
1138 (void) samhainctl (3, &argc, argv); /* does not return */
1139 else if (0 == strcmp(argv[1], _("force-reload")))
1140 (void) samhainctl (3, &argc, argv); /* does not return */
1141 else if (0 == strcmp(argv[1], _("status")))
1142 (void) samhainctl (4, &argc, argv); /* does not return */
1143 else if (0 == strcmp(argv[1], _("restart")))
1144 {
1145 res = samhainctl (2, &argc, argv);
1146 if (res == 0 || res == 7)
1147 {
1148 (void) samhainctl (1, &argc, argv); /* does not return */
1149 }
1150 else
1151 return (res);
1152 }
1153 }
1154
1155 /* if fd 0 is closed, presume that we want to be daemon and
1156 * run in check mode
1157 */
1158 if ((-1) == retry_fcntl(FIL__, __LINE__, 0, F_GETFL, 0) &&
1159 errno == EBADF)
1160 {
1161 sh.flag.opts = S_TRUE;
1162 (void) sh_unix_setdeamon(NULL);
1163#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
1164 sh.flag.checkSum = SH_CHECK_CHECK;
1165 /* (void) sh_util_setchecksum(_("check")); */
1166#endif
1167 is_samhainctl_init = S_TRUE;
1168 sh.flag.opts = S_FALSE;
1169 }
1170
1171
1172 /* --- Install the exit handler. ---
1173 */
1174 (void) atexit(exit_handler);
1175
1176 /* --- Zero the mailer key, and fill it. ---
1177 */
1178 memset (ErrFlag, 0, 2*sizeof(UINT32));
1179
1180#ifdef MKA_01
1181 ErrFlag[0] |= (1 << 0);
1182#endif
1183#ifdef MKA_02
1184 ErrFlag[0] |= (1 << 1);
1185#endif
1186#ifdef MKA_03
1187 ErrFlag[0] |= (1 << 2);
1188#endif
1189#ifdef MKA_04
1190 ErrFlag[0] |= (1 << 3);
1191#endif
1192#ifdef MKA_05
1193 ErrFlag[0] |= (1 << 4);
1194#endif
1195#ifdef MKA_06
1196 ErrFlag[0] |= (1 << 5);
1197#endif
1198#ifdef MKA_07
1199 ErrFlag[0] |= (1 << 6);
1200#endif
1201#ifdef MKA_08
1202 ErrFlag[0] |= (1 << 7);
1203#endif
1204
1205#if defined(SCREW_IT_UP)
1206 BREAKEXIT(sh_sigtrap_prepare);
1207 (void) sh_sigtrap_prepare();
1208#endif
1209
1210 /* Save the timezone.
1211 */
1212 if ((tzptr = getenv("TZ")) != NULL)
1213 {
1214 tzlen = strlen(tzptr);
1215 sh.timezone = malloc (tzlen + 1);
1216 if (sh.timezone != NULL)
1217 (void) sl_strlcpy (sh.timezone, tzptr, tzlen + 1);
1218 }
1219 else
1220 sh.timezone = NULL;
1221
1222
1223 /* -------- INIT --------
1224 */
1225
1226 /* Restrict error logging to stderr.
1227 */
1228 sh_error_only_stderr (S_TRUE);
1229
1230 BREAKEXIT(sh_derr);
1231 (void) sh_derr();
1232
1233 /* Check that first three descriptors are open.
1234 */
1235 if ( retry_fcntl(FIL__, __LINE__, 0, F_GETFL, 0) == (-1))
1236 (void) aud_open(FIL__, __LINE__, SL_NOPRIV, _("/dev/null"), O_RDWR, 0);
1237 if ( retry_fcntl(FIL__, __LINE__, 1, F_GETFL, 0) == (-1))
1238 (void) aud_open(FIL__, __LINE__, SL_NOPRIV, _("/dev/null"), O_RDWR, 1);
1239 if ( retry_fcntl(FIL__, __LINE__, 2, F_GETFL, 0) == (-1))
1240 (void) aud_open(FIL__, __LINE__, SL_NOPRIV, _("/dev/null"), O_RDWR, 2);
1241
1242 /* --- Set default values. ---
1243 */
1244 BREAKEXIT(sh_init);
1245 sh_init (); /* we are still privileged here, so we can mlock skey */
1246#if (defined (SH_WITH_SERVER) && !defined (SH_WITH_CLIENT))
1247 sh.flag.isserver = S_TRUE;
1248#endif
1249
1250 /* --- Get local hostname. ---
1251 */
1252 BREAKEXIT(sh_unix_localhost);
1253 sh_unix_localhost();
1254
1255 /* --- Read the command line. ---
1256 */
1257 sh.flag.opts = S_TRUE;
1258
1259#if !defined(SH_STEALTH_NOCL)
1260 (void) sh_getopt_get (argc, argv);
1261#else
1262 if (argc > 1 && argv[1] != NULL &&
1263 strlen(argv[1]) > 0 && strlen(NOCL_CODE) > 0)
1264 {
1265 if ( 0 == strcmp(argv[1], NOCL_CODE) &&
1266 NULL != (command_line = (char *) SH_ALLOC(256 * sizeof(char))))
1267 {
1268 my_argv[0] = argv[0]; ++my_argc;
1269 command_line[0] = '\0';
1270 (void*) fgets (command_line, 255, stdin);
1271 command_line[255] = '\0';
1272 do {
1273 my_argv[my_argc] =
1274 strtok( (my_argc == 1) ? command_line : NULL, " \n");
1275 if (my_argv[my_argc] != NULL) {
1276 ++my_argc;
1277 } else {
1278 break;
1279 }
1280 } while (my_argc < 32);
1281 (void) sh_getopt_get (my_argc, my_argv);
1282 SH_FREE (command_line);
1283 }
1284 else
1285 {
1286 /* discard command line */
1287 /* _exit(EXIT_FAILURE) */ ;
1288 }
1289 }
1290#endif
1291 sh.flag.opts = S_FALSE;
1292
1293
1294 /* close all other files
1295 */
1296 sh_unix_closeall(3, -1); /* after processing CL options */
1297
1298
1299 /* --- Get user info. ---
1300 */
1301 TPT((0, FIL__, __LINE__, _("msg=<Get user name.>\n")))
1302 if (0 != sh_unix_getUser ())
1303 {
1304 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_EXIT_ABORT1,
1305 sh.prg_name);
1306 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1307 }
1308
1309
1310 /* *****************************
1311 *
1312 * Read the configuration file.
1313 *
1314 * *****************************/
1315
1316 TPT((0, FIL__, __LINE__, _("msg=<Read the configuration file.>\n")))
1317 BREAKEXIT(sh_readconf_read);
1318 (void) sh_readconf_read ();
1319
1320#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
1321 if (sh.flag.checkSum == SH_CHECK_NONE)
1322 {
1323 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
1324 _("No action specified: init, update, or check"),
1325 _("main"));
1326 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_EXIT_ABORT1,
1327 sh.prg_name);
1328 aud_exit (FIL__, __LINE__, EXIT_FAILURE);
1329 }
1330#endif
1331
1332 /* do not append to database if run SUID
1333 */
1334 if ((sh.flag.checkSum == SH_CHECK_INIT) && (0 != sl_is_suid()))
1335 {
1336 (void) dlog(1, FIL__, __LINE__,
1337 _("Cannot initialize database when running with SUID credentials.\nYou need to run this with the user ID %d.\nYour current user ID is %d."),
1338 (int) geteuid(), (int) sh.real.uid);
1339 sh_error_handle ((-1), FIL__, __LINE__, EACCES, MSG_ACCESS,
1340 (long) sh.real.uid, sh.data.path);
1341 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1342 }
1343
1344 /* avoid daemon mode for initialization
1345 */
1346 if (sh.flag.checkSum == SH_CHECK_INIT)
1347 {
1348 sh.flag.isdaemon = S_FALSE;
1349 sh.flag.loop = S_FALSE;
1350 }
1351
1352 /* initialize signal handling etc
1353 */
1354 if (sh.flag.isdaemon == S_TRUE)
1355 sh_error_only_stderr (BAD);
1356
1357 if (sh_unix_init(sh.flag.isdaemon) == -1)
1358 {
1359 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_EXIT_ABORT1,
1360 sh.prg_name);
1361 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1362 }
1363
1364 /* --- drop privileges eventually ---
1365 */
1366#if defined(SH_WITH_SERVER)
1367 sh_create_tcp_socket ();
1368#if defined(INET_SYSLOG)
1369 create_syslog_socket (S_TRUE);
1370#endif
1371 SL_REQUIRE(sl_policy_get_real(DEFAULT_IDENT) == SL_ENONE,
1372 _("sl_policy_get_real(DEFAULT_IDENT) == SL_ENONE"));
1373#else
1374 SL_REQUIRE(sl_policy_get_user(DEFAULT_IDENT) == SL_ENONE,
1375 _("sl_policy_get_user(DEFAULT_IDENT) == SL_ENONE"));
1376#endif
1377
1378 /* --- Get user info (again). ---
1379 */
1380 TPT((0, FIL__, __LINE__, _("msg=<Get user name.>\n")))
1381 if (0 != sh_unix_getUser ())
1382 {
1383 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_EXIT_ABORT1,
1384 sh.prg_name);
1385 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1386 }
1387
1388 /* --- now check whether we really wanted it; if not, close ---
1389 */
1390#if defined(INET_SYSLOG) && defined(SH_WITH_SERVER)
1391 create_syslog_socket (S_FALSE);
1392#endif
1393
1394
1395 /* checksum of database
1396 */
1397#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
1398 TPT((0, FIL__, __LINE__, _("msg=<Get checksum of the database.>\n")))
1399 if (sh.flag.checkSum == SH_CHECK_CHECK)
1400 {
1401 if (0 == sl_strcmp(file_path('D', 'R'), _("REQ_FROM_SERVER")))
1402 {
1403 /* fetch the file from server to get checksum
1404 */
1405 sh_hash_init ();
1406 /* sh_hash_hashdelete (); */
1407 }
1408 else
1409 {
1410 (void) sl_strlcpy(sh.data.hash,
1411 sh_tiger_hash (file_path('D', 'R'),
1412 TIGER_FILE, 0),
1413 KEY_LEN+1);
1414 }
1415 }
1416#endif
1417
1418
1419 /* --- Enable full error logging ---
1420 */
1421 sh_error_only_stderr (S_FALSE);
1422
1423 /****************************************************
1424 *
1425 * SERVER
1426 *
1427 ****************************************************/
1428
1429#if defined(SH_WITH_SERVER) && !defined(SH_WITH_CLIENT)
1430
1431#if (defined(WITH_GPG) || defined(WITH_PGP))
1432 /* do nothing -- we exit earlier if error
1433 if (0 != sh_gpg_check_sign (1))
1434 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1435 */
1436#else
1437 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_START_1H,
1438 sh.prg_name, (long) sh.real.uid,
1439 (sh.flag.hidefile == S_TRUE) ?
1440 _("(hidden)") : file_path('C','R'),
1441 sh.conf.hash);
1442#endif
1443
1444#else
1445
1446 /****************************************************
1447 *
1448 * CLIENT/STANDALONE
1449 *
1450 ****************************************************/
1451
1452 BREAKEXIT(sh_error_handle);
1453
1454 if (sh.flag.checkSum == SH_CHECK_CHECK)
1455 {
1456#if (defined(WITH_GPG) || defined(WITH_PGP))
1457 /* do nothing -- we exit earlier if error
1458 if (0 != sh_gpg_check_sign (2))
1459 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1460 */
1461 ;
1462#else
1463 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_START_2H,
1464 sh.prg_name, (long) sh.real.uid,
1465 (sh.flag.hidefile == S_TRUE) ? _("(hidden)") : file_path('C', 'R'), sh.conf.hash,
1466 (sh.flag.hidefile == S_TRUE) ? _("(hidden)") : file_path('D', 'R'), sh.data.hash);
1467#endif
1468 }
1469 else
1470 {
1471#if (defined(WITH_GPG) || defined(WITH_PGP))
1472 /* do nothing -- we exit earlier if error
1473 if (0 != sh_gpg_check_sign (1))
1474 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1475 */
1476 ;
1477#else
1478 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_START_1H,
1479 sh.prg_name, (long) sh.real.uid,
1480 (sh.flag.hidefile == S_TRUE) ? _("(hidden)") : file_path('C', 'R'), sh.conf.hash);
1481#endif
1482 }
1483#endif
1484
1485
1486 if ((skey == NULL) || (skey->mlock_failed == SL_TRUE))
1487 sh_error_handle ((-1), FIL__, __LINE__, EPERM, MSG_MLOCK);
1488
1489 /* timer
1490 */
1491 tcurrent = time (NULL);
1492 told = tcurrent;
1493 sh.mailTime.alarm_last = told;
1494
1495
1496 /****************************************************
1497 *
1498 * SERVER
1499 *
1500 ****************************************************/
1501
1502#if defined(SH_WITH_SERVER)
1503 TPT((0, FIL__, __LINE__, _("msg=<Start server.>\n")))
1504
1505#if defined (SH_WITH_CLIENT)
1506 if (sh.flag.isserver == S_TRUE)
1507 {
1508 sh_receive();
1509 TPT((0, FIL__, __LINE__, _("msg=<End server.>\n")))
1510 aud_exit (FIL__, __LINE__, EXIT_SUCCESS);
1511 }
1512#else
1513 sh_receive();
1514 TPT((0, FIL__, __LINE__, _("msg=<End server.>\n")))
1515 aud_exit (FIL__, __LINE__, EXIT_SUCCESS);
1516#endif
1517
1518#endif
1519
1520 /****************************************************
1521 *
1522 * CLIENT/STANDALONE
1523 *
1524 ****************************************************/
1525#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
1526
1527
1528 /* --- Initialize modules. ---
1529 */
1530 TPT((0, FIL__, __LINE__, _("msg=<Initialize modules.>\n")))
1531 for (modnum = 0; modList[modnum].name != NULL; ++modnum)
1532 {
1533 if (0 != (status = modList[modnum].mod_init()))
1534 {
1535 if (status == (-1)) {
1536 sh_error_handle (SH_ERR_NOTICE, FIL__, __LINE__, status,
1537 MSG_MOD_FAIL,
1538 _(modList[modnum].name),
1539 status);
1540 } else {
1541 sh_error_handle ((-1), FIL__, __LINE__, status, MSG_MOD_FAIL,
1542 _(modList[modnum].name),
1543 status);
1544 }
1545 modList[modnum].initval = S_FALSE;
1546 }
1547 else
1548 {
1549 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_MOD_OK,
1550 _(modList[modnum].name));
1551 modList[modnum].initval = S_TRUE;
1552 }
1553 }
1554
1555 /* -------- TEST SETUP ---------
1556 */
1557 (void) sh_files_setrec();
1558 (void) sh_files_test_setup();
1559
1560
1561 /* -------- NICE LEVEL ---------
1562 */
1563 if (0 != sh.flag.nice)
1564 {
1565#ifdef HAVE_SETPRIORITY
1566 /*@-unrecog@*/
1567 (void) setpriority(PRIO_PROCESS, 0, sh.flag.nice);
1568 /*@+unrecog@*/
1569#else
1570 (void) nice(sh.flag.nice);
1571#endif
1572 }
1573
1574 /* -------- MAIN LOOP ---------
1575 */
1576 sh.statistics.bytes_speed = 0;
1577 sh.statistics.bytes_hashed = 0;
1578
1579 while (1 == 1)
1580 {
1581 ++cct;
1582
1583 BREAKEXIT(sh_error_handle);
1584
1585 TPT((0, FIL__, __LINE__, _("msg=<Start main loop.>, iter=<%ld>\n"), cct))
1586
1587 tcurrent = time (NULL);
1588
1589 if (sig_raised > 0)
1590 {
1591
1592 TPT((0, FIL__, __LINE__, _("msg=<Process a signal.>\n")))
1593
1594 if (sig_termfast == 1) /* SIGTERM */
1595 {
1596 TPT((0, FIL__, __LINE__, _("msg=<Terminate.>\n")));
1597 /* strncpy (sh_sig_msg, _("SIGTERM"), 20); */
1598 --sig_raised; --sig_urgent;
1599 aud_exit (FIL__, __LINE__, EXIT_SUCCESS);
1600 }
1601
1602 if (sig_force_check == 1) /* SIGTTOU */
1603 {
1604 TPT((0, FIL__, __LINE__, _("msg=<Check run triggered.>\n")));
1605 flag_check_1 = 1;
1606 flag_check_2 = 1;
1607 sig_force_check = 0;
1608 --sig_raised;
1609 }
1610
1611 if (sig_config_read_again == 1) /* SIGHUP */
1612 {
1613 TPT((0, FIL__, __LINE__, _("msg=<Re-read configuration.>\n")))
1614 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_RECONF);
1615
1616#if defined(WITH_EXTERNAL)
1617 /* delete list of external tasks
1618 */
1619 (void) sh_ext_cleanup();
1620#endif
1621 /* delete the file list, make all database
1622 * entries visible (allignore = FALSE)
1623 */
1624 (void) sh_files_deldirstack ();
1625 (void) sh_files_delfilestack ();
1626 (void) sh_ignore_clean ();
1627 (void) hash_full_tree ();
1628
1629#if defined(SH_WITH_CLIENT)
1630 reset_count_dev_server();
1631#endif
1632#if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE)
1633
1634
1635 FileSchedOne = free_sched(FileSchedOne);
1636 FileSchedTwo = free_sched(FileSchedTwo);
1637
1638 for (modnum = 0; modList[modnum].name != NULL; ++modnum)
1639 {
1640 if (modList[modnum].initval == GOOD)
1641 (void) modList[modnum].mod_reconf();
1642 }
1643#endif
1644
1645#if defined(SH_WITH_MAIL)
1646 reset_count_dev_mail();
1647#endif
1648 reset_count_dev_console();
1649 reset_count_dev_time();
1650
1651 (void) sh_unix_maskreset();
1652
1653 /* Should this be included ???
1654 * (i.e. should we reload the database ?)
1655 */
1656#ifdef RELOAD_DATABASE
1657 sh_hash_hashdelete();
1658#endif
1659 (void) sl_trust_purge_user();
1660 (void) sh_files_hle_reg (NULL);
1661 (void) sh_prelink_run (NULL, NULL, 0);
1662
1663 /* --------------------------
1664 * --- READ CONFIGURATION ---
1665 * --------------------------
1666 */
1667 (void) sh_readconf_read ();
1668 sig_config_read_again = 0;
1669 (void) sh_files_setrec();
1670 (void) sh_files_test_setup();
1671 if (0 != sh.flag.nice)
1672 {
1673#ifdef HAVE_SETPRIORITY
1674 setpriority(PRIO_PROCESS, 0, sh.flag.nice);
1675#else
1676 nice(sh.flag.nice);
1677#endif
1678 }
1679
1680 if (sh.flag.checkSum == SH_CHECK_INIT)
1681 {
1682 sh.flag.isdaemon = S_FALSE;
1683 sh.flag.loop = S_FALSE;
1684 }
1685
1686 /* --- Initialize modules. ---
1687 */
1688 TPT((0, FIL__, __LINE__, _("msg=<Initialize modules.>\n")));
1689 for (modnum = 0; modList[modnum].name != NULL; ++modnum)
1690 {
1691 if (0 != (status = modList[modnum].mod_init()))
1692 {
1693 if (status == (-1)) {
1694 sh_error_handle (SH_ERR_NOTICE, FIL__, __LINE__,
1695 status, MSG_MOD_FAIL,
1696 _(modList[modnum].name),
1697 status);
1698 } else {
1699 sh_error_handle ((-1), FIL__, __LINE__,
1700 status, MSG_MOD_FAIL,
1701 _(modList[modnum].name),
1702 status);
1703 }
1704 modList[modnum].initval = S_FALSE;
1705 }
1706 else
1707 {
1708 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_MOD_OK,
1709 _(modList[modnum].name));
1710 modList[modnum].initval = S_TRUE;
1711 }
1712 }
1713
1714 --sig_raised;
1715 }
1716
1717 if (sig_fresh_trail == 1) /* SIGIOT */
1718 {
1719 /* Logfile access
1720 */
1721#ifdef SH_USE_XML
1722 (void) sh_log_file (NULL, NULL);
1723#endif
1724 TPT((0, FIL__, __LINE__, _("msg=<Logfile stop/restart.>\n")));
1725 sh_error_only_stderr (S_TRUE);
1726 (void) sh_unix_rm_lock_file(sh.srvlog.name);
1727 (void) retry_msleep(3, 0);
1728 sh.flag.log_start = S_TRUE;
1729 sh_error_only_stderr (S_FALSE);
1730 sig_fresh_trail = 0;
1731 --sig_raised;
1732 }
1733
1734 if (sig_terminate == 1) /* SIGQUIT */
1735 {
1736 TPT((0, FIL__, __LINE__, _("msg=<Terminate.>\n")));
1737 strncpy (sh_sig_msg, _("Quit"), 20);
1738 --sig_raised; --sig_urgent;
1739 aud_exit (FIL__, __LINE__, EXIT_SUCCESS);
1740 }
1741
1742 if (sig_debug_switch == 1) /* SIGUSR1 */
1743 {
1744 TPT((0, FIL__, __LINE__, _("msg=<Debug switch.>\n")));
1745 sh_error_dbg_switch();
1746 sig_debug_switch = 0;
1747 --sig_raised;
1748 }
1749
1750 if (sig_suspend_switch == 1) /* SIGUSR2 */
1751 {
1752 TPT((0, FIL__, __LINE__, _("msg=<Suspend switch.>\n")));
1753 if (sh_global_suspend_flag == 1) {
1754 sh_global_suspend_flag = 0;
1755 } else {
1756 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_SUSPEND,
1757 sh.prg_name);
1758 sh_global_suspend_flag = 1;
1759 }
1760 sig_suspend_switch = 0;
1761 --sig_raised; --sig_urgent;
1762 }
1763 sig_raised = (sig_raised < 0) ? 0 : sig_raised;
1764 sig_urgent = (sig_urgent < 0) ? 0 : sig_urgent;
1765 TPT((0, FIL__, __LINE__, _("msg=<End signal processing.>\n")));
1766 }
1767
1768 if (sh_global_suspend_flag == 1)
1769 {
1770 (void) retry_msleep (1, 0);
1771 continue;
1772 }
1773
1774 /* see whether its time to check files
1775 */
1776 if (sh.flag.checkSum == SH_CHECK_INIT)
1777 {
1778 flag_check_1 = 1;
1779 if (FileSchedTwo != NULL)
1780 flag_check_2 = 1;
1781 }
1782 else if (sh.flag.checkSum == SH_CHECK_CHECK ||
1783 (sh.flag.update == S_TRUE &&
1784 (sh.flag.isdaemon == S_TRUE || sh.flag.loop == S_TRUE)))
1785 {
1786 if (FileSchedOne == NULL)
1787 {
1788 /* use interval if we have no schedule
1789 */
1790 if (tcurrent - sh.fileCheck.alarm_last >=
1791 sh.fileCheck.alarm_interval)
1792 flag_check_1 = 1;
1793 }
1794 else
1795 {
1796 flag_check_1 = test_sched(FileSchedOne);
1797 if (FileSchedTwo != NULL)
1798 flag_check_2 = test_sched(FileSchedTwo);
1799 if (flag_check_2 == 1)
1800 flag_check_1 = 1;
1801 }
1802 }
1803
1804 check_done = 0;
1805
1806 if (sh.flag.checkSum != SH_CHECK_NONE &&
1807 (flag_check_1 == 1 || flag_check_2 == 1))
1808 {
1809 /*
1810 * check directories and files
1811 * ORDER IS IMPORTANT -- DIRZ FIRST
1812 */
1813 sh.statistics.bytes_hashed = 0;
1814 sh.statistics.time_start = time (NULL);
1815 sh.statistics.dirs_checked = 0;
1816 sh.statistics.files_checked = 0;
1817
1818 TPT((0, FIL__, __LINE__, _("msg=<Check directories.>\n")))
1819 BREAKEXIT(sh_dirs_chk);
1820 if (flag_check_1 == 1)
1821 {
1822 (void) sh_dirs_chk (1);
1823#ifndef SH_PROFILE
1824 (void) chdir ("/");
1825#endif
1826 }
1827 if (flag_check_2 == 1)
1828 {
1829 (void) sh_dirs_chk (2);
1830#ifndef SH_PROFILE
1831 (void) chdir ("/");
1832#endif
1833 }
1834 TPT((0, FIL__, __LINE__, _("msg=<Check files.>\n")))
1835 BREAKEXIT(sh_files_chk);
1836 if (flag_check_1 == 1)
1837 (void) sh_files_chk ();
1838
1839 if (sig_urgent > 0)
1840 continue;
1841
1842 /*
1843 * check for files not visited
1844 */
1845 if (flag_check_2 == 1 || FileSchedTwo == NULL)
1846 {
1847 TPT((0, FIL__, __LINE__, _("msg=<Check for missing files.>\n")))
1848 sh_hash_unvisited (ShDFLevel[SH_ERR_T_FILE]);
1849 }
1850
1851 if (sig_urgent > 0)
1852 continue;
1853
1854 /* reset
1855 */
1856 TPT((0, FIL__, __LINE__, _("msg=<Reset status.>\n")))
1857 sh_dirs_reset ();
1858 if (sig_urgent > 0)
1859 continue;
1860
1861 sh_files_reset ();
1862 flag_check_1 = 0;
1863 flag_check_2 = 0;
1864 check_done = 1;
1865
1866 (void) sh_prelink_run (NULL, NULL, 0);
1867
1868 if (sig_urgent > 0)
1869 continue;
1870
1871 runtim = time(NULL) - sh.statistics.time_start;
1872 sh.statistics.time_check = runtim;
1873
1874 if ((sh.statistics.dirs_checked == 0) &&
1875 (sh.statistics.files_checked == 0))
1876 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_CHECK_0);
1877
1878 else
1879 {
1880 st_1 = (float) sh.statistics.bytes_hashed;
1881 st_2 = (float) runtim;
1882
1883
1884 if (st_1 > FLT_EPSILON && st_2 > FLT_EPSILON)
1885 st_1 = st_1/st_2;
1886 else if (st_1 > FLT_EPSILON)
1887 st_1 = (float) (st_1 * 1.0);
1888 else
1889 st_1 = 0.0;
1890
1891 sh.statistics.bytes_speed = (unsigned long) st_1;
1892
1893 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_CHECK_1,
1894 (long) runtim,
1895 0.001 * st_1);
1896 }
1897 sh.fileCheck.alarm_last = time (NULL);
1898
1899 if (sig_urgent > 0)
1900 continue;
1901
1902 /*
1903 * flush mail queue
1904 */
1905#if defined(SH_WITH_MAIL)
1906 TPT((0, FIL__, __LINE__, _("msg=<Flush mail queue.>\n")))
1907 (void) sh_mail_msg (NULL);
1908#endif
1909 }
1910
1911 if (sig_urgent > 0)
1912 continue;
1913
1914 /* execute modules
1915 */
1916 TPT((0, FIL__, __LINE__, _("msg=<Execute modules.>\n")))
1917 for (modnum = 0; modList[modnum].name != NULL; ++modnum)
1918 {
1919 if (modList[modnum].initval == GOOD &&
1920 0 != modList[modnum].mod_timer(tcurrent))
1921 if (0 != (status = modList[modnum].mod_check()))
1922 sh_error_handle ((-1), FIL__, __LINE__, status, MSG_MOD_EXEC,
1923 _(modList[modnum].name), (long) status);
1924 }
1925
1926 /* 27.05.2002 avoid empty database
1927 * 22.10.2002 moved here b/o suid check initialization
1928 */
1929 if (sh.flag.checkSum == SH_CHECK_INIT)
1930 sh_hash_pushdata (NULL, NULL);
1931
1932 /* write out database
1933 */
1934 if (sh.flag.checkSum == SH_CHECK_CHECK &&
1935 sh.flag.update == S_TRUE &&
1936 check_done == 1)
1937 sh_hash_writeout ();
1938
1939 /* no loop if not daemon
1940 */
1941 if (sh.flag.isdaemon != S_TRUE && sh.flag.loop == S_FALSE)
1942 break;
1943 if (sig_urgent > 0)
1944 continue;
1945
1946 /* see whether its time to send mail
1947 */
1948#if defined(SH_WITH_MAIL)
1949 if (tcurrent - sh.mailTime.alarm_last >= sh.mailTime.alarm_interval)
1950 {
1951 TPT((0, FIL__, __LINE__, _("msg=<Flush mail queue.>\n")))
1952 (void) sh_mail_msg (NULL);
1953 sh.mailTime.alarm_last = time (NULL);
1954 }
1955#endif
1956 if (sig_urgent > 0)
1957 continue;
1958
1959 /* log the timestamp
1960 */
1961 if ((int)(tcurrent - told) >= sh.looptime )
1962 {
1963 TPT((0, FIL__, __LINE__, _("msg=<Log the timestamp.>\n")))
1964 told = tcurrent;
1965#ifdef MEM_DEBUG
1966 sh_mem_check();
1967 sh_unix_count_mlock();
1968#else
1969 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_STAMP);
1970#endif
1971 }
1972
1973 /* seed / re-seed the PRNG if required
1974 */
1975 (void) taus_seed();
1976
1977 if (sig_urgent > 0)
1978 continue;
1979
1980 /* go to sleep
1981 */
1982 (void) retry_msleep (1, 0);
1983
1984 BREAKEXIT(sh_derr);
1985 (void) sh_derr();
1986 }
1987
1988 /* ------ END -----------
1989 */
1990
1991
1992
1993 /*
1994 * cleanup
1995 */
1996 TPT((0, FIL__, __LINE__, _("msg=<Cleanup.>\n")));
1997 sh_hash_hashdelete();
1998
1999#if defined(SH_WITH_MAIL)
2000 if (sh.mailNum.alarm_last > 0)
2001 (void)sh_mail_msg (NULL);
2002#endif
2003
2004 /* #if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE) */
2005#endif
2006
2007 aud_exit (FIL__, __LINE__, EXIT_SUCCESS);
2008 SL_RETURN(0, _("main"));
2009}
Note: See TracBrowser for help on using the repository browser.