source: trunk/src/sh_unix.c@ 461

Last change on this file since 461 was 460, checked in by katerina, 10 years ago

Better error message for update and fix for deadlock in UNIX entropy collector. 3.1.3 final.

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