source: trunk/src/samhain.c@ 93

Last change on this file since 93 was 92, checked in by rainer, 18 years ago

Move fd closing more towards program start. Fix OpenBSD 4.0 compatibility for kernel check.

File size: 45.7 KB
RevLine 
[1]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);
[22]384 sh.host.system[0] = '\0'; /* flawfinder: ignore *//* ff bug */
[1]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';
[22]584 skey->crypt[0] = '\0'; /* flawfinder: ignore *//* ff bug */
[1]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();
[59]654 sh_files_hle_reg (NULL);
[1]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
[22]728 if (!pidlist)
729 return NULL;
730
[1]731 for (i = 0; i < 65535; ++i) pidlist[i] = 0;
732 i = 0;
733
734 if (0 != stat(SH_INSTALL_PATH, &buf))
[22]735 {
736 free(pidlist);
737 return NULL;
738 }
[1]739
740 ino = (long) buf.st_ino;
741
742 if (NULL == (dp = opendir("/proc")))
[22]743 {
744 free(pidlist);
745 return NULL;
746 }
[1]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; }
[34]820 if (NULL == fgets(line, sizeof(line), fp))
[1]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
[22]872 fullpath = strdup (SH_INSTALL_PATH);
[1]873 if (fullpath == NULL)
[22]874 { perror(_("strdup")); exit (1); }
[1]875
[22]876 argp[0] = strdup (SH_INSTALL_PATH);
[1]877 if (argp[0] == NULL)
[22]878 { perror(_("strdup")); exit (1); }
[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 {
[22]886 argp[times-1] = strdup (argv[times]);
[1]887 if (argp[times-1] == NULL)
[22]888 { perror(_("strdup")); exit (1); }
[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 }
[22]908 (void) execv(fullpath, argp); /* flawfinder: ignore *//* wtf? */
[1]909 if (errno == EPERM)
910 _exit(4);
911 else if (errno == ENOENT)
912 _exit(5);
913 _exit (1);
914 default:
915 times = 0;
[92]916 while (times < 300) {
[1]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 }
[79]936 exit (0); /* assume that it runs ok */
[1]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 */
[22]946 {
947 free(fullpath);
948 return (0);
949 }
[1]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 }
[22]964 free(fullpath);
[1]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 }
[22]1001 free(fullpath); /* silence smatch false positive */
[1]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 */
[22]1031static sh_schedule_t * sh_set_schedule_int (const char * str,
[1]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 */
[22]1061int sh_set_schedule_one (const char * str)
[1]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 */
[22]1070int sh_set_schedule_two (const char * str)
[1]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 *******************************************************/
[18]1084#if !defined(SH_CUTEST)
[1]1085int main(int argc, char * argv[])
[18]1086#else
1087int undef_main(int argc, char * argv[])
1088#endif
[1]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)
[34]1117 char command_line[256];
[1]1118 int my_argc = 0;
1119 char * my_argv[32];
1120#endif
1121
1122 SL_ENTER(_("main"));
1123
[92]1124 /* --- Close all but first three file descriptors. ---
1125 */
1126 sh_unix_closeall(3, -1); /* at program start */
1127
1128
[1]1129 if (argc >= 2 && 0 != getuid() &&
1130 (0 == strcmp(argv[1], _("start")) ||
1131 0 == strcmp(argv[1], _("stop")) ||
1132 0 == strcmp(argv[1], _("reload")) ||
1133 0 == strcmp(argv[1], _("force-reload")) ||
1134 0 == strcmp(argv[1], _("status")) ||
1135 0 == strcmp(argv[1], _("restart"))))
1136 {
1137 return 4;
1138 }
1139
1140 if (argc >= 2 && 0 == getuid())
1141 {
1142 /* return codes:
1143 * 0 Success
1144 * 1 Can not send signal / start program
1145 * 2 Pid file does not exist
1146 */
1147 if (0 == strcmp(argv[1], _("start")))
1148 {
1149 (void) samhainctl (1, &argc, argv); /* does not return */
1150 }
1151 else if (0 == strcmp(argv[1], _("stop")))
1152 return (samhainctl (2, &argc, argv));
1153 else if (0 == strcmp(argv[1], _("reload")))
1154 (void) samhainctl (3, &argc, argv); /* does not return */
1155 else if (0 == strcmp(argv[1], _("force-reload")))
1156 (void) samhainctl (3, &argc, argv); /* does not return */
1157 else if (0 == strcmp(argv[1], _("status")))
1158 (void) samhainctl (4, &argc, argv); /* does not return */
1159 else if (0 == strcmp(argv[1], _("restart")))
1160 {
1161 res = samhainctl (2, &argc, argv);
1162 if (res == 0 || res == 7)
1163 {
1164 (void) samhainctl (1, &argc, argv); /* does not return */
1165 }
1166 else
1167 return (res);
1168 }
1169 }
1170
1171 /* if fd 0 is closed, presume that we want to be daemon and
1172 * run in check mode
1173 */
1174 if ((-1) == retry_fcntl(FIL__, __LINE__, 0, F_GETFL, 0) &&
1175 errno == EBADF)
1176 {
1177 sh.flag.opts = S_TRUE;
1178 (void) sh_unix_setdeamon(NULL);
1179#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
1180 sh.flag.checkSum = SH_CHECK_CHECK;
1181 /* (void) sh_util_setchecksum(_("check")); */
1182#endif
1183 is_samhainctl_init = S_TRUE;
1184 sh.flag.opts = S_FALSE;
1185 }
1186
1187
1188 /* --- Install the exit handler. ---
1189 */
1190 (void) atexit(exit_handler);
1191
1192 /* --- Zero the mailer key, and fill it. ---
1193 */
1194 memset (ErrFlag, 0, 2*sizeof(UINT32));
1195
1196#ifdef MKA_01
1197 ErrFlag[0] |= (1 << 0);
1198#endif
1199#ifdef MKA_02
1200 ErrFlag[0] |= (1 << 1);
1201#endif
1202#ifdef MKA_03
1203 ErrFlag[0] |= (1 << 2);
1204#endif
1205#ifdef MKA_04
1206 ErrFlag[0] |= (1 << 3);
1207#endif
1208#ifdef MKA_05
1209 ErrFlag[0] |= (1 << 4);
1210#endif
1211#ifdef MKA_06
1212 ErrFlag[0] |= (1 << 5);
1213#endif
1214#ifdef MKA_07
1215 ErrFlag[0] |= (1 << 6);
1216#endif
1217#ifdef MKA_08
1218 ErrFlag[0] |= (1 << 7);
1219#endif
1220
1221#if defined(SCREW_IT_UP)
1222 BREAKEXIT(sh_sigtrap_prepare);
1223 (void) sh_sigtrap_prepare();
1224#endif
1225
1226 /* Save the timezone.
1227 */
[22]1228 if (NULL != (tzptr = getenv("TZ"))) /* flawfinder: ignore */
[1]1229 {
1230 tzlen = strlen(tzptr);
[22]1231 if (tzlen < 1024)
1232 {
1233 sh.timezone = malloc (tzlen + 1);
1234 if (sh.timezone != NULL)
1235 (void) sl_strlcpy (sh.timezone, tzptr, tzlen + 1);
1236 }
1237 else
1238 sh.timezone = NULL;
[1]1239 }
1240 else
1241 sh.timezone = NULL;
1242
1243
1244 /* -------- INIT --------
1245 */
1246
1247 /* Restrict error logging to stderr.
1248 */
1249 sh_error_only_stderr (S_TRUE);
1250
1251 BREAKEXIT(sh_derr);
1252 (void) sh_derr();
1253
1254 /* Check that first three descriptors are open.
1255 */
1256 if ( retry_fcntl(FIL__, __LINE__, 0, F_GETFL, 0) == (-1))
1257 (void) aud_open(FIL__, __LINE__, SL_NOPRIV, _("/dev/null"), O_RDWR, 0);
1258 if ( retry_fcntl(FIL__, __LINE__, 1, F_GETFL, 0) == (-1))
1259 (void) aud_open(FIL__, __LINE__, SL_NOPRIV, _("/dev/null"), O_RDWR, 1);
1260 if ( retry_fcntl(FIL__, __LINE__, 2, F_GETFL, 0) == (-1))
1261 (void) aud_open(FIL__, __LINE__, SL_NOPRIV, _("/dev/null"), O_RDWR, 2);
1262
1263 /* --- Set default values. ---
1264 */
1265 BREAKEXIT(sh_init);
1266 sh_init (); /* we are still privileged here, so we can mlock skey */
1267#if (defined (SH_WITH_SERVER) && !defined (SH_WITH_CLIENT))
1268 sh.flag.isserver = S_TRUE;
1269#endif
1270
1271 /* --- Get local hostname. ---
1272 */
1273 BREAKEXIT(sh_unix_localhost);
1274 sh_unix_localhost();
1275
1276 /* --- Read the command line. ---
1277 */
1278 sh.flag.opts = S_TRUE;
1279
1280#if !defined(SH_STEALTH_NOCL)
[20]1281 sh_argc_store = argc;
1282 sh_argv_store = argv;
[1]1283 (void) sh_getopt_get (argc, argv);
1284#else
1285 if (argc > 1 && argv[1] != NULL &&
1286 strlen(argv[1]) > 0 && strlen(NOCL_CODE) > 0)
1287 {
[34]1288 if ( 0 == strcmp(argv[1], NOCL_CODE) )
[1]1289 {
1290 my_argv[0] = argv[0]; ++my_argc;
1291 command_line[0] = '\0';
[34]1292 (void*) fgets (command_line, sizeof(command_line), stdin);
1293 command_line[sizeof(command_line)-1] = '\0';
[1]1294 do {
1295 my_argv[my_argc] =
1296 strtok( (my_argc == 1) ? command_line : NULL, " \n");
1297 if (my_argv[my_argc] != NULL) {
1298 ++my_argc;
1299 } else {
1300 break;
1301 }
1302 } while (my_argc < 32);
[20]1303
1304 sh_argc_store = my_argc;
1305 sh_argv_store = my_argv;
1306
[1]1307 (void) sh_getopt_get (my_argc, my_argv);
1308 }
1309 else
1310 {
1311 /* discard command line */
1312 /* _exit(EXIT_FAILURE) */ ;
1313 }
1314 }
1315#endif
1316 sh.flag.opts = S_FALSE;
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
[59]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 */
[1]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))
[86]1445 /* log startup */
1446 sh_gpg_log_startup ();
[1]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))
[86]1468 /* log startup */
1469 sh_gpg_log_startup ();
[1]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))
[86]1480 /* log startup */
1481 sh_gpg_log_startup ();
[1]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
[19]1755 if (sig_suspend_switch > 0) /* SIGUSR2 */
[1]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 }
[19]1765 --sig_suspend_switch;
[1]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 */
[25]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)))
[1]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.