source: trunk/src/sh_unix.c@ 158

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

Fix more compiler warnings, and a potential NULL dereference in the unix entropy collector.

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