source: trunk/src/sh_unix.c@ 590

Last change on this file since 590 was 590, checked in by katerina, 16 hours ago

Fix for ticket #478 (cppcheck warnings).

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