source: trunk/src/sh_unix.c@ 294

Last change on this file since 294 was 294, checked in by katerina, 14 years ago

Tikets #213 and #214 (Use auditd to determine who changed a file, Windows registry check).

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