source: trunk/src/slib.c@ 20

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

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

File size: 55.0 KB
Line 
1#include "config_xor.h"
2
3
4#include <stdio.h>
5#include <stdlib.h>
6#include <stdarg.h>
7#include <string.h>
8#include <limits.h>
9
10#include <unistd.h>
11#include <sys/stat.h>
12#include <sys/types.h>
13#include <fcntl.h>
14#include <signal.h>
15
16#if TIME_WITH_SYS_TIME
17#include <sys/time.h>
18#include <time.h>
19#else
20#if HAVE_SYS_TIME_H
21#include <sys/time.h>
22#else
23#include <time.h>
24#endif
25#endif
26
27#ifdef HAVE_MEMORY_H
28#include <memory.h>
29#endif
30#ifdef HAVE_SYS_SELECT_H
31#include <sys/select.h>
32#endif
33
34#ifndef FD_SET
35#define NFDBITS 32
36#define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
37#define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
38#define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
39#endif /* !FD_SET */
40#ifndef FD_SETSIZE
41#define FD_SETSIZE 32
42#endif
43#ifndef FD_ZERO
44#define FD_ZERO(p) memset((char *)(p), '\0', sizeof(*(p)))
45#endif
46
47#include "slib.h"
48#include "sh_calls.h"
49#define SH_NEED_PWD_GRP 1
50#include "sh_static.h"
51
52#undef FIL__
53#define FIL__ _("slib.c")
54
55const uid_t sh_uid_neg = ((uid_t) -1);
56const gid_t sh_gid_neg = ((gid_t) -1);
57
58#undef BREAKEXIT
59#if defined(SCREW_IT_UP) && defined(__linux__) && defined(__i386__)
60
61#ifdef SH_DEBUG
62#define BREAKEXIT(expr) \
63 do { \
64 int ixi; \
65 for (ixi = 0; ixi < 8; ++ixi) { \
66 if ((*(volatile unsigned *)((unsigned) expr + ixi) & 0xff) == 0xcc) \
67 { dlog(0, FIL__, __LINE__, _("BREAKEXIT")); _exit(EXIT_FAILURE); } \
68 } \
69 } \
70 while (1 == 0)
71#else
72#define BREAKEXIT(expr) \
73 do { \
74 int ixi; \
75 for (ixi = 0; ixi < 8; ++ixi) { \
76 if ((*(volatile unsigned *)((unsigned) expr + ixi) & 0xff) == 0xcc) \
77 _exit(EXIT_FAILURE); \
78 } \
79 } \
80 while (1 == 0)
81#endif
82
83#else
84#define BREAKEXIT(expr)
85#endif
86
87/****************************************************************
88 *
89 * The debug/trace subsystem
90 *
91 ****************************************************************/
92
93int slib_do_trace = 0;
94int slib_trace_fd = -1;
95
96static char trace_log[256] = { '\0' };
97static int trace_level = 0;
98static FILE * trace_fp = NULL;
99
100int sl_trace_use (const char * dummy)
101{
102 if (dummy)
103 slib_do_trace = 1;
104 else
105 slib_do_trace = 1;
106 return 0;
107}
108
109int sl_trace_file (const char * str)
110{
111 if (!str)
112 return -1;
113 if (str[0] != '/')
114 return -1;
115 sl_strlcpy(trace_log, str, 256);
116 return 0;
117}
118
119FILE * sl_tracefile_open(char * file, char * mode)
120{
121 FILE * xp = NULL;
122 slib_trace_fd = open(file, O_WRONLY|O_CREAT|O_APPEND, 0600);
123 if (slib_trace_fd >= 0)
124 xp = fdopen(slib_trace_fd, mode);
125 return xp;
126}
127
128void sl_trace_in(char * str, char * file, int line)
129{
130 int i;
131 if (trace_log[0] == '\0')
132 {
133 fprintf(stderr, "++ ");
134 for (i = 0; i < trace_level; ++i)
135 fprintf(stderr, ". ");
136 fprintf(stderr, "[%2d] %s \t - File %c%s%c at line %d\n",
137 trace_level, str, 0x22, file, 0x22, line);
138 }
139 else if (!sl_is_suid())
140 {
141 if (!trace_fp)
142 trace_fp = sl_tracefile_open(trace_log, "a");
143 if (trace_fp)
144 {
145 fprintf(trace_fp, "++ ");
146 for (i = 0; i < trace_level; ++i)
147 fprintf(trace_fp, ". ");
148 fprintf(trace_fp, "[%2d] %s \t - File %c%s%c at line %d\n",
149 trace_level, str, 0x22, file, 0x22, line);
150 }
151 else
152 {
153 perror(_("sl_trace_in: fopen"));
154 _exit(1);
155 }
156 }
157 ++trace_level;
158}
159
160void sl_trace_out(char * str, char * file, int line)
161{
162 int i;
163
164 --trace_level; if (trace_level < 0) trace_level = 0;
165
166 if (trace_log[0] == '\0')
167 {
168 fprintf(stderr, "-- ");
169 for (i = 0; i < trace_level; ++i)
170 fprintf(stderr, ". ");
171 fprintf(stderr, _("[%2d] %s \t - File %c%s%c at line %d\n"),
172 trace_level, str, 0x22, file, 0x22, line);
173 }
174 else if (!sl_is_suid())
175 {
176 if (!trace_fp)
177 trace_fp = sl_tracefile_open(trace_log, "a");
178 if (trace_fp)
179 {
180 fprintf(trace_fp, "-- ");
181 for (i = 0; i < trace_level; ++i)
182 fprintf(trace_fp, ". ");
183 fprintf(trace_fp, _("[%2d] %s \t - File %c%s%c at line %d\n"),
184 trace_level, str, 0x22, file, 0x22, line);
185 }
186 else
187 {
188 perror(_("sl_trace_out: fopen"));
189 _exit(1);
190 }
191 }
192}
193
194extern int sh_log_console (char * msg);
195
196static int dlogActive = 0;
197
198/* this is called from sh_error_setprint()
199 */
200void dlog_set_active(int flag)
201{
202 dlogActive = flag;
203}
204
205/* flag = 0 debug messages
206 * = 1 descriptive error messages
207 * = 3 backtrace
208 */
209int dlog (int flag, char * file, int line, const char *fmt, ...)
210{
211 va_list ap;
212 char val[81];
213 char msg[512];
214 char tmp[512];
215 int retval = 0;
216 int i;
217
218#ifdef SH_STEALTH
219 /*
220 * do not even print descriptive failure messages in stealth mode
221 */
222 if (dlogActive == 0)
223 return 0;
224 if (dlogActive == 1 && flag == 0) /* debug requires debug level */
225 return 0;
226#else
227 if (dlogActive <= 1 && flag == 0) /* debug requires debug level */
228 return 0;
229#endif
230
231 if (flag == 1)
232 {
233 sprintf (val, _("\n--------- %10s "), file);
234 sl_strlcpy (msg, val, 80);
235 sprintf (val, _(" --- %6d ---------\n"), line);
236 sl_strlcat (msg, val, 80);
237 sh_log_console (msg);
238 }
239
240 va_start (ap, fmt);
241 if (flag == 1)
242 sl_strlcpy(tmp, fmt, 512);
243 else
244 sl_strlcpy(tmp, fmt, 256);
245 retval = sl_strlen(tmp);
246 if (retval > 0 && tmp[retval-1] == '\n')
247 tmp[retval-1] = '\0';
248 retval = 0;
249 if (flag == 1)
250 {
251 sl_vsnprintf (msg, 511, tmp, ap);
252 }
253 else
254 {
255 sl_strlcpy (msg, "## ", 256);
256 for (i = 0; i < trace_level; ++i)
257 sl_strlcat (msg, ". ", 256);
258 sprintf (val, _("[%2d] "), trace_level);
259 sl_strlcat (msg, val, 256);
260 sl_vsnprintf (&msg[sl_strlen(msg)], 255, tmp, ap);
261 sl_snprintf (tmp, 255, _(" \t - File %c%s%c at line %d"),
262 0x22, file, 0x22, line);
263 sl_strlcat (msg, tmp, 512);
264 }
265 va_end (ap);
266 if (flag != 0 || sl_is_suid())
267 retval = sh_log_console (msg);
268 else
269 {
270 if (trace_log[0] == '\0')
271 {
272 /* sh_log_console (msg); */
273 fprintf(stderr, "%s\n", msg);
274 }
275 else
276 {
277 if (!trace_fp)
278 trace_fp = sl_tracefile_open(trace_log, "a");
279 if (trace_fp)
280 {
281 fprintf(trace_fp, "%s\n", msg);
282 }
283 else
284 {
285 perror(_("dlog: fopen"));
286 _exit(1);
287 }
288 }
289 }
290 if (flag == 1)
291 sh_log_console (_("\n----------------------------------------------\n"));
292 return retval;
293}
294
295extern char aud_err_message[64];
296static char alt_err_message[64];
297char * sl_get_errmsg()
298{
299 if (aud_err_message[0] == '\0')
300 {
301 sl_strlcpy(alt_err_message, sl_error_string(sl_errno), 64);
302 return &alt_err_message[0];
303 }
304 return &aud_err_message[0];
305}
306
307
308#if defined(SL_DEBUG)
309#define SL_MAX_MYSTACK 128
310
311static char sl_mystack[SL_MAX_MYSTACK][32];
312static int sl_mystack_count = 0;
313
314void sl_stack_push(char * c, char * file, int line )
315{
316 if (slib_do_trace)
317 sl_trace_in(c, file, line);
318 if (c && sl_mystack_count < SL_MAX_MYSTACK)
319 {
320 strncpy(sl_mystack[sl_mystack_count], c, 31);
321 sl_mystack[sl_mystack_count][31] = '\0';
322 ++sl_mystack_count;
323 /*
324 fprintf(stderr, "#%03d %s\n", sl_mystack_count,
325 sl_mystack[sl_mystack_count-1]);
326 */
327 }
328 return;
329}
330
331void sl_stack_pop(char * c, char * file, int line)
332{
333 if (slib_do_trace)
334 sl_trace_out(c, file, line);
335 if (sl_mystack_count > 0)
336 {
337 /*
338 fprintf(stderr, " <- #%03d %s\n", sl_mystack_count,
339 sl_mystack[sl_mystack_count-1]);
340 */
341 --sl_mystack_count;
342 }
343 return;
344}
345
346void sl_stack_print()
347{
348 int i;
349 /* FILE * dfile; */
350
351 if (sl_mystack_count > 0)
352 {
353 sh_log_console(_("\nBacktrace:\n"));
354 /* dlog(3, FIL__, __LINE__, _("\nBacktrace:\n")); */
355 for (i = 0; i < sl_mystack_count; ++i)
356 sh_log_console(sl_mystack[i]);
357 /* dlog(3, FIL__, __LINE__, _("#%03d %s\n"), i, sl_mystack[i]); */
358 }
359 return;
360}
361
362#endif
363
364
365/*
366 * The global errno.
367 * On error, this is set to the return value of the function.
368 */
369long int sl_errno;
370
371
372/* ----------------------------------------------------------------
373 *
374 * Capability routines
375 *
376 * ---------------------------------------------------------------- */
377
378int sl_useCaps = 0;
379
380#ifdef FANCY_LIBCAP
381#include <sys/capability.h>
382
383/*
384 * While these routines are tested and work, we don't use POSIX
385 * capabilities, as they don't seem to be useful (root can write
386 * to root-owned files anyway). Things would be more interesting
387 * if we could switch to a non-root UID with just a few capabilities
388 * enabled.
389 */
390int sl_drop_cap ()
391{
392 int error;
393 cap_t caps;
394 cap_flag_t capflag;
395 cap_flag_value_t capfval = CAP_CLEAR;
396 cap_value_t capvals_e[] =
397 {
398 CAP_CHOWN, CAP_FOWNER, CAP_FSETID,
399 CAP_LINUX_IMMUTABLE, CAP_MKNOD, CAP_NET_ADMIN,
400 CAP_NET_BIND_SERVICE, CAP_NET_BROADCAST, CAP_NET_RAW,
401 CAP_SYS_ADMIN, CAP_SYS_BOOT, CAP_SYS_CHROOT,
402 CAP_SYS_PACCT, CAP_SYS_PTRACE, CAP_SYS_RAWIO,
403 CAP_SYS_RESOURCE, CAP_SYS_TIME, CAP_SYS_TTY_CONFIG,
404 CAP_SETGID, CAP_SETUID, CAP_KILL,
405 CAP_DAC_OVERRIDE,
406#if !defined(WITH_MESSAGE_QUEUE)
407 CAP_IPC_OWNER,
408#endif
409 CAP_SYS_MODULE, CAP_LEASE
410 };
411 cap_value_t capvals_p[] =
412 {
413 CAP_CHOWN, CAP_LEASE, CAP_FSETID,
414 CAP_LINUX_IMMUTABLE, CAP_MKNOD, CAP_NET_ADMIN,
415 CAP_NET_BIND_SERVICE, CAP_NET_BROADCAST, CAP_NET_RAW,
416 CAP_SYS_ADMIN, CAP_SYS_BOOT, CAP_SYS_CHROOT,
417 CAP_SYS_PACCT, CAP_SYS_PTRACE, CAP_SYS_RAWIO,
418 CAP_SYS_RESOURCE, CAP_SYS_TIME, CAP_SYS_TTY_CONFIG,
419#if !defined(WITH_EXTERNAL) && !defined(HAVE_UNIX_RANDOM)
420 CAP_SETGID, CAP_SETUID, CAP_KILL,
421#endif
422#if !defined(SH_USE_SUIDCHK)
423 CAP_DAC_OVERRIDE, CAP_FOWNER,
424#endif
425#if !defined(WITH_MESSAGE_QUEUE)
426 CAP_IPC_OWNER,
427#endif
428 CAP_SYS_MODULE
429 };
430
431 if (0 == sl_useCaps) /* 0 = S_FALSE */
432 {
433 return 0;
434 }
435
436 if(NULL == (caps = cap_get_proc()))
437 {
438 return errno;
439 }
440
441 capflag = CAP_EFFECTIVE;
442 if (0 != cap_set_flag(caps, capflag, sizeof(capvals_e)/sizeof(cap_value_t),
443 capvals_e, capfval))
444 {
445 error = errno;
446 cap_free(caps);
447 return error;
448 }
449 if (0 != cap_set_proc(caps))
450 {
451 error = errno;
452 cap_free(caps);
453 return error;
454 }
455
456 capflag = CAP_PERMITTED;
457 if (0 != cap_set_flag(caps, capflag, sizeof(capvals_p)/sizeof(cap_value_t),
458 capvals_p, capfval))
459 {
460 error = errno;
461 cap_free(caps);
462 return error;
463 }
464 if (0 != cap_set_proc(caps))
465 {
466 error = errno;
467 cap_free(caps);
468 return error;
469 }
470 cap_free(caps);
471 return 0;
472}
473
474int sl_drop_cap_int(int what)
475{
476#if defined(SL_DEBUG)
477 char * captext;
478#endif
479 cap_flag_t capflag = CAP_EFFECTIVE;
480 cap_flag_value_t capfval = CAP_CLEAR;
481 cap_value_t capvals_a[] = { CAP_SETGID, CAP_SETUID, CAP_KILL };
482 cap_value_t capvals_b[] = { CAP_DAC_OVERRIDE, CAP_FOWNER };
483 cap_value_t * capvals;
484 int nvals;
485 int error = 0;
486 cap_t caps = cap_get_proc();
487
488 if (0 == sl_useCaps) /* 0 = S_FALSE */
489 {
490 return 0;
491 }
492
493 if (caps == NULL)
494 {
495 return errno;
496 }
497
498 switch (what) {
499 case 1:
500 capvals = capvals_a;
501 nvals = 3;
502 capfval = CAP_CLEAR;
503 break;
504 case 2:
505 capvals = capvals_a;
506 nvals = 3;
507 capfval = CAP_SET;
508 break;
509 case 3:
510 capvals = capvals_b;
511 nvals = 2;
512 capfval = CAP_CLEAR;
513 break;
514 case 4:
515 capvals = capvals_b;
516 nvals = 2;
517 capfval = CAP_SET;
518 break;
519 default:
520 return (0);
521 }
522
523 if (0 != cap_set_flag(caps, capflag, nvals, capvals, capfval))
524 {
525 error = errno;
526 cap_free(caps);
527 return error;
528 }
529 if (0 != cap_set_proc(caps))
530 {
531 error = errno;
532 cap_free(caps);
533 return error;
534 }
535#if defined(SL_DEBUG)
536 captext = cap_to_text(caps, NULL);
537 TPT(( 0, FIL__, __LINE__, _("msg=<cap_int %d: %s>\n"), what, captext));
538 cap_free(captext);
539#endif
540 cap_free(caps);
541 return 0;
542}
543
544int sl_drop_cap_sub() { return sl_drop_cap_int(1); }
545int sl_get_cap_sub() { return sl_drop_cap_int(2); }
546int sl_drop_cap_qdel() { return sl_drop_cap_int(3); }
547int sl_get_cap_qdel() { return sl_drop_cap_int(4); }
548
549#else
550int sl_drop_cap () { return 0; }
551int sl_drop_cap_sub() { return 0; }
552int sl_get_cap_sub() { return 0; }
553int sl_drop_cap_qdel() { return 0; }
554int sl_get_cap_qdel() { return 0; }
555#endif
556
557/* ----------------------------------------------------------------
558 *
559 * String handling routines
560 *
561 * ---------------------------------------------------------------- */
562
563/*
564 * A memset that does not get optimized away
565 */
566void *sl_memset(void *s, int c, size_t n)
567{
568 volatile char *p = (char *) s;
569
570 if (s != NULL)
571 {
572 while (n--)
573 *p++ = c;
574 }
575 return s;
576}
577
578#if !defined(HOST_IS_I86SOLARIS)
579#if !defined (_GNU_SOURCE)
580extern int vsnprintf ( char *str, size_t n,
581 const char *format, va_list ap );
582#endif
583#endif
584
585#if !defined (VA_COPY)
586#if defined (__GNUC__) && defined (__PPC__) && (defined (_CALL_SYSV) || defined (_WIN32))
587#define VA_COPY(ap1, ap2) (*(ap1) = *(ap2))
588#elif defined (VA_COPY_AS_ARRAY)
589#define VA_COPY(ap1, ap2) memmove ((ap1), (ap2), sizeof (va_list))
590#else /* va_list is a pointer */
591#define VA_COPY(ap1, ap2) ((ap1) = (ap2))
592#endif
593#endif
594
595#if !defined(HAVE_VSNPRINTF) || defined(HAVE_BROKEN_VSNPRINTF)
596static
597size_t sl_printf_count (const char * fmt, va_list vl)
598{
599 size_t length = 1;
600 int fini = 0;
601 int islong = 0;
602 int islonglong = 0;
603 int islongdouble = 0;
604 char * string_arg;
605
606 SL_ENTER(_("sl_printf_count"));
607
608 if (fmt == NULL)
609 SL_IRETURN(SL_ENULL, _("sl_printf_count"));
610
611 while (*fmt) {
612
613 if ( (*fmt) == '%' ) { /* a format specifier */
614
615 fmt++; /* point to first char after '%' */
616
617 fini = 0;
618 islong = 0;
619 islongdouble = 0;
620
621 while (*fmt && (fini == 0) ) {
622
623 switch (*fmt) {
624
625 case '*': /* field width supplied by an integer */
626 length = length + va_arg (vl, int);
627 ++fmt;
628 break;
629 case '1':
630 case '2':
631 case '3':
632 case '4':
633 case '5':
634 case '6':
635 case '7':
636 case '8':
637 case '9':
638 length = length + strtol (fmt, (char**) &fmt, 10);
639 /* strtol makes FastForward to first invalid char */
640 break;
641
642 case 'l': /* 'long' modifier */
643 if (islong == 0)
644 islong = 1;
645 else
646 {
647 islonglong = 1;
648 islong = 0;
649 }
650 ++fmt;
651 break;
652
653 case 'L': /* 'long double' modifier */
654#ifdef HAVE_LONG_DOUBLE
655 islongdouble = 1;
656#else
657 islong = 1;
658#endif
659 ++fmt;
660 break;
661
662 case 'd':
663 case 'i':
664 case 'o':
665 case 'u':
666 case 'x':
667 case 'X':
668 if (islonglong == 1)
669#ifdef HAVE_LONG_LONG
670 (void) va_arg (vl, long long);
671#else
672 (void) va_arg (vl, long);
673#endif
674 else if (islong == 1)
675 (void) va_arg (vl, long);
676 else
677 (void) va_arg (vl, int);
678 islong = 0;
679 islonglong = 0;
680 length = length + 24;
681 ++fmt;
682 fini = 1;
683 break;
684
685 case 'D':
686 case 'O':
687 case 'U':
688 (void) va_arg (vl, long);
689 length = length + 24;
690 fmt++;
691 fini = 1;
692 break;
693
694 case 'e':
695 case 'E':
696 case 'f':
697 case 'g':
698#ifdef HAVE_LONG_DOUBLE
699 if (islongdouble == 1) {
700 (void) va_arg (vl, long double);
701 islongdouble = 0;
702 length = length + 20;
703 }
704 else
705#endif
706 (void) va_arg (vl, double);
707 length = length + 20;
708 fini = 1;
709 ++fmt;
710 break;
711
712 case 's':
713 string_arg = va_arg (vl, char *);
714 if (string_arg != NULL)
715 length = length + sl_strlen (string_arg);
716 else
717 length = length + 16;
718 fini = 1;
719 ++fmt;
720 break;
721
722 case 'c':
723 (void) va_arg (vl, int);
724 length = length + 1;
725 fini = 1;
726 ++fmt;
727 break;
728
729 case 'p':
730 case 'n':
731 (void) va_arg (vl, void * );
732 length = length + 32;
733 fini = 1;
734 ++fmt;
735 break;
736
737 case '%': /* %% will print '%' */
738 length = length + 1;
739 fini = 1;
740 ++fmt;
741 break;
742
743 default:
744 length = length + 1;
745 ++fmt;
746 break;
747
748 } /* end switch */
749 }
750 /* end parsing a single format specifier */
751 } else {
752 length = length + 1;
753 fmt++;
754 }
755 }
756 SL_IRETURN(length, _("sl_printf_count"));
757}
758#endif /* #ifndef HAVE_VSNPRINTF */
759
760/*
761 * An implementation of vsnprintf. va_start/va_end are in the caller
762 * function.
763 * Returns C99 (#bytes that would heve been written) on success.
764 */
765int sl_vsnprintf(char *str, size_t n,
766 const char *format, va_list vl )
767{
768 int len = 0;
769#if !defined(HAVE_VSNPRINTF) || defined(HAVE_BROKEN_VSNPRINTF)
770 size_t total;
771 va_list vl2;
772#endif
773
774 SL_ENTER(_("sl_vsnprintf"));
775 if (str == NULL || format == NULL)
776 SL_IRETURN(0, _("sl_vsnprintf"));
777
778#if defined(HAVE_VSNPRINTF) && !defined(HAVE_BROKEN_VSNPRINTF)
779 len = vsnprintf (str, n, format, vl);
780 str[n-1] = '\0';
781#else
782 VA_COPY (vl2, vl); /* save the argument list */
783 total = sl_printf_count (format, vl);
784 len = (int) total;
785 if (total < n)
786 {
787 vsprintf (str, format, vl2); /* program has checked that it fits */
788 str[n-1] = '\0';
789 }
790 else
791 {
792 sl_strlcpy (str, format, n);
793 va_end(vl2);
794 SL_IRETURN(len, _("sl_vsnprintf"));
795 }
796 va_end(vl2);
797#endif
798 SL_IRETURN(len, _("sl_vsnprintf"));
799}
800
801/*
802 * An implementation of snprintf.
803 * Returns SL_ENONE on success.
804 * ENULL: src || format == NULL
805 * ERANGE: n out of range
806 * ETRUNC: truncated
807 */
808int sl_snprintf(char *str, size_t n,
809 const char *format, ... )
810{
811 va_list vl;
812#if !defined(HAVE_VSNPRINTF) || defined(HAVE_BROKEN_VSNPRINTF)
813 size_t total = 0;
814 va_list vl2;
815#endif
816
817 SL_ENTER(_("sl_snprintf"));
818 if (str == NULL || format == NULL)
819 SL_IRETURN(SL_ENULL, _("sl_snprintf"));
820
821 va_start (vl, format);
822#if defined(HAVE_VSNPRINTF) && !defined(HAVE_BROKEN_VSNPRINTF)
823 vsnprintf (str, n, format, vl);
824 str[n-1] = '\0';
825#else
826 VA_COPY (vl2, vl); /* save the argument list */
827 total = sl_printf_count (format, vl);
828 if (total < n)
829 {
830 vsprintf (str, format, vl2); /* program has checked that it fits */
831 str[n-1] = '\0';
832 }
833 else
834 {
835 sl_strlcpy (str, format, n);
836 va_end(vl2);
837 va_end(vl);
838 SL_IRETURN(SL_ETRUNC, _("sl_snprintf"));
839 }
840 va_end(vl2);
841#endif
842 va_end(vl);
843 SL_IRETURN(SL_ENONE, _("sl_snprintf"));
844}
845
846/*
847 * Appends src to string dst of size siz (unlike strncat, siz is the
848 * full size of dst, not space left). At most siz-1 characters
849 * will be copied. Always NUL terminates (unless siz == 0).
850 * Returns SL_NONE on success, errcode on failure.
851 *
852 * ENULL: dst == NULL
853 * ERANGE: siz out of range
854 * ETRUNC: src truncated
855 */
856int sl_strlcat(char * dst, /*@null@*/const char *src, size_t siz)
857{
858 register size_t dst_end;
859 register size_t dst_free;
860
861 register char * p;
862 register const char * q;
863
864 if (dst == NULL)
865 return SL_ENONE;
866 if (src == NULL || *src == '\0')
867 return SL_ENONE;
868
869 if (siz > 0) {
870
871 /* How much free space do we have ?
872 */
873 dst_end = strlen(dst);
874 dst_free = siz - dst_end - 1;
875
876 p = &dst[dst_end];
877 q = src;
878
879 while (dst_free > 0 && *q != '\0')
880 {
881 *p++ = *q++;
882 --dst_free;
883 }
884
885 /* NULL terminate dst.
886 */
887 *p = '\0';
888
889 if (*q != '\0')
890 return SL_ETRUNC;
891 }
892
893 return SL_ENONE;
894}
895
896/*
897 * An alternative implementation of the OpenBSD strlcpy() function.
898 *
899 * Copy src to string dst of size siz. At most siz-1 characters
900 * will be copied. Always NUL terminates (unless siz == 0).
901 * Returns SL_NONE on success, errcode on failure.
902 *
903 * ENULL: dst == NULL
904 * ERANGE: siz out of range
905 * ETRUNC: src truncated
906 */
907int sl_strlcpy(char * dst, /*@null@*/const char * src, size_t siz)
908{
909 /* SL_ENTER(_("sl_strlcpy")); */
910
911 if (dst == NULL)
912 return SL_ENULL;
913 if (src == NULL)
914 {
915 if (siz > 0)
916 dst[0] = '\0';
917 return SL_ENONE;
918 }
919
920
921 if (siz > 0) {
922 /* copy siz-1 characters
923 */
924 (void) strncpy(dst, src, siz-1);
925
926 /* NULL terminate
927 */
928 dst[siz-1] = '\0';
929 }
930 return SL_ENONE;
931}
932
933/*
934 * A robust drop-in replacement of strncpy. strlcpy is preferable.
935 */
936char * sl_strncpy(char *dst, const char *src, size_t size)
937{
938
939#ifdef SL_FAIL_ON_ERROR
940 SL_REQUIRE(dst != NULL, _("dst != NULL"));
941 SL_REQUIRE(src != NULL, _("src != NULL"));
942 SL_REQUIRE(size > 0, _("size > 0"));
943#endif
944
945 if (dst == NULL)
946 {
947 sl_errno = SL_ENULL;
948 return (NULL);
949 }
950 if (size < 1)
951 {
952 sl_errno = SL_ERANGE;
953 return (dst);
954 }
955 if (!src)
956 {
957 sl_errno = SL_ENULL;
958 dst[0] = '\0';
959 }
960 else if (src[0] == '\0')
961 dst[0] = '\0';
962 else
963 strncpy(dst, src, size);
964
965 if (sl_strlen(src) >= size)
966 {
967 errno = ENOSPC;
968 dst[size-1] = '\0';
969 }
970 return (dst);
971}
972
973/*
974 * A robust drop-in replacement of strncat. strlcat is preferable.
975 */
976char * sl_strncat(char *dst, const char *src, size_t n)
977{
978#ifdef SL_FAIL_ON_ERROR
979 SL_REQUIRE(dst != NULL, _("dst != NULL"));
980 SL_REQUIRE(src != NULL, _("src != NULL"));
981 SL_REQUIRE(n > 0, _("n > 0"));
982#endif
983
984 if (dst == NULL)
985 {
986 sl_errno = SL_ENULL;
987 return (NULL);
988 }
989 if (n < 1)
990 {
991 sl_errno = SL_ERANGE;
992 return (dst);
993 }
994 if (!src)
995 {
996 sl_errno = SL_ENULL;
997 return (dst);
998 }
999 else if (src[0] == '\0')
1000 dst[0] = '\0';
1001 else
1002 strncat(dst, src, n);
1003
1004 return (dst);
1005}
1006
1007
1008int sl_strcmp(const char * a, const char * b)
1009{
1010#ifdef SL_FAIL_ON_ERROR
1011 SL_REQUIRE (a != NULL, _("a != NULL"));
1012 SL_REQUIRE (b != NULL, _("b != NULL"));
1013#endif
1014
1015 if (a != NULL && b != NULL)
1016 return (strcmp(a, b));
1017 else if (a == NULL && b != NULL)
1018 return (-1);
1019 else if (a != NULL && b == NULL)
1020 return (1);
1021 else
1022 return (-7); /* arbitrary */
1023}
1024
1025int sl_strncmp(const char * a, const char * b, size_t n)
1026{
1027#ifdef SL_FAIL_ON_ERROR
1028 SL_REQUIRE (a != NULL, _("a != NULL"));
1029 SL_REQUIRE (b != NULL, _("b != NULL"));
1030 SL_REQUIRE (n > 0, _("n > 0"));
1031#endif
1032
1033 if (a != NULL && b != NULL)
1034 return (strncmp(a, b, n));
1035 else if (a == NULL && b != NULL)
1036 return (-1);
1037 else if (a != NULL && b == NULL)
1038 return (1);
1039 else
1040 return (-7); /* arbitrary */
1041}
1042
1043/* string searching
1044 */
1045
1046char * sl_strstr (const char * haystack, const char * needle)
1047{
1048#ifndef HAVE_STRSTR
1049 int i;
1050 size_t needle_len;
1051 size_t haystack_len;
1052#endif
1053
1054 if (haystack == NULL || needle == NULL)
1055 return NULL;
1056 if (*needle == '\0' || *haystack == '\0')
1057 return NULL;
1058
1059#if defined(HAVE_STRSTR)
1060 return (strstr(haystack, needle));
1061#else
1062 needle_len = strlen(needle);
1063 haystack_len = strlen(haystack);
1064
1065 for (i = 0; i <= (haystack_len-needle_len); ++i)
1066 if (0 == sl_strncmp(&haystack[i], needle, needle_len))
1067 return (needle);
1068 return NULL;
1069#endif
1070}
1071
1072
1073/* ----------------------------------------------------------------
1074 *
1075 * Privilege handling routines
1076 *
1077 * ---------------------------------------------------------------- */
1078
1079
1080
1081static uid_t euid;
1082static uid_t ruid;
1083static uid_t ruid_orig;
1084static gid_t egid;
1085static gid_t rgid;
1086static gid_t rgid_orig;
1087
1088static int uids_are_stored = SL_FALSE;
1089static int suid_is_set = SL_TRUE;
1090
1091#ifdef HAVE_SETRESUID
1092extern int setresuid (uid_t truid, uid_t teuid, uid_t tsuid);
1093extern int setresgid (gid_t trgid, gid_t tegid, gid_t tsgid);
1094#endif
1095
1096
1097/*
1098 * This function returns true if the program is SUID.
1099 * It calls abort() if the uid's are not saved already.
1100 */
1101int sl_is_suid()
1102{
1103 if (uids_are_stored == SL_FALSE)
1104 {
1105 if (getuid() == geteuid() && getgid() == getegid())
1106 return (0); /* FALSE */
1107 else
1108 return (1); /* TRUE */
1109 }
1110 else
1111 {
1112 if (euid == ruid && egid == rgid)
1113 return (0); /* FALSE */
1114 else
1115 return (1); /* TRUE */
1116 }
1117}
1118
1119/*
1120 * This function returns the saved euid.
1121 * It calls abort() if the uid's are not saved already.
1122 */
1123int sl_get_euid(uid_t * ret)
1124{
1125 SL_ENTER(_("sl_get_euid"));
1126 /* SL_REQUIRE(uids_are_stored == SL_TRUE, _("uids_are_stored == SL_TRUE"));*/
1127 if (uids_are_stored == SL_TRUE)
1128 *ret = euid;
1129 else
1130 *ret = geteuid();
1131 SL_IRETURN (SL_ENONE, _("sl_get_euid"));
1132}
1133
1134uid_t sl_ret_euid()
1135{
1136 /* SL_REQUIRE(uids_are_stored == SL_TRUE, _("uids_are_stored == SL_TRUE"));*/
1137 if (uids_are_stored == SL_TRUE)
1138 return (euid);
1139 else
1140 return (geteuid());
1141}
1142
1143/*
1144 * This function returns the saved egid.
1145 * It calls abort() if the uid's are not saved already.
1146 */
1147int sl_get_egid(gid_t * ret)
1148{
1149 SL_ENTER(_("sl_get_egid"));
1150 /* SL_REQUIRE(uids_are_stored == SL_TRUE, _("uids_are_stored == SL_TRUE"));*/
1151 if (uids_are_stored == SL_TRUE)
1152 *ret = egid;
1153 else
1154 *ret = getegid();
1155 SL_IRETURN (SL_ENONE, _("sl_get_egid"));
1156}
1157
1158/*
1159 * This function returns the saved ruid.
1160 * It calls abort() if the uid's are not saved already.
1161 */
1162int sl_get_ruid(uid_t * ret)
1163{
1164 SL_ENTER(_("sl_get_ruid"));
1165 /* SL_REQUIRE(uids_are_stored == SL_TRUE, _("uids_are_stored == SL_TRUE"));*/
1166 if (uids_are_stored == SL_TRUE)
1167 *ret = ruid;
1168 else
1169 *ret = getuid();
1170 SL_IRETURN (SL_ENONE, _("sl_get_ruid"));
1171}
1172
1173/*
1174 * This function returns the saved rgid.
1175 * It calls abort() if the uid's are not saved already.
1176 */
1177int sl_get_rgid(gid_t * ret)
1178{
1179 SL_ENTER(_("sl_get_rgid"));
1180 /* SL_REQUIRE(uids_are_stored == SL_TRUE, _("uids_are_stored == SL_TRUE"));*/
1181 if (uids_are_stored == SL_TRUE)
1182 *ret = rgid;
1183 else
1184 *ret = getgid();
1185 SL_IRETURN (SL_ENONE, _("sl_get_rgid"));
1186}
1187
1188/*
1189 * This function returns the saved original ruid.
1190 * It calls abort() if the uid's are not saved already.
1191 */
1192int sl_get_ruid_orig(uid_t * ret)
1193{
1194 SL_ENTER(_("sl_get_ruid_orig"));
1195 /* SL_REQUIRE(uids_are_stored == SL_TRUE, _("uids_are_stored == SL_TRUE"));*/
1196 if (uids_are_stored == SL_TRUE)
1197 *ret = ruid_orig;
1198 else
1199 *ret = getuid();
1200 SL_IRETURN (SL_ENONE, _("sl_get_ruid_orig"));
1201}
1202
1203/*
1204 * This function returns the saved original rgid.
1205 * It calls abort() if the uid's are not saved already.
1206 */
1207int sl_get_rgid_orig(gid_t * ret)
1208{
1209 SL_ENTER(_("sl_get_rgid_orig"));
1210 /* SL_REQUIRE(uids_are_stored == SL_TRUE, _("uids_are_stored == SL_TRUE"));*/
1211 if (uids_are_stored == SL_TRUE)
1212 *ret = rgid_orig;
1213 else
1214 *ret = getgid();
1215 SL_IRETURN (SL_ENONE, _("sl_get_rgid_orig"));
1216}
1217
1218static int suid_warn_flag = 1;
1219static void suid_warn(int a)
1220{
1221 fprintf(stderr, _("ERROR: open set/unset suid !!! %d\n"), a);
1222 return;
1223}
1224
1225/*
1226 * This function sets the effective uid
1227 * to the saved effective uid.
1228 * It will abort on failure.
1229 */
1230int sl_set_suid ()
1231{
1232 int retval;
1233
1234 SL_ENTER(_("sl_set_suid"));
1235
1236 if (uids_are_stored == SL_FALSE)
1237 {
1238 SL_IRETURN(SL_ENONE, _("sl_set_suid"));
1239 }
1240
1241 SL_REQUIRE(uids_are_stored == SL_TRUE, _("uids_are_stored == SL_TRUE"));
1242
1243 if (ruid == euid && rgid == egid)
1244 {
1245 suid_is_set = SL_TRUE;
1246 SL_IRETURN(SL_ENONE, _("sl_set_suid"));
1247 }
1248 SL_REQUIRE(suid_is_set == SL_FALSE, _("suid_is_set == SL_FALSE"));
1249
1250#if defined(HAVE_SETRESUID)
1251 retval = setresuid (sh_uid_neg, euid, sh_uid_neg);
1252 if (retval == 0)
1253 retval = setresgid (sh_gid_neg, egid, sh_gid_neg);
1254
1255#elif defined(HAVE_SETEUID)
1256 retval = seteuid (egid);
1257 if (retval == 0)
1258 retval = setegid (euid);
1259
1260 /* on AIX, setreuid does not behave well for non-root users.
1261 */
1262#elif defined(HAVE_SETREUID)
1263 retval = setreuid (ruid, euid);
1264 if (retval == 0)
1265 retval = setregid (rgid, egid);
1266
1267#else
1268 retval = setuid (euid);
1269 if (retval == 0)
1270 retval = setgid (egid);
1271#endif
1272 if (suid_warn_flag == 1)
1273 suid_warn(1);
1274 suid_warn_flag = 1;
1275
1276 SL_REQUIRE(retval == 0, _("retval == 0"));
1277 suid_is_set = SL_TRUE;
1278 SL_IRETURN(SL_ENONE, _("sl_set_suid"));
1279}
1280
1281/*
1282 * This function sets the effective uid to the real uid.
1283 * It will abort on failure.
1284 */
1285int sl_unset_suid ()
1286{
1287 register int retval;
1288
1289 SL_ENTER(_("sl_unset_suid"));
1290
1291 if (uids_are_stored == SL_FALSE)
1292 {
1293 SL_IRETURN(SL_ENONE, _("sl_unset_suid"));
1294 }
1295
1296 SL_REQUIRE(uids_are_stored == SL_TRUE, _("uids_are_stored == SL_TRUE"));
1297
1298 if (ruid == euid && rgid == egid)
1299 {
1300 suid_is_set = SL_FALSE;
1301 SL_IRETURN(SL_ENONE, _("sl_unset_suid"));
1302 }
1303 SL_REQUIRE(suid_is_set == SL_TRUE, _("suid_is_set == SL_TRUE"));
1304
1305#if defined(HAVE_SETRESUID)
1306 retval = setresgid (sh_gid_neg, rgid, sh_gid_neg);
1307 if (retval == 0)
1308 retval = setresuid (sh_uid_neg, ruid, sh_uid_neg);
1309
1310#elif defined(HAVE_SETEUID)
1311 retval = setegid (rgid);
1312 if (retval == 0)
1313 retval = seteuid (ruid);
1314
1315#elif defined(HAVE_SETREUID)
1316 retval = setregid (egid, rgid);
1317 if (retval == 0)
1318 retval = setreuid (euid, ruid);
1319
1320#else
1321 retval = setgid (rgid);
1322 if (retval == 0)
1323 retval = setuid (ruid);
1324#endif
1325
1326 if (suid_warn_flag == 0)
1327 suid_warn(0);
1328 suid_warn_flag = 0;
1329
1330 SL_REQUIRE(retval == 0, _("retval == 0"));
1331 suid_is_set = SL_FALSE;
1332 SL_IRETURN(SL_ENONE, _("sl_unset_suid"));
1333}
1334
1335
1336/*
1337 * This function saves the uid's.
1338 */
1339int sl_save_uids()
1340{
1341 SL_ENTER(_("sl_save_uids"));
1342 if (uids_are_stored == SL_TRUE)
1343 SL_IRETURN(SL_EREPEAT, _("sl_save_uids"));
1344
1345 ruid_orig = getuid();
1346 rgid_orig = getgid();
1347 egid = getegid();
1348 euid = geteuid();
1349 ruid = ruid_orig;
1350 rgid = rgid_orig;
1351 uids_are_stored = SL_TRUE;
1352
1353 SL_IRETURN(SL_ENONE, _("sl_save_uids"));
1354}
1355
1356/*
1357 * This function drops SUID privileges irrevocably.
1358 * It set the effective uid to the original real uid.
1359 */
1360extern int sh_unix_initgroups2 (uid_t in_pid, gid_t in_gid);
1361int sl_drop_privileges()
1362{
1363 SL_ENTER(_("sl_drop_privileges"));
1364 SL_REQUIRE(uids_are_stored == SL_TRUE, _("uids_are_stored == SL_TRUE"));
1365
1366 SL_REQUIRE(setgid(rgid_orig) == 0, _("setgid(rgid_orig) == 0"));
1367 SL_REQUIRE(sh_unix_initgroups2(ruid_orig, rgid_orig) == 0, _("sh_unix_initgroups2(ruid_orig,rgid_orig) == 0"));
1368 SL_REQUIRE(setuid(ruid_orig) == 0, _("setuid(ruid_orig) == 0"));
1369
1370 /* make sure that setuid(0) fails
1371 */
1372 SL_REQUIRE(setuid(0) < 0, _("setuid(0) < 0"));
1373
1374 euid = ruid_orig;
1375 egid = rgid_orig;
1376 ruid = ruid_orig;
1377 rgid = rgid_orig;
1378
1379 SL_IRETURN(SL_ENONE, _("sl_drop_privileges"));
1380}
1381
1382/*
1383 * Define a policy: Stay root.
1384 * Do nothing if not SUID.
1385 */
1386int sl_policy_get_root()
1387{
1388 SL_ENTER(_("sl_policy_get_root"));
1389 SL_REQUIRE(uids_are_stored == SL_FALSE, _("uids_are_stored == SL_FALSE"));
1390
1391 SL_REQUIRE (sl_save_uids() == SL_ENONE, _("sl_save_uids() == SL_ENONE"));
1392
1393 if (euid != ruid || egid != rgid)
1394 {
1395 SL_REQUIRE(setgid(egid) == 0, _("setgid(egid) == 0"));
1396 SL_REQUIRE(setuid(euid) == 0, _("setuid(euid) == 0"));
1397 SL_REQUIRE(ruid == getuid() && rgid == getgid(),
1398 _("ruid == getuid() && rgid == getgid()"));
1399 ruid = euid;
1400 rgid = egid;
1401 }
1402 suid_is_set = SL_TRUE;
1403 if (euid == 0)
1404 {
1405 SL_REQUIRE(sh_unix_initgroups2(euid, egid) == 0, _("sh_unix_initgroups2(euid,egid) == 0"));
1406 }
1407 SL_IRETURN(SL_ENONE, _("sl_policy_get_root"));
1408}
1409
1410#include <pwd.h>
1411
1412/*
1413 * Define a policy: Get real (irrevocably).
1414 * This function drops SUID privileges irrevocably.
1415 * Do nothing if not SUID (? not true - drops if root).
1416 */
1417
1418int sl_policy_get_real(char * user)
1419{
1420 struct passwd * tempres;
1421
1422 SL_ENTER(_("sl_policy_get_real"));
1423 SL_REQUIRE(uids_are_stored == SL_FALSE, _("uids_are_stored == SL_FALSE"));
1424 SL_REQUIRE (sl_save_uids() == SL_ENONE, _("sl_save_uids() == SL_ENONE"));
1425
1426 if (euid == 0 || ruid == 0)
1427 {
1428 tempres = sh_getpwnam(user);
1429
1430 SL_REQUIRE (NULL != tempres, _("tempres != NULL"));
1431
1432 rgid_orig = tempres->pw_gid;
1433 ruid_orig = tempres->pw_uid;
1434 }
1435 else
1436 {
1437 rgid_orig = rgid;
1438 ruid_orig = ruid;
1439 }
1440
1441 SL_REQUIRE (sl_drop_privileges() == SL_ENONE,
1442 _("sl_drop_privileges() == SL_ENONE"));
1443
1444 suid_is_set = SL_TRUE;
1445 SL_IRETURN(SL_ENONE, _("sl_policy_get_real"));
1446}
1447
1448
1449/*
1450 * Define a policy: Get user.
1451 * Drops privileges.
1452 * Do nothing if not SUID.
1453 */
1454int sl_policy_get_user(char * user)
1455{
1456 struct passwd * tempres;
1457
1458 SL_ENTER(_("sl_policy_get_user"));
1459
1460 SL_REQUIRE(user != NULL, _("user != NULL"));
1461 SL_REQUIRE(uids_are_stored == SL_FALSE, _("uids_are_stored == SL_FALSE"));
1462 SL_REQUIRE (sl_save_uids() == SL_ENONE, _("sl_save_uids() == SL_ENONE"));
1463
1464 if (euid != ruid || egid != rgid)
1465 {
1466 tempres = sh_getpwnam(user);
1467
1468 SL_REQUIRE (NULL != tempres, _("tempres != NULL"));
1469
1470#if 0
1471 rgid = tempres->pw_gid;
1472 ruid = tempres->pw_uid;
1473 SL_REQUIRE(sl_unset_suid() == SL_ENONE,
1474 _("sl_unset_suid() == SL_ENONE"));
1475#endif
1476 SL_REQUIRE (sl_drop_privileges() == SL_ENONE,
1477 _("sl_drop_privileges() == SL_ENONE"));
1478 }
1479 SL_IRETURN(SL_ENONE, _("sl_policy_get_user"));
1480}
1481
1482
1483
1484/* ----------------------------------------------------------------
1485 *
1486 * File access routines
1487 *
1488 * ---------------------------------------------------------------- */
1489
1490#define TOFFSET 0x1234
1491
1492/* this would prevent opening files if the first 16 fds are open :( */
1493/* #define MAXFD FOPEN_MAX */
1494
1495#define MAXFD 1024
1496
1497typedef struct openfiles {
1498 SL_TICKET ticket; /* The unique ID. */
1499 int fd; /* The file descriptor. */
1500 char * path; /* The file path. */
1501} SL_OFILE;
1502
1503static SL_OFILE * ofiles[MAXFD];
1504
1505
1506static unsigned int nonce_counter = TOFFSET;
1507
1508static
1509SL_TICKET sl_create_ticket (unsigned int myindex)
1510{
1511 unsigned int high; /* index */
1512 unsigned int low; /* nonce */
1513
1514 SL_ENTER(_("sl_create_ticket"));
1515
1516 if (myindex >= MAXFD)
1517 SL_IRETURN (SL_EINTERNAL, _("sl_create_ticket"));
1518
1519 /* mask out the high bit and check that it is not used
1520 * -> verify that it fits into 16 bits as positive
1521 */
1522 high = (myindex + TOFFSET) & 0x7fff;
1523
1524 if (high != myindex + TOFFSET)
1525 SL_IRETURN (SL_EINTERNAL, _("sl_create_ticket"));
1526
1527 low = nonce_counter & 0xffff;
1528
1529 /* Overflow -> nonce too big.
1530 */
1531 if ((low != nonce_counter++) || low == 0)
1532 SL_IRETURN (SL_EINTERNAL, _("sl_create_ticket"));
1533
1534 /* Wrap around the nonce counter.
1535 * This is a dirty trick.
1536 */
1537 if (nonce_counter > 0x7fff)
1538 nonce_counter = TOFFSET;
1539
1540 SL_RETURN ((SL_TICKET) ((high << 16) | low), _("sl_create_ticket"));
1541}
1542
1543static
1544int sl_read_ticket (SL_TICKET fno)
1545{
1546 register unsigned myindex;
1547 register SL_OFILE *of;
1548
1549 myindex = ((fno >> 16) & 0xffff) - TOFFSET;
1550 if (myindex >= MAXFD)
1551 return (SL_ETICKET);
1552
1553 if (ofiles[myindex] == NULL)
1554 return (SL_ETICKET);
1555
1556 if (ofiles[myindex]->ticket != fno)
1557 return (SL_ETICKET);
1558
1559 if ((of = ofiles[myindex])->fd < 0 || of->fd >= MAXFD )
1560 return (SL_EINTERNAL);
1561
1562 if (((of->ticket) & 0xffff) == 0)
1563 return (SL_EINTERNAL);
1564
1565 return (myindex);
1566}
1567
1568SL_TICKET sl_make_ticket (int fd, char * filename)
1569{
1570 SL_TICKET ticket;
1571 SL_ENTER(_("sl_make_ticket"));
1572 /* Make entry.
1573 */
1574 if (fd >= MAXFD || fd < 0)
1575 {
1576 SL_IRETURN(SL_TOOMANY, _("sl_make_ticket"));
1577 }
1578
1579 if (ofiles[fd] != NULL)
1580 {
1581 SL_IRETURN(SL_EINTERNAL, _("sl_make_ticket"));
1582 }
1583
1584 if ( (ofiles[fd] = (SL_OFILE *) malloc(sizeof(SL_OFILE))) == NULL)
1585 {
1586 SL_IRETURN(SL_EMEM, _("sl_make_ticket"));
1587 }
1588
1589 if ( (ofiles[fd]->path = (char *) malloc( strlen(filename)+1) ) == NULL)
1590 {
1591 free(ofiles[fd]);
1592 ofiles[fd] = NULL;
1593 SL_IRETURN(SL_EMEM, _("sl_make_ticket"));
1594 }
1595
1596 /* Get a ticket.
1597 */
1598 ticket = sl_create_ticket((unsigned int)fd);
1599
1600 if (SL_ISERROR(ticket))
1601 {
1602 (void) free (ofiles[fd]->path);
1603 (void) free (ofiles[fd]);
1604 SL_IRETURN(ticket, _("sl_make_ticket"));
1605 }
1606
1607 strcpy (ofiles[fd]->path, filename); /* Known to fit */
1608 ofiles[fd]->ticket = ticket;
1609 ofiles[fd]->fd = fd;
1610
1611 SL_IRETURN(ticket, _("sl_make_ticket"));
1612}
1613
1614#define SL_OPEN_MIN 113
1615#define SL_OPEN_FOR_READ 113
1616#define SL_OPEN_FOR_WRITE 114
1617#define SL_OPEN_FOR_RDWR 115
1618#define SL_OPEN_FOR_WTRUNC 116
1619#define SL_OPEN_FOR_RWTRUNC 117
1620#define SL_OPEN_SAFE_RDWR 118
1621#define SL_OPEN_FOR_FASTREAD 119
1622#define SL_OPEN_MAX 119
1623
1624#if !defined(O_NOATIME)
1625#if defined(__linux__) && (defined(__i386__) || defined(__PPC__))
1626#define O_NOATIME 01000000
1627#else
1628 /*
1629 * bitwise 'or' with zero does not modify any bit
1630 */
1631#define O_NOATIME 0
1632#endif
1633#endif
1634
1635static int o_noatime = O_NOATIME;
1636static mode_t open_mode = (S_IWUSR|S_IRUSR|S_IRGRP);
1637
1638
1639static
1640int sl_open_file (const char *filename, int mode, int priv)
1641{
1642 struct stat lbuf;
1643 struct stat buf;
1644 int lstat_return;
1645 int stat_return;
1646 int fd;
1647 int sflags;
1648 SL_TICKET ticket;
1649
1650#if !defined(O_NONBLOCK)
1651#if defined(O_NDELAY)
1652#define O_NONBLOCK O_NDELAY
1653#else
1654#define O_NONBLOCK 0
1655#endif
1656#endif
1657
1658 SL_ENTER(_("sl_open_file"));
1659
1660 if (filename == NULL)
1661 SL_IRETURN(SL_ENULL, _("sl_open_file"));
1662 if (mode < SL_OPEN_MIN || mode > SL_OPEN_MAX)
1663 SL_IRETURN(SL_EINTERNAL, _("sl_open_file"));
1664
1665 /* "This system call always succeeds and the previous value of
1666 * the mask is returned."
1667 */
1668 (void) umask (0);
1669
1670 if (mode == SL_OPEN_FOR_FASTREAD)
1671 {
1672 fd = aud_open_noatime (FIL__, __LINE__, priv, filename,
1673 O_RDONLY|O_NONBLOCK, 0, &o_noatime);
1674 /*
1675 if (fd >= 0) {
1676 sflags = retry_fcntl(FIL__, __LINE__, fd, F_GETFL, 0);
1677 retry_fcntl(FIL__, __LINE__, fd, F_SETFL, sflags & ~O_NONBLOCK);
1678 }
1679 */
1680 if (fd < 0)
1681 SL_IRETURN(SL_EBADFILE, _("sl_open_file"));
1682 goto createTicket;
1683 }
1684
1685#ifdef USE_SUID
1686 if (priv == SL_YESPRIV)
1687 sl_set_suid();
1688#endif
1689 if (mode == SL_OPEN_FOR_READ)
1690 lstat_return = retry_stat (FIL__, __LINE__, filename, &lbuf);
1691 else
1692 lstat_return = retry_lstat(FIL__, __LINE__, filename, &lbuf);
1693#ifdef USE_SUID
1694 if (priv == SL_YESPRIV)
1695 sl_unset_suid();
1696#endif
1697
1698 if (lstat_return == -1)
1699 {
1700 lstat_return = ENOENT;
1701 if ( (mode == SL_OPEN_FOR_READ && lstat_return == ENOENT) ||
1702 (errno != ENOENT))
1703 {
1704 TPT(( 0, FIL__, __LINE__, _("msg=<lstat: %s> errno=<%d>\n"),
1705 filename, errno));
1706 SL_IRETURN(SL_EBADFILE, _("sl_open_file"));
1707 }
1708 }
1709
1710 if ( (mode != SL_OPEN_FOR_READ) && (lstat_return != ENOENT) &&
1711 ( S_ISDIR(lbuf.st_mode) || (S_IWOTH & lbuf.st_mode) )
1712 )
1713 SL_IRETURN(SL_EBADFILE, _("sl_open_file"));
1714
1715
1716 /* O_NOATIME has an effect for read(). But write() ?.
1717 */
1718 switch (mode)
1719 {
1720 case SL_OPEN_FOR_READ:
1721 fd = aud_open_noatime (FIL__, __LINE__, priv, filename,
1722 O_RDONLY|O_NONBLOCK, 0, &o_noatime);
1723 if (fd >= 0) {
1724 sflags = retry_fcntl(FIL__, __LINE__, fd, F_GETFL, 0);
1725 retry_fcntl(FIL__, __LINE__, fd, F_SETFL, sflags & ~O_NONBLOCK);
1726 }
1727 break;
1728 case SL_OPEN_FOR_WRITE:
1729 if (lstat_return == ENOENT)
1730 fd = aud_open (FIL__, __LINE__, priv, filename,
1731 O_WRONLY|O_CREAT|O_EXCL, open_mode);
1732 else
1733 fd = aud_open (FIL__, __LINE__, priv, filename,
1734 O_WRONLY, open_mode);
1735 break;
1736 case SL_OPEN_SAFE_RDWR:
1737 if (lstat_return == ENOENT)
1738 fd = aud_open (FIL__, __LINE__, priv, filename,
1739 O_RDWR|O_CREAT|O_EXCL, open_mode);
1740 else
1741 SL_IRETURN(SL_EBADFILE, _("sl_open_file"));
1742 break;
1743 case SL_OPEN_FOR_RDWR:
1744 if (lstat_return == ENOENT)
1745 fd = aud_open (FIL__, __LINE__, priv, filename,
1746 O_RDWR|O_CREAT|O_EXCL, open_mode);
1747 else
1748 fd = aud_open (FIL__, __LINE__, priv, filename,
1749 O_RDWR, open_mode);
1750 break;
1751 case SL_OPEN_FOR_WTRUNC:
1752 if (lstat_return == ENOENT)
1753 fd = aud_open (FIL__, __LINE__, priv, filename,
1754 O_WRONLY|O_CREAT|O_EXCL, open_mode);
1755 else
1756 fd = aud_open (FIL__, __LINE__, priv, filename,
1757 O_WRONLY|O_TRUNC, open_mode);
1758 break;
1759 case SL_OPEN_FOR_RWTRUNC:
1760 if (lstat_return == ENOENT)
1761 fd = aud_open (FIL__, __LINE__, priv, filename,
1762 O_RDWR|O_CREAT|O_EXCL, open_mode);
1763 else
1764 fd = aud_open (FIL__, __LINE__, priv, filename,
1765 O_RDWR|O_TRUNC, open_mode);
1766 break;
1767 default:
1768 SL_IRETURN(SL_EINTERNAL, _("sl_open_file"));
1769 }
1770
1771 if (fd < 0)
1772 {
1773 TPT(( 0, FIL__, __LINE__, _("msg=<Error opening: %s> errno=<%d>\n"),
1774 filename, errno));
1775 SL_IRETURN(SL_EBADFILE, _("sl_open_file"));
1776 }
1777
1778#ifdef USE_SUID
1779 if (priv == SL_YESPRIV)
1780 sl_set_suid();
1781#endif
1782 stat_return = retry_fstat(FIL__, __LINE__, fd, &buf);
1783#ifdef USE_SUID
1784 if (priv == SL_YESPRIV)
1785 sl_unset_suid();
1786#endif
1787
1788 if (stat_return < 0)
1789 {
1790 close (fd);
1791 SL_IRETURN(SL_EBADFILE, _("sl_open_file"));
1792 }
1793
1794 if (lstat_return != ENOENT && buf.st_ino != lbuf.st_ino)
1795 {
1796 close (fd);
1797 SL_IRETURN(SL_EBOGUS, _("sl_open_file"));
1798 }
1799
1800 createTicket:
1801
1802 /* Make entry.
1803 */
1804 if (fd >= MAXFD)
1805 {
1806 close(fd);
1807 SL_IRETURN(SL_TOOMANY, _("sl_open_file"));
1808 }
1809
1810 if (ofiles[fd] != NULL)
1811 {
1812 close(fd);
1813 SL_IRETURN(SL_EINTERNAL, _("sl_open_file"));
1814 }
1815
1816 if ( (ofiles[fd] = (SL_OFILE *) malloc(sizeof(SL_OFILE))) == NULL)
1817 {
1818 close(fd);
1819 SL_IRETURN(SL_EMEM, _("sl_open_file"));
1820 }
1821
1822 if ( (ofiles[fd]->path = (char *) malloc( strlen(filename)+1) ) == NULL)
1823 {
1824 free(ofiles[fd]);
1825 ofiles[fd] = NULL;
1826 close(fd);
1827 SL_IRETURN(SL_EMEM, _("sl_open_file"));
1828 }
1829
1830 /* Get a ticket.
1831 */
1832 ticket = sl_create_ticket(fd);
1833
1834 if (SL_ISERROR(ticket))
1835 {
1836 (void) free (ofiles[fd]->path);
1837 (void) free (ofiles[fd]);
1838 close(fd);
1839 SL_IRETURN(ticket, _("sl_open_file"));
1840 }
1841
1842 strcpy (ofiles[fd]->path, filename); /* Known to fit */
1843 ofiles[fd]->ticket = ticket;
1844 ofiles[fd]->fd = fd;
1845
1846 SL_IRETURN(ticket, _("sl_open_file"));
1847}
1848
1849static
1850int check_fname_priv (const char * fname, int priv)
1851{
1852 SL_ENTER(_("check_fname_priv"));
1853 if (fname == NULL)
1854 SL_IRETURN(SL_ENULL, _("check_fname_priv"));
1855 if (priv != SL_YESPRIV && priv != SL_NOPRIV)
1856 SL_IRETURN(SL_EINTERNAL, _("check_fname_priv"));
1857 SL_IRETURN(SL_ENONE, _("check_fname_priv"));
1858}
1859
1860SL_TICKET sl_open_write (const char * fname, int priv)
1861{
1862 long status;
1863 SL_ENTER(_("sl_open_write"));
1864
1865 if (SL_ENONE != (status = check_fname_priv (fname, priv)))
1866 SL_IRETURN(status, _("sl_open_write"));
1867
1868 status = sl_open_file(fname, SL_OPEN_FOR_WRITE, priv);
1869 SL_IRETURN(status, _("sl_open_write"));
1870}
1871
1872SL_TICKET sl_open_read (const char * fname, int priv)
1873{
1874 long status;
1875 SL_ENTER(_("sl_open_read"));
1876
1877 if (SL_ENONE != (status = check_fname_priv (fname, priv)))
1878 {
1879 TPT(( 0, FIL__, __LINE__,
1880 _("msg=<Error in check_fname_priv.> status=<%ld>\n"),
1881 status));
1882 SL_IRETURN(status, _("sl_open_read"));
1883 }
1884
1885 status = sl_open_file(fname, SL_OPEN_FOR_READ, priv);
1886 SL_IRETURN(status, _("sl_open_read"));
1887}
1888
1889SL_TICKET sl_open_fastread (const char * fname, int priv)
1890{
1891 long status;
1892 SL_ENTER(_("sl_open_fastread"));
1893
1894 if (SL_ENONE != (status = check_fname_priv (fname, priv)))
1895 SL_IRETURN(status, _("sl_open_read"));
1896
1897 status = sl_open_file(fname, SL_OPEN_FOR_FASTREAD, priv);
1898 SL_IRETURN(status, _("sl_open_fastread"));
1899}
1900
1901SL_TICKET sl_open_rdwr (const char * fname, int priv)
1902{
1903 long status;
1904 SL_ENTER(_("sl_open_rdwr"));
1905
1906 if (SL_ENONE != (status = check_fname_priv (fname, priv)))
1907 SL_IRETURN(status, _("sl_open_rdwr"));
1908
1909 status = sl_open_file(fname, SL_OPEN_FOR_RDWR, priv);
1910 SL_IRETURN(status, _("sl_open_rdwr"));
1911}
1912
1913SL_TICKET sl_open_safe_rdwr (const char * fname, int priv)
1914{
1915 long status;
1916 SL_ENTER(_("sl_open_safe_rdwr"));
1917
1918 if (SL_ENONE != (status = check_fname_priv (fname, priv)))
1919 SL_IRETURN(status, _("sl_open_safe_rdwr"));
1920
1921 status = sl_open_file(fname, SL_OPEN_SAFE_RDWR, priv);
1922 SL_IRETURN(status, _("sl_open_safe_rdwr"));
1923}
1924
1925SL_TICKET sl_open_write_trunc (const char * fname, int priv)
1926{
1927 long status;
1928 SL_ENTER(_("sl_open_write_trunc"));
1929
1930 if (SL_ENONE != (status = check_fname_priv (fname, priv)))
1931 SL_IRETURN(status, _("sl_open_write_trunc"));
1932
1933 status = sl_open_file(fname, SL_OPEN_FOR_WTRUNC, priv);
1934 SL_IRETURN(status, _("sl_open_write_trunc"));
1935}
1936
1937SL_TICKET sl_open_rdwr_trunc (const char * fname, int priv)
1938{
1939 long status;
1940 SL_ENTER(_("sl_open_rdwr_trunc"));
1941
1942 if (SL_ENONE != (status = check_fname_priv (fname, priv)))
1943 SL_IRETURN(status, _("sl_open_rdwr_trunc"));
1944
1945 status = sl_open_file(fname, SL_OPEN_FOR_RWTRUNC, priv);
1946 SL_IRETURN(status, _("sl_open_rdwr_trunc"));
1947}
1948
1949
1950int get_the_fd (SL_TICKET ticket)
1951{
1952 int fd;
1953
1954 if (SL_ISERROR(fd = sl_read_ticket(ticket)))
1955 return (fd);
1956
1957 if (ofiles[fd] == NULL || fd != ofiles[fd]->fd || fd < 0)
1958 return (SL_EINTERNAL);
1959 return (fd);
1960}
1961
1962int sl_close (SL_TICKET ticket)
1963{
1964 register int fd;
1965
1966 SL_ENTER(_("sl_close"));
1967
1968 if (SL_ISERROR(fd = get_the_fd (ticket)))
1969 SL_IRETURN(fd, _("sl_close"));
1970
1971 /* This may fail, but what to do then ?
1972 */
1973 if (0 != close(fd) && ofiles[fd] != NULL)
1974 {
1975 TPT((0, FIL__, __LINE__,
1976 _("msg=<Error closing file.>, path=<%s>, fd=<%d>\n"),
1977 ofiles[fd]->path, fd));
1978 }
1979
1980 if (ofiles[fd] != NULL)
1981 {
1982 (void) free(ofiles[fd]->path);
1983 (void) free(ofiles[fd]);
1984 ofiles[fd] = NULL;
1985 }
1986
1987 SL_IRETURN(SL_ENONE, _("sl_close"));
1988}
1989
1990int sl_dropall(int fd, int except)
1991{
1992 while (fd < MAXFD)
1993 {
1994 if (ofiles[fd] != NULL && fd != except)
1995 {
1996 if (ofiles[fd]->path != NULL)
1997 (void) free(ofiles[fd]->path);
1998 (void) free(ofiles[fd]);
1999 ofiles[fd] = NULL;
2000 }
2001 ++fd;
2002 }
2003 return 0;
2004}
2005
2006
2007int sl_unlink (SL_TICKET ticket)
2008{
2009 register int fd;
2010
2011 SL_ENTER(_("sl_unlink"));
2012
2013 if (SL_ISERROR(fd = get_the_fd(ticket)))
2014 SL_IRETURN(fd, _("sl_unlink"));
2015
2016 if (retry_aud_unlink(FIL__, __LINE__, ofiles[fd]->path) < 0)
2017 SL_IRETURN(SL_EUNLINK, _("sl_unlink"));
2018
2019 SL_IRETURN(SL_ENONE, _("sl_unlink"));
2020}
2021
2022
2023int sl_seek (SL_TICKET ticket, off_t off_data)
2024{
2025 register int fd;
2026
2027 SL_ENTER(_("sl_seek"));
2028
2029 if (SL_ISERROR(fd = get_the_fd(ticket)))
2030 SL_IRETURN(fd, _("sl_seek"));
2031
2032 if (lseek(fd, off_data, SEEK_SET) == (off_t)-1)
2033 SL_IRETURN(SL_EREWIND, _("sl_seek"));
2034
2035 SL_IRETURN(SL_ENONE, _("sl_seek"));
2036}
2037
2038int sl_rewind (SL_TICKET ticket)
2039{
2040 register int fd;
2041
2042 SL_ENTER(_("sl_rewind"));
2043
2044 if (SL_ISERROR(fd = get_the_fd(ticket)))
2045 SL_IRETURN(fd, _("sl_rewind"));
2046
2047 if (lseek (fd, 0L, SEEK_SET) == (off_t)-1)
2048 SL_IRETURN(SL_EREWIND, _("sl_rewind"));
2049
2050 SL_IRETURN(SL_ENONE, _("sl_rewind"));
2051}
2052
2053int sl_forward (SL_TICKET ticket)
2054{
2055 register int fd;
2056
2057 SL_ENTER(_("sl_forward"));
2058
2059 if (SL_ISERROR(fd = get_the_fd(ticket)))
2060 SL_IRETURN(fd, _("sl_forward"));
2061
2062 if (lseek (fd, 0L, SEEK_END) == (off_t)-1)
2063 SL_IRETURN(SL_EFORWARD, _("sl_forward"));
2064
2065 SL_IRETURN(SL_ENONE, _("sl_forward"));
2066}
2067
2068
2069int sl_sync (SL_TICKET ticket)
2070{
2071 register int fd;
2072
2073 SL_ENTER(_("sl_sync"));
2074
2075 if (SL_ISERROR(fd = get_the_fd(ticket)))
2076 SL_IRETURN(fd, _("sl_sync"));
2077
2078 if (fsync (fd) == -1)
2079 SL_IRETURN(SL_ESYNC, _("sl_sync"));
2080
2081 SL_IRETURN(SL_ENONE, _("sl_sync"));
2082}
2083
2084int sl_read_timeout_prep (SL_TICKET ticket)
2085{
2086 int fd;
2087 int sflags;
2088
2089 SL_ENTER(_("sl_read_timeout_prep"));
2090
2091 if (SL_ISERROR(fd = get_the_fd(ticket)))
2092 {
2093 TPT(( 0, FIL__, __LINE__, _("msg=<ticket error> errno=<%d>"), fd));
2094 SL_IRETURN(fd, _("sl_read_timeout_prep"));
2095 }
2096
2097 /* set to non-blocking mode
2098 */
2099 sflags = retry_fcntl(FIL__, __LINE__, fd, F_GETFL, 0);
2100 retry_fcntl(FIL__, __LINE__, fd, F_SETFL, sflags | O_NONBLOCK);
2101
2102 SL_IRETURN(SL_ENONE, _("sl_read_timeout_prep"));
2103}
2104
2105
2106int sl_read_timeout (SL_TICKET ticket, void * buf_in, size_t count,
2107 int timeout)
2108{
2109 fd_set readfds;
2110 struct timeval tv;
2111 /* int sflags; */
2112 int retval;
2113
2114 int fd;
2115 int byteread = 0;
2116 int bytes = 0;
2117 char * buf;
2118
2119 time_t tnow;
2120 time_t tstart;
2121 time_t tdiff;
2122 extern volatile int sig_termfast;
2123
2124 if (buf_in == NULL || SL_ISERROR(fd = get_the_fd(ticket)))
2125 {
2126 if (buf_in == NULL)
2127 {
2128 TPT(( 0, FIL__, __LINE__, _("msg=<null buffer>")));
2129 return (SL_ENULL);
2130 }
2131 if (SL_ISERROR(fd = get_the_fd(ticket)))
2132 {
2133 TPT(( 0, FIL__, __LINE__, _("msg=<ticket error> errno=<%d>"), fd));
2134 return (fd);
2135 }
2136 }
2137
2138 buf = (char *) buf_in;
2139
2140 tstart = time(NULL);
2141 tdiff = 0;
2142
2143 while (count > 0)
2144 {
2145 FD_ZERO(&readfds);
2146 FD_SET(fd, &readfds);
2147
2148 tv.tv_sec = timeout - tdiff;
2149 tv.tv_usec = 0;
2150
2151 retval = select (fd+1, &readfds, NULL, NULL, &tv);
2152
2153 if (retval > 0)
2154 {
2155 byteread = read (fd, buf, count);
2156
2157 if (byteread > 0)
2158 {
2159 bytes += byteread; count -= byteread;
2160 buf += byteread;
2161 if (count == 0)
2162 break;
2163 }
2164 else if (byteread == 0)
2165 {
2166 break;
2167 }
2168 else
2169 {
2170 if (errno == EINTR || errno == EAGAIN)
2171 {
2172 retry_msleep(1, 0);
2173 tnow = time(NULL);
2174 tdiff = tnow - tstart;
2175 continue;
2176 }
2177 else
2178 {
2179 return (SL_EREAD);
2180 }
2181 }
2182 }
2183 else if ((retval == -1) && (errno == EINTR || errno == EAGAIN))
2184 {
2185 retry_msleep(1, 0);
2186 tnow = time(NULL);
2187 tdiff = tnow - tstart;
2188 continue;
2189 }
2190 else if (retval == 0)
2191 {
2192 return (SL_TIMEOUT);
2193 }
2194 else
2195 {
2196 return (SL_EREAD);
2197 }
2198
2199 if (sig_termfast == 1)
2200 {
2201 return (SL_EREAD);
2202 }
2203
2204 tnow = time(NULL);
2205 tdiff = tnow - tstart;
2206
2207 if (tdiff > timeout)
2208 {
2209 return (SL_TIMEOUT);
2210 }
2211 }
2212
2213 return ((int) bytes);
2214}
2215
2216
2217int sl_read (SL_TICKET ticket, void * buf_in, size_t count)
2218{
2219 int fd;
2220 int byteread = 0;
2221 int bytes = 0;
2222
2223 char * buf;
2224
2225 if (count < 1)
2226 {
2227 TPT(( 0, FIL__, __LINE__, _("msg=<range error>")));
2228 return(SL_ERANGE);
2229 }
2230 if (buf_in == NULL)
2231 {
2232 TPT(( 0, FIL__, __LINE__, _("msg=<null buffer>")));
2233 return (SL_ENULL);
2234 }
2235
2236 if (SL_ISERROR(fd = get_the_fd(ticket)))
2237 {
2238 TPT(( 0, FIL__, __LINE__, _("msg=<ticket error> errno=<%d>"), fd));
2239 return (fd);
2240 }
2241
2242 buf = (char *) buf_in;
2243
2244 do
2245 {
2246 byteread = read (fd, buf, count);
2247 if (byteread > 0)
2248 {
2249 bytes += byteread; count -= byteread;
2250 buf += byteread;
2251 }
2252 } while ( byteread > 0 ||
2253 ( byteread == -1 && (errno == EINTR || errno == EAGAIN))
2254 );
2255
2256
2257 if (byteread == (-1))
2258 {
2259 TPT(( 0, FIL__, __LINE__, _("msg=<read error> errno=<%d>\n"), errno));
2260 return (SL_EREAD);
2261 }
2262 return (bytes);
2263}
2264
2265int sl_read_fast (SL_TICKET ticket, void * buf_in, size_t count)
2266{
2267 int fd;
2268 int byteread = 0;
2269
2270 char * buf;
2271
2272 if (count < 1)
2273 {
2274 TPT(( 0, FIL__, __LINE__, _("msg=<range error>")));
2275 return(SL_ERANGE);
2276 }
2277 if (buf_in == NULL)
2278 {
2279 TPT(( 0, FIL__, __LINE__, _("msg=<null buffer>")));
2280 return (SL_ENULL);
2281 }
2282
2283 if (SL_ISERROR(fd = get_the_fd(ticket)))
2284 {
2285 TPT(( 0, FIL__, __LINE__, _("msg=<ticket error> errno=<%d>"), fd));
2286 return (fd);
2287 }
2288
2289 buf = (char *) buf_in;
2290
2291 do
2292 {
2293 byteread = read (fd, buf, count);
2294 if (byteread >= 0)
2295 {
2296 return (byteread);
2297 }
2298 } while ( byteread == -1 && (errno == EINTR || errno == EAGAIN));
2299
2300
2301 if (byteread == (-1))
2302 {
2303 TPT(( 0, FIL__, __LINE__, _("msg=<read error> errno=<%d>\n"), errno));
2304 return (SL_EREAD);
2305 }
2306 return (0);
2307}
2308
2309
2310int sl_write (SL_TICKET ticket, void * msg_in, long nbytes)
2311{
2312 long bytewritten;
2313 long bytecount;
2314 int fd;
2315
2316 char * msg;
2317
2318 SL_ENTER(_("sl_write"));
2319
2320 if (nbytes < 1)
2321 SL_IRETURN(SL_ERANGE, _("sl_write"));
2322 if (msg_in == NULL)
2323 SL_IRETURN(SL_ENULL, _("sl_write"));
2324 if (SL_ISERROR(fd = get_the_fd(ticket)))
2325 SL_IRETURN(fd, _("sl_write"));
2326
2327 msg = (char *) msg_in;
2328
2329 /* write
2330 */
2331 bytecount = 0;
2332 bytewritten = 0;
2333 while (bytecount < nbytes)
2334 {
2335 if ((bytewritten = write (fd, msg, nbytes-bytecount)) > 0)
2336 {
2337 bytecount += bytewritten;
2338 msg += bytewritten; /* move buffer pointer forward */
2339 }
2340 else if (bytewritten <= 0)
2341 {
2342 if ( errno == EINTR || errno == EAGAIN) /* try again */
2343 continue;
2344 else
2345 SL_IRETURN(SL_EWRITE, _("sl_write"));
2346 }
2347 }
2348 SL_IRETURN(SL_ENONE, _("sl_write"));
2349}
2350
2351int sl_write_line (SL_TICKET ticket, void * msg, long nbytes)
2352{
2353 int status;
2354
2355 SL_ENTER(_("sl_write_line"));
2356
2357 status = sl_write(ticket, msg, nbytes);
2358 if (!SL_ISERROR(status))
2359 status = sl_write(ticket, "\n", 1);
2360
2361 SL_IRETURN(status, _("sl_write_line"));
2362}
2363
2364
2365/* ----------------------------------------------------------------
2366 *
2367 * Trustfile interface
2368 *
2369 * ---------------------------------------------------------------- */
2370
2371extern uid_t rootonly[];
2372extern int EUIDSLOT;
2373extern int ORIG_EUIDSLOT;
2374
2375extern char tf_path[MAXFILENAME]; /* Error path for trust function. */
2376extern uid_t tf_euid; /* Space for EUID of process. */
2377
2378
2379char * sl_error_string(int errorcode)
2380{
2381 switch (errorcode)
2382 {
2383 case SL_EBOGUS:
2384 return _("Bogus file. Modified during access.");
2385 case SL_EWRITE:
2386 return _("Write error.");
2387 case SL_EREAD:
2388 return _("Read error.");
2389 case SL_ESYNC:
2390 return _("Error in fsync().");
2391 case SL_EFORWARD:
2392 return _("Error in lseek().");
2393 case SL_EREWIND:
2394 return _("Error in lseek().");
2395 case SL_EUNLINK:
2396 return _("Error in unlink().");
2397 case SL_EMEM:
2398 return _("Out of memory.");
2399 case SL_EINTERNAL:
2400 return _("Internal error.");
2401 case SL_ETICKET:
2402 return _("Bad ticket.");
2403 case SL_EREPEAT:
2404 return _("Illegal repeated use of function.");
2405 case SL_ERANGE:
2406 return _("Argument out of range.");
2407 case SL_ENULL:
2408 return _("Dereferenced NULL pointer.");
2409
2410 case SL_EBADUID:
2411 return _("Owner not trustworthy.");
2412 case SL_EBADGID:
2413 return _("Group writeable and member not trustworthy.");
2414 case SL_EBADOTH:
2415 return _("World writeable.");
2416 case SL_EBADFILE:
2417 return _("File access error.");
2418 case SL_EBADNAME:
2419 return _("Invalid filename (prob. too long or null).");
2420
2421 case SL_ETRUNC:
2422 return _("Truncation occured.");
2423 case SL_ESTAT:
2424 return _("stat() failed.");
2425 default:
2426 return _("Unknown error.");
2427 }
2428}
2429
2430
2431
2432char * sl_trust_errfile()
2433{
2434 return &tf_path[0];
2435}
2436
2437extern uid_t tf_baduid;
2438uid_t sl_trust_baduid()
2439{
2440 return tf_baduid;
2441}
2442
2443extern gid_t tf_badgid;
2444gid_t sl_trust_badgid()
2445{
2446 return tf_badgid;
2447}
2448
2449
2450static int trust_count = 0;
2451
2452int sl_trust_purge_user ()
2453{
2454 int i;
2455
2456 EUIDSLOT = ORIG_EUIDSLOT;
2457 trust_count = 0;
2458
2459 for (i = EUIDSLOT; i < (EUIDSLOT + 15); ++i)
2460 rootonly[i] = sh_uid_neg;
2461 return 0;
2462}
2463
2464int sl_trust_add_user (uid_t pwid)
2465{
2466 SL_ENTER(_("sl_trust_add_user"));
2467
2468 if (trust_count == 15)
2469 SL_IRETURN(SL_ERANGE, _("sl_trust_add_user"));
2470
2471 rootonly[EUIDSLOT] = pwid;
2472 ++EUIDSLOT;
2473 ++trust_count;
2474
2475 SL_IRETURN(SL_ENONE, _("sl_trust_add_user"));
2476}
2477
2478int sl_trustfile_euid(char * filename, uid_t teuid)
2479{
2480 long status;
2481 SL_ENTER(_("sl_trustfile_euid"));
2482
2483 tf_path[0] = '\0';
2484 if (filename == NULL || filename[0] == '\0')
2485 SL_IRETURN(SL_EBADNAME, _("sl_trustfile_euid"));
2486
2487 tf_euid = teuid;
2488 status = sl_trustfile(filename, NULL, NULL);
2489 SL_IRETURN(status, _("sl_trustfile_euid"));
2490}
2491
2492/* ----------------------------------------------------------------
2493 *
2494 * Overflow tests
2495 *
2496 * ---------------------------------------------------------------- */
2497
2498int sl_ok_muli (int a, int b) /* a*b */
2499{
2500 if (a >= (INT_MIN / b) && a <= (INT_MAX / b))
2501 return SL_TRUE; /* no overflow */
2502 return SL_FALSE;
2503}
2504
2505int sl_ok_divi (int a, int b) /* a/b */
2506{
2507 (void) a;
2508 if (b != 0)
2509 return SL_TRUE; /* no overflow */
2510 return SL_FALSE;
2511}
2512
2513int sl_ok_addi (int a, int b) /* a+b */
2514{
2515 if (a >= 0 && b >= 0)
2516 {
2517 if (a <= (INT_MAX - b))
2518 return SL_TRUE; /* no overflow */
2519 else
2520 return SL_FALSE;
2521 }
2522 else if (a < 0 && b < 0)
2523 {
2524 if (a >= (INT_MIN - b))
2525 return SL_TRUE; /* no overflow */
2526 else
2527 return SL_FALSE;
2528 }
2529 return SL_TRUE;
2530}
2531
2532int sl_ok_subi (int a, int b) /* a-b */
2533{
2534 if (a >= 0 && b < 0)
2535 {
2536 if (a <= (INT_MAX + b))
2537 return SL_TRUE; /* no overflow */
2538 else
2539 return SL_FALSE;
2540 }
2541 else if (a < 0 && b >= 0)
2542 {
2543 if (a >= (INT_MIN + b))
2544 return SL_TRUE; /* no overflow */
2545 else
2546 return SL_FALSE;
2547 }
2548 return SL_TRUE;
2549}
Note: See TracBrowser for help on using the repository browser.