source: trunk/src/sh_unix.c@ 252

Last change on this file since 252 was 252, checked in by katerina, 15 years ago

Add code to check for stale file records on close() and fclose(), fix sl_close() to handle open stream (ticket #163).

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