source: trunk/src/samhain.c@ 134

Last change on this file since 134 was 134, checked in by rainer, 17 years ago

More thread-safety changes.

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