source: trunk/src/samhain.c@ 254

Last change on this file since 254 was 252, checked in by katerina, 15 years ago

Add code to check for stale file records on close() and fclose(), fix sl_close() to handle open stream (ticket #163).

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