source: trunk/src/sh_unix.c@ 27

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

Support for server-to-server relay and more user policies

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