source: trunk/src/sh_unix.c@ 162

Last change on this file since 162 was 162, checked in by katerina, 17 years ago

Fix for ticket #89, #90, and #91 (locking,compile failure).

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