source: trunk/src/sh_unix.c@ 199

Last change on this file since 199 was 199, checked in by katerina, 16 years ago

While we're at it, implement 'else' cor the config file conditionals. Also fix some compile warnings and improve docs.

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