source: trunk/src/sh_unix.c@ 18

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

Optimized version of tiger algorithm, and basic ingredients for unit testing (part 2)

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