source: trunk/src/sh_unix.c@ 5

Last change on this file since 5 was 1, checked in by katerina, 19 years ago

Initial import

File size: 94.2 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 = 1;
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#if defined(RLIMIT_NOFILE)
1197 setrlimit (RLIMIT_NOFILE, &limits);
1198#elif defined(RLIMIT_OFILE)
1199 setrlimit (RLIMIT_OFILE, &limits);
1200#endif
1201#ifdef RLIMIT_MEMLOCK
1202 setrlimit (RLIMIT_MEMLOCK, &limits);
1203#endif
1204
1205#if !defined(SL_DEBUG)
1206 /* no core dumps
1207 */
1208 limits.rlim_cur = 0;
1209 limits.rlim_max = 0;
1210#ifdef RLIMIT_CORE
1211 setrlimit (RLIMIT_CORE, &limits);
1212#endif
1213#else
1214#ifdef RLIMIT_CORE
1215 setrlimit (RLIMIT_CORE, &limits);
1216#endif
1217#endif
1218
1219
1220 SL_RET0(_("sh_unix_setlimits"));
1221}
1222
1223static void sh_unix_copyenv(void)
1224{
1225 char ** env0 = environ;
1226 char ** env1;
1227 int envlen = 0;
1228
1229 SL_ENTER(_("sh_unix_copyenv"));
1230
1231 while (env0 != NULL && env0[envlen] != NULL) {
1232 /* printf("%2d: %s\n", envlen, env0[envlen]); */
1233 ++envlen;
1234 }
1235 ++envlen;
1236
1237 /* printf("-> %2d: slots allocated\n", envlen); */
1238 env1 = malloc (sizeof(char *) * envlen); /* only once */
1239 if (env1 == NULL)
1240 {
1241 fprintf(stderr, _("%s: %d: Out of memory\n"), FIL__, __LINE__);
1242 SL_RET0(_("sh_unix_copyenv"));
1243 }
1244 env0 = environ;
1245 envlen = 0;
1246
1247 while (env0 != NULL && env0[envlen] != NULL) {
1248 env1[envlen] = malloc (strlen(env0[envlen]) + 1); /* only once */
1249 if (env1[envlen] == NULL)
1250 {
1251 fprintf(stderr, _("%s: %d: Out of memory\n"), FIL__, __LINE__);
1252 SL_RET0(_("sh_unix_copyenv"));
1253 }
1254 strcpy(env1[envlen], env0[envlen]); /* known to fit */
1255 ++envlen;
1256 }
1257 env1[envlen] = NULL;
1258
1259 environ = env1;
1260 SL_RET0(_("sh_unix_copyenv"));
1261}
1262
1263/* delete all environment variables
1264 */
1265static void sh_unix_zeroenv(void)
1266{
1267 char * c;
1268 char ** env;
1269
1270 SL_ENTER(_("sh_unix_zeroenv"));
1271
1272 sh_unix_copyenv();
1273 env = environ;
1274
1275 while (env != NULL && *env != NULL) {
1276 c = strchr ((*env), '=');
1277#ifdef WITH_MYSQL
1278 /*
1279 * Skip the MYSQL_UNIX_PORT environment variable; MySQL may need it.
1280 */
1281 if (0 == sl_strncmp((*env), _("MYSQL_UNIX_PORT="), 16))
1282 {
1283 ++(env);
1284 continue;
1285 }
1286#endif
1287#ifdef WITH_ORACLE
1288 /*
1289 * Skip the ORACLE_HOME environment variable; Oracle may need it.
1290 */
1291 if (0 == sl_strncmp((*env), _("ORACLE_HOME="), 12))
1292 {
1293 ++(env);
1294 continue;
1295 }
1296#endif
1297 /*
1298 * Skip the TZ environment variable.
1299 */
1300 if (0 == sl_strncmp((*env), _("TZ="), 3))
1301 {
1302 ++(env);
1303 continue;
1304 }
1305 ++(env);
1306 if (c != NULL)
1307 {
1308 ++c;
1309 while ((*c) != '\0') {
1310 (*c) = '\0';
1311 ++c;
1312 }
1313 }
1314 }
1315
1316 SL_RET0(_("sh_unix_zeroenv"));
1317}
1318
1319
1320static void sh_unix_resettimer(void)
1321{
1322 struct itimerval this_timer;
1323
1324 SL_ENTER(_("sh_unix_resettimer"));
1325
1326 this_timer.it_value.tv_sec = 0;
1327 this_timer.it_value.tv_usec = 0;
1328
1329 this_timer.it_interval.tv_sec = 0;
1330 this_timer.it_interval.tv_usec = 0;
1331
1332 setitimer(ITIMER_REAL, &this_timer, NULL);
1333#if !defined(SH_PROFILE)
1334 setitimer(ITIMER_VIRTUAL, &this_timer, NULL);
1335 setitimer(ITIMER_PROF, &this_timer, NULL);
1336#endif
1337
1338 SL_RET0(_("sh_unix_resettimer"));
1339}
1340
1341static void sh_unix_resetsignals(void)
1342{
1343 int sig_num;
1344#ifdef NSIG
1345 int max_sig = NSIG;
1346#else
1347 int max_sig = 255;
1348#endif
1349 int test;
1350 struct sigaction act, oldact;
1351 int status;
1352
1353 sigset_t set_proc;
1354
1355 SL_ENTER(_("sh_unix_resetsignals"));
1356 /*
1357 * Reset the current signal mask (inherited from parent process).
1358 */
1359
1360 sigfillset(&set_proc);
1361
1362 do {
1363 errno = 0;
1364 test = sigprocmask(SIG_UNBLOCK, &set_proc, NULL);
1365 } while (test < 0 && errno == EINTR);
1366
1367 /*
1368 * Reset signal handling.
1369 */
1370
1371 act.sa_handler = SIG_DFL; /* signal action */
1372 sigemptyset( &act.sa_mask ); /* set an empty mask */
1373 act.sa_flags = 0; /* init sa_flags */
1374
1375 for (sig_num = 1; sig_num <= max_sig; ++sig_num)
1376 {
1377#if !defined(SH_PROFILE)
1378 test = retry_sigaction(FIL__, __LINE__, sig_num, &act, &oldact);
1379#else
1380 test = 0;
1381#endif
1382 if ((test == -1) && (errno != EINVAL))
1383 {
1384 status = errno;
1385 sh_error_handle ((-1), FIL__, __LINE__, status, MSG_W_SIG,
1386 sh_error_message (status), sig_num);
1387 }
1388 }
1389
1390 SL_RET0(_("sh_unix_resetsignals"));
1391}
1392
1393/* Get the local hostname (FQDN)
1394 */
1395#include <sys/socket.h>
1396
1397/* Required for BSD
1398 */
1399#ifdef HAVE_NETINET_IN_H
1400#include <netinet/in.h>
1401#endif
1402
1403#include <arpa/inet.h>
1404
1405/* uname() on FreeBSD is broken, because the 'nodename' buf is too small
1406 * to hold a valid (leftmost) domain label.
1407 */
1408#if defined(HAVE_UNAME) && !defined(HOST_IS_FREEBSD)
1409#include <sys/utsname.h>
1410void sh_unix_localhost()
1411{
1412 struct utsname buf;
1413 struct hostent * he1;
1414 int i;
1415 int ddot = 0;
1416 int len;
1417 char * p;
1418 char hostname[256];
1419
1420
1421 SL_ENTER(_("sh_unix_localhost"));
1422
1423 (void) uname (&buf);
1424
1425 sl_strlcpy (sh.host.system, buf.sysname, SH_MINIBUF);
1426 sl_strlcpy (sh.host.release, buf.release, SH_MINIBUF);
1427 sl_strlcpy (sh.host.machine, buf.machine, SH_MINIBUF);
1428
1429 /* Workaround for cases where nodename could be
1430 * a truncated FQDN.
1431 */
1432 if (strlen(buf.nodename) == (sizeof(buf.nodename)-1))
1433 {
1434 p = strchr(buf.nodename, '.');
1435 if (NULL != p) {
1436 *p = '\0';
1437 sl_strlcpy(hostname, buf.nodename, 256);
1438 } else {
1439#ifdef HAVE_GETHOSTNAME
1440 if (0 != gethostname(hostname, 256))
1441 {
1442 sh_error_handle(SH_ERR_WARN, FIL__, __LINE__, 0, MSG_E_SUBGEN,
1443 _("nodename returned by uname may be truncated"),
1444 _("sh_unix_localhost"));
1445 sl_strlcpy (hostname, buf.nodename, 256);
1446 }
1447 else
1448 {
1449 hostname[255] = '\0';
1450 }
1451#else
1452 sh_error_handle(SH_ERR_WARN, FIL__, __LINE__, 0, MSG_E_SUBGEN,
1453 _("nodename returned by uname may be truncated"),
1454 _("sh_unix_localhost"));
1455 sl_strlcpy(hostname, buf.nodename, 256);
1456#endif
1457 }
1458 }
1459 else
1460 {
1461 sl_strlcpy(hostname, buf.nodename, 256);
1462 }
1463
1464 he1 = sh_gethostbyname(hostname);
1465
1466 if (he1 == NULL)
1467 {
1468 dlog(1, FIL__, __LINE__,
1469 _("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"),
1470 hostname);
1471 sl_strlcpy (sh.host.name, hostname, SH_PATHBUF);
1472 }
1473 else
1474 {
1475 sl_strlcpy (sh.host.name, he1->h_name, SH_PATHBUF);
1476 }
1477
1478
1479 /* check whether it looks like a FQDN
1480 */
1481 len = sl_strlen(sh.host.name);
1482 for (i = 0; i < len; ++i)
1483 if (sh.host.name[i] == '.') ++ddot;
1484
1485 if (ddot == 0 && he1 != NULL)
1486 {
1487 dlog(1, FIL__, __LINE__,
1488 _("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"),
1489 hostname, sh.host.name);
1490 sl_strlcpy (sh.host.name,
1491 inet_ntoa (*(struct in_addr *) he1->h_addr),
1492 SH_PATHBUF);
1493 SL_RET0(_("sh_unix_localhost"));
1494 }
1495
1496 if (is_numeric(sh.host.name))
1497 {
1498 dlog(1, FIL__, __LINE__,
1499 _("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"),
1500 hostname, sh.host.name);
1501 }
1502
1503 SL_RET0(_("sh_unix_localhost"));
1504}
1505#else
1506void sh_unix_localhost()
1507{
1508 struct hostent * he1;
1509 int i;
1510 int ddot = 0;
1511 int len;
1512 char hostname[1024];
1513
1514
1515 SL_ENTER(_("sh_unix_localhost"));
1516
1517 (void) gethostname (hostname, 1024);
1518 hostname[1023] = '\0';
1519 he1 = sh_gethostbyname(hostname);
1520
1521 if (he1 != NULL)
1522 {
1523 sl_strlcpy (sh.host.name, he1->h_name, SH_PATHBUF);
1524 }
1525 else
1526 {
1527 dlog(1, FIL__, __LINE__,
1528 _("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"),
1529 hostname);
1530 sl_strlcpy (sh.host.name, _("localhost"), SH_PATHBUF);
1531 SL_RET0(_("sh_unix_localhost"));
1532 }
1533
1534 /* check whether it looks like a FQDN
1535 */
1536 len = sl_strlen(sh.host.name);
1537 for (i = 0; i < len; ++i)
1538 if (sh.host.name[i] == '.') ++ddot;
1539 if (ddot == 0)
1540 {
1541 dlog(1, FIL__, __LINE__,
1542 _("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"),
1543 hostname, sh.host.name);
1544 sl_strlcpy (sh.host.name,
1545 inet_ntoa (*(struct in_addr *) he1->h_addr),
1546 SH_PATHBUF);
1547 SL_RET0(_("sh_unix_localhost"));
1548 }
1549
1550 if (is_numeric(sh.host.name))
1551 {
1552 dlog(1, FIL__, __LINE__,
1553 _("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"),
1554 hostname, sh.host.name);
1555 }
1556
1557 SL_RET0(_("sh_unix_localhost"));
1558}
1559#endif
1560
1561
1562void sh_unix_memlock()
1563{
1564 SL_ENTER(_("sh_unix_memlock"));
1565
1566 /* do this before dropping privileges
1567 */
1568#if defined(HAVE_MLOCK) && !defined(HAVE_BROKEN_MLOCK)
1569 if (skey->mlock_failed == SL_FALSE)
1570 {
1571 if ( (-1) == sh_unix_mlock( (char *) skey, sizeof (sh_key_t)) )
1572 {
1573 skey->mlock_failed = SL_TRUE;
1574 }
1575 }
1576#else
1577 if (skey->mlock_failed == SL_FALSE)
1578 {
1579 skey->mlock_failed = SL_TRUE;
1580 }
1581#endif
1582
1583 SL_RET0(_("sh_unix_memlock"));
1584}
1585
1586#ifdef SH_WITH_SERVER
1587char * chroot_dir = NULL;
1588
1589int sh_unix_set_chroot(char * str)
1590{
1591 size_t len;
1592 static int block = 0;
1593
1594 if (block == 1)
1595 return 0;
1596
1597 if (str && *str == '/')
1598 {
1599 len = strlen(str) + 1;
1600 chroot_dir = malloc(strlen(str) + 1); /* only once */
1601 if (!chroot_dir)
1602 {
1603 fprintf(stderr, _("%s: %d: Out of memory\n"), FIL__, __LINE__);
1604 return 1;
1605 }
1606 sl_strlcpy(chroot_dir, str, len);
1607 block = 1;
1608 return 0;
1609 }
1610 return 1;
1611}
1612
1613int sh_unix_chroot()
1614{
1615 int status;
1616
1617 if (chroot_dir != NULL)
1618 {
1619 status = retry_aud_chdir(FIL__, __LINE__, chroot_dir);
1620 if ( (-1) == status )
1621 {
1622 status = errno;
1623 sh_error_handle ((-1), FIL__, __LINE__, status, MSG_W_CHDIR,
1624 sh_error_message (status), chroot_dir);
1625 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1626 }
1627 return (chroot(chroot_dir));
1628 }
1629 return 0;
1630}
1631/* #ifdef SH_WITH_SERVER */
1632#else
1633int sh_unix_chroot() { return 0; }
1634#endif
1635
1636/* daemon mode
1637 */
1638static int block_setdeamon = 0;
1639
1640int sh_unix_setdeamon(char * dummy)
1641{
1642 int res = 0;
1643
1644 SL_ENTER(_("sh_unix_setdeamon"));
1645
1646 if (block_setdeamon != 0)
1647 SL_RETURN((0),_("sh_unix_setdeamon"));
1648
1649 if (dummy == NULL)
1650 sh.flag.isdaemon = ON;
1651 else
1652 res = sh_util_flagval (dummy, &sh.flag.isdaemon);
1653
1654 if (sh.flag.opts == S_TRUE)
1655 block_setdeamon = 1;
1656
1657 SL_RETURN(res, _("sh_unix_setdeamon"));
1658}
1659#if defined(HAVE_LIBPRELUDE)
1660#include "sh_prelude.h"
1661#endif
1662
1663int sh_unix_setnodeamon(char * dummy)
1664{
1665 int res = 0;
1666
1667 SL_ENTER(_("sh_unix_setnodeamon"));
1668
1669 if (block_setdeamon != 0)
1670 SL_RETURN((0),_("sh_unix_setmodeamon"));
1671
1672 if (dummy == NULL)
1673 sh.flag.isdaemon = OFF;
1674 else
1675 res = sh_util_flagval (dummy, &sh.flag.isdaemon);
1676
1677 if (sh.flag.opts == S_TRUE)
1678 block_setdeamon = 1;
1679
1680 SL_RETURN(res, _("sh_unix_setnodeamon"));
1681}
1682
1683int sh_unix_init(int goDaemon)
1684{
1685 int status;
1686 uid_t uid;
1687 pid_t oldpid = getpid();
1688#if defined(SH_WITH_SERVER)
1689 extern int sh_socket_open_int ();
1690#endif
1691
1692 SL_ENTER(_("sh_unix_init"));
1693
1694 /* fork twice, exit the parent process
1695 */
1696 if (goDaemon == 1) {
1697
1698 switch (aud_fork(FIL__, __LINE__)) {
1699 case 0: break; /* child process continues */
1700 case -1: SL_RETURN((-1),_("sh_unix_init")); /* error */
1701 default: aud__exit(FIL__, __LINE__, 0); /* parent process exits */
1702 }
1703
1704 /* Child processes do not inherit page locks across a fork.
1705 * Error in next fork would return in this (?) thread of execution.
1706 */
1707 sh_unix_memlock();
1708
1709 setsid(); /* should not fail */
1710
1711 switch (aud_fork(FIL__, __LINE__)) {
1712 case 0: break; /* child process continues */
1713 case -1: SL_RETURN((-1),_("sh_unix_init")); /* error */
1714 default: aud__exit(FIL__, __LINE__, 0); /* parent process exits */
1715 }
1716
1717 /* Child processes do not inherit page locks across a fork.
1718 */
1719 sh_unix_memlock();
1720
1721 } else {
1722 setsid(); /* should not fail */
1723 }
1724
1725 /* set working directory
1726 */
1727#ifdef SH_PROFILE
1728 status = 0;
1729#else
1730 status = retry_aud_chdir(FIL__, __LINE__, "/");
1731#endif
1732 if ( (-1) == status )
1733 {
1734 status = errno;
1735 sh_error_handle ((-1), FIL__, __LINE__, status, MSG_W_CHDIR,
1736 sh_error_message (status), "/");
1737 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1738 }
1739
1740 /* reset timers
1741 */
1742 sh_unix_resettimer();
1743
1744 /* signal handlers
1745 */
1746 sh_unix_resetsignals();
1747#if defined(SCREW_IT_UP)
1748 sh_sigtrap_prepare();
1749#endif
1750 sh_unix_siginstall (goDaemon);
1751
1752 /* set file creation mask
1753 */
1754 (void) umask (0); /* should not fail */
1755
1756 /* set resource limits to maximum, and
1757 * core dump size to zero
1758 */
1759 sh_unix_setlimits();
1760
1761 /* zero out the environment (like PATH='\0')
1762 */
1763 sh_unix_zeroenv();
1764
1765
1766 /* close all file descriptors, and
1767 * open first three streams to /dev/null
1768 */
1769 if (goDaemon == 1)
1770 {
1771 sh_unix_closeall (0, -1); /* if running as daemon */
1772 aud_open(FIL__, __LINE__, SL_NOPRIV, _("/dev/null"), O_RDWR, 0);
1773 retry_aud_dup(FIL__, __LINE__, 0);
1774 retry_aud_dup(FIL__, __LINE__, 0);
1775#if defined(HAVE_LIBPRELUDE)
1776 sh_prelude_reset ();
1777#endif
1778
1779 /* --- wait until parent has exited ---
1780 */
1781 while (1 == 1)
1782 {
1783 errno = 0;
1784 if (0 > aud_kill (FIL__, __LINE__, oldpid, 0) && errno == ESRCH)
1785 {
1786 break;
1787 }
1788 retry_msleep(0, 1);
1789 }
1790
1791 /* write PID file
1792 */
1793 status = sh_unix_write_pid_file();
1794 if (status < 0)
1795 {
1796 sl_get_euid(&uid);
1797 sh_error_handle ((-1), FIL__, __LINE__, status, MSG_PIDFILE,
1798 (long) uid, sh.srvlog.alt);
1799 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1800 }
1801#if defined(SH_WITH_SERVER)
1802 sh_socket_open_int ();
1803#endif
1804 }
1805 else
1806 {
1807 sh_unix_closeall(3, -1); /* if not daemon */
1808#if defined(HAVE_LIBPRELUDE)
1809 sh_prelude_reset ();
1810#endif
1811#if defined(SH_WITH_SERVER)
1812 sh_socket_open_int ();
1813#endif
1814 }
1815
1816 /* chroot (this is a no-op if no chroot dir is specified
1817 */
1818 status = sh_unix_chroot();
1819 if (status < 0)
1820 {
1821 status = errno;
1822 sh_error_handle((-1), FIL__, __LINE__, status, MSG_E_SUBGEN,
1823 sh_error_message(status), _("chroot"));
1824 aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1825 }
1826
1827 /* drop capabilities
1828 */
1829 sl_drop_cap();
1830
1831 SL_RETURN((0),_("sh_unix_init"));
1832}
1833
1834/********************************************************
1835 *
1836 * TIME
1837 *
1838 ********************************************************/
1839
1840/* Figure out the time offset of the current timezone
1841 * in a portable way.
1842 */
1843char * t_zone(const time_t * xx)
1844{
1845 struct tm aa;
1846 struct tm bb;
1847 struct tm * cc;
1848 int sign = 0;
1849 int diff = 0;
1850 int hh, mm;
1851 static char tz[64];
1852
1853 SL_ENTER(_("t_zone"));
1854
1855
1856 cc = gmtime (xx);
1857 memcpy (&aa, cc, sizeof(struct tm));
1858 cc = localtime (xx);
1859 memcpy (&bb, cc, sizeof(struct tm));
1860
1861 /* Check for datum wrap-around.
1862 */
1863 if (aa.tm_year < bb.tm_year)
1864 sign = (-1);
1865 else if (aa.tm_mon < bb.tm_mon)
1866 sign = (-1);
1867 else if (aa.tm_mday < bb.tm_mday)
1868 sign = (-1);
1869 else if (bb.tm_year < aa.tm_year)
1870 sign = ( 1);
1871 else if (bb.tm_mon < aa.tm_mon)
1872 sign = ( 1);
1873 else if (bb.tm_mday < aa.tm_mday)
1874 sign = ( 1);
1875
1876 diff = aa.tm_hour * 60 + aa.tm_min;
1877 diff = (bb.tm_hour * 60 + bb.tm_min) - diff;
1878 diff = diff - (sign * 24 * 60); /* datum wrap-around correction */
1879 hh = diff / 60;
1880 mm = diff - (hh * 60);
1881 sprintf (tz, _("%+03d%02d"), hh, mm); /* known to fit */
1882
1883 SL_RETURN(tz, _("t_zone"));
1884}
1885
1886unsigned long sh_unix_longtime ()
1887{
1888 return ((unsigned long)time(NULL));
1889}
1890
1891#ifdef HAVE_GETTIMEOFDAY
1892unsigned long sh_unix_notime ()
1893{
1894 struct timeval tv;
1895
1896 gettimeofday (&tv, NULL);
1897
1898 return ((unsigned long)(tv.tv_sec + tv.tv_usec * 10835 + getpid() + getppid()));
1899
1900}
1901#endif
1902
1903static int count_dev_time = 0;
1904
1905void reset_count_dev_time(void)
1906{
1907 count_dev_time = 0;
1908 return;
1909}
1910
1911int sh_unix_settimeserver (char * address)
1912{
1913
1914 SL_ENTER(_("sh_unix_settimeserver"));
1915
1916 if (address != NULL && count_dev_time < 2
1917 && sl_strlen(address) < SH_PATHBUF)
1918 {
1919 if (count_dev_time == 0)
1920 sl_strlcpy (sh.srvtime.name, address, SH_PATHBUF);
1921 else
1922 sl_strlcpy (sh.srvtime.alt, address, SH_PATHBUF);
1923
1924 ++count_dev_time;
1925 SL_RETURN((0), _("sh_unix_settimeserver"));
1926 }
1927 SL_RETURN((-1), _("sh_unix_settimeserver"));
1928}
1929
1930
1931#ifdef HAVE_NTIME
1932#define UNIXEPOCH 2208988800UL /* difference between Unix time and net time
1933 * The UNIX EPOCH starts in 1970.
1934 */
1935#include <sys/socket.h>
1936#include <netinet/in.h>
1937#include <arpa/inet.h>
1938#include <netdb.h>
1939#include <ctype.h>
1940#endif
1941
1942/* Timeserver service. */
1943/* define is missing on HP-UX 10.20 */
1944#ifndef IPPORT_TIMESERVER
1945#define IPPORT_TIMESERVER 37
1946#endif
1947
1948char * sh_unix_time (time_t thetime)
1949{
1950
1951 int status;
1952
1953 time_t time_now;
1954 struct tm * time_ptr;
1955 static char AsciiTime[81]; /* local time */
1956 static char RetTime[81]; /* local time */
1957#ifdef SH_USE_XML
1958 static char deftime[] = N_("0000-00-00T00:00:00"); /* default time */
1959#else
1960 static char deftime[] = N_("[0000-00-00T00:00:00]"); /* default time */
1961#endif
1962
1963#ifdef HAVE_NTIME
1964 int fd; /* network file descriptor */
1965 u_char net_time[4]; /* remote time in network format */
1966 static int failerr = 0; /* no net time */
1967 int fail = 0; /* no net time */
1968 int errflag;
1969 char errmsg[256];
1970 char error_call[SH_MINIBUF];
1971 int error_num;
1972#endif
1973
1974 SL_ENTER(_("sh_unix_time"));
1975
1976#ifdef HAVE_NTIME
1977 if (thetime == 0)
1978 {
1979 if (sh.srvtime.name[0] == '\0')
1980 {
1981 fail = 1;
1982 (void) time (&time_now);
1983 }
1984 else /* have a timeserver address */
1985 {
1986 fd = connect_port_2 (sh.srvtime.name, sh.srvtime.alt,
1987 IPPORT_TIMESERVER,
1988 error_call, &error_num, errmsg, sizeof(errmsg));
1989 if (fd >= 0)
1990 {
1991 if (4 != read_port (fd, (char *) net_time, 4, &errflag, 2))
1992 {
1993 fail = 1;
1994 sh_error_handle ((-1), FIL__, __LINE__, errflag,
1995 MSG_E_NLOST,
1996 _("time"), sh.srvtime.name);
1997 }
1998 close(fd);
1999 }
2000 else
2001 {
2002 sh_error_handle ((-1), FIL__, __LINE__, error_num,
2003 MSG_E_NET, errmsg, error_call,
2004 _("time"), sh.srvtime.name);
2005 fail = 1;
2006 }
2007
2008 if (fail == 0)
2009 {
2010 time_now = ntohl(* (long *) net_time) - UNIXEPOCH;
2011 /* fprintf(stderr, "TIME IS %ld\n", time_now); */
2012 if (failerr == 1) {
2013 failerr = 0;
2014 sh_error_handle ((-1), FIL__, __LINE__, 0,
2015 MSG_E_NEST,
2016 _("time"), sh.srvtime.name);
2017 }
2018 }
2019 else
2020 {
2021 (void) time (&time_now);
2022 if (failerr == 0)
2023 {
2024 failerr = 1;
2025 sh_error_handle ((-1), FIL__, __LINE__, errflag,
2026 MSG_SRV_FAIL,
2027 _("time"), sh.srvtime.name);
2028 }
2029 }
2030 }
2031 }
2032 else
2033 {
2034 time_now = thetime;
2035 }
2036
2037 /* #ifdef HAVE_NTIME */
2038#else
2039
2040 if (thetime == 0)
2041 {
2042 (void) time (&time_now);
2043 }
2044 else
2045 {
2046 time_now = thetime;
2047 }
2048
2049 /* #ifdef HAVE_NTIME */
2050#endif
2051
2052 if (time_now == (-1) )
2053 SL_RETURN( _(deftime), _("sh_unix_time"));
2054 else
2055 time_ptr = localtime (&time_now);
2056
2057 if (time_ptr != NULL)
2058 {
2059 status = strftime (AsciiTime, 80,
2060#ifdef SH_USE_XML
2061 _("%Y-%m-%dT%H:%M:%S%%s"),
2062#else
2063 _("[%Y-%m-%dT%H:%M:%S%%s]"),
2064#endif
2065 time_ptr);
2066
2067 sl_snprintf(RetTime, 80, AsciiTime, t_zone(&time_now));
2068
2069 if ( (status == 0) || (status == 80) )
2070 SL_RETURN( _(deftime), _("sh_unix_time"));
2071 else
2072 SL_RETURN( &RetTime[0], _("sh_unix_time"));
2073 }
2074
2075 /* last resort
2076 */
2077 SL_RETURN( _(deftime), _("sh_unix_time"));
2078}
2079
2080static int sh_unix_use_localtime = S_FALSE;
2081
2082/* whether to use localtime for file timesatams in logs
2083 */
2084int sh_unix_uselocaltime (char * c)
2085{
2086 int i;
2087 SL_ENTER(_("sh_unix_uselocaltime"));
2088 i = sh_util_flagval(c, &(sh_unix_use_localtime));
2089
2090 SL_RETURN(i, _("sh_unix_uselocaltime"));
2091}
2092
2093char * sh_unix_gmttime (time_t thetime)
2094{
2095
2096 int status;
2097
2098 struct tm * time_ptr;
2099 static char AsciiTime[81]; /* GMT time */
2100#ifdef SH_USE_XML
2101 static char deftime[] = N_("0000-00-00T00:00:00"); /* default time */
2102#else
2103 static char deftime[] = N_("[0000-00-00T00:00:00]"); /* default time */
2104#endif
2105
2106 SL_ENTER(_("sh_unix_gmttime"));
2107
2108 if (sh_unix_use_localtime == S_FALSE)
2109 time_ptr = gmtime (&thetime);
2110 else
2111 time_ptr = localtime (&thetime);
2112
2113 if (time_ptr != NULL)
2114 {
2115 status = strftime (AsciiTime, 80,
2116#ifdef SH_USE_XML
2117 _("%Y-%m-%dT%H:%M:%S"),
2118#else
2119 _("[%Y-%m-%dT%H:%M:%S]"),
2120#endif
2121 time_ptr);
2122
2123 if ( (status == 0) || (status == 80) )
2124 SL_RETURN( _(deftime), _("sh_unix_gmttime"));
2125 else
2126 SL_RETURN( &AsciiTime[0], _("sh_unix_gmttime"));
2127 }
2128
2129 /* last resort
2130 */
2131 SL_RETURN( _(deftime), _("sh_unix_gmttime"));
2132}
2133
2134
2135
2136char * sh_unix_getUIDdir (int level, uid_t uid)
2137{
2138 struct passwd * tempres;
2139 int status = 0;
2140
2141 SL_ENTER(_("sh_unix_getUIDdir"));
2142
2143 errno = 0;
2144 tempres = sh_getpwuid(uid);
2145 status = errno;
2146
2147 if (tempres == NULL) {
2148 sh_error_handle (level, FIL__, __LINE__, EINVAL, MSG_E_PWNULL,
2149 sh_error_message(status),
2150 _("getpwuid"), (long) uid, _("completely missing"));
2151 SL_RETURN( NULL, _("sh_unix_getUIDdir"));
2152 }
2153
2154 if (tempres->pw_dir != NULL) {
2155 SL_RETURN( tempres->pw_dir, _("sh_unix_getUIDdir"));
2156 } else {
2157 sh_error_handle (level, FIL__, __LINE__, EINVAL, MSG_E_PWNULL,
2158 sh_error_message(status),
2159 _("getpwuid"), (long) uid, _("pw_dir"));
2160 SL_RETURN( NULL, _("sh_unix_getUIDdir"));
2161 }
2162}
2163
2164char * sh_unix_getUIDname (int level, uid_t uid)
2165{
2166 struct passwd * tempres;
2167 int status = 0;
2168 static uid_t old_uid;
2169 static char name[32] = { '\0' };
2170
2171 SL_ENTER(_("sh_unix_getUIDname"));
2172
2173 if ((uid == old_uid) && (name[0] != '\0')) {
2174 SL_RETURN( name, _("sh_unix_getUIDname"));
2175 }
2176
2177 errno = 0;
2178 tempres = sh_getpwuid(uid);
2179 status = errno;
2180
2181 if (tempres == NULL) {
2182 sh_error_handle (level, FIL__, __LINE__, EINVAL, MSG_E_PWNULL,
2183 sh_error_message(status),
2184 _("getpwuid"), (long) uid, _("completely missing"));
2185 SL_RETURN( NULL, _("sh_unix_getUIDname"));
2186 }
2187
2188
2189 if (tempres->pw_name != NULL) {
2190 sl_strlcpy(name, tempres->pw_name, sizeof(name));
2191 old_uid = uid;
2192 SL_RETURN( name, _("sh_unix_getUIDname"));
2193 } else {
2194 sh_error_handle (level, FIL__, __LINE__, EINVAL, MSG_E_PWNULL,
2195 sh_error_message(status),
2196 _("getpwuid"), (long) uid, _("pw_user"));
2197 SL_RETURN( NULL, _("sh_unix_getUIDname"));
2198 }
2199}
2200
2201char * sh_unix_getGIDname (int level, gid_t gid)
2202{
2203 struct group * tempres;
2204 int status = 0;
2205 static gid_t old_gid;
2206 static char name[32] = { '\0' };
2207
2208 SL_ENTER(_("sh_unix_getGIDname"));
2209
2210 if ((gid == old_gid) && (name[0] != '\0')) {
2211 SL_RETURN( name, _("sh_unix_getUIDname"));
2212 }
2213
2214 errno = 0;
2215 tempres = sh_getgrgid(gid);
2216 status = errno;
2217
2218 if (tempres == NULL) {
2219 sh_error_handle (level, FIL__, __LINE__, EINVAL, MSG_E_GRNULL,
2220 sh_error_message(status),
2221 _("getgrgid"), (long) gid, _("completely missing"));
2222
2223 SL_RETURN( NULL, _("sh_unix_getGIDname"));
2224 }
2225
2226 if (tempres->gr_name != NULL) {
2227 sl_strlcpy(name, tempres->gr_name, sizeof(name));
2228 old_gid = gid;
2229 SL_RETURN( name, _("sh_unix_getGIDname"));
2230 } else {
2231 sh_error_handle (level, FIL__, __LINE__, EINVAL, MSG_E_GRNULL,
2232 sh_error_message(status),
2233 _("getgrgid"), (long) gid, _("gr_name"));
2234 SL_RETURN( NULL, _("sh_unix_getGIDname"));
2235 }
2236}
2237
2238int sh_unix_getUser ()
2239{
2240 char * p;
2241 uid_t seuid, sruid;
2242
2243 SL_ENTER(_("sh_unix_getUser"));
2244
2245 seuid = geteuid();
2246
2247 sh.effective.uid = seuid;
2248
2249 p = sh_unix_getUIDdir (SH_ERR_ERR, seuid);
2250
2251 if (p == NULL)
2252 SL_RETURN((-1), _("sh_unix_getUser"));
2253 else
2254 {
2255 if (sl_strlen(p) >= SH_PATHBUF) {
2256 sh_error_handle (SH_ERR_ERR, FIL__, __LINE__, EINVAL, MSG_E_PWLONG,
2257 _("getpwuid"), (long) seuid, _("pw_home"));
2258 SL_RETURN((-1), _("sh_unix_getUser"));
2259 } else {
2260 sl_strlcpy ( sh.effective.home, p, SH_PATHBUF);
2261 }
2262 }
2263
2264 sruid = getuid();
2265
2266 sh.real.uid = sruid;
2267
2268 p = sh_unix_getUIDname (SH_ERR_ERR, sruid);
2269 if (p == NULL)
2270 SL_RETURN((-1), _("sh_unix_getUser"));
2271 else
2272 {
2273 if (sl_strlen(p) >= USER_MAX) {
2274 sh_error_handle (SH_ERR_ERR, FIL__, __LINE__, EINVAL, MSG_E_PWLONG,
2275 _("getpwuid"), (long) sruid, _("pw_user"));
2276 SL_RETURN((-1), _("sh_unix_getUser"));
2277 } else {
2278 sl_strlcpy ( sh.real.user, p, USER_MAX);
2279 }
2280 }
2281
2282 p = sh_unix_getUIDdir (SH_ERR_ERR, sruid);
2283
2284 if (p == NULL)
2285 SL_RETURN((-1), _("sh_unix_getUser"));
2286 else
2287 {
2288 if (sl_strlen(p) >= SH_PATHBUF) {
2289 sh_error_handle (SH_ERR_ERR, FIL__, __LINE__, EINVAL, MSG_E_PWLONG,
2290 _("getpwuid"), (long) sruid, _("pw_home"));
2291 SL_RETURN((-1), _("sh_unix_getUser"));
2292 } else {
2293 sl_strlcpy ( sh.real.home, p, SH_PATHBUF);
2294 }
2295 }
2296
2297 SL_RETURN((0), _("sh_unix_getUser"));
2298
2299 /* notreached */
2300}
2301
2302
2303int sh_unix_getline (SL_TICKET fd, char * line, int sizeofline)
2304{
2305 register int count;
2306 register int n = 0;
2307 char c;
2308
2309 SL_ENTER(_("sh_unix_getline"));
2310
2311 if (sizeofline < 2) {
2312 line[n] = '\0';
2313 SL_RETURN((0), _("sh_unix_getline"));
2314 }
2315
2316 while (n < sizeofline) {
2317
2318 count = sl_read (fd, &c, 1);
2319
2320 /* end of file
2321 */
2322 if (count < 1) {
2323 line[n] = '\0';
2324 n = -1;
2325 break;
2326 }
2327
2328 if (/* c != '\0' && */ c != '\n') {
2329 line[n] = c;
2330 ++n;
2331 } else if (c == '\n') {
2332 if (n > 0) {
2333 line[n] = '\0';
2334 break;
2335 } else {
2336 line[n] = '\n'; /* get newline only if only char on line */
2337 ++n;
2338 line[n] = '\0';
2339 break;
2340 }
2341 } else {
2342 line[n] = '\0';
2343 break;
2344 }
2345
2346 }
2347
2348
2349 line[sizeofline] = '\0'; /* make sure line is terminated */
2350 SL_RETURN((n), _("sh_unix_getline"));
2351}
2352
2353
2354#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
2355
2356/**************************************************************
2357 *
2358 * --- FILE INFO ---
2359 *
2360 **************************************************************/
2361
2362#if defined(__linux__)
2363
2364#if defined(HAVE_LINUX_EXT2_FS_H) || defined(HAVE_EXT2FS_EXT2_FS_H)
2365
2366/* --- Determine ext2fs file attributes. ---
2367 */
2368#include <sys/ioctl.h>
2369#if defined(HAVE_EXT2FS_EXT2_FS_H)
2370#include <ext2fs/ext2_fs.h>
2371#else
2372#include <linux/ext2_fs.h>
2373#endif
2374
2375static
2376int sh_unix_getinfo_attr (char * name,
2377 unsigned long * flags,
2378 char * c_attr,
2379 int fd)
2380{
2381
2382/* TAKEN FROM:
2383 *
2384 * lsattr.c - List file attributes on an ext2 file system
2385 *
2386 * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
2387 * Laboratoire MASI, Institut Blaise Pascal
2388 * Universite Pierre et Marie Curie (Paris VI)
2389 *
2390 * This file can be redistributed under the terms of the GNU General
2391 * Public License
2392 */
2393
2394#ifdef HAVE_STAT_FLAGS
2395 struct stat buf;
2396 int i;
2397
2398 SL_ENTER(_("sh_unix_getinfo_attr"));
2399
2400 *flags = 0;
2401
2402 i = retry_stat (FIL__, __LINE__, name, &buf);
2403
2404 if (i == -1)
2405 SL_RETURN(-1, _("sh_unix_getinfo_attr"));
2406
2407#ifdef UF_IMMUTABLE
2408 if (buf.st_flags & UF_IMMUTABLE)
2409 *flags |= EXT2_IMMUTABLE_FL;
2410#endif
2411#ifdef UF_APPEND
2412 if (buf.st_flags & UF_APPEND)
2413 *flags |= EXT2_APPEND_FL;
2414#endif
2415#ifdef UF_NODUMP
2416 if (buf.st_flags & UF_NODUMP)
2417 *flags |= EXT2_NODUMP_FL;
2418#endif
2419
2420#else
2421
2422#ifdef HAVE_EXT2_IOCTLS
2423 int /* fd, */ r, f;
2424
2425 SL_ENTER(_("sh_unix_getinfo_attr"));
2426
2427 *flags = 0;
2428
2429 /* open() -> aud_open() R.Wichmann
2430 fd = aud_open (FIL__, __LINE__, SL_YESPRIV, name, O_RDONLY|O_NONBLOCK, 0);
2431 */
2432
2433 if (fd == -1 || name == NULL)
2434 SL_RETURN(-1, _("sh_unix_getinfo_attr"));
2435
2436
2437 r = ioctl (fd, EXT2_IOC_GETFLAGS, &f);
2438 /* close (fd); */
2439
2440 if (r == -1)
2441 SL_RETURN(-1, _("sh_unix_getinfo_attr"));
2442
2443 *flags = f;
2444
2445/* ! HAVE_EXT2_IOCTLS */
2446#else
2447
2448 SL_ENTER(_("sh_unix_getinfo_attr"));
2449
2450 *flags = 0; /* modified by R.Wichmann */
2451
2452/* ! HAVE_EXT2_IOCTLS */
2453#endif
2454#endif
2455/*
2456 * END
2457 *
2458 * lsattr.c - List file attributes on an ext2 file system
2459 */
2460
2461#ifdef EXT2_SECRM_FL
2462 if ( (*flags & EXT2_SECRM_FL) != 0 ) c_attr[0] = 's';
2463#endif
2464#ifdef EXT2_UNRM_FL
2465 if ( (*flags & EXT2_UNRM_FL) != 0 ) c_attr[1] = 'u';
2466#endif
2467#ifdef EXT2_SYNC_FL
2468 if ( (*flags & EXT2_SYNC_FL) != 0 ) c_attr[2] = 'S';
2469#endif
2470#ifdef EXT2_IMMUTABLE_FL
2471 if ( (*flags & EXT2_IMMUTABLE_FL) != 0) c_attr[3] = 'i';
2472#endif
2473#ifdef EXT2_APPEND_FL
2474 if ( (*flags & EXT2_APPEND_FL) != 0 ) c_attr[4] = 'a';
2475#endif
2476#ifdef EXT2_NODUMP_FL
2477 if ( (*flags & EXT2_NODUMP_FL) != 0 ) c_attr[5] = 'd';
2478#endif
2479#ifdef EXT2_NOATIME_FL
2480 if ( (*flags & EXT2_NOATIME_FL) != 0) c_attr[6] = 'A';
2481#endif
2482#ifdef EXT2_COMPR_FL
2483 if ( (*flags & EXT2_COMPR_FL) != 0 ) c_attr[7] = 'c';
2484#endif
2485#ifdef EXT2_COMPRBLK_FL
2486 if ( (*flags & EXT2_COMPRBLK_FL) != 0) c_attr[8] = 'B';
2487#endif
2488#ifdef EXT2_DIRTY_FL
2489 if ( (*flags & EXT2_DIRTY_FL) != 0 ) c_attr[9] = 'D';
2490#endif
2491#ifdef EXT2_NOCOMPR_FL
2492 if ( (*flags & EXT2_NOCOMPR_FL) != 0 ) c_attr[10] = 'D';
2493#endif
2494#ifdef EXT2_ECOMPR_FL
2495 if ( (*flags & EXT2_ECOMPR_FL) != 0 ) c_attr[11] = 'D';
2496#endif
2497
2498 c_attr[12] = '\0';
2499
2500 SL_RETURN(0, _("sh_unix_getinfo_attr"));
2501}
2502#else
2503static
2504int sh_unix_getinfo_attr (char * name,
2505 unsigned long * flags,
2506 char * c_attr,
2507 int fd)
2508{
2509 return 0;
2510}
2511#endif
2512
2513/* __LINUX__ */
2514#endif
2515
2516/* determine file type
2517 */
2518static
2519int sh_unix_getinfo_type (struct stat * buf,
2520 ShFileType * type,
2521 char * c_mode)
2522{
2523 SL_ENTER(_("sh_unix_getinfo_type"));
2524
2525 if ( S_ISREG(buf->st_mode) ) {
2526 (*type) = SH_FILE_REGULAR;
2527 c_mode[0] = '-';
2528 }
2529 else if ( S_ISLNK(buf->st_mode) ) {
2530 (*type) = SH_FILE_SYMLINK;
2531 c_mode[0] = 'l';
2532 }
2533 else if ( S_ISDIR(buf->st_mode) ) {
2534 (*type) = SH_FILE_DIRECTORY;
2535 c_mode[0] = 'd';
2536 }
2537 else if ( S_ISCHR(buf->st_mode) ) {
2538 (*type) = SH_FILE_CDEV;
2539 c_mode[0] = 'c';
2540 }
2541 else if ( S_ISBLK(buf->st_mode) ) {
2542 (*type) = SH_FILE_BDEV;
2543 c_mode[0] = 'b';
2544 }
2545 else if ( S_ISFIFO(buf->st_mode) ) {
2546 (*type) = SH_FILE_FIFO;
2547 c_mode[0] = '|';
2548 }
2549 else if ( S_ISSOCK(buf->st_mode) ) {
2550 (*type) = SH_FILE_SOCKET;
2551 c_mode[0] = 's';
2552 }
2553 else {
2554 (*type) = SH_FILE_UNKNOWN;
2555 c_mode[0] = '?';
2556 }
2557
2558 SL_RETURN(0, _("sh_unix_getinfo_type"));
2559}
2560
2561int sh_unix_get_ftype(char * fullpath)
2562{
2563 char c_mode[16];
2564 struct stat buf;
2565 ShFileType type;
2566 int res;
2567
2568 SL_ENTER(_("sh_unix_get_ftype"));
2569
2570 res = retry_lstat(FIL__, __LINE__, fullpath, &buf);
2571
2572 if (res < 0)
2573 SL_RETURN(SH_FILE_UNKNOWN, _("sh_unix_getinfo_type"));
2574
2575 sh_unix_getinfo_type (&buf, &type, c_mode);
2576
2577 SL_RETURN(type, _("sh_unix_get_ftype"));
2578}
2579
2580
2581static
2582int sh_unix_getinfo_mode (struct stat *buf,
2583 unsigned int * mode,
2584 char * c_mode)
2585{
2586
2587 SL_ENTER(_("sh_unix_getinfo_mode"));
2588
2589 (*mode) = buf->st_mode;
2590
2591 /* make 'ls'-like string */
2592
2593 if ( (buf->st_mode & S_IRUSR) != 0 ) c_mode[1] = 'r';
2594 if ( (buf->st_mode & S_IWUSR) != 0 ) c_mode[2] = 'w';
2595 if ( (buf->st_mode & S_IXUSR) != 0 ) {
2596 if ((buf->st_mode & S_ISUID) != 0 ) c_mode[3] = 's';
2597 else c_mode[3] = 'x';
2598 } else {
2599 if ((buf->st_mode & S_ISUID) != 0 ) c_mode[3] = 'S';
2600 }
2601
2602 if ( (buf->st_mode & S_IRGRP) != 0 ) c_mode[4] = 'r';
2603 if ( (buf->st_mode & S_IWGRP) != 0 ) c_mode[5] = 'w';
2604 if ( (buf->st_mode & S_IXGRP) != 0 ) {
2605 if ((buf->st_mode & S_ISGID) != 0 ) c_mode[6] = 's';
2606 else c_mode[6] = 'x';
2607 } else {
2608 if ((buf->st_mode & S_ISGID) != 0 ) c_mode[6] = 'S';
2609 }
2610
2611 if ( (buf->st_mode & S_IROTH) != 0 ) c_mode[7] = 'r';
2612 if ( (buf->st_mode & S_IWOTH) != 0 ) c_mode[8] = 'w';
2613#ifdef S_ISVTX /* not POSIX */
2614 if ( (buf->st_mode & S_IXOTH) != 0 ) {
2615 if ((buf->st_mode & S_ISVTX) != 0 ) c_mode[9] = 't';
2616 else c_mode[9] = 'x';
2617 } else {
2618 if ((buf->st_mode & S_ISVTX) != 0 ) c_mode[9] = 'T';
2619 }
2620#else
2621 if ( (buf->st_mode & S_IXOTH) != 0 ) c_mode[9] = 'x';
2622#endif
2623
2624 SL_RETURN(0, _("sh_unix_getinfo_mode"));
2625}
2626
2627
2628long IO_Limit = 0;
2629
2630void sh_unix_io_pause ()
2631{
2632 long runtime;
2633 float someval;
2634 unsigned long sometime;
2635
2636 if (IO_Limit == 0)
2637 {
2638 return;
2639 }
2640 else
2641 {
2642 runtime = (long) (time(NULL) - sh.statistics.time_start);
2643
2644 if (runtime > 0 && (long)(sh.statistics.bytes_hashed/runtime) > IO_Limit)
2645 {
2646 someval = sh.statistics.bytes_hashed - (IO_Limit * runtime);
2647 someval /= (float) IO_Limit;
2648 if (someval < 1.0)
2649 {
2650 someval *= 1000; /* milliseconds in a second */
2651 sometime = (unsigned long) someval;
2652 /* fprintf(stderr, "FIXME PAUSE %ld\n", sometime); */
2653 retry_msleep(0, sometime);
2654 }
2655 else
2656 {
2657 sometime = (unsigned long) someval;
2658 /* fprintf(stderr, "FIXME PAUSE %ld sec\n", sometime); */
2659 retry_msleep (sometime, 0);
2660 }
2661 }
2662 }
2663 return;
2664}
2665
2666int sh_unix_set_io_limit (char * c)
2667{
2668 long val;
2669
2670 SL_ENTER(_("sh_unix_set_io_limit"));
2671
2672 val = strtol (c, (char **)NULL, 10);
2673 if (val < 0)
2674 sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS,
2675 _("set I/O limit"), c);
2676
2677 val = (val < 0 ? 0 : val);
2678
2679 IO_Limit = val * 1024;
2680 SL_RETURN( 0, _("sh_unix_set_io_limit"));
2681}
2682
2683/* obtain file info
2684 */
2685extern int flag_err_debug;
2686
2687#include "sh_ignore.h"
2688
2689int sh_unix_getinfo (int level, char * filename, file_type * theFile,
2690 char * fileHash, int policy)
2691{
2692 char timestr[81];
2693 long runtim;
2694 struct stat buf;
2695 struct stat lbuf;
2696 struct stat fbuf;
2697 int stat_return;
2698 register int i;
2699 ShFileType type;
2700 unsigned int mode;
2701 char * name;
2702 char * tmp;
2703 char * tmp2;
2704 /* char * p; */
2705 char * linknamebuf;
2706 int linksize;
2707
2708 extern int get_the_fd (SL_TICKET ticket);
2709
2710 SL_TICKET rval_open;
2711 int fd;
2712#if defined(__linux__)
2713 int fd_2;
2714#endif
2715 int fstat_return;
2716
2717 time_t tend;
2718 time_t tstart;
2719
2720
2721 char * path = NULL;
2722
2723 int alert_timeout = 120;
2724
2725 path = theFile->fullpath;
2726
2727#if 0
2728 {
2729 char pwd[256];
2730 printf("%d %s %s %s (%s)\n", flagrel, theFile->fullpath, filename, path,
2731 getcwd (pwd, 256));
2732 }
2733#endif
2734
2735 SL_ENTER(_("sh_unix_getinfo"));
2736
2737 /* --- Stat the file, and get checksum. ---
2738 */
2739 tstart = time(NULL);
2740 stat_return = retry_lstat (FIL__, __LINE__,
2741 path /* theFile->fullpath */, &buf);
2742
2743 if (stat_return == 0 && S_ISREG(buf.st_mode))
2744 {
2745 rval_open = sl_open_fastread (path /* theFile->fullpath */, SL_YESPRIV);
2746
2747 alert_timeout = 120; /* this is per 8K block now ! */
2748
2749 if (path[0] == '/' && path[1] == 'p' && path[2] == 'r' &&
2750 path[3] == 'o' && path[4] == 'c' && path[5] == '/')
2751 {
2752 /* seven is magic */
2753 alert_timeout = 7;
2754 }
2755 }
2756 else
2757 rval_open = -1;
2758
2759 if (SL_ISERROR(rval_open))
2760 fd = -1;
2761 else
2762 fd = get_the_fd(rval_open);
2763
2764 tend = time(NULL);
2765
2766 /* An unprivileged user may slow lstat/open to a crawl
2767 * with clever path/symlink setup
2768 */
2769 if ((tend - tstart) > (time_t) /* 60 */ 6)
2770 {
2771 tmp2 = sh_util_safe_name (theFile->fullpath);
2772 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_TOOLATE,
2773 (long)(tend - tstart), tmp2);
2774 SH_FREE(tmp2);
2775 }
2776
2777 if (fd >= 0)
2778 {
2779 fstat_return = retry_fstat (FIL__, __LINE__, fd, &fbuf);
2780 }
2781 else
2782 {
2783 fstat_return = -1;
2784 fd = -1;
2785 }
2786#if defined(__linux__)
2787 fd_2 = fd;
2788#endif
2789
2790 /* --- case 1: lstat failed ---
2791 */
2792 if (stat_return != 0)
2793 {
2794 stat_return = errno;
2795 if (!SL_ISERROR(rval_open))
2796 sl_close(rval_open);
2797 if (sh.flag.checkSum == SH_CHECK_INIT ||
2798 (sh_hash_have_it (theFile->fullpath) >= 0 &&
2799 theFile->reported == S_FALSE))
2800 {
2801 if (S_FALSE == sh_ignore_chk_del(theFile->fullpath)) {
2802 tmp2 = sh_util_safe_name (theFile->fullpath);
2803 sh_error_handle (level, FIL__, __LINE__, stat_return, MSG_FI_LSTAT,
2804 sh_error_message (stat_return), tmp2);
2805 SH_FREE(tmp2);
2806 }
2807 }
2808 SL_RETURN((-1),_("sh_unix_getinfo"));
2809 }
2810
2811 /* --- case 2: not a regular file, or [IgnoreAll] ---
2812 */
2813 else if (! S_ISREG(buf.st_mode))
2814 {
2815 if (fileHash != NULL)
2816 strcpy(fileHash, /* known to fit */
2817 _("000000000000000000000000000000000000000000000000"));
2818 }
2819
2820 /* --- case 3a: a regular file, fstat ok ---
2821 */
2822 else if (fstat_return == 0 &&
2823 buf.st_mode == fbuf.st_mode &&
2824 buf.st_ino == fbuf.st_ino &&
2825 buf.st_uid == fbuf.st_uid &&
2826 buf.st_gid == fbuf.st_gid &&
2827 buf.st_dev == fbuf.st_dev )
2828 {
2829 if (fileHash != NULL)
2830 {
2831 if ((theFile->check_mask & MODI_CHK) == 0)
2832 {
2833 strcpy(fileHash, /* known to fit */
2834 _("000000000000000000000000000000000000000000000000"));
2835 }
2836 else if (policy == SH_LEVEL_PRELINK &&
2837 S_TRUE == sh_prelink_iself(rval_open, fbuf.st_size,
2838 alert_timeout))
2839 {
2840 if (0 != sh_prelink_run (theFile->fullpath,
2841 fileHash, alert_timeout))
2842 strcpy(fileHash, /* known to fit */
2843 _("000000000000000000000000000000000000000000000000"));
2844 }
2845 else
2846 {
2847 tiger_fd = rval_open;
2848 strcpy(fileHash, /* known to fit */
2849 sh_tiger_generic_hash (theFile->fullpath, TIGER_FD, 0,
2850 alert_timeout));
2851 }
2852 }
2853 }
2854
2855 /* --- case 3b: a regular file, fstat ok, but different ---
2856 */
2857 else if (fstat_return == 0 && S_ISREG(fbuf.st_mode))
2858 {
2859 memcpy (&buf, &fbuf, sizeof( struct stat ));
2860
2861 if (fileHash != NULL)
2862 {
2863 if ((theFile->check_mask & MODI_CHK) == 0)
2864 {
2865 strcpy(fileHash, /* known to fit */
2866 _("000000000000000000000000000000000000000000000000"));
2867 }
2868 else if (policy == SH_LEVEL_PRELINK &&
2869 S_TRUE == sh_prelink_iself(rval_open, fbuf.st_size,
2870 alert_timeout))
2871 {
2872 if (0 != sh_prelink_run (theFile->fullpath,
2873 fileHash, alert_timeout))
2874 strcpy(fileHash, /* known to fit */
2875 _("000000000000000000000000000000000000000000000000"));
2876 }
2877 else
2878 {
2879 tiger_fd = rval_open;
2880 sl_strlcpy(fileHash,
2881 sh_tiger_generic_hash (theFile->fullpath, TIGER_FD, 0,
2882 alert_timeout),
2883 KEY_LEN + 1);
2884 }
2885 }
2886 }
2887
2888 /* --- case 4: a regular file, fstat failed ---
2889 */
2890
2891 else /* fstat_return != 0 or !S_ISREG(fbuf->st_mode) */
2892 {
2893 fstat_return = errno;
2894 if (fileHash != NULL)
2895 sl_strlcpy(fileHash,
2896 _("000000000000000000000000000000000000000000000000"),
2897 KEY_LEN + 1);
2898
2899 tmp2 = sh_util_safe_name (theFile->fullpath);
2900 sh_error_handle (level, FIL__, __LINE__, fstat_return, MSG_E_READ,
2901 tmp2);
2902 SH_FREE(tmp2);
2903 }
2904
2905
2906 /* --- Determine file type. ---
2907 */
2908 for (i = 0; i < 10; ++i) theFile->c_mode[i] = '-';
2909 theFile->c_mode[10] = '\0';
2910 for (i = 0; i < 11; ++i) theFile->link_c_mode[i] = '-';
2911 theFile->link_c_mode[10] = '\0';
2912
2913 sh_unix_getinfo_type (&buf, &type, theFile->c_mode);
2914 theFile->type = type;
2915
2916#if defined(__linux__)
2917
2918 /* --- Determine file attributes. ---
2919 */
2920 for (i = 0; i < 12; ++i) theFile->c_attributes[i] = '-';
2921 theFile->c_attributes[12] = '\0';
2922 theFile->attributes = 0;
2923
2924 if (theFile->c_mode[0] != 'c' && theFile->c_mode[0] != 'b' &&
2925 theFile->c_mode[0] != 'l' )
2926 sh_unix_getinfo_attr(theFile->fullpath,
2927 &theFile->attributes, theFile->c_attributes, fd_2);
2928
2929#endif
2930
2931 if (!SL_ISERROR(rval_open))
2932 sl_close(rval_open);
2933
2934
2935 /* --- I/O limit. ---
2936 */
2937 if (IO_Limit > 0)
2938 {
2939 runtim = (long) (time(NULL) - sh.statistics.time_start);
2940
2941 if (runtim > 0 && (long)(sh.statistics.bytes_hashed/runtim) > IO_Limit)
2942 retry_msleep(1, 0);
2943 }
2944
2945 /* --- Determine permissions. ---
2946 */
2947 sh_unix_getinfo_mode (&buf, &mode, theFile->c_mode);
2948
2949 /* --- Trivia. ---
2950 */
2951 theFile->dev = buf.st_dev;
2952 theFile->ino = buf.st_ino;
2953 theFile->mode = buf.st_mode;
2954 theFile->hardlinks = buf.st_nlink;
2955 theFile->owner = buf.st_uid;
2956 theFile->group = buf.st_gid;
2957 theFile->rdev = buf.st_rdev;
2958 theFile->size = buf.st_size;
2959 theFile->blksize = (unsigned long) buf.st_blksize;
2960 theFile->blocks = (unsigned long) buf.st_blocks;
2961 theFile->atime = buf.st_atime;
2962 theFile->mtime = buf.st_mtime;
2963 theFile->ctime = buf.st_ctime;
2964
2965
2966 /* --- Owner and group. ---
2967 */
2968
2969 if ( (name = sh_unix_getGIDname(SH_ERR_ALL,
2970 buf.st_gid)) != NULL) {
2971 sl_strlcpy (theFile->c_group, name, GROUP_MAX+1);
2972 } else {
2973
2974 tmp2 = sh_util_safe_name (theFile->fullpath);
2975
2976 if (policy == SH_LEVEL_ALLIGNORE)
2977 {
2978 sh_error_handle (SH_ERR_ALL, FIL__, __LINE__, ENOENT,
2979 MSG_FI_NOGRP,
2980 (long) buf.st_gid, tmp2);
2981 }
2982 else
2983 {
2984 sh_error_handle (ShDFLevel[SH_ERR_T_NAME], FIL__, __LINE__, ENOENT,
2985 MSG_FI_NOGRP,
2986 (long) buf.st_gid, tmp2);
2987 }
2988 SH_FREE(tmp2);
2989 sl_snprintf(theFile->c_group, GROUP_MAX+1, "%d", (long) buf.st_gid);
2990 }
2991
2992
2993 if ( (name = sh_unix_getUIDname(SH_ERR_ALL,
2994 buf.st_uid)) != NULL) {
2995 sl_strlcpy (theFile->c_owner, name, USER_MAX+1);
2996 } else {
2997
2998 tmp2 = sh_util_safe_name (theFile->fullpath);
2999
3000 if (policy == SH_LEVEL_ALLIGNORE)
3001 {
3002 sh_error_handle (SH_ERR_ALL, FIL__, __LINE__, ENOENT,
3003 MSG_FI_NOUSR,
3004 (long) buf.st_uid, tmp2);
3005 }
3006 else
3007 {
3008 sh_error_handle (ShDFLevel[SH_ERR_T_NAME], FIL__, __LINE__, ENOENT,
3009 MSG_FI_NOUSR,
3010 (long) buf.st_uid, tmp2);
3011 }
3012 SH_FREE(tmp2);
3013 sl_snprintf(theFile->c_owner, USER_MAX+1, "%d", (long) buf.st_uid);
3014 }
3015
3016 /* --- Output the file. ---
3017 */
3018 if (flag_err_debug == SL_TRUE)
3019 {
3020 tmp2 = sh_util_safe_name ((filename == NULL) ?
3021 theFile->fullpath : filename);
3022 sl_strlcpy(timestr, sh_unix_time(theFile->mtime), 81);
3023 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_LIST,
3024 theFile->c_mode,
3025 theFile->hardlinks,
3026 theFile->c_owner,
3027 theFile->c_group,
3028 (unsigned long) theFile->size,
3029 timestr,
3030 tmp2);
3031 SH_FREE(tmp2);
3032 }
3033
3034 /* --- Check for links. ---
3035 */
3036 if (theFile->c_mode[0] == 'l')
3037 {
3038
3039 linknamebuf = SH_ALLOC(PATH_MAX);
3040
3041 linksize = readlink (theFile->fullpath, linknamebuf, PATH_MAX-1);
3042
3043 if (linksize < (PATH_MAX-1) && linksize >= 0)
3044 linknamebuf[linksize] = '\0';
3045 else
3046 linknamebuf[PATH_MAX-1] = '\0';
3047
3048 if (linksize < 0)
3049 {
3050 linksize = errno;
3051 tmp2 = sh_util_safe_name (theFile->fullpath);
3052 sh_error_handle (level, FIL__, __LINE__, linksize, MSG_FI_RDLNK,
3053 sh_error_message (linksize), tmp2);
3054 SH_FREE(tmp2);
3055 SH_FREE(linknamebuf);
3056 SL_RETURN((-1),_("sh_unix_getinfo"));
3057 }
3058
3059 if (linknamebuf[0] == '/')
3060 {
3061 sl_strlcpy (theFile->linkpath, linknamebuf, PATH_MAX);
3062 }
3063 else
3064 {
3065 tmp = sh_util_basename(theFile->fullpath);
3066 sl_strlcpy (theFile->linkpath,
3067 tmp,
3068 PATH_MAX);
3069 SH_FREE(tmp);
3070 sl_strlcat (theFile->linkpath,
3071 "/", PATH_MAX);
3072 sl_strlcat (theFile->linkpath,
3073 linknamebuf,
3074 PATH_MAX);
3075 }
3076
3077 /* stat the link
3078 */
3079 stat_return = retry_lstat (FIL__, __LINE__, theFile->linkpath, &lbuf);
3080
3081 /* check for error
3082 */
3083 if (stat_return != 0)
3084 {
3085 stat_return = errno;
3086 tmp = sh_util_safe_name (theFile->fullpath);
3087 tmp2 = sh_util_safe_name (theFile->linkpath);
3088 if (stat_return != ENOENT)
3089 {
3090 sh_error_handle (level, FIL__, __LINE__, stat_return,
3091 MSG_FI_LSTAT,
3092 sh_error_message (stat_return), tmp2);
3093 }
3094 else
3095 {
3096 /* a dangling link -- everybody seems to have plenty of them
3097 */
3098 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_DLNK,
3099 tmp, tmp2);
3100 }
3101 theFile->linkisok = BAD;
3102 SH_FREE(tmp);
3103 SH_FREE(tmp2);
3104 SH_FREE(linknamebuf);
3105 /*
3106 * changed Tue Feb 10 16:16:13 CET 2004:
3107 * add dangling symlinks into database
3108 * SL_RETURN((-1),_("sh_unix_getinfo"));
3109 */
3110 theFile->linkmode = 0;
3111 SL_RETURN((0),_("sh_unix_getinfo"));
3112 }
3113
3114 theFile->linkisok = GOOD;
3115
3116
3117 /* --- Determine file type. ---
3118 */
3119 sh_unix_getinfo_type (&lbuf, &type, theFile->link_c_mode);
3120 theFile->type = type;
3121
3122 /* --- Determine permissions. ---
3123 */
3124 sh_unix_getinfo_mode (&lbuf, &mode, theFile->link_c_mode);
3125 theFile->linkmode = lbuf.st_mode;
3126
3127 /* --- Output the link. ---
3128 */
3129 if (theFile->linkisok == GOOD)
3130 {
3131 tmp2 = sh_util_safe_name (linknamebuf);
3132 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_FI_LLNK,
3133 theFile->link_c_mode, tmp2);
3134 SH_FREE(tmp2);
3135 }
3136 SH_FREE(linknamebuf);
3137 }
3138 SL_RETURN((0),_("sh_unix_getinfo"));
3139}
3140
3141/* #if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE) */
3142#endif
3143
3144int sh_unix_unlock (char * lockfile, char * flag);
3145int sh_unix_lock (char * lockfile, char * flag);
3146
3147/* check whether file is locked
3148 */
3149int sh_unix_test_and_lock (char * filename, char * lockfile)
3150{
3151 static struct stat buf;
3152 int status = 0;
3153
3154
3155 SL_TICKET fd;
3156 char line_in[128];
3157
3158 SL_ENTER(_("sh_unix_test_and_lock"));
3159
3160 if (filename != NULL)
3161 {
3162 status = retry_lstat (FIL__, __LINE__, filename, &buf);
3163
3164 /* no logfile to lock
3165 */
3166 if (status < 0)
3167 SL_RETURN((-1),_("sh_unix_test_and_lock"));
3168 }
3169
3170 status = retry_lstat (FIL__, __LINE__, lockfile, &buf);
3171
3172 /* --- No lock file found, try to lock. ---
3173 */
3174
3175 if (status < 0 && errno == ENOENT)
3176 {
3177 if (0 == sh_unix_lock (lockfile, filename))
3178 {
3179 if (filename != NULL)
3180 sh.flag.islocked = GOOD;
3181 SL_RETURN((0),_("sh_unix_test_and_lock"));
3182 }
3183 }
3184 else if (status == 0 && buf.st_size == 0)
3185 {
3186 if (filename != NULL)
3187 sh.flag.islocked = GOOD;
3188 sh_unix_unlock (lockfile, filename);
3189 if (filename != NULL)
3190 sh.flag.islocked = BAD;
3191 if (0 == sh_unix_lock (lockfile, filename))
3192 {
3193 if (filename != NULL)
3194 sh.flag.islocked = GOOD;
3195 SL_RETURN((0),_("sh_unix_test_and_lock"));
3196 }
3197 else
3198 {
3199 sh_error_handle ((-1), FIL__, __LINE__, status,
3200 MSG_E_SUBGEN,
3201 (filename == NULL) ? _("Cannot create PID file") : _("Cannot create lock file"),
3202 _("sh_unix_test_and_lock"));
3203 SL_RETURN((-1),_("sh_unix_test_and_lock"));
3204 }
3205 }
3206
3207 /* --- Check on lock. ---
3208 */
3209
3210 if (status >= 0)
3211 {
3212 fd = sl_open_read (lockfile, SL_YESPRIV);
3213 if (SL_ISERROR(fd))
3214 sh_error_handle ((-1), FIL__, __LINE__, fd,
3215 MSG_E_SUBGEN,
3216 (filename == NULL) ? _("Cannot open PID file for read") : _("Cannot open lock file for read"),
3217 _("sh_unix_test_and_lock"));
3218 }
3219 else
3220 fd = -1;
3221
3222 if (!SL_ISERROR(fd))
3223 {
3224 /* read the PID in the lock file
3225 */
3226 status = sh_unix_getline (fd, line_in, sizeof(line_in)-1);
3227
3228 /* convert to numeric
3229 */
3230 if (status > 0)
3231 {
3232 errno = 0;
3233 status = strtol(line_in, (char **)NULL, 10);
3234 if (errno == ERANGE || status <= 0)
3235 {
3236 sh_error_handle ((-1), FIL__, __LINE__, status,
3237 MSG_E_SUBGEN,
3238 (filename == NULL) ? _("Bad PID in PID file") : _("Bad PID in lock file"),
3239 _("sh_unix_test_and_lock"));
3240
3241 status = -1;
3242 }
3243 }
3244 else
3245 {
3246 sh_error_handle ((-1), FIL__, __LINE__, status,
3247 MSG_E_SUBGEN,
3248 (filename == NULL) ? _("Cannot read PID file") : _("Cannot read lock file"),
3249 _("sh_unix_test_and_lock"));
3250 }
3251 sl_close(fd);
3252
3253 if (status == (int) getpid())
3254 {
3255 if (filename != NULL)
3256 sh.flag.islocked = GOOD;
3257 SL_RETURN((0),_("sh_unix_test_and_lock"));
3258 }
3259
3260
3261 /* --- Check whether the process exists. ---
3262 */
3263 if (status > 0)
3264 {
3265 errno = 0;
3266 status = aud_kill (FIL__, __LINE__, status, 0);
3267
3268 /* Does not exist, so remove the stale lock
3269 * and create a new one.
3270 */
3271 if (status < 0 && errno == ESRCH)
3272 {
3273 if (filename != NULL)
3274 sh.flag.islocked = GOOD;
3275 if (0 != sh_unix_unlock(lockfile, filename) && (filename !=NULL))
3276 sh.flag.islocked = BAD;
3277 else
3278 {
3279 if (0 == sh_unix_lock (lockfile, filename))
3280 {
3281 if (filename != NULL)
3282 sh.flag.islocked = GOOD;
3283 SL_RETURN((0),_("sh_unix_test_and_lock"));
3284 }
3285 else
3286 {
3287 sh_error_handle ((-1), FIL__, __LINE__, status,
3288 MSG_E_SUBGEN,
3289 (filename == NULL) ? _("Cannot create PID file") : _("Cannot create lock file"),
3290 _("sh_unix_test_and_lock"));
3291 }
3292 if (filename != NULL)
3293 sh.flag.islocked = BAD;
3294 }
3295 }
3296 else
3297 {
3298 sh_error_handle ((-1), FIL__, __LINE__, status,
3299 MSG_E_SUBGEN,
3300 (filename == NULL) ? _("Cannot remove stale PID file, PID may be a running process") : _("Cannot remove stale lock file, PID may be a running process"),
3301 _("sh_unix_test_and_lock"));
3302 if (filename != NULL)
3303 sh.flag.islocked = BAD;
3304 }
3305 }
3306 }
3307 SL_RETURN((-1),_("sh_unix_testlock"));
3308}
3309
3310/* write the PID file
3311 */
3312int sh_unix_write_pid_file()
3313{
3314 return sh_unix_test_and_lock(NULL, sh.srvlog.alt);
3315}
3316
3317/* write lock for filename
3318 */
3319int sh_unix_write_lock_file(char * filename)
3320{
3321 int i;
3322 char * lockfile;
3323
3324 if (filename == NULL)
3325 return (-1);
3326
3327 i = 6 + sl_strlen(filename);
3328 lockfile = SH_ALLOC(i);
3329 sl_strlcpy(lockfile, filename, i);
3330 sl_strlcat(lockfile, _(".lock"), i);
3331 i = sh_unix_test_and_lock(filename, lockfile);
3332 SH_FREE(lockfile);
3333 return i;
3334}
3335
3336int sh_unix_unlock(char * lockfile, char * flag)
3337{
3338 int error = 0;
3339
3340 SL_ENTER(_("sh_unix_unlock"));
3341
3342 /* --- Logfile is not locked to us. ---
3343 */
3344 if (sh.flag.islocked == BAD && flag != NULL)
3345 SL_RETURN((-1),_("sh_unix_unlock"));
3346
3347 /* --- Check whether the directory is secure. ---
3348 */
3349 if (0 != tf_trust_check (lockfile, SL_YESPRIV))
3350 SL_RETURN((-1),_("sh_unix_unlock"));
3351
3352 /* --- Delete the lock file. ---
3353 */
3354 error = retry_aud_unlink (FIL__, __LINE__, lockfile);
3355
3356 if (error == 0)
3357 {
3358 if (flag != NULL)
3359 sh.flag.islocked = BAD; /* not locked anymore */
3360 }
3361 else if (flag != NULL)
3362 {
3363 error = errno;
3364 sh_error_handle ((-1), FIL__, __LINE__, error, MSG_E_UNLNK,
3365 sh_error_message(error), lockfile);
3366 SL_RETURN((-1),_("sh_unix_unlock"));
3367 }
3368 SL_RETURN((0),_("sh_unix_unlock"));
3369}
3370
3371/* rm lock for filename
3372 */
3373int sh_unix_rm_lock_file(char * filename)
3374{
3375 int i;
3376 char * lockfile;
3377
3378 if (filename == NULL)
3379 return (-1);
3380
3381 i = 6 + sl_strlen(filename);
3382 lockfile = SH_ALLOC(i);
3383 sl_strlcpy(lockfile, filename, i);
3384 sl_strlcat(lockfile, _(".lock"), i);
3385 i = sh_unix_unlock(lockfile, filename);
3386 SH_FREE(lockfile);
3387 return i;
3388}
3389
3390/* rm lock for filename
3391 */
3392int sh_unix_rm_pid_file()
3393{
3394 return sh_unix_unlock(sh.srvlog.alt, NULL);
3395}
3396
3397int sh_unix_lock (char * lockfile, char * flag)
3398{
3399 struct stat buf;
3400 int status;
3401 int filed;
3402 int errnum;
3403 char myPid[64];
3404 SL_TICKET fd;
3405 extern int get_the_fd (SL_TICKET ticket);
3406
3407
3408 status = retry_lstat (FIL__, __LINE__, lockfile, &buf);
3409
3410 SL_ENTER(_("sh_unix_lock"));
3411
3412 if (0 == status)
3413 {
3414 if (flag != NULL)
3415 sh.flag.islocked = BAD;
3416 SL_RETURN((-1),_("sh_unix_lock"));
3417 }
3418
3419 sprintf (myPid, "%ld\n", (long) getpid()); /* known to fit */
3420
3421 fd = sl_open_write (lockfile, SL_YESPRIV);
3422
3423 if (!SL_ISERROR(fd))
3424 {
3425 errnum = sl_write (fd, myPid, sl_strlen(myPid));
3426 filed = get_the_fd(fd);
3427 fchmod (filed, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
3428 sl_close (fd);
3429
3430 if (!SL_ISERROR(errnum))
3431 {
3432 if (flag != NULL)
3433 sh.flag.islocked = GOOD;
3434 SL_RETURN((0),_("sh_unix_lock"));
3435 }
3436 }
3437
3438 TPT((0, FIL__, __LINE__, _("msg=<open pid file failed>\n")));
3439 if (flag != NULL)
3440 sh.flag.islocked = BAD;
3441 SL_RETURN((-1),_("sh_unix_lock"));
3442
3443 /* notreached */
3444}
3445
3446/* Test whether file exists
3447 */
3448int sh_unix_file_stat(char * path)
3449{
3450 struct stat buf;
3451
3452 SL_ENTER(_("sh_unix_file_stat"));
3453
3454 if (-1 == retry_stat(FIL__, __LINE__, path, &buf))
3455 SL_RETURN( (0), _("sh_unix_file_stat"));
3456 else
3457 SL_RETURN( (-1), _("sh_unix_file_stat"));
3458}
3459
3460
3461/* Test whether file exists, is a character device, allows read
3462 * access, and is not world writeable.
3463 */
3464int sh_unix_file_exists(int fd)
3465{
3466 struct stat buf;
3467
3468 SL_ENTER(_("sh_unix_file_exists"));
3469
3470 if (retry_fstat(FIL__, __LINE__, fd, &buf) == -1)
3471 SL_RETURN( (-1), _("sh_unix_file_exists"));
3472 else if ( S_ISCHR(buf.st_mode) && 0 != (S_IROTH & buf.st_mode)
3473 /*
3474 * #if !defined(__CYGWIN32__) && !defined(__CYGWIN__)
3475 * && 0 == (S_IWOTH & buf.st_mode)
3476 * #endif
3477 */
3478 )
3479 SL_RETURN( (0), _("sh_unix_file_exists"));
3480 else
3481 SL_RETURN( (-1), _("sh_unix_file_exists"));
3482}
3483
3484static char preq[16];
3485
3486/* return true if database is remote
3487 */
3488int file_is_remote ()
3489{
3490 static int init = 0;
3491
3492 SL_ENTER(_("file_is_remote"));
3493
3494 if (init == 0)
3495 {
3496 sl_strlcpy(preq, _("REQ_FROM_SERVER"), 16);
3497 ++init;
3498 }
3499 if (0 == sl_strncmp (sh.data.path, preq, 15))
3500 {
3501 SL_RETURN( S_TRUE, _("file_is_remote"));
3502 }
3503 SL_RETURN( S_FALSE, _("file_is_remote"));
3504}
3505
3506/* Return the path to the configuration/database file.
3507 */
3508char * file_path(char what, char flag)
3509{
3510 static int init = 0;
3511
3512 SL_ENTER(_("file_path"));
3513
3514 if (init == 0)
3515 {
3516 sl_strlcpy(preq, _("REQ_FROM_SERVER"), 16);
3517 ++init;
3518 }
3519
3520 switch (what)
3521 {
3522
3523 case 'C':
3524 if (0 == sl_strncmp (sh.conf.path, preq, 15))
3525 {
3526#if defined(SH_WITH_SERVER)
3527 if (sh.flag.isserver == S_TRUE && sl_strlen(sh.conf.path) == 15)
3528 SL_RETURN( NULL, _("file_path"));
3529 if (sh.flag.isserver == S_TRUE)
3530 SL_RETURN( &(sh.conf.path[15]), _("file_path"));
3531#endif
3532 if (flag == 'R')
3533 SL_RETURN( preq, _("file_path"));
3534 if (flag == 'I')
3535 {
3536 if (sl_strlen(sh.conf.path) == 15)
3537 SL_RETURN( NULL, _("file_path"));
3538 else
3539 SL_RETURN( &(sh.conf.path[15]), _("file_path"));
3540 }
3541 SL_RETURN ( preq, _("file_path"));
3542 }
3543 else
3544 SL_RETURN( sh.conf.path, _("file_path"));
3545 /* break; *//* unreachable */
3546
3547 case 'D':
3548 if (0 == sl_strncmp (sh.data.path, preq, 15))
3549 {
3550 if (flag == 'R')
3551 SL_RETURN( preq, _("file_path"));
3552 if (flag == 'W' && sl_strlen(sh.data.path) == 15)
3553 SL_RETURN (NULL, _("file_path"));
3554 if (flag == 'W')
3555 SL_RETURN( &(sh.data.path[15]), _("file_path"));
3556 }
3557 else
3558 SL_RETURN( sh.data.path, _("file_path"));
3559 break;
3560
3561 default:
3562 SL_RETURN( NULL, _("file_path"));
3563 }
3564
3565 return NULL; /* notreached */
3566}
3567/************************************************/
3568/**** Mlock Utilities ****/
3569/************************************************/
3570
3571#include <limits.h>
3572
3573int sh_unix_pagesize()
3574{
3575 int pagesize = 4096;
3576#if defined(_SC_PAGESIZE)
3577 pagesize = sysconf(_SC_PAGESIZE);
3578#elif defined(_SC_PAGE_SIZE)
3579 pagesize = sysconf(_SC_PAGE_SIZE);
3580#elif defined(HAVE_GETPAGESIZE)
3581 pagesize = getpagesize();
3582#elif defined(PAGESIZE)
3583 pagesize = PAGESIZE;
3584#endif
3585
3586 return ((pagesize > 0) ? pagesize : 4096);
3587}
3588
3589typedef struct sh_page_lt {
3590 unsigned long page_start;
3591 int page_refcount;
3592 struct sh_page_lt * next;
3593} sh_page_l;
3594
3595sh_page_l * sh_page_locked = NULL;
3596volatile int page_locking = 0;
3597
3598unsigned long sh_unix_lookup_page (void * in_addr, size_t len, int * num_pages)
3599{
3600 int pagesize = sh_unix_pagesize();
3601 unsigned long addr = (unsigned long) in_addr;
3602
3603 unsigned long pagebase;
3604 unsigned long pagediff;
3605 unsigned long pagenum = addr / pagesize;
3606
3607 SL_ENTER(_("sh_unix_lookup_page"));
3608#if 0
3609 fprintf(stderr, "mlock: --> base %ld, pagenum: %ld\n",
3610 addr, pagenum);
3611#endif
3612
3613 /* address of first page
3614 */
3615 pagebase = pagenum * pagesize;
3616
3617 /* number of pages
3618 */
3619 pagediff = (addr + len) - pagebase;
3620 pagenum = pagediff / pagesize;
3621 if (pagenum * pagesize < pagediff)
3622 ++pagenum;
3623
3624#if 0
3625 fprintf(stderr, "mlock: --> pagebase %ld, pagediff %ld, (addr + len) %ld\n",
3626 pagebase, pagediff, (addr + len));
3627#endif
3628
3629 *num_pages = pagenum;
3630 SL_RETURN((pagebase), _("sh_unix_lookup_page"));
3631}
3632
3633
3634#if defined(HAVE_MLOCK) && !defined(HAVE_BROKEN_MLOCK)
3635int sh_unix_mlock (void * in_addr, size_t len)
3636{
3637 int num_pages;
3638 int status = 0;
3639 int pagesize;
3640 sh_page_l * page_list = sh_page_locked;
3641 unsigned long addr;
3642#ifdef TEST_MLOCK
3643 int i = 0;
3644#endif
3645
3646 SL_ENTER(_("sh_unix_mlock"));
3647
3648 if (0 != page_locking)
3649 {
3650 SL_RETURN((-1), _("sh_unix_mlock"));
3651 }
3652 page_locking = 1;
3653
3654 pagesize = sh_unix_pagesize();
3655 addr = sh_unix_lookup_page (in_addr, len, &num_pages);
3656
3657#ifdef TEST_MLOCK
3658 fprintf(stderr, "mlock: addr %ld, base %ld, pages: %d, length %d\n",
3659 (unsigned long) in_addr, addr, num_pages, len);
3660#endif
3661
3662 /* increase refcount of locked pages
3663 * addr is first page; num_pages is #(consecutive pages) to lock
3664 */
3665 while ((page_list != NULL) && (num_pages > 0))
3666 {
3667#ifdef TEST_MLOCK
3668 fprintf(stderr, "mlock: check page %d: %ld [%d]\n",
3669 i, page_list->page_start, page_list->page_refcount);
3670#endif
3671 if (page_list->page_start == addr)
3672 {
3673 page_list->page_refcount += 1;
3674 num_pages -= 1;
3675 addr += pagesize;
3676#ifdef TEST_MLOCK
3677 fprintf(stderr, "mlock: found page %d: %ld [%d], next page %ld\n",
3678 i, page_list->page_start, page_list->page_refcount, addr);
3679#endif
3680 }
3681#ifdef TEST_MLOCK
3682 ++i;
3683#endif
3684 page_list = page_list->next;
3685 }
3686
3687 /* mlock some more pages, if needed
3688 */
3689 while (num_pages > 0)
3690 {
3691#ifdef TEST_MLOCK
3692 fprintf(stderr, "mlock: lock page %d: mlock %ld [num_pages %d]\n",
3693 i, addr, num_pages);
3694 ++i;
3695#endif
3696 page_list = SH_ALLOC(sizeof(sh_page_l));
3697 page_list->page_start = addr;
3698 page_list->page_refcount = 1;
3699 status = mlock( (void *) addr, pagesize);
3700 if (status != 0)
3701 {
3702#ifdef TEST_MLOCK
3703 fprintf(stderr, "mlock: error: %s\n", sh_error_message(errno));
3704#endif
3705 SH_FREE(page_list);
3706 page_locking = 0;
3707 SL_RETURN((status), _("sh_unix_mlock"));
3708 }
3709 page_list->next = sh_page_locked;
3710 sh_page_locked = page_list;
3711 num_pages -= 1;
3712 addr += pagesize;
3713 }
3714
3715 page_locking = 0;
3716 SL_RETURN((status), _("sh_unix_mlock"));
3717}
3718#else
3719int sh_unix_mlock (void * in_addr, size_t len)
3720{
3721 (void) in_addr; (void) len;
3722 return -1;
3723}
3724#endif
3725
3726#if defined(HAVE_MLOCK) && !defined(HAVE_BROKEN_MLOCK)
3727int sh_unix_munlock (void * in_addr, size_t len)
3728{
3729 int num_pages;
3730 int unlocked = 0;
3731 int status = 0;
3732 int pagesize;
3733 sh_page_l * page_list = sh_page_locked;
3734 sh_page_l * page_last;
3735 unsigned long addr;
3736
3737 int test_count;
3738 int test_status;
3739 int test_pages;
3740
3741#ifdef TEST_MLOCK
3742 int i = 0;
3743#endif
3744
3745 SL_ENTER(_("sh_unix_munlock"));
3746
3747 if (0 != page_locking)
3748 {
3749 SL_RETURN((-1), _("sh_unix_munlock"));
3750 }
3751 page_locking = 1;
3752
3753 pagesize = sh_unix_pagesize();
3754 addr = sh_unix_lookup_page (in_addr, len, &num_pages);
3755
3756#ifdef TEST_MLOCK
3757 fprintf(stderr, "munlock: in_addr %ld, addr %ld, pages: %d, length %d\n",
3758 (unsigned long) in_addr, addr, num_pages, len);
3759#endif
3760
3761 test_pages = num_pages;
3762
3763 /* reduce refcount of locked pages
3764 * addr is first page; num_pages is #(consecutive pages) to lock
3765 */
3766 while ((page_list != NULL) && (num_pages > 0))
3767 {
3768#ifdef TEST_MLOCK
3769 fprintf(stderr, "munlock: page %d: %ld [%d]\n",
3770 i, page_list->page_start, page_list->page_refcount);
3771#endif
3772
3773 test_status = 0;
3774 for (test_count = 0; test_count < test_pages; ++test_count)
3775 {
3776 if (page_list->page_start == (addr + (test_count * pagesize)))
3777 {
3778 test_status = 1;
3779 break;
3780 }
3781 }
3782
3783 if (test_status == 1)
3784 {
3785 page_list->page_refcount -= 1;
3786 if (page_list->page_refcount == 0)
3787 {
3788 status = munlock ( (void *) addr, pagesize);
3789 ++unlocked;
3790 }
3791 num_pages -= 1;
3792#ifdef TEST_MLOCK
3793 fprintf(stderr,
3794 "munlock: page %d: %ld [refcount %d], refcount reduced\n",
3795 i, page_list->page_start, page_list->page_refcount);
3796#endif
3797 }
3798#ifdef TEST_MLOCK
3799 ++i;
3800#endif
3801 page_list = page_list->next;
3802 }
3803
3804#ifdef TEST_MLOCK
3805 i = 0;
3806#endif
3807
3808 if (unlocked > 0)
3809 {
3810 page_list = sh_page_locked;
3811 page_last = sh_page_locked;
3812
3813 while ((page_list != NULL) && (unlocked > 0))
3814 {
3815 if (page_list->page_refcount == 0)
3816 {
3817#ifdef TEST_MLOCK
3818 fprintf(stderr, "munlock: remove page %d: %ld [refcount %d]\n",
3819 i, page_list->page_start, page_list->page_refcount);
3820#endif
3821 if (page_last != page_list)
3822 {
3823 page_last->next = page_list->next;
3824 SH_FREE(page_list);
3825 page_list = page_last->next;
3826 }
3827 else
3828 {
3829 page_last = page_list->next;
3830 if (page_list == sh_page_locked)
3831 sh_page_locked = page_list->next;
3832 SH_FREE(page_list);
3833 page_list = page_last;
3834 }
3835 --unlocked;
3836 }
3837 else
3838 {
3839#ifdef TEST_MLOCK
3840 fprintf(stderr, "munlock: skip page %d: %ld [refcount %d]\n",
3841 i, page_list->page_start, page_list->page_refcount);
3842#endif
3843
3844 page_last = page_list;
3845 page_list = page_list->next;
3846 }
3847#ifdef TEST_MLOCK
3848 ++i;
3849#endif
3850 }
3851 }
3852
3853 page_locking = 0;
3854 SL_RETURN((status), _("sh_unix_munlock"));
3855}
3856#else
3857int sh_unix_munlock (void * in_addr, size_t len)
3858{
3859 (void) in_addr; (void) len;
3860 return -1;
3861}
3862#endif
3863
3864int sh_unix_count_mlock()
3865{
3866 int i = 0;
3867 char str[128];
3868 sh_page_l * page_list = sh_page_locked;
3869
3870 SL_ENTER(_("sh_unix_count_mlock"));
3871 while (page_list != NULL)
3872 {
3873 page_list = page_list->next;
3874 ++i;
3875 }
3876 sprintf(str, _("%d pages locked"), i); /* known to fit */
3877 sh_error_handle(SH_ERR_INFO, FIL__, __LINE__, i, MSG_E_SUBGEN,
3878 str, _("sh_unix_count_mlock"));
3879 SL_RETURN((i), _("sh_unix_count_mlock"));
3880}
3881
3882/************************************************/
3883/************************************************/
3884/**** Stealth Utilities ****/
3885/************************************************/
3886/************************************************/
3887#ifdef SH_STEALTH
3888
3889void sh_unix_xor_code (char * str, int len)
3890{
3891 register int i;
3892
3893 for (i = 0; i < len; ++i) str[i] ^= (char) XOR_CODE;
3894 return;
3895}
3896
3897#if !defined(SH_STEALTH_MICRO)
3898
3899static unsigned long off_data = 0;
3900static unsigned long max_data = 0;
3901static int stealth_init = BAD;
3902
3903int hideout_hex_block(SL_TICKET fd, unsigned char * str, int len);
3904unsigned long first_hex_block(SL_TICKET fd, unsigned long * max);
3905
3906/*
3907 * --- Get hidden data from a block of hex data. ---
3908 */
3909int sh_unix_getline_stealth (SL_TICKET fd, char * str, int len)
3910{
3911 int add_off, llen;
3912
3913 SL_ENTER(_("sh_unix_getline_stealth"));
3914
3915 /* --- Initialize. ---
3916 */
3917 if (stealth_init == BAD)
3918 {
3919 off_data = first_hex_block(fd, &max_data);
3920 if (off_data == 0)
3921 {
3922 dlog(1, FIL__, __LINE__,
3923 _("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"));
3924 sh_error_handle ((-1), FIL__, __LINE__, EIO, MSG_P_NODATA,
3925 _("Stealth config file."));
3926 aud_exit (FIL__, __LINE__, EXIT_FAILURE);
3927 }
3928 stealth_init = GOOD;
3929 }
3930
3931 /* --- Seek to proper position. ---
3932 */
3933 sl_seek(fd, off_data);
3934
3935 /* --- Read one line. ---
3936 */
3937 add_off = hideout_hex_block(fd, (unsigned char *) str, len);
3938 off_data += add_off;
3939
3940
3941 llen = sl_strlen(str);
3942 SL_RETURN(llen, _("sh_unix_getline_stealth"));
3943}
3944
3945int hideout_hex_block(SL_TICKET fd, unsigned char * str, int len)
3946{
3947
3948 register int i, j, k;
3949 unsigned char c, e;
3950 register int num;
3951 unsigned char mask[9] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
3952 unsigned long here = 0;
3953 unsigned long retval = 0;
3954
3955 SL_ENTER(_("hideout_hex_block"));
3956
3957 i = 0;
3958 while (i < len)
3959 {
3960 for (j = 0; j < 8; ++j)
3961 {
3962
3963 /* --- Get a low byte, modify, read back. ---
3964 */
3965 for (k = 0; k < 2; ++k)
3966 {
3967 /* -- Skip whitespace. ---
3968 */
3969 c = ' ';
3970 do {
3971 do {
3972 num = sl_read (fd, &c, 1);
3973 } while (num == 0 && errno == EINTR);
3974 if (num == 0)
3975 SL_RETURN((-1), _("hideout_hex_block"));
3976 ++here;
3977 } while (c == '\n' || c == '\t' || c == '\r' ||
3978 c == ' ');
3979 }
3980
3981
3982 /* --- e is the value of the low byte. ---
3983 */
3984 e = (unsigned char) sh_util_hexchar( c );
3985 if ((e & mask[7]) != 0) /* bit is set */
3986 str[i] |= mask[j];
3987 else /* bit is not set */
3988 str[i] &= ~mask[j];
3989
3990 }
3991 if (str[i] == '\n') break;
3992 ++i;
3993 }
3994
3995 if (i != 0)
3996 str[i] = '\0';
3997 else
3998 str[i+1] = '\0';
3999 retval += here;
4000
4001 SL_RETURN(retval, _("hideout_hex_block"));
4002}
4003
4004/* --- Get offset of first data block. ---
4005 */
4006unsigned long first_hex_block(SL_TICKET fd, unsigned long * max)
4007{
4008 int i;
4009 register int num = 1;
4010 char c;
4011 int nothex = 0;
4012 unsigned long retval = 0;
4013 int this_line = 0;
4014 char theline[SH_BUFSIZE];
4015
4016 SL_ENTER(_("first_hex_block"));
4017
4018 *max = 0;
4019
4020 while (1)
4021 {
4022 theline[0] = '\0';
4023 this_line = 0;
4024 c = '\0';
4025 while (c != '\n' && num > 0)
4026 {
4027 do {
4028 num = sl_read (fd, &c, 1);
4029 } while (num == 0 && errno == EINTR);
4030 if (num > 0)
4031 theline[this_line] = c;
4032 else
4033 SL_RETURN((0), _("first_hex_block"));
4034 this_line += num;
4035 }
4036 theline[this_line] = '\0';
4037
4038 /* not only 'newline' */
4039 if (this_line > 60)
4040 {
4041 nothex = 0;
4042 i = 0;
4043 while (nothex == 0 && i < (this_line-1))
4044 {
4045 if (! isxdigit((int)theline[i])) nothex = 1;
4046 ++i;
4047 }
4048 if (nothex == 1) retval += this_line;
4049 }
4050 else
4051 {
4052 nothex = 1;
4053 retval += this_line;
4054 }
4055
4056 if (nothex == 0)
4057 {
4058 *max = 0;
4059 do {
4060 do {
4061 num = sl_read (fd, theline, SH_BUFSIZE);
4062 } while (num == 0 && errno == EINTR);
4063 for (i = 0; i < num; ++i)
4064 {
4065 c = theline[i];
4066 if (c == '\n' || c == '\t' || c == '\r' || c == ' ')
4067 ;
4068 else if (!isxdigit((int)c))
4069 break;
4070 else
4071 *max += 1;
4072 }
4073 } while (num > 0);
4074
4075 *max /= 16;
4076 SL_RETURN((retval), _("first_hex_block"));
4077 }
4078
4079 }
4080 /* SL_RETURN((0), _("first_hex_block")); *//* unreachable */
4081}
4082
4083 /* if !defined(SH_STEALTH_MICRO) */
4084#endif
4085
4086 /* ifdef SH_STEALTH */
4087#endif
4088
4089/*
4090 * anti-debugger code
4091 */
4092#if defined(SCREW_IT_UP)
4093volatile int sh_not_traced = 0;
4094
4095#ifdef HAVE_GETTIMEOFDAY
4096struct timeval save_tv;
4097#endif
4098
4099void sh_sigtrap_handler (int signum)
4100{
4101#ifdef HAVE_GETTIMEOFDAY
4102 struct timeval tv;
4103 long difftv;
4104
4105 gettimeofday(&tv, NULL);
4106 difftv = (tv.tv_sec - save_tv.tv_sec) * 1000000 +
4107 (tv.tv_usec - save_tv.tv_usec);
4108 if (difftv > 500000)
4109 _exit(6);
4110#endif
4111 sh_not_traced += signum;
4112 return;
4113}
4114#endif
Note: See TracBrowser for help on using the repository browser.