source: trunk/src/sh_unix.c@ 26

Last change on this file since 26 was 25, checked in by rainer, 19 years ago

More tests; fix for update+schedule issue.

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