source: trunk/src/sh_unix.c@ 485

Last change on this file since 485 was 481, checked in by katerina, 9 years ago

Enhancements and fixes for tickets #374, #375, #376, #377, #378, and #379.

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