source: trunk/src/sh_unix.c@ 20

Last change on this file since 20 was 20, checked in by rainer, 19 years ago

Enable command-line parsing for prelude, and make prelude regression test safer.

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