source: trunk/src/sh_unix.c@ 153

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

Use -D_FORTIFY_SOURCE=1 -fstack-protector-all if supported. Compiler warnings fixed.

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