source: trunk/src/samhain.c@ 143

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

Bugfixes and threaded process check.

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