source: trunk/src/sh_unix.c@ 486

Last change on this file since 486 was 486, checked in by katerina, 9 years ago

Fix for ticket #384 (use logger utility in posix compliant way).

File size: 132.4 KB
Line 
1/* SAMHAIN file system integrity testing */
2/* Copyright (C) 1999 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 <ctype.h>
27#ifdef HAVE_LINUX_FS_H
28#include <linux/fs.h>
29#endif
30
31#ifdef HAVE_MEMORY_H
32#include <memory.h>
33#endif
34
35#ifdef HAVE_UNISTD_H
36#include <errno.h>
37#include <signal.h>
38#include <pwd.h>
39#include <grp.h>
40#include <sys/types.h>
41#include <sys/stat.h>
42#include <sys/resource.h>
43#include <fcntl.h>
44#include <unistd.h>
45/* need to undef these, since the #define's may be picked up from
46 * linux/wait.h, and will clash with a typedef in sys/wait.h
47 */
48#undef P_ALL
49#undef P_PID
50#undef P_PGID
51#include <sys/wait.h>
52
53/*********************
54#ifdef HAVE_SYS_VFS_H
55#include <sys/vfs.h>
56#endif
57**********************/
58#endif
59
60#if TIME_WITH_SYS_TIME
61#include <sys/time.h>
62#include <time.h>
63#else
64#if HAVE_SYS_TIME_H
65#include <sys/time.h>
66#else
67#include <time.h>
68#endif
69#endif
70
71#ifdef HAVE_SYS_SELECT_H
72#include <sys/select.h>
73#endif
74
75#ifndef FD_SET
76#define NFDBITS 32
77#define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
78#define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
79#define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
80#endif /* !FD_SET */
81#ifndef FD_SETSIZE
82#define FD_SETSIZE 32
83#endif
84#ifndef FD_ZERO
85#define FD_ZERO(p) memset((char *)(p), '\0', sizeof(*(p)))
86#endif
87
88
89#if defined(HAVE_MLOCK) && !defined(HAVE_BROKEN_MLOCK)
90#include <sys/mman.h>
91#endif
92
93#include "samhain.h"
94#include "sh_error.h"
95#include "sh_unix.h"
96#include "sh_utils.h"
97#include "sh_mem.h"
98#include "sh_hash.h"
99#include "sh_tools.h"
100#include "sh_restrict.h"
101#include "sh_ipvx.h"
102#include "sh_tiger.h"
103#include "sh_prelink.h"
104#include "sh_pthread.h"
105#include "sh_sem.h"
106
107/* moved here from far below
108 */
109#include <netdb.h>
110
111#define SH_NEED_PWD_GRP
112#define SH_NEED_GETHOSTBYXXX
113#include "sh_static.h"
114
115#ifndef HAVE_LSTAT
116#define lstat stat
117#endif
118
119#if defined(S_IFLNK) && !defined(S_ISLNK)
120#define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
121#else
122#if !defined(S_ISLNK)
123#define S_ISLNK(mode) (0)
124#endif
125#endif
126
127#if defined(S_IFSOCK) && !defined(S_ISSOCK)
128#define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
129#else
130#if !defined(S_ISSOCK)
131#define S_ISSOCK(mode) (0)
132#endif
133#endif
134
135#if defined(S_IFDOOR) && !defined(S_ISDOOR)
136#define S_ISDOOR(mode) (((mode) & S_IFMT) == S_IFDOOR)
137#else
138#if !defined(S_ISDOOR)
139#define S_ISDOOR(mode) (0)
140#endif
141#endif
142
143#if defined(S_IFPORT) && !defined(S_ISPORT)
144#define S_ISPORT(mode) (((mode) & S_IFMT) == S_IFPORT)
145#else
146#if !defined(S_ISPORT)
147#define S_ISPORT(mode) (0)
148#endif
149#endif
150
151#define SH_KEY_NULL _("000000000000000000000000000000000000000000000000")
152
153#undef FIL__
154#define FIL__ _("sh_unix.c")
155
156unsigned long mask_PRELINK = MASK_PRELINK_;
157unsigned long mask_USER0 = MASK_USER_;
158unsigned long mask_USER1 = MASK_USER_;
159unsigned long mask_USER2 = MASK_USER_;
160unsigned long mask_USER3 = MASK_USER_;
161unsigned long mask_USER4 = MASK_USER_;
162unsigned long mask_ALLIGNORE = MASK_ALLIGNORE_;
163unsigned long mask_ATTRIBUTES = MASK_ATTRIBUTES_;
164unsigned long mask_LOGFILES = MASK_LOGFILES_;
165unsigned long mask_LOGGROW = MASK_LOGGROW_;
166unsigned long mask_READONLY = MASK_READONLY_;
167unsigned long mask_NOIGNORE = MASK_NOIGNORE_;
168
169
170extern char **environ;
171
172int sh_unix_maskreset()
173{
174 mask_PRELINK = MASK_PRELINK_;
175 mask_USER0 = MASK_USER_;
176 mask_USER1 = MASK_USER_;
177 mask_USER2 = MASK_USER_;
178 mask_USER3 = MASK_USER_;
179 mask_USER4 = MASK_USER_;
180 mask_ALLIGNORE = MASK_ALLIGNORE_;
181 mask_ATTRIBUTES = MASK_ATTRIBUTES_;
182 mask_LOGFILES = MASK_LOGFILES_;
183 mask_LOGGROW = MASK_LOGGROW_;
184 mask_READONLY = MASK_READONLY_;
185 mask_NOIGNORE = MASK_NOIGNORE_;
186 return 0;
187}
188
189
190#ifdef SYS_SIGLIST_DECLARED
191/* extern const char * const sys_siglist[]; */
192#else
193char * sh_unix_siglist (int signum)
194{
195 switch (signum)
196 {
197#ifdef SIGHUP
198 case SIGHUP:
199 return _("Hangup");
200#endif
201#ifdef SIGINT
202 case SIGINT:
203 return _("Interrupt");
204#endif
205#ifdef SIGQUIT
206 case SIGQUIT:
207 return _("Quit");
208#endif
209#ifdef SIGILL
210 case SIGILL:
211 return _("Illegal instruction");
212#endif
213#ifdef SIGTRAP
214 case SIGTRAP:
215 return _("Trace/breakpoint trap");
216#endif
217#ifdef SIGABRT
218 case SIGABRT:
219 return _("IOT trap/Abort");
220#endif
221#ifdef SIGBUS
222 case SIGBUS:
223 return _("Bus error");
224#endif
225#ifdef SIGFPE
226 case SIGFPE:
227 return _("Floating point exception");
228#endif
229#ifdef SIGUSR1
230 case SIGUSR1:
231 return _("User defined signal 1");
232#endif
233#ifdef SIGSEGV
234 case SIGSEGV:
235 return _("Segmentation fault");
236#endif
237#ifdef SIGUSR2
238 case SIGUSR2:
239 return _("User defined signal 2");
240#endif
241#ifdef SIGPIPE
242 case SIGPIPE:
243 return _("Broken pipe");
244#endif
245#ifdef SIGALRM
246 case SIGALRM:
247 return _("Alarm clock");
248#endif
249#ifdef SIGTERM
250 case SIGTERM:
251 return _("Terminated");
252#endif
253#ifdef SIGSTKFLT
254 case SIGSTKFLT:
255 return _("Stack fault");
256#endif
257#ifdef SIGCHLD
258 case SIGCHLD:
259 return _("Child exited");
260#endif
261#ifdef SIGCONT
262 case SIGCONT:
263 return _("Continued");
264#endif
265#ifdef SIGSTOP
266 case SIGSTOP:
267 return _("Stopped");
268#endif
269#ifdef SIGTSTP
270 case SIGTSTP:
271 return _("Stop typed at tty");
272#endif
273#ifdef SIGTTIN
274 case SIGTTIN:
275 return _("Stopped (tty input)");
276#endif
277#ifdef SIGTTOU
278 case SIGTTOU:
279 return _("Stopped (tty output)");
280#endif
281#ifdef SIGURG
282 case SIGURG:
283 return _("Urgent condition");
284#endif
285#ifdef SIGXCPU
286 case SIGXCPU:
287 return _("CPU time limit exceeded");
288#endif
289#ifdef SIGXFSZ
290 case SIGXFSZ:
291 return _("File size limit exceeded");
292#endif
293#ifdef SIGVTALRM
294 case SIGVTALRM:
295 return _("Virtual time alarm");
296#endif
297#ifdef SIGPROF
298 case SIGPROF:
299 return _("Profile signal");
300#endif
301#ifdef SIGWINCH
302 case SIGWINCH:
303 return _("Window size changed");
304#endif
305#ifdef SIGIO
306 case SIGIO:
307 return _("Possible I/O");
308#endif
309#ifdef SIGPWR
310 case SIGPWR:
311 return _("Power failure");
312#endif
313#ifdef SIGUNUSED
314 case SIGUNUSED:
315 return _("Unused signal");
316#endif
317 }
318 return _("Unknown");
319}
320#endif
321
322
323/* Log from within a signal handler without using any
324 * functions that are not async signal safe.
325 *
326 * This is the safe_itoa helper function.
327 */
328char * safe_itoa(int i, char * str, int size)
329{
330 unsigned int u;
331 int iisneg = 0;
332 char *p = &str[size-1];
333
334 *p = '\0';
335 if (i < 0) {
336 iisneg = 1;
337 u = ((unsigned int)(-(1+i))) + 1;
338 } else {
339 u = i;
340 }
341 do {
342 --p;
343 *p = '0' + (u % 10);
344 u /= 10;
345 } while (u && (p != str));
346 if ((iisneg == 1) && (p != str)) {
347 --p;
348 *p = '-';
349 }
350 return p;
351}
352
353/* Log from within a signal handler without using any
354 * functions that are not async signal safe.
355 *
356 * This is the safe_logger function.
357 * Arguments: signal (signal number), method (0=logger, 1=stderr), thepid (pid)
358 */
359extern int OnlyStderr;
360
361int safe_logger (int thesignal, int method, char * details)
362{
363 unsigned int i = 0;
364 int status = -1;
365 struct stat buf;
366 pid_t newpid;
367 char str[128];
368 char * p;
369
370 char l0[64], l1[64], l2[64], l3[64];
371 char a0[32];
372 char e0[128];
373 char msg[128];
374
375 char * locations[] = { NULL, NULL, NULL, NULL, NULL };
376 char * envp[] = { NULL, NULL };
377 char * argp[] = { NULL, NULL, NULL };
378
379 pid_t thepid = getpid();
380
381 if ((sh.flag.isdaemon == S_FALSE) || (OnlyStderr == S_TRUE))
382 method = 1;
383
384 /* seems that solaris cc needs this way of initializing ...
385 */
386 locations[0] = l0;
387 locations[1] = l1;
388 locations[2] = l2;
389 locations[3] = l3;
390
391 envp[0] = e0;
392 argp[0] = a0;
393
394 sl_strlcpy(msg, _("samhain["), 128);
395 p = safe_itoa((int) thepid, str, 128);
396 if (p && *p)
397 sl_strlcat(msg, p, 128);
398 if (thesignal == 0)
399 {
400 if (details == NULL) {
401 sl_strlcat(msg, _("]: out of memory"), 128);
402 } else {
403 sl_strlcat(msg, _("]: "), 128);
404 sl_strlcat(msg, details, 128);
405 }
406 }
407 else
408 {
409 sl_strlcat(msg, _("]: exit on signal "), 128);
410 p = safe_itoa(thesignal, str, 128);
411 if (p && *p)
412 sl_strlcat(msg, p, 128);
413 }
414
415 if (method == 1) {
416#ifndef STDERR_FILENO
417#define STDERR_FILENO 2
418#endif
419 int retval = 0;
420 do {
421 retval = write(STDERR_FILENO, msg, strlen(msg));
422 } while (retval < 0 && errno == EINTR);
423 do {
424 retval = write(STDERR_FILENO, "\n", 1);
425 } while (retval < 0 && errno == EINTR);
426 return 0;
427 }
428
429 sl_strlcpy (l0, _("/usr/bin/logger"), 64);
430 sl_strlcpy (l1, _("/usr/sbin/logger"), 64);
431 sl_strlcpy (l2, _("/usr/ucb/logger"), 64);
432 sl_strlcpy (l3, _("/bin/logger"), 64);
433
434 sl_strlcpy (a0, _("logger"), 32);
435 sl_strlcpy (e0,
436 _("PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/ucb:/usr/local/bin"),
437 128);
438
439 while (locations[i] != NULL) {
440 status = stat(locations[i], &buf);
441 if (status == 0)
442 break;
443 ++i;
444 }
445
446 if (locations[i] != NULL) {
447 argp[1] = msg;
448 newpid = fork();
449 if (newpid == 0) {
450 execve(locations[i], argp, envp);
451 _exit(1);
452 }
453 else if (newpid > 0) {
454 waitpid(newpid, &status, WUNTRACED);
455 }
456 }
457 return 0;
458}
459
460void safe_fatal (const char * details,
461 const char * file, int line)
462{
463 char msg[128];
464 char str[128];
465 char * p;
466 int thesignal = 0;
467 int method = 0;
468
469 p = safe_itoa((int) line, str, 128);
470 sl_strlcpy(msg, _("FATAL: "), 128);
471 sl_strlcat(msg, file, 128);
472 sl_strlcat(msg, ": ", 128);
473 if (p && (*p)) {
474 sl_strlcat(msg, p , 128);
475 sl_strlcat(msg, ": ", 128);
476 }
477 sl_strlcat(msg, details, 128);
478 (void) safe_logger (thesignal, method, msg);
479
480 close_ipc ();
481 raise(SIGKILL);
482}
483
484extern char sh_sig_msg[64];
485
486volatile int immediate_exit_normal = 0;
487
488#if defined(SA_SIGACTION_WORKS)
489static
490void sh_unix_sigexit (int mysignal, siginfo_t * signal_info, void * signal_add)
491#else
492static
493void sh_unix_sigexit (int mysignal)
494#endif
495{
496
497#if defined(SA_SIGACTION_WORKS)
498 if (signal_info != NULL && signal_info->si_code == SI_USER &&
499 mysignal != SIGTERM && mysignal != SIGINT)
500 {
501 return;
502 }
503
504 /* avoid compiler warning (unused var)
505 */
506 (void) signal_add;
507#endif
508
509 /*
510 * Block re-entry
511 */
512 if (immediate_exit_normal > 0)
513 {
514 ++immediate_exit_normal;
515 if ((skey != NULL) && (immediate_exit_normal == 2))
516 memset (skey, '\0', sizeof(sh_key_t));
517 if (immediate_exit_normal == 2)
518 {
519 int val_return;
520
521 do {
522 val_return = chdir ("/");
523 } while (val_return < 0 && errno == EINTR);
524
525 close_ipc ();
526 safe_logger (mysignal, 0, NULL);
527 }
528 raise(SIGKILL);
529 }
530 else
531 {
532 immediate_exit_normal = 1;
533 }
534
535#ifdef SYS_SIGLIST_DECLARED
536 strncpy (sh_sig_msg, sys_siglist[mysignal], 40);
537#else
538 strncpy (sh_sig_msg, sh_unix_siglist(mysignal), 40);
539#endif
540 sh_sig_msg[63] = '\0';
541
542 ++sig_raised;
543 ++sig_urgent;
544 sig_termfast = 1;
545 return;
546}
547
548volatile int immediate_exit_fast = 0;
549
550#if defined(SA_SIGACTION_WORKS)
551static
552void sh_unix_sigexit_fast (int mysignal, siginfo_t * signal_info,
553 void * signal_add)
554#else
555static
556void sh_unix_sigexit_fast (int mysignal)
557#endif
558{
559#if defined(SL_DEBUG) && (defined(USE_SYSTEM_MALLOC) || !defined(USE_MALLOC_LOCK))
560 int retval;
561#endif
562
563#if defined(SA_SIGACTION_WORKS)
564 if (signal_info != NULL && signal_info->si_code == SI_USER)
565 {
566 return;
567 }
568#endif
569
570 /* avoid compiler warning (unused var)
571 */
572#if defined(SA_SIGACTION_WORKS)
573 (void) signal_add;
574#endif
575
576 /* Check whether the heap is ok; otherwise _exit
577 */
578#if !defined(SL_DEBUG) || (!defined(USE_SYSTEM_MALLOC) && defined(USE_MALLOC_LOCK))
579 ++immediate_exit_fast;
580 if (skey != NULL && immediate_exit_fast < 2)
581 memset (skey, '\0', sizeof(sh_key_t));
582 if (immediate_exit_fast < 2)
583 safe_logger (mysignal, 0, NULL);
584 raise(SIGKILL);
585#else
586
587 /* debug code
588 */
589 if (immediate_exit_fast == 1)
590 {
591 ++immediate_exit_fast;
592 if (skey != NULL)
593 memset (skey, '\0', sizeof(sh_key_t));
594 close_ipc ();
595 safe_logger (mysignal, 0, NULL);
596 do {
597 retval = chdir ("/");
598 } while (retval < 0 && errno == EINTR);
599 raise(SIGFPE);
600 }
601 else if (immediate_exit_fast == 2)
602 {
603 do {
604 retval = chdir ("/");
605 } while (retval < 0 && errno == EINTR);
606 raise(SIGFPE);
607 }
608 else if (immediate_exit_fast != 0)
609 {
610 raise(SIGKILL);
611 }
612
613 ++immediate_exit_fast;
614
615 /* The FPE|BUS|SEGV|ILL signals leave the system in an undefined
616 * state, thus it is best to exit immediately.
617 */
618#ifdef SYS_SIGLIST_DECLARED
619 strncpy (sh_sig_msg, sys_siglist[mysignal], 40);
620#else
621 strncpy (sh_sig_msg, sh_unix_siglist(mysignal), 40);
622#endif
623 sh_sig_msg[63] = '\0';
624
625 sl_stack_print();
626
627 /* Try to push out an error message.
628 */
629 sh_error_handle ((-1), FIL__, __LINE__, mysignal, MSG_EXIT_NORMAL,
630 sh.prg_name, sh_sig_msg);
631
632 if (skey != NULL)
633 memset (skey, '\0', sizeof(sh_key_t));
634 close_ipc ();
635
636 do {
637 retval = chdir ("/");
638 } while (retval < 0 && errno == EINTR);
639
640 raise(SIGFPE);
641#endif
642}
643
644
645static
646void sh_unix_sigaction (int mysignal)
647{
648 ++sig_raised;
649#ifdef SIGUSR1
650 if (mysignal == SIGUSR1)
651 sig_debug_switch = 1;
652#endif
653#ifdef SIGUSR2
654 if (mysignal == SIGUSR2)
655 {
656 ++sig_suspend_switch;
657 ++sig_urgent;
658 }
659#endif
660#ifdef SIGHUP
661 if (mysignal == SIGHUP)
662 sig_config_read_again = 1;
663#endif
664#ifdef SIGTTOU
665 if (mysignal == SIGTTOU) {
666 sig_force_check = 1; sh_sem_trylock(); }
667#endif
668#ifdef SIGTTIN
669 if (mysignal == SIGTTIN)
670 sig_fresh_trail = 1;
671#endif
672#ifdef SIGABRT
673 if (mysignal == SIGABRT)
674 sig_fresh_trail = 1;
675#endif
676#ifdef SIGQUIT
677 if (mysignal == SIGQUIT)
678 sig_terminate = 1;
679#endif
680#ifdef SIGTERM
681 if (mysignal == SIGTERM)
682 {
683 strncpy (sh_sig_msg, _("Terminated"), 40);
684 sig_termfast = 1;
685 ++sig_urgent;
686 }
687#endif
688
689 return;
690}
691
692void sh_unix_ign_sigpipe()
693{
694 struct sigaction ignact;
695
696 ignact.sa_handler = SIG_IGN; /* signal action */
697 sigemptyset( &ignact.sa_mask ); /* set an empty mask */
698 ignact.sa_flags = 0; /* init sa_flags */
699
700#ifdef SIGPIPE
701 retry_sigaction(FIL__, __LINE__, SIGPIPE, &ignact, NULL);
702#endif
703
704 return;
705}
706static
707void sh_unix_siginstall (int goDaemon)
708{
709 struct sigaction act, act_fast, act2, oldact, ignact;
710#if defined (SH_WITH_SERVER)
711 (void) goDaemon;
712#endif
713
714 SL_ENTER(_("sh_unix_siginstall"));
715
716 ignact.sa_handler = SIG_IGN; /* signal action */
717 sigemptyset( &ignact.sa_mask ); /* set an empty mask */
718 ignact.sa_flags = 0; /* init sa_flags */
719
720#if defined(SA_SIGACTION_WORKS)
721 act.sa_sigaction = &sh_unix_sigexit; /* signal action */
722#else
723 act.sa_handler = &sh_unix_sigexit; /* signal action */
724#endif
725
726 sigfillset ( &act.sa_mask ); /* set a full mask */
727
728
729 /* Block all but deadly signals.
730 */
731#ifdef SIGILL
732 sigdelset ( &act.sa_mask, SIGILL );
733#endif
734#ifndef SL_DEBUG
735#ifdef SIGFPE
736 sigdelset ( &act.sa_mask, SIGFPE );
737#endif
738#endif
739#ifdef SIGSEGV
740 sigdelset ( &act.sa_mask, SIGSEGV );
741#endif
742#ifdef SIGBUS
743 sigdelset ( &act.sa_mask, SIGBUS );
744#endif
745
746#if defined(SA_SIGACTION_WORKS)
747 act_fast.sa_sigaction = &sh_unix_sigexit_fast; /* signal action */
748#else
749 act_fast.sa_handler = &sh_unix_sigexit_fast; /* signal action */
750#endif
751
752 sigfillset ( &act_fast.sa_mask ); /* set a full mask */
753
754#ifdef SIGILL
755 sigdelset ( &act_fast.sa_mask, SIGILL );
756#endif
757#ifndef SL_DEBUG
758#ifdef SIGFPE
759 sigdelset ( &act_fast.sa_mask, SIGFPE );
760#endif
761#endif
762#ifdef SIGSEGV
763 sigdelset ( &act_fast.sa_mask, SIGSEGV );
764#endif
765#ifdef SIGBUS
766 sigdelset ( &act_fast.sa_mask, SIGBUS );
767#endif
768
769
770 /* Use siginfo to verify origin of signal, if possible.
771 */
772#if defined(SA_SIGACTION_WORKS)
773 act.sa_flags = SA_SIGINFO;
774 act_fast.sa_flags = SA_SIGINFO;
775#else
776 act.sa_flags = 0;
777 act_fast.sa_flags = 0;
778#endif
779
780 /* Do not block the signal from being received in its handler ...
781 * (is this a good or a bad idea ??).
782 */
783#if defined(SA_NOMASK)
784 act_fast.sa_flags |= SA_NOMASK;
785#elif defined(SA_NODEFER)
786 act_fast.sa_flags |= SA_NODEFER;
787#endif
788
789
790 act2.sa_handler = &sh_unix_sigaction; /* signal action */
791 sigemptyset( &act2.sa_mask ); /* set an empty mask */
792 act2.sa_flags = 0; /* init sa_flags */
793
794 /* signals to control the daemon */
795
796#ifdef SIGHUP
797 retry_sigaction(FIL__, __LINE__, SIGHUP, &act2, &oldact);
798#endif
799#ifdef SIGABRT
800 retry_sigaction(FIL__, __LINE__, SIGABRT, &act2, &oldact);
801#endif
802#ifdef SIGUSR1
803 retry_sigaction(FIL__, __LINE__, SIGUSR1, &act2, &oldact);
804#endif
805#ifdef SIGUSR2
806 retry_sigaction(FIL__, __LINE__, SIGUSR2, &act2, &oldact);
807#endif
808#ifdef SIGQUIT
809 retry_sigaction(FIL__, __LINE__, SIGQUIT, &act2, &oldact);
810#endif
811#ifdef SIGTERM
812 retry_sigaction(FIL__, __LINE__, SIGTERM, &act, &oldact);
813#endif
814
815 /* fatal signals that may cause termination */
816
817#ifdef SIGILL
818 retry_sigaction(FIL__, __LINE__, SIGILL, &act_fast, &oldact);
819#endif
820#ifndef SL_DEBUG
821#ifdef SIGFPE
822 retry_sigaction(FIL__, __LINE__, SIGFPE, &act_fast, &oldact);
823#endif
824#endif
825#ifdef SIGSEGV
826 retry_sigaction(FIL__, __LINE__, SIGSEGV, &act_fast, &oldact);
827#endif
828#ifdef SIGBUS
829 retry_sigaction(FIL__, __LINE__, SIGBUS, &act_fast, &oldact);
830#endif
831
832 /* other signals */
833
834#ifdef SIGINT
835 retry_sigaction(FIL__, __LINE__, SIGINT, &act, &oldact);
836#endif
837#ifdef SIGPIPE
838 retry_sigaction(FIL__, __LINE__, SIGPIPE, &ignact, &oldact);
839#endif
840#ifdef SIGALRM
841 retry_sigaction(FIL__, __LINE__, SIGALRM, &ignact, &oldact);
842#endif
843#ifdef SIGTSTP
844 retry_sigaction(FIL__, __LINE__, SIGTSTP, &ignact, &oldact);
845#endif
846
847#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
848#ifdef SIGTTOU
849 if (goDaemon == 1)
850 retry_sigaction(FIL__, __LINE__, SIGTTOU, &act2, &oldact);
851 else
852 retry_sigaction(FIL__, __LINE__, SIGTTOU, &ignact, &oldact);
853#endif
854#ifdef SIGTTIN
855 if (goDaemon == 1)
856 retry_sigaction(FIL__, __LINE__, SIGTTIN, &act2, &oldact);
857 else
858 retry_sigaction(FIL__, __LINE__, SIGTTIN, &ignact, &oldact);
859#endif
860#else
861#ifdef SIGTTOU
862 retry_sigaction(FIL__, __LINE__, SIGTTOU, &ignact, &oldact);
863#endif
864#ifdef SIGTTIN
865 retry_sigaction(FIL__, __LINE__, SIGTTIN, &ignact, &oldact);
866#endif
867#endif
868
869#ifdef SIGTRAP
870#if !defined(SCREW_IT_UP)
871 retry_sigaction(FIL__, __LINE__, SIGTRAP, &act, &oldact);
872#endif
873#endif
874
875#ifdef SIGPOLL
876 retry_sigaction(FIL__, __LINE__, SIGPOLL, &ignact, &oldact);
877#endif
878#if defined(SIGPROF) && !defined(SH_PROFILE)
879 retry_sigaction(FIL__, __LINE__, SIGPROF, &ignact, &oldact);
880#endif
881#ifdef SIGSYS
882 retry_sigaction(FIL__, __LINE__, SIGSYS, &act, &oldact);
883#endif
884#ifdef SIGURG
885 retry_sigaction(FIL__, __LINE__, SIGURG, &ignact, &oldact);
886#endif
887#if defined(SIGVTALRM) && !defined(SH_PROFILE)
888 retry_sigaction(FIL__, __LINE__, SIGVTALRM, &ignact, &oldact);
889#endif
890#ifdef SIGXCPU
891 retry_sigaction(FIL__, __LINE__, SIGXCPU, &act, &oldact);
892#endif
893#ifdef SIGXFSZ
894 retry_sigaction(FIL__, __LINE__, SIGXFSZ, &act, &oldact);
895#endif
896
897#ifdef SIGEMT
898 retry_sigaction(FIL__, __LINE__, SIGEMT, &ignact, &oldact);
899#endif
900#ifdef SIGSTKFLT
901 retry_sigaction(FIL__, __LINE__, SIGSTKFLT, &act, &oldact);
902#endif
903#ifdef SIGIO
904 retry_sigaction(FIL__, __LINE__, SIGIO, &ignact, &oldact);
905#endif
906#ifdef SIGPWR
907 retry_sigaction(FIL__, __LINE__, SIGPWR, &act, &oldact);
908#endif
909
910#ifdef SIGLOST
911 retry_sigaction(FIL__, __LINE__, SIGLOST, &ignact, &oldact);
912#endif
913#ifdef SIGUNUSED
914 retry_sigaction(FIL__, __LINE__, SIGUNUSED, &ignact, &oldact);
915#endif
916
917 SL_RET0(_("sh_unix_siginstall"));
918}
919
920/* ---------------------------------------------------------------- */
921
922/* checksum the own binary
923 */
924int sh_unix_self_hash (const char * c)
925{
926 char message[512];
927 char hashbuf[KEYBUF_SIZE];
928
929 SL_ENTER(_("sh_unix_self_hash"));
930
931 if (c == NULL)
932 {
933 sh.exec.path[0] = '\0';
934 SL_RETURN((0), _("sh_unix_self_hash"));
935 }
936 sl_strlcpy(sh.exec.path, c, SH_PATHBUF);
937
938 sl_strlcpy(sh.exec.hash,
939 sh_tiger_hash (c, TIGER_FILE, TIGER_NOLIM, hashbuf, sizeof(hashbuf)),
940 KEY_LEN+1);
941 sl_snprintf(message, 512, _("%s has checksum: %s"),
942 sh.exec.path, sh.exec.hash);
943 message[511] = '\0';
944 sh_error_handle(SH_ERR_INFO, FIL__, __LINE__, 0, MSG_E_SUBGEN,
945 message, _("sh_unix_self_hash"));
946 if (0 == sl_strcmp(sh.exec.hash, SH_KEY_NULL ))
947 {
948 dlog(1, FIL__, __LINE__,
949 _("Could not checksum my own executable because of the\nfollowing error: %s: %s\n\nPossible reasons include:\n Wrong path in configure file option SamhainPath=/path/to/executable\n No read permission for the effective UID: %d\n"),
950 sh.exec.path, sl_get_errmsg(), (int) sl_ret_euid());
951 sh_error_handle ((-1), FIL__, __LINE__, EACCES, MSG_NOACCESS,
952 (long) sh.real.uid, c);
953 aud_exit (FIL__, __LINE__, EXIT_FAILURE);
954 }
955 SL_RETURN((0), _("sh_unix_self_hash"));
956}
957
958int sh_unix_self_check ()
959{
960 char newhash[KEY_LEN+1];
961 char message[512];
962 char hashbuf[KEYBUF_SIZE];
963
964 SL_ENTER(_("sh_unix_self_check"));
965 if (sh.exec.path[0] == '\0')
966 SL_RETURN((0), _("sh_unix_self_check"));
967
968 sl_strlcpy(newhash,
969 sh_tiger_hash (sh.exec.path, TIGER_FILE, TIGER_NOLIM, hashbuf, sizeof(hashbuf)),
970 KEY_LEN+1);
971 if (0 == sl_strncmp(sh.exec.hash,
972 newhash,
973 KEY_LEN))
974 SL_RETURN((0), _("sh_unix_self_check"));
975
976
977 dlog(1, FIL__, __LINE__,
978 _("The checksum of the executable: %s has changed since startup (%s -> %s).\n"),
979 sh.exec.path, sh.exec.hash, newhash);
980
981 sl_snprintf(message, 512,
982 _("The checksum of %s has changed since startup (%s -> %s)"),
983 sh.exec.path, sh.exec.hash, newhash);
984 message[511] = '\0';
985
986 sh_error_handle(SH_ERR_INFO, FIL__, __LINE__, 0, MSG_E_SUBGEN,
987 message, _("sh_unix_self_check"));
988 sh_error_handle ((-1), FIL__, __LINE__, EACCES, MSG_E_AUTH,
989 sh.exec.path);
990 SL_RETURN((-1), _("sh_unix_self_check"));
991}
992
993
994/* ---------------------------------------------------------------- */
995
996long sh_group_to_gid (const char * g, int * fail)
997{
998 struct group * w;
999 gid_t gid = 0;
1000 int status = 0;
1001
1002#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
1003 struct group grp;
1004 char * buffer;
1005 static size_t gbufsize = SH_GRBUF_SIZE;
1006#endif
1007
1008 *fail = -1;
1009
1010 if (g)
1011 {
1012 size_t i;
1013 size_t len = strlen(g);
1014
1015 *fail = 0;
1016
1017 for (i = 0; i < len; ++i)
1018 {
1019 char c = g[i];
1020
1021 if (!isdigit((int) c))
1022 goto is_a_name;
1023 }
1024 return atol(g);
1025
1026 is_a_name:
1027
1028#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
1029
1030 buffer = SH_ALLOC(gbufsize);
1031 status = sh_getgrnam_r(g, &grp, buffer, gbufsize, &w);
1032
1033 if ((status == ERANGE) && (w == NULL))
1034 {
1035 if (S_TRUE == sl_ok_adds( gbufsize, SH_GRBUF_SIZE ))
1036 {
1037 SH_FREE(buffer);
1038 gbufsize += SH_GRBUF_SIZE;
1039 goto is_a_name;
1040 }
1041 }
1042
1043#else
1044
1045 errno = 0;
1046 w = sh_getgrnam(g);
1047 status = errno;
1048
1049#endif
1050
1051 if ((status == ERANGE) && (w == NULL))
1052 {
1053 static int seen = 0;
1054
1055 if (seen == 0)
1056 {
1057 char errbuf[SH_ERRBUF_SIZE];
1058
1059 sh_error_handle (SH_ERR_ERR, FIL__, __LINE__, EINVAL, MSG_E_GRNULL,
1060 sh_error_message(status, errbuf, sizeof(errbuf)),
1061 _("sh_group_to_gid"), (long) -1, _("line too long in group entry"));
1062 ++seen;
1063 }
1064 *fail = -1;
1065 }
1066 else if (w == NULL)
1067 {
1068 char * tmp = sh_util_strdup(g);
1069 sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS,
1070 _("sh_group_to_gid"), tmp);
1071 SH_FREE(tmp);
1072 *fail = -1;
1073 }
1074 else
1075 {
1076 gid = w->gr_gid;
1077 }
1078#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
1079 SH_FREE(buffer);
1080#endif
1081 }
1082
1083 return gid;
1084}
1085
1086/* ---------------------------------------------------------------- */
1087
1088
1089/* added Tue Feb 22 10:36:44 NFT 2000 Rainer Wichmann */
1090static int tf_add_trusted_user_int(const char * c)
1091{
1092 struct passwd * w;
1093 int count;
1094 uid_t pwid = (uid_t)-1;
1095
1096#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
1097 struct passwd pwd;
1098 char * buffer;
1099#endif
1100
1101 SL_ENTER(_("tf_add_trusted_user_int"));
1102
1103 /* First check for a user name.
1104 */
1105#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
1106 buffer = SH_ALLOC(SH_PWBUF_SIZE);
1107 sh_getpwnam_r(c, &pwd, buffer, SH_PWBUF_SIZE, &w);
1108#else
1109 w = sh_getpwnam(c);
1110#endif
1111
1112 if ((w != NULL) && ((pwid = w->pw_uid) > 0))
1113 goto succe;
1114
1115 /* Failed, so check for a numerical value.
1116 */
1117 pwid = strtol(c, (char **)NULL, 10);
1118 if (pwid > 0 && pwid < 65535)
1119 goto succe;
1120
1121 sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS,
1122 _("add trusted user"), c);
1123#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
1124 SH_FREE(buffer);
1125#endif
1126 SL_RETURN((-1), _("tf_add_trusted_user_int"));
1127
1128 succe:
1129 count = sl_trust_add_user(pwid);
1130#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
1131 SH_FREE(buffer);
1132#endif
1133 SL_RETURN((count), _("tf_add_trusted_user_int"));
1134}
1135
1136int tf_add_trusted_user(const char * c)
1137{
1138 int i;
1139 char * q;
1140 char * p = sh_util_strdup (c);
1141#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
1142 char * saveptr;
1143#endif
1144
1145 SL_ENTER(_("tf_add_trusted_user"));
1146
1147#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
1148 q = strtok_r(p, ", \t", &saveptr);
1149#else
1150 q = strtok(p, ", \t");
1151#endif
1152 if (!q)
1153 {
1154 SH_FREE(p);
1155 SL_RETURN((-1), _("tf_add_trusted_user"));
1156 }
1157 while (q)
1158 {
1159 i = tf_add_trusted_user_int(q);
1160 if (SL_ISERROR(i))
1161 {
1162 SH_FREE(p);
1163 SL_RETURN((i), _("tf_add_trusted_user"));
1164 }
1165#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
1166 q = strtok_r(NULL, ", \t", &saveptr);
1167#else
1168 q = strtok(NULL, ", \t");
1169#endif
1170 }
1171 SH_FREE(p);
1172 SL_RETURN((0), _("tf_add_trusted_user"));
1173}
1174
1175extern uid_t sl_trust_baduid(void);
1176extern gid_t sl_trust_badgid(void);
1177
1178#if defined(HOST_IS_CYGWIN) || defined(__cygwin__) || defined(__CYGWIN32__) || defined(__CYGWIN__)
1179int tf_trust_check (const char * file, int mode)
1180{
1181 (void) file;
1182 (void) mode;
1183 return 0;
1184}
1185#else
1186int tf_trust_check (const char * file, int mode)
1187{
1188 char * tmp;
1189 char * tmp2;
1190 char * p;
1191 int status;
1192 int level;
1193 uid_t ff_euid = (uid_t) -1;
1194
1195 SL_ENTER(_("tf_trust_check"));
1196
1197 if (mode == SL_YESPRIV)
1198 sl_get_euid(&ff_euid);
1199 else
1200 sl_get_ruid(&ff_euid);
1201
1202#if defined(SH_WITH_SERVER)
1203 if (0 == sl_ret_euid()) /* privileges not dropped yet */
1204 {
1205#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
1206 struct passwd pwd;
1207 char * buffer = SH_ALLOC(SH_PWBUF_SIZE);
1208 struct passwd * tempres;
1209 sh_getpwnam_r(DEFAULT_IDENT, &pwd, buffer, SH_PWBUF_SIZE, &tempres);
1210#else
1211 struct passwd * tempres = sh_getpwnam(DEFAULT_IDENT);
1212#endif
1213
1214 if (!tempres)
1215 {
1216 dlog(1, FIL__, __LINE__,
1217 _("User %s does not exist. Please add the user to your system.\n"),
1218 DEFAULT_IDENT);
1219 aud_exit (FIL__, __LINE__, EXIT_FAILURE);
1220 }
1221 else
1222 {
1223 ff_euid = tempres->pw_uid;
1224 }
1225#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
1226 SH_FREE(buffer);
1227#endif
1228 }
1229#endif
1230
1231 status = sl_trustfile_euid(file, ff_euid);
1232
1233 if ( SL_ENONE != status)
1234 {
1235 if (status == SL_ESTAT)
1236 level = SH_ERR_ALL;
1237 else
1238 level = SH_ERR_ERR;
1239
1240 tmp = sh_util_safe_name (file);
1241 p = sl_trust_errfile();
1242 if (p && *p != '\0')
1243 {
1244 tmp2 = sh_util_safe_name (sl_trust_errfile());
1245 sh_error_handle(level, FIL__, __LINE__, status, MSG_E_TRUST2,
1246 sl_error_string(status), tmp, tmp2);
1247 SH_FREE(tmp2);
1248 }
1249 else
1250 {
1251 sh_error_handle(level, FIL__, __LINE__, status, MSG_E_TRUST1,
1252 sl_error_string(status), tmp);
1253 }
1254 SH_FREE(tmp);
1255
1256 if (status == SL_EBADUID || status == SL_EBADGID ||
1257 status == SL_EBADOTH || status == SL_ETRUNC ||
1258 status == SL_EINTERNAL )
1259 {
1260 switch (status) {
1261 case SL_EINTERNAL:
1262 dlog(1, FIL__, __LINE__,
1263 _("An internal error occured in the trustfile function.\n"));
1264 break;
1265 case SL_ETRUNC:
1266 tmp = sh_util_safe_name (file);
1267 dlog(1, FIL__, __LINE__,
1268 _("A filename truncation occured in the trustfile function.\nProbably the normalized filename for %s\nis too long. This may be due e.g. to deep or circular softlinks.\n"),
1269 tmp);
1270 SH_FREE(tmp);
1271 break;
1272 case SL_EBADOTH:
1273 tmp = sh_util_safe_name (file);
1274 p = sl_trust_errfile();
1275 dlog(1, FIL__, __LINE__,
1276 _("The path element: %s\nin the filename: %s is world writeable.\n"),
1277 p, tmp);
1278 SH_FREE(tmp);
1279 break;
1280 case SL_EBADUID:
1281 tmp = sh_util_safe_name (file);
1282 p = sl_trust_errfile();
1283 dlog(1, FIL__, __LINE__,
1284 _("The owner (UID = %ld) of the path element: %s\nin the filename: %s\nis not in the list of trusted users.\nTo fix the problem, you can:\n - run ./configure again with the option --with-trusted=0,...,UID\n where UID is the UID of the untrusted user, or\n - use the option TrustedUser=UID in the configuration file.\n"),
1285 (UID_CAST)sl_trust_baduid(), p, tmp);
1286 SH_FREE(tmp);
1287 break;
1288 case SL_EBADGID:
1289 tmp = sh_util_safe_name (file);
1290 p = sl_trust_errfile();
1291 dlog(1, FIL__, __LINE__,
1292 _("The path element: %s\nin the filename: %s\nis group writeable (GID = %ld), and at least one of the group\nmembers (UID = %ld) is not in the list of trusted users.\nTo fix the problem, you can:\n - run ./configure again with the option --with-trusted=0,...,UID\n where UID is the UID of the untrusted user, or\n - use the option TrustedUser=UID in the configuration file.\n"),
1293 p, tmp, (UID_CAST)sl_trust_badgid(),
1294 (UID_CAST)sl_trust_baduid());
1295 SH_FREE(tmp);
1296 break;
1297 default:
1298 break;
1299 }
1300
1301 SL_RETURN((-1), _("tf_trust_check"));
1302 }
1303 }
1304
1305 SL_RETURN((0), _("tf_trust_check"));
1306}
1307#endif
1308
1309#ifdef HAVE_INITGROUPS
1310#ifdef HOST_IS_OSF
1311int sh_unix_initgroups ( char * in_user, gid_t in_gid)
1312#else
1313int sh_unix_initgroups (const char * in_user, gid_t in_gid)
1314#endif
1315{
1316 int status = -1;
1317 status = sh_initgroups (in_user, in_gid);
1318 if (status < 0)
1319 {
1320 if (errno == EPERM)
1321 return 0;
1322 if (errno == EINVAL)
1323 return 0;
1324 return -1;
1325 }
1326 return 0;
1327}
1328#else
1329int sh_unix_initgroups (const char * in_user, gid_t in_gid)
1330{
1331 (void) in_user;
1332 (void) in_gid;
1333 return 0;
1334}
1335#endif
1336
1337#ifdef HAVE_INITGROUPS
1338char * sh_unix_getUIDname (int level, uid_t uid, char * out, size_t len);
1339int sh_unix_initgroups2 (uid_t in_pid, gid_t in_gid)
1340{
1341 int status = -1;
1342 char user[SH_MINIBUF];
1343
1344 SL_ENTER(_("sh_unix_initgroups2"));
1345
1346 if (NULL == sh_unix_getUIDname (SH_ERR_ERR, in_pid, user, sizeof(user)))
1347 SL_RETURN((-1), _("sh_unix_initgroups2"));
1348 status = sh_initgroups (user, in_gid);
1349 if (status < 0)
1350 {
1351 if (errno == EPERM)
1352 status = 0;
1353 if (errno == EINVAL)
1354 status = 0;
1355 }
1356 SL_RETURN((status), _("sh_unix_initgroups2"));
1357}
1358#else
1359int sh_unix_initgroups2 (uid_t in_pid, gid_t in_gid)
1360{
1361 (void) in_pid;
1362 (void) in_gid;
1363 return 0;
1364}
1365#endif
1366
1367void sh_unix_closeall (int fd, int except, int inchild)
1368{
1369 int fdx = fd;
1370#ifdef _SC_OPEN_MAX
1371 int fdlimit = sysconf (_SC_OPEN_MAX);
1372#else
1373#ifdef OPEN_MAX
1374 int fdlimit = OPEN_MAX;
1375#else
1376 int fdlimit = _POSIX_OPEN_MAX;
1377#endif
1378#endif
1379
1380 SL_ENTER(_("sh_unix_closeall"));
1381
1382 /* can't happen - so fix it :-(
1383 */
1384 if (fdlimit < 0)
1385 fdlimit = 20; /* POSIX lower limit */
1386
1387 if (fdlimit > 65536)
1388 fdlimit = 65536;
1389
1390 if (!inchild)
1391 sl_dropall (fdx, except);
1392 else
1393 sl_dropall_dirty (fdx, except);
1394
1395 /* Close everything from fd (inclusive) up to fdlimit (exclusive).
1396 */
1397 while (fd < fdlimit)
1398 {
1399 if (fd == except)
1400 fd++;
1401 else if (slib_do_trace != 0 && fd == slib_trace_fd)
1402 fd++;
1403 else
1404 sl_close_fd(FIL__, __LINE__, fd++);
1405 }
1406
1407 SL_RET0(_("sh_unix_closeall"));
1408}
1409
1410static void sh_unix_setlimits(void)
1411{
1412 struct rlimit limits;
1413
1414 SL_ENTER(_("sh_unix_setlimits"));
1415
1416 limits.rlim_cur = RLIM_INFINITY;
1417 limits.rlim_max = RLIM_INFINITY;
1418
1419#ifdef RLIMIT_CPU
1420 setrlimit (RLIMIT_CPU, &limits);
1421#endif
1422#ifdef RLIMIT_FSIZE
1423 setrlimit (RLIMIT_FSIZE, &limits);
1424#endif
1425#ifdef RLIMIT_DATA
1426 setrlimit (RLIMIT_DATA, &limits);
1427#endif
1428#ifdef RLIMIT_STACK
1429 setrlimit (RLIMIT_STACK, &limits);
1430#endif
1431#ifdef RLIMIT_RSS
1432 setrlimit (RLIMIT_RSS, &limits);
1433#endif
1434#ifdef RLIMIT_NPROC
1435 setrlimit (RLIMIT_NPROC, &limits);
1436#endif
1437#ifdef RLIMIT_MEMLOCK
1438 setrlimit (RLIMIT_MEMLOCK, &limits);
1439#endif
1440
1441#if !defined(SL_DEBUG)
1442 /* no core dumps
1443 */
1444 limits.rlim_cur = 0;
1445 limits.rlim_max = 0;
1446#ifdef RLIMIT_CORE
1447 setrlimit (RLIMIT_CORE, &limits);
1448#endif
1449#else
1450#ifdef RLIMIT_CORE
1451 setrlimit (RLIMIT_CORE, &limits);
1452#endif
1453#endif
1454
1455 limits.rlim_cur = 1024;
1456 limits.rlim_max = 1024;
1457
1458#if defined(RLIMIT_NOFILE)
1459 setrlimit (RLIMIT_NOFILE, &limits);
1460#elif defined(RLIMIT_OFILE)
1461 setrlimit (RLIMIT_OFILE, &limits);
1462#endif
1463
1464 SL_RET0(_("sh_unix_setlimits"));
1465}
1466
1467static void sh_unix_copyenv(void)
1468{
1469 char ** env0 = environ;
1470 char ** env1;
1471 int envlen = 0;
1472 size_t len;
1473
1474 SL_ENTER(_("sh_unix_copyenv"));
1475
1476 while (env0 != NULL && env0[envlen] != NULL) {
1477 /* printf("%2d: %s\n", envlen, env0[envlen]); */
1478 ++envlen;
1479 }
1480 ++envlen;
1481
1482 /* printf("-> %2d: slots allocated\n", envlen); */
1483 env1 = calloc(1,sizeof(char *) * envlen); /* only once */
1484 if (env1 == NULL)
1485 {
1486 fprintf(stderr, _("%s: %d: Out of memory\n"), FIL__, __LINE__);
1487 SL_RET0(_("sh_unix_copyenv"));
1488 }
1489 env0 = environ;
1490 envlen = 0;
1491
1492 while (env0 != NULL && env0[envlen] != NULL) {
1493 len = strlen(env0[envlen]) + 1;
1494 env1[envlen] = calloc(1,len); /* only once */
1495 if (env1[envlen] == NULL)
1496 {
1497 int i;
1498 fprintf(stderr, _("%s: %d: Out of memory\n"), FIL__, __LINE__);
1499 for (i = 0; i < envlen; ++i) free(env1[len]);
1500 free(env1);
1501 SL_RET0(_("sh_unix_copyenv"));
1502 }
1503 sl_strlcpy(env1[envlen], env0[envlen], len);
1504 ++envlen;
1505 }
1506 env1[envlen] = NULL;
1507
1508 environ = env1;
1509 SL_RET0(_("sh_unix_copyenv"));
1510}
1511
1512/* delete all environment variables
1513 */
1514static void sh_unix_zeroenv(void)
1515{
1516 char * c;
1517 char ** env;
1518
1519 SL_ENTER(_("sh_unix_zeroenv"));
1520
1521 sh_unix_copyenv();
1522 env = environ;
1523
1524 while (env != NULL && *env != NULL) {
1525 c = strchr ((*env), '=');
1526#ifdef WITH_MYSQL
1527 /*
1528 * Skip the MYSQL_UNIX_PORT environment variable; MySQL may need it.
1529 */
1530 if (0 == sl_strncmp((*env), _("MYSQL_UNIX_PORT="), 16))
1531 {
1532 ++(env);
1533 continue;
1534 }
1535 if (0 == sl_strncmp((*env), _("MYSQL_TCP_PORT="), 15))
1536 {
1537 ++(env);
1538 continue;
1539 }
1540 if (0 == sl_strncmp((*env), _("MYSQL_HOME="), 11))
1541 {
1542 ++(env);
1543 continue;
1544 }
1545#endif
1546#ifdef WITH_ORACLE
1547 /*
1548 * Skip the ORACLE_HOME and TNS_ADMIN environment variables;
1549 * Oracle may need them.
1550 */
1551 if (0 == sl_strncmp((*env), _("ORACLE_HOME="), 12))
1552 {
1553 ++(env);
1554 continue;
1555 }
1556 if (0 == sl_strncmp((*env), _("TNS_ADMIN="), 10))
1557 {
1558 ++(env);
1559 continue;
1560 }
1561#endif
1562 /*
1563 * Skip the TZ environment variable.
1564 */
1565 if (0 == sl_strncmp((*env), _("TZ="), 3))
1566 {
1567 ++(env);
1568 continue;
1569 }
1570 ++(env);
1571 if (c != NULL)
1572 {
1573 ++c;
1574 while ((*c) != '\0') {
1575 (*c) = '\0';
1576 ++c;
1577 }
1578 }
1579 }
1580
1581#ifdef HAVE_TZSET
1582 tzset();
1583#endif
1584
1585 SL_RET0(_("sh_unix_zeroenv"));
1586}
1587
1588
1589static void sh_unix_resettimer(void)
1590{
1591 struct itimerval this_timer;
1592
1593 SL_ENTER(_("sh_unix_resettimer"));
1594
1595 this_timer.it_value.tv_sec = 0;
1596 this_timer.it_value.tv_usec = 0;
1597
1598 this_timer.it_interval.tv_sec = 0;
1599 this_timer.it_interval.tv_usec = 0;
1600
1601 setitimer(ITIMER_REAL, &this_timer, NULL);
1602#if !defined(SH_PROFILE)
1603 setitimer(ITIMER_VIRTUAL, &this_timer, NULL);
1604 setitimer(ITIMER_PROF, &this_timer, NULL);
1605#endif
1606
1607 SL_RET0(_("sh_unix_resettimer"));
1608}
1609
1610static void sh_unix_resetsignals(void)
1611{
1612 int sig_num;
1613#ifdef NSIG
1614 int max_sig = NSIG;
1615#else
1616 int max_sig = 255;
1617#endif
1618 int test;
1619 int status;
1620 struct sigaction act;
1621#if !defined(SH_PROFILE)
1622 struct sigaction oldact;
1623#endif
1624
1625 sigset_t set_proc;
1626
1627 SL_ENTER(_("sh_unix_resetsignals"));
1628 /*
1629 * Reset the current signal mask (inherited from parent process).
1630 */
1631
1632 sigfillset(&set_proc);
1633
1634 do {
1635 errno = 0;
1636 test = SH_SETSIGMASK(SIG_UNBLOCK, &set_proc, NULL);
1637 } while (test < 0 && errno == EINTR);
1638
1639 /*
1640 * Reset signal handling.
1641 */
1642
1643 act.sa_handler = SIG_DFL; /* signal action */
1644 sigemptyset( &act.sa_mask ); /* set an empty mask */
1645 act.sa_flags = 0; /* init sa_flags */
1646
1647 for (sig_num = 1; sig_num <= max_sig; ++sig_num)
1648 {
1649#if !defined(SH_PROFILE)
1650 test = retry_sigaction(FIL__, __LINE__, sig_num, &act, &oldact);
1651#else
1652 test = 0;
1653#endif
1654 if ((test == -1) && (errno != EINVAL))
1655 {
1656 char errbuf[SH_ERRBUF_SIZE];
1657 status = errno;
1658 sh_error_handle ((-1), FIL__, __LINE__, status, MSG_W_SIG,
1659 sh_error_message (status, errbuf, sizeof(errbuf)), sig_num);
1660 }
1661 }
1662
1663 SL_RET0(_("sh_unix_resetsignals"));
1664}
1665
1666/* Get the local hostname (FQDN)
1667 */
1668static char * sh_tolower (char * s)
1669{
1670 char * ret = s;
1671 if (s)
1672 {
1673 for (; *s; ++s)
1674 {
1675 *s = tolower((unsigned char) *s);
1676 }
1677 }
1678 return ret;
1679}
1680
1681
1682#include <sys/socket.h>
1683
1684/* Required for BSD
1685 */
1686#ifdef HAVE_NETINET_IN_H
1687#include <netinet/in.h>
1688#endif
1689
1690#include <arpa/inet.h>
1691
1692const char * sh_unix_h_name (struct hostent * host_entry)
1693{
1694 char ** p;
1695 if (strchr(host_entry->h_name, '.')) {
1696 return host_entry->h_name;
1697 } else {
1698 for (p = host_entry->h_aliases; *p; ++p) {
1699 if (strchr(*p, '.'))
1700 return *p;
1701 }
1702 }
1703 return host_entry->h_name;
1704}
1705
1706/* uname() on FreeBSD is broken, because the 'nodename' buf is too small
1707 * to hold a valid (leftmost) domain label.
1708 */
1709#if defined(HAVE_UNAME) && !defined(HOST_IS_FREEBSD)
1710#include <sys/utsname.h>
1711void sh_unix_localhost()
1712{
1713 struct utsname buf;
1714 int i;
1715 unsigned int ddot;
1716 int len;
1717 char * p;
1718 char hostname[256];
1719 char numeric[SH_IP_BUF];
1720 char * canonical;
1721
1722
1723 SL_ENTER(_("sh_unix_localhost"));
1724
1725 (void) uname (&buf);
1726 /* flawfinder: ignore */ /* ff bug, ff sees system() */
1727 sl_strlcpy (sh.host.system, buf.sysname, SH_MINIBUF);
1728 sl_strlcpy (sh.host.release, buf.release, SH_MINIBUF);
1729 sl_strlcpy (sh.host.machine, buf.machine, SH_MINIBUF);
1730
1731 /* Workaround for cases where nodename could be
1732 * a truncated FQDN.
1733 */
1734 if (strlen(buf.nodename) == (sizeof(buf.nodename)-1))
1735 {
1736 p = strchr(buf.nodename, '.');
1737 if (NULL != p) {
1738 *p = '\0';
1739 sl_strlcpy(hostname, buf.nodename, 256);
1740 } else {
1741#ifdef HAVE_GETHOSTNAME
1742 if (0 != gethostname(hostname, 256))
1743 {
1744 sh_error_handle(SH_ERR_WARN, FIL__, __LINE__, 0, MSG_E_SUBGEN,
1745 _("nodename returned by uname may be truncated"),
1746 _("sh_unix_localhost"));
1747 sl_strlcpy (hostname, buf.nodename, 256);
1748 }
1749 else
1750 {
1751 hostname[255] = '\0';
1752 }
1753#else
1754 sh_error_handle(SH_ERR_WARN, FIL__, __LINE__, 0, MSG_E_SUBGEN,
1755 _("nodename returned by uname may be truncated"),
1756 _("sh_unix_localhost"));
1757 sl_strlcpy(hostname, buf.nodename, 256);
1758#endif
1759 }
1760 }
1761 else
1762 {
1763 sl_strlcpy(hostname, buf.nodename, 256);
1764 }
1765
1766 canonical = sh_ipvx_canonical(hostname, numeric, sizeof(numeric));
1767
1768 if (canonical == NULL)
1769 {
1770 sl_strlcpy (sh.host.name, hostname, SH_PATHBUF);
1771 sh_tolower (sh.host.name);
1772 }
1773 else
1774 {
1775 sl_strlcpy (sh.host.name, canonical, SH_PATHBUF);
1776 SH_FREE(canonical);
1777 }
1778
1779 /* check whether it looks like a FQDN
1780 */
1781 len = sl_strlen(sh.host.name);
1782 ddot = 0;
1783 for (i = 0; i < len; ++i)
1784 if (sh.host.name[i] == '.') ++ddot;
1785
1786 if (ddot == 0)
1787 {
1788 dlog(1, FIL__, __LINE__,
1789 _("According to uname, your nodename is %s, but your resolver\nlibrary cannot resolve this nodename to a FQDN.\nRather, it resolves this to %s.\nFor more information, see the entry about self-resolving under\n'Most frequently' in the FAQ that you will find in the docs/ subdirectory.\n"),
1790 hostname, sh.host.name);
1791 sl_strlcpy (sh.host.name, numeric, SH_PATHBUF);
1792 SL_RET0(_("sh_unix_localhost"));
1793 }
1794
1795 if (sh_ipvx_is_numeric(sh.host.name))
1796 {
1797 dlog(1, FIL__, __LINE__,
1798 _("According to uname, your nodename is %s, but your resolver\nlibrary cannot resolve this nodename to a FQDN.\nRather, it resolves this to %s.\nFor more information, see the entry about self-resolving under\n'Most frequently' in the FAQ that you will find in the docs/ subdirectory.\n"),
1799 hostname, sh.host.name);
1800 }
1801
1802 SL_RET0(_("sh_unix_localhost"));
1803}
1804
1805#else
1806
1807/*
1808 * --FreeBSD code
1809 */
1810#if defined(HAVE_UNAME)
1811#include <sys/utsname.h>
1812#endif
1813void sh_unix_localhost()
1814{
1815#if defined(HAVE_UNAME)
1816 struct utsname buf;
1817#endif
1818 int i;
1819 int ddot;
1820 int len;
1821 char hostname[1024];
1822 char numeric[SH_IP_BUF];
1823 char * canonical;
1824
1825 SL_ENTER(_("sh_unix_localhost"));
1826
1827#if defined(HAVE_UNAME)
1828 (void) uname (&buf);
1829 /* flawfinder: ignore */ /* ff bug, ff sees system() */
1830 sl_strlcpy (sh.host.system, buf.sysname, SH_MINIBUF);
1831 sl_strlcpy (sh.host.release, buf.release, SH_MINIBUF);
1832 sl_strlcpy (sh.host.machine, buf.machine, SH_MINIBUF);
1833#endif
1834
1835 (void) gethostname (hostname, 1024);
1836 hostname[1023] = '\0';
1837
1838 canonical = sh_ipvx_canonical(hostname, numeric, sizeof(numeric));
1839
1840 if (canonical == NULL)
1841 {
1842 sl_strlcpy (sh.host.name, hostname, SH_PATHBUF);
1843 sh_tolower (sh.host.name);
1844 }
1845 else
1846 {
1847 sl_strlcpy (sh.host.name, canonical, SH_PATHBUF);
1848 SH_FREE(canonical);
1849 }
1850
1851 /* check whether it looks like a FQDN
1852 */
1853 len = sl_strlen(sh.host.name);
1854 ddot = 0;
1855 for (i = 0; i < len; ++i)
1856 if (sh.host.name[i] == '.') ++ddot;
1857 if (ddot == 0)
1858 {
1859 dlog(1, FIL__, __LINE__,
1860 _("According to uname, your nodename is %s, but your resolver\nlibrary cannot resolve this nodename to a FQDN.\nRather, it resolves this to %s.\nFor more information, see the entry about self-resolving under\n'Most frequently' in the FAQ that you will find in the docs/ subdirectory.\n"),
1861 hostname, sh.host.name);
1862 sl_strlcpy (sh.host.name, numeric, SH_PATHBUF);
1863 SL_RET0(_("sh_unix_localhost"));
1864 }
1865
1866 if (sh_ipvx_is_numeric(sh.host.name))
1867 {
1868 dlog(1, FIL__, __LINE__,
1869 _("According to uname, your nodename is %s, but your resolver\nlibrary cannot resolve this nodename to a FQDN.\nRather, it resolves this to %s.\nFor more information, see the entry about self-resolving under\n'Most frequently' in the FAQ that you will find in the docs/ subdirectory.\n"),
1870 hostname, sh.host.name);
1871 }
1872
1873 SL_RET0(_("sh_unix_localhost"));
1874}
1875#endif
1876
1877
1878void sh_unix_memlock()
1879{
1880 SL_ENTER(_("sh_unix_memlock"));
1881
1882 /* do this before dropping privileges
1883 */
1884#if defined(HAVE_MLOCK) && !defined(HAVE_BROKEN_MLOCK)
1885 if (skey->mlock_failed == S_FALSE)
1886 {
1887 if ( (-1) == sh_unix_mlock( FIL__, __LINE__,
1888 (char *) skey, sizeof (sh_key_t)) )
1889 {
1890 SH_MUTEX_LOCK_UNSAFE(mutex_skey);
1891 skey->mlock_failed = S_TRUE;
1892 SH_MUTEX_UNLOCK_UNSAFE(mutex_skey);
1893 }
1894 }
1895#else
1896 if (skey->mlock_failed == S_FALSE)
1897 {
1898 SH_MUTEX_LOCK_UNSAFE(mutex_skey);
1899 skey->mlock_failed = S_TRUE;
1900 SH_MUTEX_UNLOCK_UNSAFE(mutex_skey);
1901 }
1902#endif
1903
1904 SL_RET0(_("sh_unix_memlock"));
1905}
1906
1907#ifdef SH_WITH_SERVER
1908char * chroot_dir = NULL;
1909
1910int sh_unix_set_chroot(const char * str)
1911{
1912 size_t len;
1913 static int block = 0;
1914
1915 if (block == 1)
1916 return 0;
1917
1918 if (str && *str == '/')
1919 {
1920 len = strlen(str) + 1;
1921 chroot_dir = calloc(1,strlen(str) + 1); /* only once */
1922 if (!chroot_dir)
1923 {
1924 fprintf(stderr, _("%s: %d: Out of memory\n"), FIL__, __LINE__);
1925 return 1;
1926 }
1927 sl_strlcpy(chroot_dir, str, len);
1928 block = 1;
1929 return 0;
1930 }
1931 return 1;
1932}
1933
1934int sh_unix_chroot(void)
1935{
1936 int status;
1937
1938 if (chroot_dir != NULL)
1939 {
1940 status = retry_aud_chdir(FIL__, __LINE__, chroot_dir);
1941 if ( (-1) == status )
1942 {
1943 char errbuf[SH_ERRBUF_SIZE];
1944 status = errno;
1945 sh_error_handle ((-1), FIL__, __LINE__, status, MSG_W_CHDIR,
1946 sh_error_message (status, errbuf, sizeof(errbuf)), chroot_dir);
1947 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1948 }
1949 /* flawfinder: ignore */
1950 return (chroot(chroot_dir));
1951 }
1952 return 0;
1953}
1954/* #ifdef SH_WITH_SERVER */
1955#else
1956int sh_unix_chroot(void) { return 0; }
1957#endif
1958
1959/* daemon mode
1960 */
1961static int block_setdeamon = 0;
1962
1963int sh_unix_setdeamon(const char * dummy)
1964{
1965 int res = 0;
1966
1967 SL_ENTER(_("sh_unix_setdeamon"));
1968
1969 if (block_setdeamon != 0)
1970 SL_RETURN((0),_("sh_unix_setdeamon"));
1971
1972 if (dummy == NULL)
1973 sh.flag.isdaemon = S_TRUE;
1974 else
1975 res = sh_util_flagval (dummy, &sh.flag.isdaemon);
1976
1977 if (sh.flag.opts == S_TRUE)
1978 block_setdeamon = 1;
1979
1980 SL_RETURN(res, _("sh_unix_setdeamon"));
1981}
1982#if defined(HAVE_LIBPRELUDE)
1983#include "sh_prelude.h"
1984#endif
1985
1986int sh_unix_setnodeamon(const char * dummy)
1987{
1988 int res = 0;
1989
1990 SL_ENTER(_("sh_unix_setnodeamon"));
1991
1992 if (block_setdeamon != 0)
1993 SL_RETURN((0),_("sh_unix_setmodeamon"));
1994
1995 if (dummy == NULL)
1996 sh.flag.isdaemon = S_FALSE;
1997 else
1998 res = sh_util_flagval (dummy, &sh.flag.isdaemon);
1999
2000 if (sh.flag.opts == S_TRUE)
2001 block_setdeamon = 1;
2002
2003 SL_RETURN(res, _("sh_unix_setnodeamon"));
2004}
2005
2006int sh_unix_init(int goDaemon)
2007{
2008 int status;
2009 uid_t uid;
2010 pid_t oldpid = getpid();
2011#if defined(SH_WITH_SERVER)
2012 extern int sh_socket_open_int (void);
2013#endif
2014 char errbuf[SH_ERRBUF_SIZE];
2015
2016 extern void sh_kill_sub();
2017
2018 SL_ENTER(_("sh_unix_init"));
2019
2020 /* fork twice, exit the parent process
2021 */
2022 if (goDaemon == 1) {
2023
2024 switch (aud_fork(FIL__, __LINE__)) {
2025 case 0: break; /* child process continues */
2026 case -1: SL_RETURN((-1),_("sh_unix_init")); /* error */
2027 default: /* parent process exits */
2028 sh_kill_sub();
2029 aud__exit(FIL__, __LINE__, 0);
2030 }
2031
2032 /* Child processes do not inherit page locks across a fork.
2033 * Error in next fork would return in this (?) thread of execution.
2034 */
2035 sh_unix_memlock();
2036
2037 setsid(); /* should not fail */
2038 sh.pid = (UINT64) getpid();
2039
2040 switch (aud_fork(FIL__, __LINE__)) {
2041 case 0: break; /* child process continues */
2042 case -1: SL_RETURN((-1),_("sh_unix_init")); /* error */
2043 default: /* parent process exits */
2044 sh_kill_sub();
2045 aud__exit(FIL__, __LINE__, 0);
2046 }
2047
2048 /* Child processes do not inherit page locks across a fork.
2049 */
2050 sh_unix_memlock();
2051 sh.pid = (UINT64) getpid();
2052
2053 } else {
2054 setsid(); /* should not fail */
2055 }
2056
2057 /* set working directory
2058 */
2059#ifdef SH_PROFILE
2060 status = 0;
2061#else
2062 status = retry_aud_chdir(FIL__, __LINE__, "/");
2063#endif
2064 if ( (-1) == status )
2065 {
2066 status = errno;
2067 sh_error_handle ((-1), FIL__, __LINE__, status, MSG_W_CHDIR,
2068 sh_error_message (status, errbuf, sizeof(errbuf)), "/");
2069 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
2070 }
2071
2072 /* reset timers
2073 */
2074 sh_unix_resettimer();
2075
2076 /* signal handlers
2077 */
2078 sh_unix_resetsignals();
2079#if defined(SCREW_IT_UP)
2080 sh_sigtrap_prepare();
2081#endif
2082 sh_unix_siginstall (goDaemon);
2083
2084 /* set file creation mask
2085 */
2086 (void) umask (0); /* should not fail */
2087
2088 /* set resource limits to maximum, and
2089 * core dump size to zero
2090 */
2091 sh_unix_setlimits();
2092
2093 /* zero out the environment (like PATH='\0')
2094 */
2095 sh_unix_zeroenv();
2096
2097 if (goDaemon == 1)
2098 {
2099 /* Close first tree file descriptors
2100 */
2101 sl_close_fd (FIL__, __LINE__, 0); /* if running as daemon */
2102 sl_close_fd (FIL__, __LINE__, 1); /* if running as daemon */
2103 sl_close_fd (FIL__, __LINE__, 2); /* if running as daemon */
2104
2105 /* Enable full error logging
2106 */
2107 sh_error_only_stderr (S_FALSE);
2108
2109 /* open first three streams to /dev/null
2110 */
2111 status = aud_open(FIL__, __LINE__, SL_NOPRIV, _("/dev/null"), O_RDWR, 0);
2112 if (status < 0)
2113 {
2114 status = errno;
2115 sh_error_handle((-1), FIL__, __LINE__, status, MSG_E_SUBGEN,
2116 sh_error_message(status, errbuf, sizeof(errbuf)), _("open"));
2117 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
2118 }
2119
2120 status = retry_aud_dup(FIL__, __LINE__, 0);
2121 if (status >= 0)
2122 retry_aud_dup(FIL__, __LINE__, 0);
2123
2124 if (status < 0)
2125 {
2126 status = errno;
2127 sh_error_handle((-1), FIL__, __LINE__, status, MSG_E_SUBGEN,
2128 sh_error_message(status, errbuf, sizeof(errbuf)), _("dup"));
2129 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
2130 }
2131
2132 sh_error_enable_unsafe (S_TRUE);
2133#if defined(HAVE_LIBPRELUDE)
2134 sh_prelude_reset ();
2135#endif
2136
2137 /* --- wait until parent has exited ---
2138 */
2139 while (1 == 1)
2140 {
2141 errno = 0;
2142 if (0 > aud_kill (FIL__, __LINE__, oldpid, 0) && errno == ESRCH)
2143 {
2144 break;
2145 }
2146 retry_msleep(0, 1);
2147 }
2148
2149 /* write PID file
2150 */
2151 status = sh_unix_write_pid_file();
2152 if (status < 0)
2153 {
2154 sl_get_euid(&uid);
2155 sh_error_handle ((-1), FIL__, __LINE__, status, MSG_PIDFILE,
2156 (long) uid, sh.srvlog.alt);
2157 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
2158 }
2159#if defined(SH_WITH_SERVER)
2160 sh_socket_open_int ();
2161#endif
2162 }
2163 else
2164 {
2165 sh_error_enable_unsafe (S_TRUE);
2166#if defined(HAVE_LIBPRELUDE)
2167 sh_prelude_reset ();
2168#endif
2169#if defined(SH_WITH_SERVER)
2170 sh_socket_open_int ();
2171#endif
2172 }
2173
2174 /* chroot (this is a no-op if no chroot dir is specified
2175 */
2176 status = sh_unix_chroot();
2177 if (status < 0)
2178 {
2179 status = errno;
2180 sh_error_handle((-1), FIL__, __LINE__, status, MSG_E_SUBGEN,
2181 sh_error_message(status, errbuf, sizeof(errbuf)), _("chroot"));
2182 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
2183 }
2184
2185 /* drop capabilities
2186 */
2187 sl_drop_cap();
2188
2189 SL_RETURN((0),_("sh_unix_init"));
2190}
2191
2192/* --- run a command, securely --- */
2193
2194int sh_unix_run_command (const char * str)
2195{
2196 pid_t pid;
2197 char * arg[4];
2198 char * env[5];
2199 char * path = sh_util_strdup(_("/bin/sh"));
2200
2201 int status = -1;
2202
2203 arg[0] = sh_util_strdup(_("/bin/sh"));
2204 arg[1] = sh_util_strdup(_("-c"));
2205 arg[2] = sh_util_strdup(str);
2206 arg[3] = NULL;
2207
2208 env[0] = sh_util_strdup(_("PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/ucb"));
2209 env[1] = sh_util_strdup(_("SHELL=/bin/sh"));
2210 env[2] = sh_util_strdup(_("IFS= \t\n"));
2211 if (getenv("TZ")) { /* flawfinder: ignore */
2212 char * tz = sh_util_strdup(getenv("TZ")); /* flawfinder: ignore */
2213 size_t tzlen = strlen(tz);
2214 if (S_TRUE == sl_ok_adds (4, tzlen)) {
2215 env[3] = SH_ALLOC(4+tzlen);
2216 sl_strlcpy(env[3], "TZ=", 4);
2217 sl_strlcat(env[3], tz , 4+tzlen);
2218 } else {
2219 env[3] = NULL;
2220 }
2221 } else {
2222 env[3] = NULL;
2223 }
2224 env[4] = NULL;
2225
2226 pid = fork();
2227
2228 if (pid == (pid_t)(-1))
2229 {
2230 return -1;
2231 }
2232
2233 else if (pid == 0) /* child */
2234 {
2235 memset(skey, 0, sizeof(sh_key_t));
2236 (void) umask(S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH);
2237 sh_unix_closeall (3, -1, S_TRUE); /* in child process */
2238 execve(path, arg, env);
2239 _exit(EXIT_FAILURE);
2240 }
2241
2242 else /* parent */
2243 {
2244 int r;
2245
2246 while((r = waitpid(pid, &status, WUNTRACED)) != pid && r != -1) ;
2247
2248#if !defined(USE_UNO)
2249 if (r == -1 || !WIFEXITED(status))
2250 {
2251 status = -1;
2252 }
2253 else
2254 {
2255 status = WEXITSTATUS(status);
2256 }
2257#endif
2258 }
2259
2260 return status;
2261}
2262
2263/********************************************************
2264 *
2265 * TIME
2266 *
2267 ********************************************************/
2268
2269/* Figure out the time offset of the current timezone
2270 * in a portable way.
2271 */
2272char * t_zone(const time_t * xx)
2273{
2274 struct tm aa;
2275 struct tm bb;
2276
2277 struct tm * aptr;
2278 struct tm * bptr;
2279
2280 int sign = 0;
2281 int diff = 0;
2282 int hh, mm;
2283 static char tz[64];
2284
2285 SL_ENTER(_("t_zone"));
2286
2287#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GMTIME_R)
2288 aptr = gmtime_r (xx, &aa);
2289#else
2290 aptr = gmtime(xx);
2291 if (aptr)
2292 memcpy (&aa, aptr, sizeof(struct tm));
2293#endif
2294
2295#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_LOCALTIME_R)
2296 bptr = localtime_r (xx, &bb);
2297#else
2298 bptr = localtime(xx);
2299 if (bptr)
2300 memcpy (&bb, bptr, sizeof(struct tm));
2301#endif
2302
2303 if (bptr && aptr)
2304 {
2305 /* Check for datum wrap-around.
2306 */
2307 if (aa.tm_year < bb.tm_year)
2308 sign = (-1);
2309 else if (aa.tm_mon < bb.tm_mon)
2310 sign = (-1);
2311 else if (aa.tm_mday < bb.tm_mday)
2312 sign = (-1);
2313 else if (bb.tm_year < aa.tm_year)
2314 sign = ( 1);
2315 else if (bb.tm_mon < aa.tm_mon)
2316 sign = ( 1);
2317 else if (bb.tm_mday < aa.tm_mday)
2318 sign = ( 1);
2319
2320 diff = aa.tm_hour * 60 + aa.tm_min;
2321 diff = (bb.tm_hour * 60 + bb.tm_min) - diff;
2322 diff = diff - (sign * 24 * 60); /* datum wrap-around correction */
2323 hh = diff / 60;
2324 mm = diff - (hh * 60);
2325 sprintf (tz, _("%+03d%02d"), hh, mm); /* known to fit */
2326 }
2327 else
2328 {
2329 sprintf (tz, _("%+03d%02d"), 0, 0);
2330 }
2331 SL_RETURN(tz, _("t_zone"));
2332}
2333
2334unsigned long sh_unix_longtime ()
2335{
2336 return ((unsigned long)time(NULL));
2337}
2338
2339#ifdef HAVE_GETTIMEOFDAY
2340unsigned long sh_unix_notime ()
2341{
2342 struct timeval tv;
2343
2344 gettimeofday (&tv, NULL);
2345
2346 return ((unsigned long)(tv.tv_sec + tv.tv_usec * 10835 + getpid() + getppid()));
2347
2348}
2349#endif
2350
2351static int count_dev_time = 0;
2352
2353void reset_count_dev_time(void)
2354{
2355 count_dev_time = 0;
2356 return;
2357}
2358
2359int sh_unix_settimeserver (const char * address)
2360{
2361
2362 SL_ENTER(_("sh_unix_settimeserver"));
2363
2364 if (address != NULL && count_dev_time < 2
2365 && sl_strlen(address) < SH_PATHBUF)
2366 {
2367 if (count_dev_time == 0)
2368 sl_strlcpy (sh.srvtime.name, address, SH_PATHBUF);
2369 else
2370 sl_strlcpy (sh.srvtime.alt, address, SH_PATHBUF);
2371
2372 ++count_dev_time;
2373 SL_RETURN((0), _("sh_unix_settimeserver"));
2374 }
2375 SL_RETURN((-1), _("sh_unix_settimeserver"));
2376}
2377
2378
2379#ifdef HAVE_NTIME
2380#define UNIXEPOCH 2208988800UL /* difference between Unix time and net time
2381 * The UNIX EPOCH starts in 1970.
2382 */
2383#include <sys/socket.h>
2384#include <netinet/in.h>
2385#include <arpa/inet.h>
2386#include <netdb.h>
2387#include <ctype.h>
2388#endif
2389
2390/* Timeserver service. */
2391/* define is missing on HP-UX 10.20 */
2392#ifndef IPPORT_TIMESERVER
2393#define IPPORT_TIMESERVER 37
2394#endif
2395
2396char * sh_unix_time (time_t thetime, char * buffer, size_t len)
2397{
2398
2399 int status;
2400 char AsciiTime[81]; /* local time */
2401 time_t time_now;
2402 struct tm * time_ptr;
2403#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_LOCALTIME_R)
2404 struct tm time_tm;
2405#endif
2406#ifdef SH_USE_XML
2407 static char deftime[] = N_("0000-00-00T00:00:00"); /* default time */
2408#else
2409 static char deftime[] = N_("[0000-00-00T00:00:00]"); /* default time */
2410#endif
2411
2412#ifdef HAVE_NTIME
2413 int fd; /* network file descriptor */
2414 u_char net_time[4]; /* remote time in network format */
2415 static int failerr = 0; /* no net time */
2416 int fail = 0; /* no net time */
2417 int errflag;
2418 char errmsg[256];
2419 char error_call[SH_MINIBUF];
2420 int error_num;
2421#endif
2422
2423 SL_ENTER(_("sh_unix_time"));
2424
2425#ifdef HAVE_NTIME
2426 if (thetime == 0)
2427 {
2428 if (sh.srvtime.name[0] == '\0')
2429 {
2430 fail = 1;
2431 (void) time (&time_now);
2432 }
2433 else /* have a timeserver address */
2434 {
2435 /* don't call timeserver more than once per second */
2436 static time_t time_old = 0;
2437 time_t time_new;
2438 static time_t time_saved = 0;
2439 (void) time (&time_new);
2440 if ((time_new == time_old) && (time_saved != 0))
2441 {
2442 time_now = time_saved;
2443 goto end;
2444 }
2445 time_old = time_new;
2446
2447
2448 fd = connect_port_2 (sh.srvtime.name, sh.srvtime.alt,
2449 IPPORT_TIMESERVER,
2450 error_call, &error_num, errmsg, sizeof(errmsg));
2451 if (fd >= 0)
2452 {
2453 if (4 != read_port (fd, (char *) net_time, 4, &errflag, 2))
2454 {
2455 fail = 1;
2456 sh_error_handle ((-1), FIL__, __LINE__, errflag,
2457 MSG_E_NLOST,
2458 _("time"), sh.srvtime.name);
2459 }
2460 sl_close_fd(FIL__, __LINE__, fd);
2461 }
2462 else
2463 {
2464 sh_error_handle ((-1), FIL__, __LINE__, error_num,
2465 MSG_E_NET, errmsg, error_call,
2466 _("time"), sh.srvtime.name);
2467 fail = 1;
2468 }
2469
2470 if (fail == 0)
2471 {
2472 unsigned long ltmp;
2473 UINT32 ttmp;
2474 memcpy(&ttmp, net_time, sizeof(UINT32)); ltmp = ttmp;
2475 time_now = ntohl(ltmp) - UNIXEPOCH;
2476 time_saved = time_now;
2477
2478 if (failerr == 1) {
2479 failerr = 0;
2480 sh_error_handle ((-1), FIL__, __LINE__, 0,
2481 MSG_E_NEST,
2482 _("time"), sh.srvtime.name);
2483 }
2484 }
2485 else
2486 {
2487 (void) time (&time_now);
2488 time_saved = 0;
2489
2490 if (failerr == 0)
2491 {
2492 failerr = 1;
2493 sh_error_handle ((-1), FIL__, __LINE__, errflag,
2494 MSG_SRV_FAIL,
2495 _("time"), sh.srvtime.name);
2496 }
2497 }
2498 end:
2499 ; /* 'label at end of compound statement' */
2500 }
2501 }
2502 else
2503 {
2504 time_now = thetime;
2505 }
2506
2507 /* #ifdef HAVE_NTIME */
2508#else
2509
2510 if (thetime == 0)
2511 {
2512 (void) time (&time_now);
2513 }
2514 else
2515 {
2516 time_now = thetime;
2517 }
2518
2519 /* #ifdef HAVE_NTIME */
2520#endif
2521
2522 if (time_now == (-1) )
2523 {
2524 sl_strlcpy(buffer, _(deftime), len);
2525 SL_RETURN(buffer, _("sh_unix_time"));
2526 }
2527 else
2528 {
2529#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_LOCALTIME_R)
2530 time_ptr = localtime_r (&time_now, &time_tm);
2531#else
2532 time_ptr = localtime (&time_now);
2533#endif
2534 }
2535 if (time_ptr != NULL)
2536 {
2537 status = strftime (AsciiTime, sizeof(AsciiTime),
2538#ifdef SH_USE_XML
2539 _("%Y-%m-%dT%H:%M:%S%%s"),
2540#else
2541 _("[%Y-%m-%dT%H:%M:%S%%s]"),
2542#endif
2543 time_ptr);
2544
2545 sl_snprintf(buffer, len, AsciiTime, t_zone(&time_now));
2546
2547 if ( (status == 0) || (status == sizeof(AsciiTime)) )
2548 {
2549 sl_strlcpy(buffer, _(deftime), len);
2550 SL_RETURN( buffer, _("sh_unix_time"));
2551 }
2552 else
2553 {
2554 SL_RETURN(buffer, _("sh_unix_time"));
2555 }
2556 }
2557
2558 /* last resort
2559 */
2560 sl_strlcpy(buffer, _(deftime), len);
2561 SL_RETURN( buffer, _("sh_unix_time"));
2562}
2563
2564static int sh_unix_use_localtime = S_FALSE;
2565
2566/* whether to use localtime for file timestamps in logs
2567 */
2568int sh_unix_uselocaltime (const char * c)
2569{
2570 int i;
2571 SL_ENTER(_("sh_unix_uselocaltime"));
2572 i = sh_util_flagval(c, &(sh_unix_use_localtime));
2573
2574 SL_RETURN(i, _("sh_unix_uselocaltime"));
2575}
2576
2577char * sh_unix_gmttime (time_t thetime, char * buffer, size_t len)
2578{
2579
2580 int status;
2581
2582 struct tm * time_ptr;
2583#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS)
2584 struct tm time_tm;
2585#endif
2586 char AsciiTime[81]; /* GMT time */
2587#ifdef SH_USE_XML
2588 static char deftime[] = N_("0000-00-00T00:00:00"); /* default time */
2589#else
2590 static char deftime[] = N_("[0000-00-00T00:00:00]"); /* default time */
2591#endif
2592
2593 SL_ENTER(_("sh_unix_gmttime"));
2594
2595 if (sh_unix_use_localtime == S_FALSE)
2596 {
2597#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GMTIME_R)
2598 time_ptr = gmtime_r (&thetime, &time_tm);
2599#else
2600 time_ptr = gmtime (&thetime);
2601#endif
2602 }
2603 else
2604 {
2605#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_LOCALTIME_R)
2606 time_ptr = localtime_r (&thetime, &time_tm);
2607#else
2608 time_ptr = localtime (&thetime);
2609#endif
2610 }
2611 if (time_ptr != NULL)
2612 {
2613 status = strftime (AsciiTime, 80,
2614#ifdef SH_USE_XML
2615 _("%Y-%m-%dT%H:%M:%S"),
2616#else
2617 _("[%Y-%m-%dT%H:%M:%S]"),
2618#endif
2619 time_ptr);
2620
2621 if ( (status == 0) || (status == 80) )
2622 sl_strlcpy(buffer, _(deftime), len);
2623 else
2624 sl_strlcpy(buffer, AsciiTime, len);
2625 SL_RETURN( buffer, _("sh_unix_gmttime"));
2626 }
2627
2628 /* last resort
2629 */
2630 sl_strlcpy(buffer, _(deftime), len);
2631 SL_RETURN( buffer, _("sh_unix_gmttime"));
2632}
2633
2634
2635char * sh_unix_getUIDdir (int level, uid_t uid, char * out, size_t len)
2636{
2637 struct passwd * tempres;
2638 int status = 0;
2639
2640#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWUID_R)
2641 struct passwd pwd;
2642 char * buffer;
2643#endif
2644 char errbuf[SH_ERRBUF_SIZE];
2645
2646 SL_ENTER(_("sh_unix_getUIDdir"));
2647
2648#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWUID_R)
2649 buffer = SH_ALLOC(SH_PWBUF_SIZE);
2650 sh_getpwuid_r(uid, &pwd, buffer, SH_PWBUF_SIZE, &tempres);
2651#else
2652 errno = 0;
2653 tempres = sh_getpwuid(uid);
2654 status = errno;
2655#endif
2656
2657 if (tempres == NULL) {
2658 sh_error_handle (level, FIL__, __LINE__, EINVAL, MSG_E_PWNULL,
2659 sh_error_message(status, errbuf, sizeof(errbuf)),
2660 _("getpwuid"), (long) uid, _("completely missing"));
2661#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R)
2662 SH_FREE(buffer);
2663#endif
2664 SL_RETURN( NULL, _("sh_unix_getUIDdir"));
2665 }
2666
2667 if (tempres->pw_dir != NULL) {
2668 sl_strlcpy(out, tempres->pw_dir, len);
2669#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R)
2670 SH_FREE(buffer);
2671#endif
2672 SL_RETURN( out, _("sh_unix_getUIDdir"));
2673 } else {
2674 sh_error_handle (level, FIL__, __LINE__, EINVAL, MSG_E_PWNULL,
2675 sh_error_message(status, errbuf, sizeof(errbuf)),
2676 _("getpwuid"), (long) uid, _("pw_dir"));
2677#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R)
2678 SH_FREE(buffer);
2679#endif
2680 SL_RETURN( NULL, _("sh_unix_getUIDdir"));
2681 }
2682}
2683
2684/* ------------------- Caching ----------------*/
2685#include "zAVLTree.h"
2686
2687#define CACHE_GID 0
2688#define CACHE_UID 1
2689
2690struct user_id {
2691 char * name;
2692 uid_t id;
2693 struct user_id * next;
2694};
2695
2696static struct user_id * uid_list = NULL;
2697static struct user_id * gid_list = NULL;
2698
2699SH_MUTEX_STATIC(mutex_cache, PTHREAD_MUTEX_INITIALIZER);
2700
2701static void sh_userid_free(struct user_id * item)
2702{
2703 while (item)
2704 {
2705 struct user_id * user = item;
2706 item = item->next;
2707
2708 SH_FREE(user->name);
2709 SH_FREE(user);
2710 }
2711 return;
2712}
2713
2714void sh_userid_destroy ()
2715{
2716 struct user_id * tmp_uid;
2717 struct user_id * tmp_gid;
2718
2719 SH_MUTEX_LOCK_UNSAFE(mutex_cache);
2720 tmp_gid = gid_list;
2721 gid_list = NULL;
2722 tmp_uid = uid_list;
2723 uid_list = NULL;
2724 SH_MUTEX_UNLOCK_UNSAFE(mutex_cache);
2725
2726 sh_userid_free(tmp_uid);
2727 sh_userid_free(tmp_gid);
2728 return;
2729}
2730
2731static void sh_userid_additem(struct user_id * list, struct user_id * item)
2732{
2733 if (list)
2734 {
2735 while (list && list->next)
2736 list = list->next;
2737 list->next = item;
2738 }
2739 return;
2740}
2741
2742static void sh_userid_add(uid_t id, char * username, int which)
2743{
2744 size_t len;
2745 struct user_id * user = SH_ALLOC(sizeof(struct user_id));
2746
2747 if (username)
2748 len = strlen(username) + 1;
2749 else
2750 len = 1;
2751
2752 user->name = SH_ALLOC(len);
2753 user->id = id;
2754 if (username)
2755 sl_strlcpy(user->name, username, len);
2756 else
2757 user->name[0] = '\0';
2758 user->next = NULL;
2759
2760 SH_MUTEX_LOCK(mutex_cache);
2761 if (which == CACHE_UID)
2762 {
2763 if (!uid_list)
2764 uid_list = user;
2765 else
2766 sh_userid_additem(uid_list, user);
2767 }
2768 else
2769 {
2770 if (!gid_list)
2771 gid_list = user;
2772 else
2773 sh_userid_additem(gid_list, user);
2774 }
2775 SH_MUTEX_UNLOCK(mutex_cache);
2776
2777 return;
2778}
2779
2780static char * sh_userid_search(struct user_id * list, uid_t id)
2781{
2782 while (list)
2783 {
2784 if (list->id == id)
2785 return list->name;
2786 list = list->next;
2787 }
2788 return NULL;
2789}
2790
2791static char * sh_userid_get (uid_t id, int which, char * out, size_t len)
2792{
2793 char * user = NULL;
2794
2795 SH_MUTEX_LOCK_UNSAFE(mutex_cache);
2796 if (which == CACHE_UID)
2797 user = sh_userid_search(uid_list, id);
2798 else
2799 user = sh_userid_search(gid_list, id);
2800 if (user)
2801 {
2802 sl_strlcpy(out, user, len);
2803 user = out;
2804 }
2805 SH_MUTEX_UNLOCK_UNSAFE(mutex_cache);
2806
2807 return user;
2808}
2809
2810/* --------- end caching code --------- */
2811
2812char * sh_unix_getUIDname (int level, uid_t uid, char * out, size_t len)
2813{
2814 struct passwd * tempres;
2815#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWUID_R)
2816 struct passwd pwd;
2817 char * buffer;
2818#endif
2819 int status = 0;
2820 char errbuf[SH_ERRBUF_SIZE];
2821 char * tmp;
2822
2823 SL_ENTER(_("sh_unix_getUIDname"));
2824
2825 tmp = sh_userid_get(uid, CACHE_UID, out, len);
2826
2827 if (tmp)
2828 {
2829 if (tmp[0] != '\0')
2830 {
2831 SL_RETURN( out, _("sh_unix_getUIDname"));
2832 }
2833 else
2834 {
2835 SL_RETURN( NULL, _("sh_unix_getUIDname"));
2836 }
2837 }
2838
2839#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWUID_R)
2840 buffer = SH_ALLOC(SH_PWBUF_SIZE);
2841 sh_getpwuid_r(uid, &pwd, buffer, SH_PWBUF_SIZE, &tempres);
2842#else
2843 errno = 0;
2844 tempres = sh_getpwuid(uid);
2845 status = errno;
2846#endif
2847
2848 if (tempres == NULL)
2849 {
2850 sh_error_handle (level, FIL__, __LINE__, EINVAL, MSG_E_PWNULL,
2851 sh_error_message(status, errbuf, sizeof(errbuf)),
2852 _("getpwuid"), (long) uid, _("completely missing"));
2853#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R)
2854 SH_FREE(buffer);
2855#endif
2856 sh_userid_add(uid, NULL, CACHE_UID);
2857 SL_RETURN( NULL, _("sh_unix_getUIDname"));
2858 }
2859
2860
2861 if (tempres->pw_name != NULL)
2862 {
2863
2864 sl_strlcpy(out, tempres->pw_name, len);
2865 sh_userid_add(uid, out, CACHE_UID);
2866
2867#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R)
2868 SH_FREE(buffer);
2869#endif
2870
2871 SL_RETURN( out, _("sh_unix_getUIDname"));
2872 }
2873 else
2874 {
2875 sh_error_handle (level, FIL__, __LINE__, EINVAL, MSG_E_PWNULL,
2876 sh_error_message(status, errbuf, sizeof(errbuf)),
2877 _("getpwuid"), (long) uid, _("pw_user"));
2878#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R)
2879 SH_FREE(buffer);
2880#endif
2881 SL_RETURN( NULL, _("sh_unix_getUIDname"));
2882 }
2883 /* notreached */
2884}
2885
2886char * sh_unix_getGIDname (int level, gid_t gid, char * out, size_t len)
2887{
2888 struct group * tempres;
2889 int status = 0;
2890
2891#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R)
2892 struct group grp;
2893 char * buffer;
2894#endif
2895 char errbuf[SH_ERRBUF_SIZE];
2896 char * tmp;
2897
2898 SL_ENTER(_("sh_unix_getGIDname"));
2899
2900 tmp = sh_userid_get((uid_t)gid, CACHE_GID, out, len);
2901
2902 if (tmp)
2903 {
2904 if (tmp[0] != '\0')
2905 {
2906 SL_RETURN( out, _("sh_unix_getGIDname"));
2907 }
2908 else
2909 {
2910 SL_RETURN( NULL, _("sh_unix_getGIDname"));
2911 }
2912 }
2913
2914#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R)
2915 buffer = SH_ALLOC(SH_GRBUF_SIZE);
2916 status = sh_getgrgid_r(gid, &grp, buffer, SH_GRBUF_SIZE, &tempres);
2917#else
2918 errno = 0;
2919 tempres = sh_getgrgid(gid);
2920 status = errno;
2921#endif
2922
2923 if (status == ERANGE)
2924 {
2925 static int seen = 0;
2926
2927 if (seen == 0)
2928 {
2929 sh_error_handle (SH_ERR_ERR, FIL__, __LINE__, EINVAL, MSG_E_GRNULL,
2930 sh_error_message(status, errbuf, sizeof(errbuf)),
2931 _("getgrgid"), (long) gid, _("line too long in group entry"));
2932 ++seen;
2933 }
2934
2935#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R)
2936 SH_FREE(buffer);
2937#endif
2938
2939 sh_userid_add(gid, NULL, CACHE_GID);
2940 SL_RETURN( NULL, _("sh_unix_getGIDname"));
2941 }
2942
2943 if (tempres == NULL)
2944 {
2945 sh_error_handle (level, FIL__, __LINE__, EINVAL, MSG_E_GRNULL,
2946 sh_error_message(status, errbuf, sizeof(errbuf)),
2947 _("getgrgid"), (long) gid, _("completely missing"));
2948
2949#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R)
2950 SH_FREE(buffer);
2951#endif
2952
2953 sh_userid_add(gid, NULL, CACHE_GID);
2954 SL_RETURN( NULL, _("sh_unix_getGIDname"));
2955 }
2956
2957 if (tempres->gr_name != NULL)
2958 {
2959
2960 sl_strlcpy(out, tempres->gr_name, len);
2961 sh_userid_add((uid_t)gid, out, CACHE_GID);
2962
2963#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R)
2964 SH_FREE(buffer);
2965#endif
2966
2967 SL_RETURN( out, _("sh_unix_getGIDname"));
2968 }
2969 else
2970 {
2971 sh_error_handle (level, FIL__, __LINE__, EINVAL, MSG_E_GRNULL,
2972 sh_error_message(status, errbuf, sizeof(errbuf)),
2973 _("getgrgid"), (long) gid, _("gr_name"));
2974
2975#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R)
2976 SH_FREE(buffer);
2977#endif
2978
2979 SL_RETURN( NULL, _("sh_unix_getGIDname"));
2980 }
2981 /* notreached */
2982}
2983
2984int sh_unix_getUser ()
2985{
2986 char * p;
2987 uid_t seuid, sruid;
2988 char user[USER_MAX];
2989 char dir[SH_PATHBUF];
2990
2991 SL_ENTER(_("sh_unix_getUser"));
2992
2993 seuid = geteuid();
2994
2995 sh.effective.uid = seuid;
2996
2997 p = sh_unix_getUIDdir (SH_ERR_ERR, seuid, dir, sizeof(dir));
2998
2999 if (p == NULL)
3000 SL_RETURN((-1), _("sh_unix_getUser"));
3001 else
3002 {
3003 if (sl_strlen(p) >= SH_PATHBUF) {
3004 sh_error_handle (SH_ERR_ERR, FIL__, __LINE__, EINVAL, MSG_E_PWLONG,
3005 _("getpwuid"), (long) seuid, _("pw_home"));
3006 SL_RETURN((-1), _("sh_unix_getUser"));
3007 } else {
3008 sl_strlcpy ( sh.effective.home, p, SH_PATHBUF);
3009 }
3010 }
3011
3012 sruid = getuid();
3013
3014 sh.real.uid = sruid;
3015
3016 p = sh_unix_getUIDname (SH_ERR_ERR, sruid, user, sizeof(user));
3017 if (p == NULL)
3018 SL_RETURN((-1), _("sh_unix_getUser"));
3019 else
3020 {
3021 if (sl_strlen(p) >= USER_MAX) {
3022 sh_error_handle (SH_ERR_ERR, FIL__, __LINE__, EINVAL, MSG_E_PWLONG,
3023 _("getpwuid"), (long) sruid, _("pw_user"));
3024 SL_RETURN((-1), _("sh_unix_getUser"));
3025 } else {
3026 sl_strlcpy ( sh.real.user, p, USER_MAX);
3027 }
3028 }
3029
3030 p = sh_unix_getUIDdir (SH_ERR_ERR, sruid, dir, sizeof(dir));
3031
3032 if (p == NULL)
3033 SL_RETURN((-1), _("sh_unix_getUser"));
3034 else
3035 {
3036 if (sl_strlen(p) >= SH_PATHBUF) {
3037 sh_error_handle (SH_ERR_ERR, FIL__, __LINE__, EINVAL, MSG_E_PWLONG,
3038 _("getpwuid"), (long) sruid, _("pw_home"));
3039 SL_RETURN((-1), _("sh_unix_getUser"));
3040 } else {
3041 sl_strlcpy ( sh.real.home, p, SH_PATHBUF);
3042 }
3043 }
3044
3045 SL_RETURN((0), _("sh_unix_getUser"));
3046
3047 /* notreached */
3048}
3049
3050
3051int sh_unix_getline (SL_TICKET fd, char * line, int sizeofline)
3052{
3053 register int count;
3054 register int n = 0;
3055 char c;
3056
3057 SL_ENTER(_("sh_unix_getline"));
3058
3059 if (sizeofline < 2) {
3060 line[0] = '\0';
3061 SL_RETURN((0), _("sh_unix_getline"));
3062 }
3063
3064 --sizeofline;
3065
3066 while (n < sizeofline) {
3067
3068 count = sl_read (fd, &c, 1);
3069
3070 /* end of file
3071 */
3072 if (count < 1) {
3073 line[n] = '\0';
3074 n = -1;
3075 break;
3076 }
3077
3078 if (/* c != '\0' && */ c != '\n') {
3079 line[n] = c;
3080 ++n;
3081 } else if (c == '\n') {
3082 if (n > 0) {
3083 line[n] = '\0';
3084 break;
3085 } else {
3086 line[n] = '\n'; /* get newline only if only char on line */
3087 ++n;
3088 line[n] = '\0';
3089 break;
3090 }
3091 } else {
3092 line[n] = '\0';
3093 break;
3094 }
3095
3096 }
3097
3098
3099 line[sizeofline] = '\0'; /* make sure line is terminated */
3100 SL_RETURN((n), _("sh_unix_getline"));
3101}
3102
3103
3104#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
3105
3106/**************************************************************
3107 *
3108 * --- FILE INFO ---
3109 *
3110 **************************************************************/
3111
3112#if (defined(__linux__) && (defined(HAVE_LINUX_EXT2_FS_H) || defined(HAVE_EXT2FS_EXT2_FS_H))) || defined(HAVE_STAT_FLAGS)
3113
3114#if defined(__linux__)
3115
3116/* --- Determine ext2fs file attributes. ---
3117 */
3118#include <sys/ioctl.h>
3119#if defined(HAVE_EXT2FS_EXT2_FS_H)
3120#include <ext2fs/ext2_fs.h>
3121#else
3122#include <linux/ext2_fs.h>
3123#endif
3124
3125/* __linux__ includes */
3126#endif
3127
3128static
3129int sh_unix_getinfo_attr (char * name,
3130 unsigned long * flags,
3131 char * c_attr,
3132 int fd, struct stat * buf)
3133{
3134
3135/* TAKEN FROM:
3136 *
3137 * lsattr.c - List file attributes on an ext2 file system
3138 *
3139 * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
3140 * Laboratoire MASI, Institut Blaise Pascal
3141 * Universite Pierre et Marie Curie (Paris VI)
3142 *
3143 * This file can be redistributed under the terms of the GNU General
3144 * Public License
3145 */
3146
3147#ifdef HAVE_STAT_FLAGS
3148
3149 SL_ENTER(_("sh_unix_getinfo_attr"));
3150
3151 *flags = 0;
3152
3153 /* cast to void to avoid compiler warning about unused parameters */
3154 (void) fd;
3155 (void) name;
3156
3157#ifdef UF_NODUMP
3158 if (buf->st_flags & UF_NODUMP) {
3159 *flags |= UF_NODUMP;
3160 c_attr[0] = 'd';
3161 }
3162#endif
3163#ifdef UF_IMMUTABLE
3164 if (buf->st_flags & UF_IMMUTABLE) {
3165 *flags |= UF_IMMUTABLE;
3166 c_attr[1] = 'i';
3167 }
3168#endif
3169#ifdef UF_APPEND
3170 if (buf->st_flags & UF_APPEND) {
3171 *flags |= UF_APPEND;
3172 c_attr[2] = 'a';
3173 }
3174#endif
3175#ifdef UF_NOUNLINK
3176 if (buf->st_flags & UF_NOUNLINK) {
3177 *flags |= UF_NOUNLINK;
3178 c_attr[3] = 'u';
3179 }
3180#endif
3181#ifdef UF_OPAQUE
3182 if (buf->st_flags & UF_OPAQUE) {
3183 *flags |= UF_OPAQUE;
3184 c_attr[4] = 'o';
3185 }
3186#endif
3187#ifdef SF_ARCHIVED
3188 if (buf->st_flags & SF_ARCHIVED) {
3189 *flags |= SF_ARCHIVED;
3190 c_attr[5] = 'R';
3191 }
3192
3193#endif
3194#ifdef SF_IMMUTABLE
3195 if (buf->st_flags & SF_IMMUTABLE) {
3196 *flags |= SF_IMMUTABLE;
3197 c_attr[6] = 'I';
3198 }
3199#endif
3200#ifdef SF_APPEND
3201 if (buf->st_flags & SF_APPEND) {
3202 *flags |= SF_APPEND;
3203 c_attr[7] = 'A';
3204 }
3205#endif
3206#ifdef SF_NOUNLINK
3207 if (buf->st_flags & SF_NOUNLINK) {
3208 *flags |= SF_NOUNLINK;
3209 c_attr[8] = 'U';
3210 }
3211#endif
3212
3213 /* ! HAVE_STAT_FLAGS */
3214#else
3215
3216#ifdef HAVE_EXT2_IOCTLS
3217 int /* fd, */ r, f;
3218
3219 SL_ENTER(_("sh_unix_getinfo_attr"));
3220
3221 *flags = 0;
3222 (void) buf;
3223
3224 /* open() -> aud_open() R.Wichmann
3225 fd = aud_open (FIL__, __LINE__, SL_YESPRIV, name, O_RDONLY|O_NONBLOCK, 0);
3226 */
3227
3228 if (fd == -1 || name == NULL)
3229 SL_RETURN(-1, _("sh_unix_getinfo_attr"));
3230
3231
3232 r = ioctl (fd, EXT2_IOC_GETFLAGS, &f);
3233 /* sl_close_fd (FIL__, __LINE__, fd); */
3234
3235 if (r == -1)
3236 SL_RETURN(-1, _("sh_unix_getinfo_attr"));
3237
3238 if (f == 0)
3239 SL_RETURN(0, _("sh_unix_getinfo_attr"));
3240
3241 *flags = f;
3242
3243/* ! HAVE_EXT2_IOCTLS */
3244#else
3245
3246 SL_ENTER(_("sh_unix_getinfo_attr"));
3247
3248 *flags = 0; /* modified by R.Wichmann */
3249
3250/* ! HAVE_EXT2_IOCTLS */
3251#endif
3252/*
3253 * END
3254 *
3255 * lsattr.c - List file attributes on an ext2 file system
3256 */
3257
3258 if (*flags == 0)
3259 goto theend;
3260
3261#ifdef EXT2_SECRM_FL
3262 if ( (*flags & EXT2_SECRM_FL) != 0 ) c_attr[0] = 's';
3263#endif
3264#ifdef EXT2_UNRM_FL
3265 if ( (*flags & EXT2_UNRM_FL) != 0 ) c_attr[1] = 'u';
3266#endif
3267#ifdef EXT2_SYNC_FL
3268 if ( (*flags & EXT2_SYNC_FL) != 0 ) c_attr[2] = 'S';
3269#endif
3270#ifdef EXT2_IMMUTABLE_FL
3271 if ( (*flags & EXT2_IMMUTABLE_FL) != 0) c_attr[3] = 'i';
3272#endif
3273#ifdef EXT2_APPEND_FL
3274 if ( (*flags & EXT2_APPEND_FL) != 0 ) c_attr[4] = 'a';
3275#endif
3276#ifdef EXT2_NODUMP_FL
3277 if ( (*flags & EXT2_NODUMP_FL) != 0 ) c_attr[5] = 'd';
3278#endif
3279#ifdef EXT2_NOATIME_FL
3280 if ( (*flags & EXT2_NOATIME_FL) != 0) c_attr[6] = 'A';
3281#endif
3282#ifdef EXT2_COMPR_FL
3283 if ( (*flags & EXT2_COMPR_FL) != 0 ) c_attr[7] = 'c';
3284#endif
3285
3286#ifdef EXT2_TOPDIR_FL
3287 if ( (*flags & EXT2_TOPDIR_FL) != 0 ) c_attr[8] = 'T';
3288#endif
3289#ifdef EXT2_DIRSYNC_FL
3290 if ( (*flags & EXT2_DIRSYNC_FL) != 0 ) c_attr[9] = 'D';
3291#endif
3292#ifdef EXT2_NOTAIL_FL
3293 if ( (*flags & EXT2_NOTAIL_FL) != 0 ) c_attr[10] = 't';
3294#endif
3295#ifdef EXT2_JOURNAL_DATA_FL
3296 if ( (*flags & EXT2_JOURNAL_DATA_FL) != 0) c_attr[11] = 'j';
3297#endif
3298
3299 theend:
3300 /* ext2 */
3301#endif
3302
3303 c_attr[12] = '\0';
3304
3305 SL_RETURN(0, _("sh_unix_getinfo_attr"));
3306}
3307
3308/* defined(__linux__) || defined(HAVE_STAT_FLAGS) */
3309#endif
3310
3311/* determine file type
3312 */
3313static
3314int sh_unix_getinfo_type (struct stat * buf,
3315 ShFileType * type,
3316 char * c_mode)
3317{
3318 SL_ENTER(_("sh_unix_getinfo_type"));
3319
3320 if ( S_ISREG(buf->st_mode) ) {
3321 (*type) = SH_FILE_REGULAR;
3322 c_mode[0] = '-';
3323 }
3324 else if ( S_ISLNK(buf->st_mode) ) {
3325 (*type) = SH_FILE_SYMLINK;
3326 c_mode[0] = 'l';
3327 }
3328 else if ( S_ISDIR(buf->st_mode) ) {
3329 (*type) = SH_FILE_DIRECTORY;
3330 c_mode[0] = 'd';
3331 }
3332 else if ( S_ISCHR(buf->st_mode) ) {
3333 (*type) = SH_FILE_CDEV;
3334 c_mode[0] = 'c';
3335 }
3336 else if ( S_ISBLK(buf->st_mode) ) {
3337 (*type) = SH_FILE_BDEV;
3338 c_mode[0] = 'b';
3339 }
3340 else if ( S_ISFIFO(buf->st_mode) ) {
3341 (*type) = SH_FILE_FIFO;
3342 c_mode[0] = '|';
3343 }
3344 else if ( S_ISSOCK(buf->st_mode) ) {
3345 (*type) = SH_FILE_SOCKET;
3346 c_mode[0] = 's';
3347 }
3348 else if ( S_ISDOOR(buf->st_mode) ) {
3349 (*type) = SH_FILE_DOOR;
3350 c_mode[0] = 'D';
3351 }
3352 else if ( S_ISPORT(buf->st_mode) ) {
3353 (*type) = SH_FILE_PORT;
3354 c_mode[0] = 'P';
3355 }
3356 else {
3357 (*type) = SH_FILE_UNKNOWN;
3358 c_mode[0] = '?';
3359 }
3360
3361 SL_RETURN(0, _("sh_unix_getinfo_type"));
3362}
3363
3364int sh_unix_get_ftype(char * fullpath)
3365{
3366 char c_mode[CMODE_SIZE];
3367 struct stat buf;
3368 ShFileType type;
3369 int res;
3370
3371 SL_ENTER(_("sh_unix_get_ftype"));
3372
3373 res = retry_lstat(FIL__, __LINE__, fullpath, &buf);
3374
3375 if (res < 0)
3376 SL_RETURN(SH_FILE_UNKNOWN, _("sh_unix_getinfo_type"));
3377
3378 sh_unix_getinfo_type (&buf, &type, c_mode);
3379
3380 SL_RETURN(type, _("sh_unix_get_ftype"));
3381}
3382
3383
3384static
3385int sh_unix_getinfo_mode (struct stat *buf,
3386 unsigned int * mode,
3387 char * c_mode)
3388{
3389
3390 SL_ENTER(_("sh_unix_getinfo_mode"));
3391
3392 (*mode) = buf->st_mode;
3393
3394 /* make 'ls'-like string */
3395
3396 if ( (buf->st_mode & S_IRUSR) != 0 ) c_mode[1] = 'r';
3397 if ( (buf->st_mode & S_IWUSR) != 0 ) c_mode[2] = 'w';
3398 if ( (buf->st_mode & S_IXUSR) != 0 ) {
3399 if ((buf->st_mode & S_ISUID) != 0 ) c_mode[3] = 's';
3400 else c_mode[3] = 'x';
3401 } else {
3402 if ((buf->st_mode & S_ISUID) != 0 ) c_mode[3] = 'S';
3403 }
3404
3405 if ( (buf->st_mode & S_IRGRP) != 0 ) c_mode[4] = 'r';
3406 if ( (buf->st_mode & S_IWGRP) != 0 ) c_mode[5] = 'w';
3407 if ( (buf->st_mode & S_IXGRP) != 0 ) {
3408 if ((buf->st_mode & S_ISGID) != 0 ) c_mode[6] = 's';
3409 else c_mode[6] = 'x';
3410 } else {
3411 if ((buf->st_mode & S_ISGID) != 0 ) c_mode[6] = 'S';
3412 }
3413
3414 if ( (buf->st_mode & S_IROTH) != 0 ) c_mode[7] = 'r';
3415 if ( (buf->st_mode & S_IWOTH) != 0 ) c_mode[8] = 'w';
3416#ifdef S_ISVTX /* not POSIX */
3417 if ( (buf->st_mode & S_IXOTH) != 0 ) {
3418 if ((buf->st_mode & S_ISVTX) != 0 ) c_mode[9] = 't';
3419 else c_mode[9] = 'x';
3420 } else {
3421 if ((buf->st_mode & S_ISVTX) != 0 ) c_mode[9] = 'T';
3422 }
3423#else
3424 if ( (buf->st_mode & S_IXOTH) != 0 ) c_mode[9] = 'x';
3425#endif
3426
3427 SL_RETURN(0, _("sh_unix_getinfo_mode"));
3428}
3429
3430
3431long IO_Limit = 0;
3432
3433void sh_unix_io_pause ()
3434{
3435 long runtime;
3436 float someval;
3437 unsigned long sometime;
3438
3439 if (IO_Limit == 0)
3440 {
3441 return;
3442 }
3443 else
3444 {
3445 runtime = (long) (time(NULL) - sh.statistics.time_start);
3446
3447 if (runtime > 0 && (long)(sh.statistics.bytes_hashed/runtime) > IO_Limit)
3448 {
3449 someval = sh.statistics.bytes_hashed - (IO_Limit * runtime);
3450 someval /= (float) IO_Limit;
3451 if (someval < 1.0)
3452 {
3453 someval *= 1000; /* milliseconds in a second */
3454 sometime = (unsigned long) someval;
3455 retry_msleep(0, sometime);
3456 }
3457 else
3458 {
3459 sometime = (unsigned long) someval;
3460 retry_msleep (sometime, 0);
3461 }
3462 }
3463 }
3464 return;
3465}
3466
3467int sh_unix_set_io_limit (const char * c)
3468{
3469 long val;
3470
3471 SL_ENTER(_("sh_unix_set_io_limit"));
3472
3473 val = strtol (c, (char **)NULL, 10);
3474 if (val < 0)
3475 sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS,
3476 _("set I/O limit"), c);
3477
3478 val = (val < 0 ? 0 : val);
3479
3480 IO_Limit = val * 1024;
3481 SL_RETURN( 0, _("sh_unix_set_io_limit"));
3482}
3483
3484/* obtain file info
3485 */
3486extern int flag_err_debug;
3487
3488#include "sh_ignore.h"
3489
3490int sh_unix_checksum_size (char * filename, off_t size, int is_max_size,
3491 char * fileHash, int alert_timeout, SL_TICKET fd, unsigned long mask)
3492{
3493 file_type * tmpFile;
3494 int status;
3495
3496 SL_ENTER(_("sh_unix_checksum_size"));
3497
3498 tmpFile = SH_ALLOC(sizeof(file_type));
3499 tmpFile->link_path = NULL;
3500
3501 if (sh.flag.checkSum != SH_CHECK_INIT)
3502 {
3503 /* lookup file in database */
3504 if (is_max_size == S_TRUE) {
3505 status = sh_hash_get_it (filename, tmpFile, NULL);
3506 if ((status != 0) || (tmpFile->size > size)) {
3507 goto out;
3508 }
3509 } else {
3510 tmpFile->size = size;
3511 }
3512 }
3513 else
3514 {
3515 tmpFile->size = size;
3516 }
3517
3518 /* if last <= current get checksum */
3519 if (tmpFile->size <= size)
3520 {
3521 char hashbuf[KEYBUF_SIZE];
3522 UINT64 local_length = (UINT64) (tmpFile->size < 0 ? 0 : tmpFile->size);
3523 if (sh.flag.opts == S_TRUE) sh_tiger_set_hashtype_mask(mask);
3524 sl_strlcpy(fileHash,
3525 sh_tiger_generic_hash (filename, fd, &(local_length),
3526 alert_timeout, hashbuf, sizeof(hashbuf)),
3527 KEY_LEN+1);
3528
3529 /* return */
3530 if (tmpFile->link_path) SH_FREE(tmpFile->link_path);
3531 SH_FREE(tmpFile);
3532 SL_RETURN( 0, _("sh_unix_checksum_size"));
3533 }
3534
3535 out:
3536 if (tmpFile->link_path) SH_FREE(tmpFile->link_path);
3537 SH_FREE(tmpFile);
3538 sl_strlcpy(fileHash, SH_KEY_NULL, KEY_LEN+1);
3539 SL_RETURN( -1, _("sh_unix_checksum_size"));
3540}
3541
3542/********************************************************
3543 * Search rotated logfile
3544 */
3545extern char * sh_rotated_log_search(const char * path, struct stat * buf);
3546
3547int sh_check_rotated_log (const char * path,
3548 UINT64 old_size, UINT64 old_inode, const char * old_hash, unsigned long mask)
3549{
3550 struct stat obuf;
3551 UINT64 length_nolim = TIGER_NOLIM;
3552 int retval = S_FALSE;
3553
3554 if (old_size != length_nolim)
3555 {
3556 char hashbuf[KEYBUF_SIZE];
3557 char * rotated_file;
3558
3559 obuf.st_ino = old_inode;
3560 rotated_file = sh_rotated_log_search(path, &obuf);
3561
3562 if (rotated_file && (0 != strcmp(path, rotated_file)))
3563 {
3564 SL_TICKET fd = sl_open_fastread (FIL__, __LINE__, rotated_file, SL_YESPRIV);
3565 if (!SL_ISERROR(fd))
3566 {
3567 sh_unix_checksum_size (rotated_file, old_size, S_FALSE,
3568 hashbuf, 120 /* alert_timeout */, fd, mask);
3569
3570 sl_close(fd);
3571
3572 if (strncmp (old_hash, hashbuf, KEY_LEN) == 0) {
3573 retval = S_TRUE;
3574 }
3575 }
3576 SH_FREE(rotated_file);
3577 }
3578 }
3579 return retval;
3580}
3581
3582
3583int sh_unix_check_selinux = S_FALSE;
3584int sh_unix_check_acl = S_FALSE;
3585
3586#ifdef USE_ACL
3587
3588#include <sys/acl.h>
3589static char * sh_unix_getinfo_acl (char * path, int fd, struct stat * buf)
3590{
3591 /* system.posix_acl_access, system.posix_acl_default
3592 */
3593 char * out = NULL;
3594 char * collect = NULL;
3595 char * tmp;
3596 char * out_compact;
3597 ssize_t len;
3598 acl_t result;
3599
3600 SL_ENTER(_("sh_unix_getinfo_acl"));
3601
3602 result = (fd == -1) ?
3603 acl_get_file (path, ACL_TYPE_ACCESS) :
3604 acl_get_fd (fd);
3605
3606 if (result)
3607 {
3608 out = acl_to_text (result, &len);
3609 if (out && (len > 0)) {
3610 out_compact = sh_util_acl_compact (out, len);
3611 acl_free(out);
3612 if (out_compact)
3613 {
3614 collect = sh_util_strconcat (_("acl_access:"), out_compact, NULL);
3615 SH_FREE(out_compact);
3616 }
3617 }
3618 acl_free(result);
3619 }
3620
3621
3622 if ( S_ISDIR(buf->st_mode) )
3623 {
3624 result = acl_get_file (path, ACL_TYPE_DEFAULT);
3625
3626 if (result)
3627 {
3628 out = acl_to_text (result, &len);
3629 if (out && (len > 0)) {
3630 out_compact = sh_util_acl_compact (out, len);
3631 acl_free(out);
3632 if (out_compact) {
3633 if (collect) {
3634 tmp = sh_util_strconcat (_("acl_default:"),
3635 out_compact, ":", collect, NULL);
3636 SH_FREE(collect);
3637 }
3638 else {
3639 tmp = sh_util_strconcat (_("acl_default:"), out_compact, NULL);
3640 }
3641 SH_FREE(out_compact);
3642 collect = tmp;
3643 }
3644 }
3645 acl_free(result);
3646 }
3647 }
3648
3649 SL_RETURN((collect),_("sh_unix_getinfo_acl"));
3650}
3651#endif
3652
3653#ifdef USE_XATTR
3654
3655#include <attr/xattr.h>
3656static char * sh_unix_getinfo_xattr_int (char * path, int fd, char * name)
3657{
3658 char * out = NULL;
3659 char * tmp = NULL;
3660 size_t size = 256;
3661 ssize_t result;
3662
3663 SL_ENTER(_("sh_unix_getinfo_xattr_int"));
3664
3665 out = SH_ALLOC(size);
3666
3667 result = (fd == -1) ?
3668 lgetxattr (path, name, out, size-1) :
3669 fgetxattr (fd, name, out, size-1);
3670
3671 if (result == -1 && errno == ERANGE)
3672 {
3673 SH_FREE(out);
3674 result = (fd == -1) ?
3675 lgetxattr (path, name, NULL, 0) :
3676 fgetxattr (fd, name, NULL, 0);
3677 size = result + 1;
3678 out = SH_ALLOC(size);
3679 result = (fd == -1) ?
3680 lgetxattr (path, name, out, size-1) :
3681 fgetxattr (fd, name, out, size-1);
3682 }
3683
3684 if ((result > 0) && ((size_t)result < size))
3685 {
3686 out[size-1] = '\0';
3687 tmp = out;
3688 }
3689 else
3690 {
3691 SH_FREE(out);
3692 }
3693
3694 SL_RETURN((tmp),_("sh_unix_getinfo_xattr_int"));
3695}
3696
3697
3698static char * sh_unix_getinfo_xattr (char * path, int fd, struct stat * buf)
3699{
3700 /* system.posix_acl_access, system.posix_acl_default, security.selinux
3701 */
3702 char * tmp;
3703 char * out = NULL;
3704 char * collect = NULL;
3705
3706 SL_ENTER(_("sh_unix_getinfo_xattr"));
3707
3708#ifdef USE_ACL
3709 /*
3710 * we need the acl_get_fd/acl_get_file functions, getxattr will only
3711 * yield the raw bytes
3712 */
3713 if (sh_unix_check_acl == S_TRUE)
3714 {
3715 out = sh_unix_getinfo_acl(path, fd, buf);
3716
3717 if (out)
3718 {
3719 collect = out;
3720 }
3721 }
3722#else
3723 (void) buf;
3724#endif
3725
3726 if (sh_unix_check_selinux == S_TRUE)
3727 {
3728 out = sh_unix_getinfo_xattr_int(path, fd, _("security.selinux"));
3729
3730 if (out)
3731 {
3732 if (collect) {
3733 tmp = sh_util_strconcat(_("selinux:"), out, ":", collect, NULL);
3734 SH_FREE(collect);
3735 }
3736 else {
3737 tmp = sh_util_strconcat(_("selinux:"), out, NULL);
3738 }
3739 SH_FREE(out);
3740 collect = tmp;
3741 }
3742 }
3743
3744 SL_RETURN((collect),_("sh_unix_getinfo_xattr"));
3745}
3746#endif
3747
3748#ifdef USE_XATTR
3749int sh_unix_setcheckselinux (const char * c)
3750{
3751 int i;
3752 SL_ENTER(_("sh_unix_setcheckselinux"));
3753 i = sh_util_flagval(c, &(sh_unix_check_selinux));
3754
3755 SL_RETURN(i, _("sh_unix_setcheckselinux"));
3756}
3757#endif
3758
3759#ifdef USE_ACL
3760int sh_unix_setcheckacl (const char * c)
3761{
3762 int i;
3763 SL_ENTER(_("sh_unix_setcheckacl"));
3764 i = sh_util_flagval(c, &(sh_unix_check_acl));
3765
3766 SL_RETURN(i, _("sh_unix_setcheckacl"));
3767}
3768#endif
3769
3770#ifdef HAVE_LIBZ
3771#include <zlib.h>
3772#endif
3773
3774
3775static void * sh_dummy_filename;
3776static void * sh_dummy_tmp;
3777static void * sh_dummy_tmp2;
3778
3779int sh_unix_getinfo (int level, const char * filename, file_type * theFile,
3780 char * fileHash, int policy)
3781{
3782 char timestr[81];
3783 long runtim;
3784 struct stat buf;
3785 struct stat lbuf;
3786 struct stat fbuf;
3787 volatile int stat_return;
3788 volatile int stat_errno = 0;
3789
3790 ShFileType type;
3791 unsigned int mode;
3792 char * tmp;
3793 char * tmp2;
3794
3795 char * linknamebuf;
3796 volatile int linksize;
3797
3798 extern int get_the_fd (SL_TICKET ticket);
3799
3800 volatile SL_TICKET rval_open;
3801 volatile int err_open = 0;
3802
3803 volatile int fd;
3804 volatile int fstat_return;
3805 volatile int fstat_errno = 0;
3806 volatile int try = 0;
3807
3808 sh_string * content = NULL;
3809
3810 time_t tend;
3811 time_t tstart;
3812
3813
3814 char * path = NULL;
3815
3816 volatile int alert_timeout = 120;
3817
3818 path = theFile->fullpath;
3819
3820 SL_ENTER(_("sh_unix_getinfo"));
3821
3822 if (!MODI_INITIALIZED(theFile->check_flags))
3823 {
3824 tmp2 = sh_util_safe_name (theFile->fullpath);
3825 SH_MUTEX_LOCK(mutex_thread_nolog);
3826 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_E_SUBGPATH,
3827 _("Uninitialized check mask"), _("sh_unix_getinfo"),
3828 tmp2);
3829 SH_MUTEX_UNLOCK(mutex_thread_nolog);
3830 SH_FREE(tmp2);
3831 SL_RETURN((-1),_("sh_unix_getinfo"));
3832 }
3833
3834 /* Take the address to keep gcc from putting it into a register.
3835 * Avoids the 'clobbered by longjmp' warning.
3836 */
3837 sh_dummy_filename = (void *) &filename;
3838 sh_dummy_tmp = (void *) &tmp;
3839 sh_dummy_tmp2 = (void *) &tmp2;
3840
3841 /* --- Stat the file, and get checksum. ---
3842 */
3843 tstart = time(NULL);
3844
3845 stat_return = retry_lstat (FIL__, __LINE__,
3846 path /* theFile->fullpath */, &buf);
3847
3848 if (stat_return)
3849 stat_errno = errno;
3850
3851 theFile->link_path = NULL;
3852
3853 try_again:
3854
3855 fd = -1;
3856 fstat_return = -1;
3857 rval_open = -1;
3858
3859 if (stat_return == 0 && S_ISREG(buf.st_mode))
3860 {
3861 rval_open = sl_open_fastread (FIL__, __LINE__,
3862 path /* theFile->fullpath */, SL_YESPRIV);
3863 if (SL_ISERROR(rval_open))
3864 {
3865 char * stale = sl_check_stale();
3866
3867 if (stale)
3868 {
3869 SH_MUTEX_LOCK(mutex_thread_nolog);
3870 sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, err_open, MSG_E_SUBGEN,
3871 stale, _("sh_unix_getinfo_open"));
3872 SH_MUTEX_UNLOCK(mutex_thread_nolog);
3873 }
3874
3875 if (errno == EBADF && try == 0) /* obsolete, but we keep this, just in case */
3876 {
3877 ++try;
3878 goto try_again;
3879 }
3880 err_open = errno;
3881 }
3882
3883 alert_timeout = 120; /* this is per 8K block now ! */
3884
3885 if (path[1] == 'p' && path[5] == '/' && path[2] == 'r' &&
3886 path[3] == 'o' && path[4] == 'c' && path[0] == '/')
3887 {
3888 /* seven is magic */
3889 alert_timeout = 7;
3890 }
3891
3892 fd = get_the_fd(rval_open);
3893 }
3894
3895 tend = time(NULL);
3896
3897 /* An unprivileged user may slow lstat/open to a crawl
3898 * with clever path/symlink setup
3899 */
3900 if ((tend - tstart) > (time_t) /* 60 */ 6)
3901 {
3902 tmp2 = sh_util_safe_name (theFile->fullpath);
3903 SH_MUTEX_LOCK(mutex_thread_nolog);
3904 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_TOOLATE,
3905 (long)(tend - tstart), tmp2);
3906 SH_MUTEX_UNLOCK(mutex_thread_nolog);
3907 SH_FREE(tmp2);
3908 }
3909
3910 if (fd >= 0)
3911 {
3912 fstat_return = retry_fstat (FIL__, __LINE__, fd, &fbuf);
3913
3914 if (fstat_return)
3915 {
3916 char * stale;
3917
3918 fstat_errno = errno;
3919
3920 stale = sl_check_stale();
3921
3922 if (stale)
3923 {
3924 SH_MUTEX_LOCK(mutex_thread_nolog);
3925 sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, fstat_errno,
3926 MSG_E_SUBGEN,
3927 stale, _("sh_unix_getinfo_fstat"));
3928 SH_MUTEX_UNLOCK(mutex_thread_nolog);
3929 }
3930
3931 if (try == 0) /* obsolete, but we keep this, just in case */
3932 {
3933 ++try;
3934 sl_close(rval_open);
3935 goto try_again;
3936 }
3937 }
3938 }
3939 else
3940 {
3941 fd = -1;
3942 }
3943
3944
3945 /* --- case 1: lstat failed ---
3946 */
3947 if (stat_return != 0)
3948 {
3949 stat_return = errno;
3950 if (!SL_ISERROR(rval_open))
3951 sl_close(rval_open);
3952 if (sh.flag.checkSum == SH_CHECK_INIT ||
3953 (sh_hash_have_it (theFile->fullpath) >= 0 &&
3954 (!SH_FFLAG_REPORTED_SET(theFile->file_reported))))
3955 {
3956 if (S_FALSE == sh_ignore_chk_del(theFile->fullpath)) {
3957 int flags = sh_hash_getflags (theFile->fullpath);
3958
3959 if ((flags >= 0) && (flags & SH_FFLAG_ENOENT) == 0) {
3960 char errbuf[SH_ERRBUF_SIZE];
3961 uid_t euid;
3962 (void) sl_get_euid(&euid);
3963 tmp2 = sh_util_safe_name (theFile->fullpath);
3964 SH_MUTEX_LOCK(mutex_thread_nolog);
3965 sh_error_handle (level, FIL__, __LINE__, stat_return, MSG_FI_STAT,
3966 _("lstat"),
3967 sh_error_message (stat_errno, errbuf, sizeof(errbuf)),
3968 (long) euid,
3969 tmp2);
3970 SH_MUTEX_UNLOCK(mutex_thread_nolog);
3971 SH_FREE(tmp2);
3972 sh_hash_set_flag (theFile->fullpath, SH_FFLAG_ENOENT);
3973 }
3974 }
3975 }
3976 SL_RETURN((-1),_("sh_unix_getinfo"));
3977 }
3978
3979 /* --- case 2: not a regular file ---
3980 */
3981 else if (! S_ISREG(buf.st_mode))
3982 {
3983 if (fileHash != NULL)
3984 sl_strlcpy(fileHash, SH_KEY_NULL, KEY_LEN+1);
3985 }
3986
3987 /* --- case 3a: a regular file, fstat ok ---
3988 */
3989 else if (fstat_return == 0 &&
3990 buf.st_mode == fbuf.st_mode &&
3991 buf.st_ino == fbuf.st_ino &&
3992 buf.st_uid == fbuf.st_uid &&
3993 buf.st_gid == fbuf.st_gid &&
3994 buf.st_dev == fbuf.st_dev )
3995 {
3996 if (fileHash != NULL)
3997 {
3998 if ((theFile->check_flags & MODI_CHK) == 0 ||
3999 sh_restrict_this(theFile->fullpath, (UINT64) fbuf.st_size,
4000 (UINT64) fbuf.st_mode, rval_open))
4001 {
4002 sl_strlcpy(fileHash, SH_KEY_NULL, KEY_LEN+1);
4003 }
4004 else if ((theFile->check_flags & MODI_PREL) != 0 &&
4005 S_TRUE == sh_prelink_iself(rval_open, fbuf.st_size,
4006 alert_timeout, theFile->fullpath))
4007 {
4008 if (0 != sh_prelink_run (theFile->fullpath,
4009 fileHash, alert_timeout, theFile->check_flags))
4010 sl_strlcpy(fileHash, SH_KEY_NULL, KEY_LEN+1);
4011 }
4012 else
4013 {
4014 char hashbuf[KEYBUF_SIZE];
4015 UINT64 length_current = TIGER_NOLIM;
4016
4017 if (MODI_TXT_ENABLED(theFile->check_flags) && fbuf.st_size < (10 * SH_TXT_MAX))
4018 {
4019 sl_init_content (rval_open, fbuf.st_size);
4020 }
4021
4022 if (sh.flag.opts == S_TRUE) sh_tiger_set_hashtype_mask(theFile->check_flags);
4023 sl_strlcpy(fileHash,
4024 sh_tiger_generic_hash (theFile->fullpath,
4025 rval_open, &length_current,
4026 alert_timeout,
4027 hashbuf, sizeof(hashbuf)),
4028 KEY_LEN+1);
4029
4030 content = sl_get_content(rval_open);
4031 content = sh_string_copy(content);
4032
4033 if ((theFile->check_flags & MODI_SGROW) != 0)
4034 {
4035 /* Update size so it matches the one for which the checksum
4036 has been computed */
4037 fbuf.st_size = length_current;
4038 buf.st_size = fbuf.st_size;
4039 sl_rewind(rval_open);
4040 sh_unix_checksum_size (theFile->fullpath, length_current, S_TRUE,
4041 &fileHash[KEY_LEN + 1],
4042 alert_timeout, rval_open, theFile->check_flags);
4043 }
4044 }
4045 }
4046 }
4047
4048 /* --- case 3b: a regular file, fstat ok, but different ---
4049 */
4050 else if (fstat_return == 0 && S_ISREG(fbuf.st_mode))
4051 {
4052 memcpy (&buf, &fbuf, sizeof( struct stat ));
4053
4054 if (fileHash != NULL)
4055 {
4056 if ((theFile->check_flags & MODI_CHK) == 0 ||
4057 sh_restrict_this(theFile->fullpath, (UINT64) fbuf.st_size,
4058 (UINT64) fbuf.st_mode, rval_open))
4059 {
4060 sl_strlcpy(fileHash, SH_KEY_NULL, KEY_LEN+1);
4061 }
4062 else if (policy == SH_LEVEL_PRELINK &&
4063 S_TRUE == sh_prelink_iself(rval_open, fbuf.st_size,
4064 alert_timeout, theFile->fullpath))
4065 {
4066 if (0 != sh_prelink_run (theFile->fullpath,
4067 fileHash, alert_timeout, theFile->check_flags))
4068 sl_strlcpy(fileHash, SH_KEY_NULL, KEY_LEN+1);
4069 }
4070 else
4071 {
4072 char hashbuf[KEYBUF_SIZE];
4073 UINT64 length_current = TIGER_NOLIM;
4074
4075 if (MODI_TXT_ENABLED(theFile->check_flags) && fbuf.st_size < (10 * SH_TXT_MAX))
4076 {
4077 sl_init_content (rval_open, fbuf.st_size);
4078 }
4079
4080 if (sh.flag.opts == S_TRUE) sh_tiger_set_hashtype_mask(theFile->check_flags);
4081 sl_strlcpy(fileHash,
4082 sh_tiger_generic_hash (theFile->fullpath, rval_open,
4083 &length_current,
4084 alert_timeout,
4085 hashbuf, sizeof(hashbuf)),
4086 KEY_LEN + 1);
4087
4088 content = sl_get_content(rval_open);
4089 content = sh_string_copy(content);
4090
4091 if ((theFile->check_flags & MODI_SGROW) != 0)
4092 {
4093 /* Update size so it matches the one for which the checksum
4094 has been computed */
4095 fbuf.st_size = length_current;
4096 buf.st_size = fbuf.st_size;
4097 sl_rewind(rval_open);
4098 sh_unix_checksum_size (theFile->fullpath, length_current, S_TRUE,
4099 &fileHash[KEY_LEN + 1],
4100 alert_timeout, rval_open, theFile->check_flags);
4101 }
4102 }
4103 }
4104 }
4105
4106 /* --- case 4: a regular file, fstat failed ---
4107 */
4108
4109 else /* fstat_return != 0 or !S_ISREG(fbuf.st_mode) or open() failed */
4110 {
4111 uid_t euid;
4112
4113 if (fileHash != NULL)
4114 sl_strlcpy(fileHash, SH_KEY_NULL, KEY_LEN+1);
4115
4116 if ((theFile->check_flags & MODI_CHK) != 0)
4117 {
4118 tmp2 = sh_util_safe_name (theFile->fullpath);
4119
4120
4121 if (fd >= 0 && fstat_return != 0)
4122 {
4123 char errbuf[SH_ERRBUF_SIZE];
4124 (void) sl_get_euid(&euid);
4125
4126 SH_MUTEX_LOCK(mutex_thread_nolog);
4127 sh_error_handle (level, FIL__, __LINE__, stat_return, MSG_FI_STAT,
4128 _("fstat"),
4129 sh_error_message (fstat_errno, errbuf, sizeof(errbuf)),
4130 (long) euid,
4131 tmp2);
4132 SH_MUTEX_UNLOCK(mutex_thread_nolog);
4133 }
4134 else if (fd >= 0 && !S_ISREG(fbuf.st_mode))
4135 {
4136 SH_MUTEX_LOCK(mutex_thread_nolog);
4137 sh_error_handle (level, FIL__, __LINE__, fstat_errno,
4138 MSG_E_NOTREG, tmp2);
4139 SH_MUTEX_UNLOCK(mutex_thread_nolog);
4140 }
4141 else
4142 {
4143 char errbuf[SH_ERRBUF_SIZE];
4144 char errbuf2[SH_ERRBUF_SIZE];
4145 sl_strlcpy(errbuf, sl_error_string(rval_open), sizeof(errbuf));
4146 sh_error_message(err_open, errbuf2, sizeof(errbuf2));
4147 SH_MUTEX_LOCK(mutex_thread_nolog);
4148 sh_error_handle (level, FIL__, __LINE__, err_open,
4149 MSG_E_READ, errbuf, errbuf2, tmp2);
4150 SH_MUTEX_UNLOCK(mutex_thread_nolog);
4151 }
4152 SH_FREE(tmp2);
4153 }
4154 }
4155
4156
4157 /* --- Determine file type. ---
4158 */
4159 memset (theFile->c_mode, '-', CMODE_SIZE-1);
4160 theFile->c_mode[CMODE_SIZE-1] = '\0';
4161
4162 memset (theFile->link_c_mode, '-', CMODE_SIZE-1);
4163 theFile->link_c_mode[CMODE_SIZE-1] = '\0';
4164
4165 sh_unix_getinfo_type (&buf, &type, theFile->c_mode);
4166 theFile->type = type;
4167
4168#if defined(__linux__) || defined(HAVE_STAT_FLAGS)
4169
4170 /* --- Determine file attributes. ---
4171 */
4172 memset (theFile->c_attributes, '-', ATTRBUF_SIZE);
4173 theFile->c_attributes[ATTRBUF_USED] = '\0';
4174 theFile->attributes = 0;
4175
4176#if (defined(__linux__) && (defined(HAVE_LINUX_EXT2_FS_H) || defined(HAVE_EXT2FS_EXT2_FS_H))) || defined(HAVE_STAT_FLAGS)
4177 if (theFile->c_mode[0] != 'c' && theFile->c_mode[0] != 'b' &&
4178 theFile->c_mode[0] != 'l' )
4179 sh_unix_getinfo_attr(theFile->fullpath,
4180 &theFile->attributes, theFile->c_attributes,
4181 fd, &buf);
4182#endif
4183#endif
4184
4185#if defined(USE_XATTR) && defined(USE_ACL)
4186 if (sh_unix_check_selinux == S_TRUE || sh_unix_check_acl == S_TRUE)
4187 theFile->attr_string = sh_unix_getinfo_xattr (theFile->fullpath, fd, &buf);
4188#elif defined(USE_XATTR)
4189 if (sh_unix_check_selinux == S_TRUE)
4190 theFile->attr_string = sh_unix_getinfo_xattr (theFile->fullpath, fd, &buf);
4191#elif defined(USE_ACL)
4192 if (sh_unix_check_acl == S_TRUE)
4193 theFile->attr_string = sh_unix_getinfo_acl (theFile->fullpath, fd, &buf);
4194#else
4195 theFile->attr_string = NULL;
4196#endif
4197
4198 if (!SL_ISERROR(rval_open))
4199 sl_close(rval_open);
4200
4201
4202 /* --- I/O limit. ---
4203 */
4204 if (IO_Limit > 0)
4205 {
4206 runtim = (long) (time(NULL) - sh.statistics.time_start);
4207
4208 if (runtim > 0 && (long)(sh.statistics.bytes_hashed/runtim) > IO_Limit)
4209 retry_msleep(1, 0);
4210 }
4211
4212 /* --- Determine permissions. ---
4213 */
4214 sh_unix_getinfo_mode (&buf, &mode, theFile->c_mode);
4215
4216 /* --- Trivia. ---
4217 */
4218 theFile->dev = buf.st_dev;
4219 theFile->ino = buf.st_ino;
4220 theFile->mode = buf.st_mode;
4221 theFile->hardlinks = buf.st_nlink;
4222 theFile->owner = buf.st_uid;
4223 theFile->group = buf.st_gid;
4224 theFile->rdev = buf.st_rdev;
4225 theFile->size = buf.st_size;
4226 theFile->blksize = (unsigned long) buf.st_blksize;
4227 theFile->blocks = (unsigned long) buf.st_blocks;
4228 theFile->atime = buf.st_atime;
4229 theFile->mtime = buf.st_mtime;
4230 theFile->ctime = buf.st_ctime;
4231
4232
4233 /* --- Owner and group. ---
4234 */
4235
4236 if (NULL == sh_unix_getGIDname(SH_ERR_ALL, buf.st_gid, theFile->c_group, GROUP_MAX+1)) {
4237
4238 tmp2 = sh_util_safe_name (theFile->fullpath);
4239
4240 if (policy == SH_LEVEL_ALLIGNORE)
4241 {
4242 SH_MUTEX_LOCK(mutex_thread_nolog);
4243 sh_error_handle (SH_ERR_ALL, FIL__, __LINE__, ENOENT,
4244 MSG_FI_NOGRP,
4245 (long) buf.st_gid, tmp2);
4246 SH_MUTEX_UNLOCK(mutex_thread_nolog);
4247 }
4248 else
4249 {
4250 SH_MUTEX_LOCK(mutex_thread_nolog);
4251 sh_error_handle (ShDFLevel[SH_ERR_T_NAME], FIL__, __LINE__, ENOENT,
4252 MSG_FI_NOGRP,
4253 (long) buf.st_gid, tmp2);
4254 SH_MUTEX_UNLOCK(mutex_thread_nolog);
4255 }
4256 SH_FREE(tmp2);
4257 sl_snprintf(theFile->c_group, GROUP_MAX+1, "%d", (long) buf.st_gid);
4258 }
4259
4260
4261 if (NULL == sh_unix_getUIDname(SH_ERR_ALL, buf.st_uid, theFile->c_owner, USER_MAX+1)) {
4262
4263 tmp2 = sh_util_safe_name (theFile->fullpath);
4264
4265 if (policy == SH_LEVEL_ALLIGNORE)
4266 {
4267 SH_MUTEX_LOCK(mutex_thread_nolog);
4268 sh_error_handle (SH_ERR_ALL, FIL__, __LINE__, ENOENT,
4269 MSG_FI_NOUSR,
4270 (long) buf.st_uid, tmp2);
4271 SH_MUTEX_UNLOCK(mutex_thread_nolog);
4272 }
4273 else
4274 {
4275 SH_MUTEX_LOCK(mutex_thread_nolog);
4276 sh_error_handle (ShDFLevel[SH_ERR_T_NAME], FIL__, __LINE__, ENOENT,
4277 MSG_FI_NOUSR,
4278 (long) buf.st_uid, tmp2);
4279 SH_MUTEX_UNLOCK(mutex_thread_nolog);
4280 }
4281 SH_FREE(tmp2);
4282 sl_snprintf(theFile->c_owner, USER_MAX+1, "%d", (long) buf.st_uid);
4283 }
4284
4285 /* --- Output the file. ---
4286 */
4287 if (flag_err_debug == S_TRUE)
4288 {
4289 tmp2 = sh_util_safe_name ((filename == NULL) ?
4290 theFile->fullpath : filename);
4291 (void) sh_unix_time(theFile->mtime, timestr, sizeof(timestr));
4292 SH_MUTEX_LOCK(mutex_thread_nolog);
4293 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_LIST,
4294 theFile->c_mode,
4295 theFile->hardlinks,
4296 theFile->c_owner,
4297 theFile->c_group,
4298 (unsigned long) theFile->size,
4299 timestr,
4300 tmp2);
4301 SH_MUTEX_UNLOCK(mutex_thread_nolog);
4302 SH_FREE(tmp2);
4303 }
4304
4305 /* --- Check for links. ---
4306 */
4307 if (theFile->c_mode[0] == 'l')
4308 {
4309 linknamebuf = SH_ALLOC(PATH_MAX);
4310
4311 /* flawfinder: ignore */
4312 linksize = readlink (theFile->fullpath, linknamebuf, PATH_MAX-1);
4313
4314 if (linksize < (PATH_MAX-1) && linksize >= 0)
4315 linknamebuf[linksize] = '\0';
4316 else
4317 linknamebuf[PATH_MAX-1] = '\0';
4318
4319 if (linksize < 0)
4320 {
4321 char errbuf[SH_ERRBUF_SIZE];
4322 linksize = errno;
4323 tmp2 = sh_util_safe_name (theFile->fullpath);
4324 SH_MUTEX_LOCK(mutex_thread_nolog);
4325 sh_error_handle (level, FIL__, __LINE__, linksize, MSG_FI_RDLNK,
4326 sh_error_message (linksize, errbuf, sizeof(errbuf)), tmp2);
4327 SH_MUTEX_UNLOCK(mutex_thread_nolog);
4328 SH_FREE(tmp2);
4329 SH_FREE(linknamebuf);
4330 theFile->link_path = sh_util_strdup("-");
4331 SL_RETURN((-1),_("sh_unix_getinfo"));
4332 }
4333
4334 if (linknamebuf[0] == '/')
4335 {
4336 theFile->link_path = sh_util_strdup (linknamebuf);
4337 }
4338 else
4339 {
4340 tmp = sh_util_dirname(theFile->fullpath);
4341 if (tmp) {
4342 theFile->link_path = SH_ALLOC(PATH_MAX);
4343 sl_strlcpy (theFile->link_path, tmp, PATH_MAX);
4344 SH_FREE(tmp);
4345 } else {
4346 theFile->link_path = SH_ALLOC(PATH_MAX);
4347 theFile->link_path[0] = '\0';
4348 }
4349 /*
4350 * Only attach '/' if not root directory. Handle "//", which
4351 * according to POSIX is implementation-defined, and may be
4352 * different from "/" (however, three or more '/' will collapse
4353 * to one).
4354 */
4355 tmp = theFile->link_path; while (*tmp == '/') ++tmp;
4356 if (*tmp != '\0')
4357 {
4358 sl_strlcat (theFile->link_path, "/", PATH_MAX);
4359 }
4360 sl_strlcat (theFile->link_path, linknamebuf, PATH_MAX);
4361 }
4362
4363 /* stat the link
4364 */
4365 stat_return = retry_lstat (FIL__, __LINE__, theFile->link_path, &lbuf);
4366
4367 /* check for error
4368 */
4369 if (stat_return != 0)
4370 {
4371 stat_return = errno;
4372 tmp = sh_util_safe_name (theFile->fullpath);
4373 tmp2 = sh_util_safe_name (theFile->link_path);
4374 if (stat_return != ENOENT)
4375 {
4376 uid_t euid;
4377 char errbuf[SH_ERRBUF_SIZE];
4378
4379 (void) sl_get_euid(&euid);
4380 SH_MUTEX_LOCK(mutex_thread_nolog);
4381 sh_error_handle (level, FIL__, __LINE__, stat_return,
4382 MSG_FI_STAT,
4383 _("lstat (link target)"),
4384 sh_error_message (stat_return,errbuf, sizeof(errbuf)),
4385 (long) euid,
4386 tmp2);
4387 SH_MUTEX_UNLOCK(mutex_thread_nolog);
4388 }
4389 else
4390 {
4391 /* a dangling link -- everybody seems to have plenty of them
4392 */
4393 SH_MUTEX_LOCK(mutex_thread_nolog);
4394 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_DLNK,
4395 tmp, tmp2);
4396 SH_MUTEX_UNLOCK(mutex_thread_nolog);
4397 }
4398 theFile->linkisok = BAD;
4399 SH_FREE(tmp);
4400 SH_FREE(tmp2);
4401 SH_FREE(linknamebuf);
4402 /*
4403 * changed Tue Feb 10 16:16:13 CET 2004:
4404 * add dangling symlinks into database
4405 * SL_RETURN((-1),_("sh_unix_getinfo"));
4406 */
4407 theFile->linkmode = 0;
4408 SL_RETURN((0),_("sh_unix_getinfo"));
4409 }
4410
4411 theFile->linkisok = GOOD;
4412
4413
4414 /* --- Determine file type. ---
4415 */
4416 sh_unix_getinfo_type (&lbuf, &type, theFile->link_c_mode);
4417 theFile->type = type;
4418
4419 /* --- Determine permissions. ---
4420 */
4421 sh_unix_getinfo_mode (&lbuf, &mode, theFile->link_c_mode);
4422 theFile->linkmode = lbuf.st_mode;
4423
4424 /* --- Output the link. ---
4425 */
4426 if (theFile->linkisok == GOOD)
4427 {
4428 tmp2 = sh_util_safe_name (linknamebuf);
4429 SH_MUTEX_LOCK(mutex_thread_nolog);
4430 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_LLNK,
4431 theFile->link_c_mode, tmp2);
4432 SH_MUTEX_UNLOCK(mutex_thread_nolog);
4433 SH_FREE(tmp2);
4434 }
4435 SH_FREE(linknamebuf);
4436 }
4437 else /* not a link, theFile->c_mode[0] != 'l' */
4438 {
4439 if (content)
4440 {
4441#ifdef HAVE_LIBZ
4442 unsigned long clen;
4443 unsigned char * compressed;
4444#ifdef HAVE_COMPRESSBOUND
4445 clen = compressBound(sh_string_len(content));
4446#else
4447 if (sh_string_len(content) > 10*SH_TXT_MAX)
4448 clen = SH_TXT_MAX;
4449 else
4450 clen = 13 + (int)(1.0001*sh_string_len(content));
4451#endif
4452 compressed = SH_ALLOC(clen);
4453 if (Z_OK == compress(compressed, &clen,
4454 (unsigned char *) sh_string_str(content),
4455 sh_string_len(content)))
4456 {
4457 if (clen < SH_TXT_MAX)
4458 {
4459 sh_util_base64_enc_alloc (&(theFile->link_path),
4460 (char *) compressed, clen);
4461 }
4462 else
4463 {
4464 char tmsg[128];
4465 char * tpath = sh_util_safe_name (theFile->fullpath);
4466 sl_snprintf(tmsg, sizeof(tmsg),
4467 _("compressed file too large (%lu bytes)"),
4468 clen);
4469 SH_MUTEX_LOCK(mutex_thread_nolog);
4470 sh_error_handle (SH_ERR_WARN, FIL__, __LINE__, -1,
4471 MSG_E_SUBGPATH, tmsg,
4472 _("sh_unix_getinfo"), tpath);
4473 SH_MUTEX_UNLOCK(mutex_thread_nolog);
4474 SH_FREE(tpath);
4475 }
4476 }
4477 SH_FREE(compressed);
4478#endif
4479 sh_string_destroy(&content);
4480 }
4481 }
4482 SL_RETURN((0),_("sh_unix_getinfo"));
4483}
4484
4485/* #if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE) */
4486#endif
4487
4488int sh_unix_unlock(char * lockfile, char * flag)
4489{
4490 int error = 0;
4491
4492 SL_ENTER(_("sh_unix_unlock"));
4493
4494 if (sh.flag.isdaemon == S_FALSE && flag == NULL)
4495 SL_RETURN((0),_("sh_unix_unlock"));
4496
4497 /* --- Logfile is not locked to us. ---
4498 */
4499 if (sh.flag.islocked == BAD && flag != NULL)
4500 SL_RETURN((-1),_("sh_unix_unlock"));
4501
4502 /* --- Check whether the directory is secure. ---
4503 */
4504 if (0 != tf_trust_check (lockfile, SL_YESPRIV))
4505 SL_RETURN((-1),_("sh_unix_unlock"));
4506
4507 /* --- Delete the lock file. ---
4508 */
4509 error = retry_aud_unlink (FIL__, __LINE__, lockfile);
4510
4511 if (error == 0)
4512 {
4513 if (flag != NULL)
4514 sh.flag.islocked = BAD; /* not locked anymore */
4515 }
4516 else if (flag != NULL)
4517 {
4518 char errbuf[SH_ERRBUF_SIZE];
4519 error = errno;
4520 sh_error_handle ((-1), FIL__, __LINE__, error, MSG_E_UNLNK,
4521 sh_error_message(error, errbuf, sizeof(errbuf)),
4522 lockfile);
4523 SL_RETURN((-1),_("sh_unix_unlock"));
4524 }
4525 SL_RETURN((0),_("sh_unix_unlock"));
4526}
4527
4528int sh_unix_check_piddir (char * pidpath)
4529{
4530 static struct stat buf;
4531 int status = 0;
4532 char * pid_dir;
4533
4534 SL_ENTER(_("sh_unix_check_piddir"));
4535
4536 pid_dir = sh_util_dirname (pidpath);
4537
4538 status = retry_lstat (FIL__, __LINE__, pid_dir, &buf);
4539
4540 if (status < 0 && errno == ENOENT)
4541 {
4542 status = mkdir (pid_dir, 0777);
4543 if (status < 0)
4544 {
4545 sh_error_handle ((-1), FIL__, __LINE__, status,
4546 MSG_E_SUBGEN,
4547 _("Cannot create PID directory"),
4548 _("sh_unix_check_piddir"));
4549 SH_FREE(pid_dir);
4550 SL_RETURN((-1),_("sh_unix_check_piddir"));
4551 }
4552 }
4553 else if (!S_ISDIR(buf.st_mode))
4554 {
4555 sh_error_handle ((-1), FIL__, __LINE__, status,
4556 MSG_E_SUBGEN,
4557 _("Path of PID directory refers to a non-directory object"),
4558 _("sh_unix_check_piddir"));
4559 SH_FREE(pid_dir);
4560 SL_RETURN((-1),_("sh_unix_check_piddir"));
4561 }
4562 SH_FREE(pid_dir);
4563 SL_RETURN((0),_("sh_unix_check_piddir"));
4564}
4565
4566int sh_unix_lock (char * lockfile, char * flag)
4567{
4568 int filed;
4569 int errnum;
4570 char myPid[64];
4571 SL_TICKET fd;
4572 extern int get_the_fd (SL_TICKET ticket);
4573
4574 SL_ENTER(_("sh_unix_lock"));
4575
4576 sprintf (myPid, "%ld\n", (long) sh.pid); /* known to fit */
4577
4578 if (flag == NULL) /* PID file, check for directory */
4579 {
4580 if (0 != sh_unix_check_piddir (lockfile))
4581 {
4582 SL_RETURN((-1),_("sh_unix_lock"));
4583 }
4584 }
4585
4586 fd = sl_open_safe_rdwr (FIL__, __LINE__,
4587 lockfile, SL_YESPRIV); /* fails if file exists */
4588
4589 if (!SL_ISERROR(fd))
4590 {
4591 errnum = sl_write (fd, myPid, sl_strlen(myPid));
4592 filed = get_the_fd(fd);
4593 fchmod (filed, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
4594 sl_close (fd);
4595
4596 if (!SL_ISERROR(errnum))
4597 {
4598 if (flag != NULL)
4599 sh.flag.islocked = GOOD;
4600 SL_RETURN((0),_("sh_unix_lock"));
4601 }
4602 }
4603
4604 TPT((0, FIL__, __LINE__, _("msg=<open pid file failed>\n")));
4605 if (flag != NULL)
4606 sh.flag.islocked = BAD;
4607 SL_RETURN((-1),_("sh_unix_lock"));
4608
4609 /* notreached */
4610}
4611
4612
4613/* check whether file is locked
4614 */
4615int sh_unix_test_and_lock (char * filename, char * lockfile)
4616{
4617 static struct stat buf;
4618 int status = 0;
4619
4620
4621 SL_TICKET fd;
4622 char line_in[128];
4623
4624 SL_ENTER(_("sh_unix_test_and_lock"));
4625
4626 status = retry_lstat (FIL__, __LINE__, lockfile, &buf);
4627
4628 /* --- No lock file found, try to lock. ---
4629 */
4630
4631 if (status < 0 && errno == ENOENT)
4632 {
4633 if (0 == sh_unix_lock (lockfile, filename))
4634 {
4635 if (filename != NULL)
4636 sh.flag.islocked = GOOD;
4637 SL_RETURN((0),_("sh_unix_test_and_lock"));
4638 }
4639 else
4640 {
4641 sh_error_handle ((-1), FIL__, __LINE__, status,
4642 MSG_E_SUBGEN,
4643 (filename == NULL) ? _("Cannot create PID file (1)") : _("Cannot create lock file (1)"),
4644 _("sh_unix_test_and_lock"));
4645 SL_RETURN((-1),_("sh_unix_test_and_lock"));
4646 }
4647 }
4648 else if (status == 0 && buf.st_size == 0)
4649 {
4650 if (filename != NULL)
4651 sh.flag.islocked = GOOD;
4652 sh_unix_unlock (lockfile, filename);
4653 if (filename != NULL)
4654 sh.flag.islocked = BAD;
4655 if (0 == sh_unix_lock (lockfile, filename))
4656 {
4657 if (filename != NULL)
4658 sh.flag.islocked = GOOD;
4659 SL_RETURN((0),_("sh_unix_test_and_lock"));
4660 }
4661 else
4662 {
4663 sh_error_handle ((-1), FIL__, __LINE__, status,
4664 MSG_E_SUBGEN,
4665 (filename == NULL) ? _("Cannot create PID file (2)") : _("Cannot create lock file (2)"),
4666 _("sh_unix_test_and_lock"));
4667 SL_RETURN((-1),_("sh_unix_test_and_lock"));
4668 }
4669 }
4670
4671 /* --- Check on lock. ---
4672 */
4673
4674 if (status >= 0)
4675 {
4676 fd = sl_open_read (FIL__, __LINE__, lockfile, SL_YESPRIV);
4677 if (SL_ISERROR(fd))
4678 sh_error_handle ((-1), FIL__, __LINE__, fd,
4679 MSG_E_SUBGEN,
4680 (filename == NULL) ? _("Cannot open PID file for read") : _("Cannot open lock file for read"),
4681 _("sh_unix_test_and_lock"));
4682 }
4683 else
4684 fd = -1;
4685
4686 if (!SL_ISERROR(fd))
4687 {
4688 /* read the PID in the lock file
4689 */
4690 status = sl_read (fd, line_in, sizeof(line_in));
4691 line_in[sizeof(line_in)-1] = '\0';
4692
4693 /* convert to numeric
4694 */
4695 if (status > 0)
4696 {
4697 errno = 0;
4698 status = strtol(line_in, (char **)NULL, 10);
4699 if (errno == ERANGE || status <= 0)
4700 {
4701 sh_error_handle ((-1), FIL__, __LINE__, status,
4702 MSG_E_SUBGEN,
4703 (filename == NULL) ? _("Bad PID in PID file") : _("Bad PID in lock file"),
4704 _("sh_unix_test_and_lock"));
4705
4706 status = -1;
4707 }
4708 }
4709 else
4710 {
4711 sh_error_handle ((-1), FIL__, __LINE__, status,
4712 MSG_E_SUBGEN,
4713 (filename == NULL) ? _("Cannot read PID file") : _("Cannot read lock file"),
4714 _("sh_unix_test_and_lock"));
4715 }
4716 sl_close(fd);
4717
4718 if (status > 0 && (unsigned int) status == sh.pid)
4719 {
4720 if (filename != NULL)
4721 sh.flag.islocked = GOOD;
4722 SL_RETURN((0),_("sh_unix_test_and_lock"));
4723 }
4724
4725
4726 /* --- Check whether the process exists. ---
4727 */
4728 if (status > 0)
4729 {
4730 errno = 0;
4731 status = aud_kill (FIL__, __LINE__, status, 0);
4732
4733 /* Does not exist, so remove the stale lock
4734 * and create a new one.
4735 */
4736 if (status < 0 && errno == ESRCH)
4737 {
4738 if (filename != NULL)
4739 sh.flag.islocked = GOOD;
4740 if (0 != sh_unix_unlock(lockfile, filename) && (filename !=NULL))
4741 sh.flag.islocked = BAD;
4742 else
4743 {
4744 if (0 == sh_unix_lock (lockfile, filename))
4745 {
4746 if (filename != NULL)
4747 sh.flag.islocked = GOOD;
4748 SL_RETURN((0),_("sh_unix_test_and_lock"));
4749 }
4750 else
4751 {
4752 sh_error_handle ((-1), FIL__, __LINE__, status,
4753 MSG_E_SUBGEN,
4754 (filename == NULL) ? _("Cannot create PID file (3)") : _("Cannot create lock file (3)"),
4755 _("sh_unix_test_and_lock"));
4756 }
4757 if (filename != NULL)
4758 sh.flag.islocked = BAD;
4759 }
4760 }
4761 else
4762 {
4763 sh_error_handle ((-1), FIL__, __LINE__, status,
4764 MSG_E_SUBGEN,
4765 (filename == NULL) ? _("Cannot remove stale PID file, PID may be a running process") : _("Cannot remove stale lock file, PID may be a running process"),
4766 _("sh_unix_test_and_lock"));
4767 if (filename != NULL)
4768 sh.flag.islocked = BAD;
4769 }
4770 }
4771 }
4772 SL_RETURN((-1),_("sh_unix_testlock"));
4773}
4774
4775/* write the PID file
4776 */
4777int sh_unix_write_pid_file()
4778{
4779 return sh_unix_test_and_lock(NULL, sh.srvlog.alt);
4780}
4781
4782/* write lock for filename
4783 */
4784int sh_unix_write_lock_file(char * filename)
4785{
4786 size_t len;
4787 int res;
4788 char * lockfile;
4789
4790 if (filename == NULL)
4791 return (-1);
4792
4793 len = sl_strlen(filename);
4794 if (sl_ok_adds(len, 6))
4795 len += 6;
4796 lockfile = SH_ALLOC(len);
4797 sl_strlcpy(lockfile, filename, len);
4798 sl_strlcat(lockfile, _(".lock"), len);
4799 res = sh_unix_test_and_lock(filename, lockfile);
4800 SH_FREE(lockfile);
4801 return res;
4802}
4803
4804/* rm lock for filename
4805 */
4806int sh_unix_rm_lock_file(char * filename)
4807{
4808 size_t len;
4809 int res;
4810 char * lockfile;
4811
4812 if (filename == NULL)
4813 return (-1);
4814
4815 len = sl_strlen(filename);
4816 if (sl_ok_adds(len, 6))
4817 len += 6;
4818 lockfile = SH_ALLOC(len);
4819 sl_strlcpy(lockfile, filename, len);
4820 sl_strlcat(lockfile, _(".lock"), len);
4821
4822 res = sh_unix_unlock(lockfile, filename);
4823 SH_FREE(lockfile);
4824 return res;
4825}
4826
4827/* rm lock for filename
4828 */
4829int sh_unix_rm_pid_file()
4830{
4831 return sh_unix_unlock(sh.srvlog.alt, NULL);
4832}
4833
4834/* Test whether file exists
4835 */
4836int sh_unix_file_exists(char * path)
4837{
4838 struct stat buf;
4839
4840 SL_ENTER(_("sh_unix_file_exists"));
4841
4842 if (0 == retry_lstat(FIL__, __LINE__, path, &buf))
4843 SL_RETURN( S_TRUE, _("sh_unix_file_exists"));
4844 else
4845 SL_RETURN( S_FALSE, _("sh_unix_file_exists"));
4846}
4847
4848
4849/* Test whether file exists, is a character device, and allows read
4850 * access.
4851 */
4852int sh_unix_device_readable(int fd)
4853{
4854 struct stat buf;
4855
4856 SL_ENTER(_("sh_unix_device_readable"));
4857
4858 if (retry_fstat(FIL__, __LINE__, fd, &buf) == -1)
4859 SL_RETURN( (-1), _("sh_unix_device_readable"));
4860 else if ( S_ISCHR(buf.st_mode) && 0 != (S_IROTH & buf.st_mode) )
4861 SL_RETURN( (0), _("sh_unix_device_readable"));
4862 else
4863 SL_RETURN( (-1), _("sh_unix_device_readable"));
4864}
4865
4866static char preq[16];
4867
4868/* return true if database is remote
4869 */
4870int file_is_remote ()
4871{
4872 static int init = 0;
4873 struct stat buf;
4874
4875 SL_ENTER(_("file_is_remote"));
4876
4877 if (init == 0)
4878 {
4879 sl_strlcpy(preq, _("REQ_FROM_SERVER"), 16);
4880 ++init;
4881 }
4882 if (0 == sl_strncmp (sh.data.path, preq, 15))
4883 {
4884 if (sh.data.path[15] != '\0') /* should be start of path */
4885 {
4886 if (0 == stat(&(sh.data.path[15]), &buf))
4887 {
4888 SL_RETURN( S_FALSE, _("file_is_remote"));
4889 }
4890 else
4891 {
4892 char * tmp = sh_util_safe_name (&(sh.data.path[15]));
4893 sh_error_handle((-1), FIL__, __LINE__, S_FALSE, MSG_E_SUBGPATH,
4894 _("No local baseline database at expected path"),
4895 _("file_is_remote"),
4896 tmp);
4897 SH_FREE(tmp);
4898 }
4899 }
4900 else
4901 {
4902 sh_error_handle((-1), FIL__, __LINE__, S_FALSE, MSG_E_SUBGEN,
4903 _("No local baseline database path known"),
4904 _("file_is_remote"));
4905 }
4906 SL_RETURN( S_TRUE, _("file_is_remote"));
4907 }
4908 SL_RETURN( S_FALSE, _("file_is_remote"));
4909}
4910
4911/* Return the path to the configuration/database file.
4912 */
4913char * file_path(char what, char flag)
4914{
4915 static int init = 0;
4916
4917 SL_ENTER(_("file_path"));
4918
4919 if (init == 0)
4920 {
4921 sl_strlcpy(preq, _("REQ_FROM_SERVER"), 16);
4922 ++init;
4923 }
4924
4925 switch (what)
4926 {
4927
4928 case 'C':
4929 if (0 == sl_strncmp (sh.conf.path, preq, 15))
4930 {
4931#if defined(SH_WITH_SERVER)
4932 if (sh.flag.isserver == S_TRUE && sl_strlen(sh.conf.path) == 15)
4933 SL_RETURN( NULL, _("file_path"));
4934 if (sh.flag.isserver == S_TRUE)
4935 SL_RETURN( &(sh.conf.path[15]), _("file_path"));
4936#endif
4937 if (flag == 'R')
4938 SL_RETURN( preq, _("file_path"));
4939 if (flag == 'I')
4940 {
4941 if (sl_strlen(sh.conf.path) == 15)
4942 SL_RETURN( NULL, _("file_path"));
4943 else
4944 SL_RETURN( &(sh.conf.path[15]), _("file_path"));
4945 }
4946 SL_RETURN ( preq, _("file_path"));
4947 }
4948 else
4949 SL_RETURN( sh.conf.path, _("file_path"));
4950 /* break; *//* unreachable */
4951
4952 case 'D':
4953 if (0 == sl_strncmp (sh.data.path, preq, 15))
4954 {
4955 if (flag == 'R')
4956 SL_RETURN( preq, _("file_path"));
4957 if (flag == 'W' && sl_strlen(sh.data.path) == 15)
4958 SL_RETURN (NULL, _("file_path"));
4959 if (flag == 'W')
4960 SL_RETURN( &(sh.data.path[15]), _("file_path"));
4961 }
4962 else
4963 SL_RETURN( sh.data.path, _("file_path"));
4964 break;
4965
4966 default:
4967 SL_RETURN( NULL, _("file_path"));
4968 }
4969
4970 return NULL; /* notreached */
4971}
4972/************************************************/
4973/**** Mlock Utilities ****/
4974/************************************************/
4975
4976#include <limits.h>
4977
4978int sh_unix_pagesize()
4979{
4980 int pagesize = 4096;
4981#if defined(_SC_PAGESIZE)
4982 pagesize = sysconf(_SC_PAGESIZE);
4983#elif defined(_SC_PAGE_SIZE)
4984 pagesize = sysconf(_SC_PAGE_SIZE);
4985#elif defined(HAVE_GETPAGESIZE)
4986 pagesize = getpagesize();
4987#elif defined(PAGESIZE)
4988 pagesize = PAGESIZE;
4989#endif
4990
4991 return ((pagesize > 0) ? pagesize : 4096);
4992}
4993
4994typedef struct sh_page_lt {
4995 unsigned long page_start;
4996 int page_refcount;
4997 char file[64];
4998 int line;
4999 struct sh_page_lt * next;
5000} sh_page_l;
5001
5002sh_page_l * sh_page_locked = NULL;
5003volatile int page_locking = 0;
5004
5005unsigned long sh_unix_lookup_page (void * in_addr, size_t len, int * num_pages)
5006{
5007 int pagesize = sh_unix_pagesize();
5008 unsigned long addr = (unsigned long) in_addr;
5009
5010 unsigned long pagebase;
5011 unsigned long pagediff;
5012 unsigned long pagenum = addr / pagesize;
5013
5014 SL_ENTER(_("sh_unix_lookup_page"));
5015#if 0
5016 fprintf(stderr, "mlock: --> base %ld, pagenum: %ld\n",
5017 addr, pagenum);
5018#endif
5019
5020 /* address of first page
5021 */
5022 pagebase = pagenum * pagesize;
5023
5024 /* number of pages
5025 */
5026 pagediff = (addr + len) - pagebase;
5027 pagenum = pagediff / pagesize;
5028 if (pagenum * pagesize < pagediff)
5029 ++pagenum;
5030
5031#if 0
5032 fprintf(stderr, "mlock: --> pagebase %ld, pagediff %ld, (addr + len) %ld\n",
5033 pagebase, pagediff, (addr + len));
5034#endif
5035
5036 *num_pages = pagenum;
5037 SL_RETURN((pagebase), _("sh_unix_lookup_page"));
5038}
5039
5040
5041#if defined(HAVE_MLOCK) && !defined(HAVE_BROKEN_MLOCK)
5042
5043SH_MUTEX_STATIC(mutex_mlock,PTHREAD_MUTEX_INITIALIZER);
5044
5045int sh_unix_mlock (const char * file, int line, void * in_addr, size_t len)
5046{
5047 int num_pages;
5048 int status = 0;
5049 int pagesize;
5050 sh_page_l * page_list;
5051 unsigned long addr;
5052#ifdef TEST_MLOCK
5053 int i = 0;
5054#endif
5055
5056 SL_ENTER(_("sh_unix_mlock"));
5057
5058 /* There's no cancellation point here, except if tracing is on
5059 */
5060 SH_MUTEX_LOCK_UNSAFE(mutex_mlock);
5061
5062 page_list = sh_page_locked;
5063
5064 if (0 != page_locking)
5065 {
5066 status = -1;
5067 goto exit_mlock;
5068 }
5069
5070 page_locking = 1;
5071
5072 pagesize = sh_unix_pagesize();
5073 addr = sh_unix_lookup_page (in_addr, len, &num_pages);
5074
5075#ifdef TEST_MLOCK
5076 fprintf(stderr, "mlock: addr %ld, base %ld, pages: %d, length %d\n",
5077 (unsigned long) in_addr, addr, num_pages, len);
5078#endif
5079
5080 /* increase refcount of locked pages
5081 * addr is first page; num_pages is #(consecutive pages) to lock
5082 */
5083
5084 while ((page_list != NULL) && (num_pages > 0))
5085 {
5086#ifdef TEST_MLOCK
5087 fprintf(stderr, "mlock: check page %d: %ld [%d]\n",
5088 i, page_list->page_start, page_list->page_refcount);
5089#endif
5090 if (page_list->page_start == addr)
5091 {
5092 page_list->page_refcount += 1;
5093 num_pages -= 1;
5094 addr += pagesize;
5095#ifdef TEST_MLOCK
5096 fprintf(stderr, "mlock: found page %d: %ld [%d], next page %ld\n",
5097 i, page_list->page_start, page_list->page_refcount, addr);
5098#endif
5099 }
5100#ifdef TEST_MLOCK
5101 ++i;
5102#endif
5103 page_list = page_list->next;
5104 }
5105
5106 /* mlock some more pages, if needed
5107 */
5108 while (num_pages > 0)
5109 {
5110#ifdef TEST_MLOCK
5111 fprintf(stderr, "mlock: lock page %d: mlock %ld [num_pages %d]\n",
5112 i, addr, num_pages);
5113 ++i;
5114#endif
5115 page_list = SH_ALLOC(sizeof(sh_page_l));
5116 page_list->page_start = addr;
5117 page_list->page_refcount = 1;
5118 sl_strlcpy(page_list->file, file, 64);
5119 page_list->line = line;
5120 status = mlock( (void *) addr, pagesize);
5121 if (status != 0)
5122 {
5123#ifdef TEST_MLOCK
5124 char errbuf[SH_ERRBUF_SIZE];
5125 fprintf(stderr, "mlock: error: %s\n",
5126 sh_error_message(errno, errbuf, sizeof(errbuf)));
5127#endif
5128 SH_FREE(page_list);
5129 page_locking = 0;
5130 goto exit_mlock;
5131 }
5132 page_list->next = sh_page_locked;
5133 sh_page_locked = page_list;
5134 num_pages -= 1;
5135 addr += pagesize;
5136 }
5137 page_locking = 0;
5138
5139 exit_mlock:
5140 SH_MUTEX_UNLOCK_UNSAFE(mutex_mlock);
5141
5142 SL_RETURN((status), _("sh_unix_mlock"));
5143}
5144#else
5145int sh_unix_mlock (const char * file, int line, void * in_addr, size_t len)
5146{
5147 (void) file; (void) line;
5148 (void) in_addr; (void) len;
5149 return -1;
5150}
5151#endif
5152
5153#if defined(HAVE_MLOCK) && !defined(HAVE_BROKEN_MLOCK)
5154int sh_unix_munlock (void * in_addr, size_t len)
5155{
5156 int num_pages;
5157 int unlocked;
5158 int status;
5159 int pagesize;
5160 sh_page_l * page_list;
5161 sh_page_l * page_last;
5162 unsigned long addr;
5163
5164 int test_count;
5165 int test_status;
5166 int test_pages;
5167
5168#ifdef TEST_MLOCK
5169 int i = 0;
5170#endif
5171
5172 SL_ENTER(_("sh_unix_munlock"));
5173
5174 /* There's no cancellation point here, except if tracing is on
5175 */
5176 SH_MUTEX_LOCK_UNSAFE(mutex_mlock);
5177
5178 unlocked = 0;
5179 status = 0;
5180 page_list = sh_page_locked;
5181
5182 if (0 != page_locking)
5183 {
5184 status = -1;
5185 goto exit_munlock;
5186 }
5187 page_locking = 1;
5188
5189 pagesize = sh_unix_pagesize();
5190 addr = sh_unix_lookup_page (in_addr, len, &num_pages);
5191
5192#ifdef TEST_MLOCK
5193 fprintf(stderr, "munlock: in_addr %ld, addr %ld, pages: %d, length %d\n",
5194 (unsigned long) in_addr, addr, num_pages, len);
5195#endif
5196
5197 test_pages = num_pages;
5198
5199 /* reduce refcount of locked pages
5200 * addr is first page; num_pages is #(consecutive pages) to lock
5201 */
5202 while ((page_list != NULL) && (num_pages > 0))
5203 {
5204#ifdef TEST_MLOCK
5205 fprintf(stderr, "munlock: page %d: %ld [%d]\n",
5206 i, page_list->page_start, page_list->page_refcount);
5207#endif
5208
5209 test_status = 0;
5210 for (test_count = 0; test_count < test_pages; ++test_count)
5211 {
5212 if (page_list->page_start == (addr + (test_count * pagesize)))
5213 {
5214 test_status = 1;
5215 break;
5216 }
5217 }
5218
5219 if (test_status == 1)
5220 {
5221 page_list->page_refcount -= 1;
5222 if (page_list->page_refcount == 0)
5223 {
5224 status = munlock ( (void *) addr, pagesize);
5225 ++unlocked;
5226 }
5227 num_pages -= 1;
5228#ifdef TEST_MLOCK
5229 fprintf(stderr,
5230 "munlock: page %d: %ld [refcount %d], refcount reduced\n",
5231 i, page_list->page_start, page_list->page_refcount);
5232#endif
5233 }
5234#ifdef TEST_MLOCK
5235 ++i;
5236#endif
5237 page_list = page_list->next;
5238 }
5239
5240#ifdef TEST_MLOCK
5241 i = 0;
5242#endif
5243
5244 if (unlocked > 0)
5245 {
5246 page_list = sh_page_locked;
5247 page_last = sh_page_locked;
5248
5249 while ((page_list != NULL) && (unlocked > 0))
5250 {
5251 if (page_list->page_refcount == 0)
5252 {
5253#ifdef TEST_MLOCK
5254 fprintf(stderr, "munlock: remove page %d: %ld [refcount %d]\n",
5255 i, page_list->page_start, page_list->page_refcount);
5256#endif
5257 if (page_last != page_list)
5258 {
5259 page_last->next = page_list->next;
5260 SH_FREE(page_list);
5261 page_list = page_last->next;
5262 }
5263 else
5264 {
5265 page_last = page_list->next;
5266 if (page_list == sh_page_locked)
5267 sh_page_locked = page_list->next;
5268 SH_FREE(page_list);
5269 page_list = page_last;
5270 }
5271 --unlocked;
5272 }
5273 else
5274 {
5275#ifdef TEST_MLOCK
5276 fprintf(stderr, "munlock: skip page %d: %ld [refcount %d]\n",
5277 i, page_list->page_start, page_list->page_refcount);
5278#endif
5279
5280 page_last = page_list;
5281 page_list = page_list->next;
5282 }
5283#ifdef TEST_MLOCK
5284 ++i;
5285#endif
5286 }
5287 }
5288
5289 page_locking = 0;
5290
5291 exit_munlock:
5292 SH_MUTEX_UNLOCK_UNSAFE(mutex_mlock);
5293 SL_RETURN((status), _("sh_unix_munlock"));
5294}
5295#else
5296int sh_unix_munlock (void * in_addr, size_t len)
5297{
5298 (void) in_addr; (void) len;
5299 return -1;
5300}
5301#endif
5302
5303int sh_unix_count_mlock()
5304{
5305 unsigned int i = 0;
5306 char str[32][64];
5307 sh_page_l * page_list;
5308
5309 SL_ENTER(_("sh_unix_count_mlock"));
5310
5311#if defined(HAVE_MLOCK) && !defined(HAVE_BROKEN_MLOCK)
5312 /* There's no cancellation point here, except if tracing is on
5313 */
5314 SH_MUTEX_LOCK_UNSAFE(mutex_mlock);
5315#endif
5316
5317 page_list = sh_page_locked;
5318
5319 while (page_list != NULL)
5320 {
5321#ifdef WITH_TPT
5322 if (i < 32)
5323 sl_snprintf(str[i], 64, _("file: %s line: %d page: %d"),
5324 page_list->file, page_list->line, i+1);
5325#endif
5326 page_list = page_list->next;
5327 ++i;
5328 }
5329
5330#if defined(HAVE_MLOCK) && !defined(HAVE_BROKEN_MLOCK)
5331 SH_MUTEX_UNLOCK_UNSAFE(mutex_mlock);
5332#endif
5333
5334#ifdef WITH_TPT
5335 {
5336 unsigned int j = 0;
5337 while (j < i && j < 32)
5338 {
5339 sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, j, MSG_E_SUBGEN,
5340 str[j], _("sh_unix_count_mlock"));
5341 ++j;
5342 }
5343 }
5344#endif
5345
5346 sl_snprintf(str[0], 64, _("%d pages locked"), i);
5347 sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, i, MSG_E_SUBGEN,
5348 str[0], _("sh_unix_count_mlock"));
5349 SL_RETURN((i), _("sh_unix_count_mlock"));
5350}
5351
5352/************************************************/
5353/************************************************/
5354/**** Stealth Utilities ****/
5355/************************************************/
5356/************************************************/
5357#ifdef SH_STEALTH
5358
5359void sh_unix_xor_code (char * str, int len)
5360{
5361 register int i;
5362
5363 for (i = 0; i < len; ++i) str[i] ^= (char) XOR_CODE;
5364 return;
5365}
5366
5367#if !defined(SH_STEALTH_MICRO)
5368
5369
5370int hideout_hex_block(SL_TICKET fd, unsigned char * str, int len,
5371 unsigned long * bytes_read);
5372unsigned long first_hex_block(SL_TICKET fd, unsigned long * max);
5373
5374/*
5375 * --- Get hidden data from a block of hex data. ---
5376 */
5377int sh_unix_getline_stealth (SL_TICKET fd, char * str, int len)
5378{
5379 int add_off = 0, llen;
5380 static unsigned long off_data = 0;
5381 static unsigned long max_data = 0;
5382 static unsigned long bytes_read = 0;
5383 static int stealth_init = BAD;
5384
5385 SL_ENTER(_("sh_unix_getline_stealth"));
5386
5387 if (str == NULL)
5388 {
5389 off_data = 0;
5390 max_data = 0;
5391 bytes_read = 0;
5392 stealth_init = BAD;
5393 SL_RETURN(0, _("sh_unix_getline_stealth"));
5394 }
5395
5396 /* --- Initialize. ---
5397 */
5398 if (stealth_init == BAD)
5399 {
5400 off_data = first_hex_block(fd, &max_data);
5401 if (off_data == 0)
5402 {
5403 dlog(1, FIL__, __LINE__,
5404 _("The stealth config file does not contain any steganographically\nhidden data. This file must be an image file in _uncompressed_\npostscript format.\nTo hide data in it, use:\n samhain_stealth -s postscript_file orig_config_file\n mv postscript_file /path/to/config/file\n"));
5405 sh_error_handle ((-1), FIL__, __LINE__, EIO, MSG_P_NODATA,
5406 _("Stealth config file."));
5407 aud_exit (FIL__, __LINE__, EXIT_FAILURE);
5408 }
5409 stealth_init = GOOD;
5410 max_data += off_data;
5411 }
5412
5413 /* --- Seek to proper position. ---
5414 */
5415 if (bytes_read >= max_data || add_off < 0)
5416 {
5417 dlog(1, FIL__, __LINE__,
5418 _("The capacity of the container image file for the stealth config file seems to be too small. Your config file is likely truncated.\n"));
5419 sh_error_handle ((-1), FIL__, __LINE__, EIO, MSG_P_NODATA,
5420 _("Stealth config file."));
5421 aud_exit (FIL__, __LINE__, EXIT_FAILURE);
5422 }
5423 sl_seek(fd, off_data);
5424
5425 /* --- Read one line. ---
5426 */
5427 add_off = hideout_hex_block(fd, (unsigned char *) str, len, &bytes_read);
5428 off_data += add_off;
5429
5430 llen = sl_strlen(str);
5431 SL_RETURN(llen, _("sh_unix_getline_stealth"));
5432}
5433
5434int hideout_hex_block(SL_TICKET fd, unsigned char * str, int len,
5435 unsigned long * bytes_read)
5436{
5437
5438 register int i, j, k;
5439 unsigned char c, e;
5440 register int num;
5441 unsigned char mask[9] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
5442 unsigned long here = 0;
5443 unsigned long retval = 0;
5444 unsigned long bread = 0;
5445
5446 SL_ENTER(_("hideout_hex_block"));
5447
5448 ASSERT_RET((len > 1), _("len > 1"), (0));
5449
5450 --len;
5451
5452 i = 0;
5453 while (i < len)
5454 {
5455 for (j = 0; j < 8; ++j)
5456 {
5457
5458 /* --- Get a low byte, modify, read back. ---
5459 */
5460 for (k = 0; k < 2; ++k)
5461 {
5462 /* -- Skip whitespace. ---
5463 */
5464 c = ' ';
5465 do {
5466 do {
5467 num = sl_read (fd, &c, 1);
5468 } while (num == 0 && errno == EINTR);
5469 if (num > 0)
5470 ++here;
5471 else if (num == 0)
5472 SL_RETURN((0), _("hideout_hex_block"));
5473 else
5474 SL_RETURN((-1), _("hideout_hex_block"));
5475 } while (c == '\n' || c == '\t' || c == '\r' ||
5476 c == ' ');
5477 }
5478
5479
5480 /* --- e is the value of the low byte. ---
5481 */
5482 e = (unsigned char) sh_util_hexchar( c );
5483 if ((e & mask[7]) != 0) /* bit is set */
5484 str[i] |= mask[j];
5485 else /* bit is not set */
5486 str[i] &= ~mask[j];
5487
5488 bread += 1;
5489 }
5490 if (str[i] == '\n') break;
5491 ++i;
5492 }
5493
5494 if (i != 0)
5495 str[i] = '\0';
5496 else
5497 str[i+1] = '\0'; /* keep newline and terminate */
5498 retval += here;
5499 *bytes_read += (bread/8);
5500
5501 SL_RETURN(retval, _("hideout_hex_block"));
5502}
5503
5504/* --- Get offset of first data block. ---
5505 */
5506unsigned long first_hex_block(SL_TICKET fd, unsigned long * max)
5507{
5508 unsigned int i;
5509 long num = 1;
5510 unsigned long lnum;
5511 char c;
5512 int nothex = 0;
5513 unsigned long retval = 0;
5514 unsigned int this_line = 0;
5515 char theline[SH_BUFSIZE];
5516
5517 SL_ENTER(_("first_hex_block"));
5518
5519 *max = 0;
5520
5521 while (1)
5522 {
5523 theline[0] = '\0';
5524 this_line = 0;
5525 c = '\0';
5526 while (c != '\n' && this_line < (sizeof(theline)-1))
5527 {
5528 do {
5529 num = sl_read (fd, &c, 1);
5530 } while (num == 0 && errno == EINTR);
5531 if (num > 0)
5532 theline[this_line] = c;
5533 else
5534 SL_RETURN((0), _("first_hex_block"));
5535 ++this_line;
5536 }
5537 theline[this_line] = '\0';
5538
5539 /* not only 'newline' */
5540 if (this_line > 60)
5541 {
5542 nothex = 0;
5543 i = 0;
5544 while (nothex == 0 && i < (this_line-1))
5545 {
5546 if (! isxdigit((int)theline[i])) nothex = 1;
5547 ++i;
5548 }
5549 if (nothex == 1) retval += this_line;
5550 }
5551 else
5552 {
5553 nothex = 1;
5554 retval += this_line;
5555 }
5556
5557 if (nothex == 0)
5558 {
5559 *max = 0;
5560 do {
5561 do {
5562 num = sl_read (fd, theline, SH_BUFSIZE);
5563 } while (num == 0 && errno == EINTR);
5564 if (num > 0)
5565 {
5566 lnum = (unsigned long) num;
5567 for (i = 0; i < lnum; ++i)
5568 {
5569 c = theline[i];
5570 if (c == '\n' || c == '\t' || c == '\r' || c == ' ')
5571 ;
5572 else if (!isxdigit((int)c))
5573 break;
5574 else
5575 *max += 1;
5576 }
5577 }
5578 } while (num > 0);
5579
5580 *max /= 16;
5581 SL_RETURN((retval), _("first_hex_block"));
5582 }
5583
5584 }
5585 /* SL_RETURN((0), _("first_hex_block")); *//* unreachable */
5586}
5587
5588 /* if !defined(SH_STEALTH_MICRO) */
5589#endif
5590
5591 /* ifdef SH_STEALTH */
5592#endif
5593
5594/*
5595 * anti-debugger code
5596 */
5597#if defined(SCREW_IT_UP)
5598
5599#if defined(HAVE_PTHREAD)
5600
5601static pthread_key_t gSigtrapVariables_key;
5602static pthread_once_t gSigtrapVariables_key_once = PTHREAD_ONCE_INIT;
5603
5604static inline void make_gSigtrapVariables_key()
5605{
5606 (void) pthread_key_create(&gSigtrapVariables_key, free);
5607}
5608
5609struct sh_sigtrap_variables * sh_sigtrap_variables_get()
5610{
5611 void * ptr;
5612
5613 (void) pthread_once(&gSigtrapVariables_key_once, make_gSigtrapVariables_key);
5614
5615 ptr = pthread_getspecific(gSigtrapVariables_key);
5616 if (ptr == NULL) {
5617 ptr = calloc(1,sizeof(struct sh_sigtrap_variables));
5618 if (ptr == NULL) {
5619 return NULL;
5620 }
5621 (void) pthread_setspecific(gSigtrapVariables_key, ptr);
5622 }
5623
5624 return (struct sh_sigtrap_variables *) ptr;
5625}
5626
5627/* !defined(HAVE_PTHREAD) */
5628#else
5629
5630static struct sh_sigtrap_variables global_sigtrap_variables;
5631struct sh_sigtrap_variables * sh_sigtrap_variables_get()
5632{
5633 return &global_sigtrap_variables;
5634}
5635
5636#endif
5637
5638int sh_sigtrap_max_duration_set (const char * str)
5639{
5640 /* For security (prevent reloading with larger value)
5641 * this value can only be set once.
5642 */
5643 static int once = 0;
5644 int i;
5645
5646 SL_ENTER(_("sh_sigtrap_max_duration_set"));
5647
5648 i = atoi (str);
5649
5650 if (i >= 0 && once == 0)
5651 {
5652 sh.sigtrap_max_duration = i;
5653 once = 1;
5654 }
5655 else
5656 {
5657 SL_RETURN ((-1), _("sh_sigtrap_max_duration_set"));
5658 }
5659 SL_RETURN( (0), _("sh_sigtrap_max_duration_set"));
5660}
5661
5662void sh_sigtrap_handler (int signum)
5663{
5664 struct sh_sigtrap_variables * sigtrap_variables;
5665 sigtrap_variables = sh_sigtrap_variables_get();
5666 if (sigtrap_variables == NULL) {
5667 /* Perhaps, it's better to not die, and to continue using Samhain,
5668 even if this part does not work. */
5669 return;
5670 }
5671
5672#ifdef HAVE_GETTIMEOFDAY
5673 {
5674 struct timeval tv;
5675 long difftv;
5676
5677 gettimeofday(&tv, NULL);
5678 difftv = (tv.tv_sec - sigtrap_variables->save_tv.tv_sec) * 1000000 +
5679 (tv.tv_usec - sigtrap_variables->save_tv.tv_usec);
5680 if (difftv > sh.sigtrap_max_duration)
5681 raise(SIGKILL);
5682 }
5683#endif
5684
5685 sigtrap_variables->not_traced = signum;
5686 /* cppcheck-suppress memleak */
5687 return;
5688}
5689#endif
Note: See TracBrowser for help on using the repository browser.