source: trunk/src/sh_unix.c@ 92

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

Move fd closing more towards program start. Fix OpenBSD 4.0 compatibility for kernel check.

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