source: trunk/src/slib.c@ 29

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

Fixes for test suite, OpenBSD portability, self-resolving, and suidchk patch by Neil

File size: 55.2 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 sl_snprintf (val, 81, _("\n--------- %10s "), file);
234 sl_strlcpy (msg, val, 80);
235 sl_snprintf (val, 81, _(" --- %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) && !defined(__linux__)
580/* flawfinder: ignore */
581extern int vsnprintf ( char *str, size_t n,
582 const char *format, va_list ap );
583#endif
584#endif
585
586#if !defined (VA_COPY)
587#if defined (__GNUC__) && defined (__PPC__) && (defined (_CALL_SYSV) || defined (_WIN32))
588#define VA_COPY(ap1, ap2) (*(ap1) = *(ap2))
589#elif defined (VA_COPY_AS_ARRAY)
590#define VA_COPY(ap1, ap2) memmove ((ap1), (ap2), sizeof (va_list))
591#else /* va_list is a pointer */
592#define VA_COPY(ap1, ap2) ((ap1) = (ap2))
593#endif
594#endif
595
596#if !defined(HAVE_VSNPRINTF) || defined(HAVE_BROKEN_VSNPRINTF)
597static
598size_t sl_printf_count (const char * fmt, va_list vl)
599{
600 size_t length = 1;
601 int fini = 0;
602 int islong = 0;
603 int islonglong = 0;
604 int islongdouble = 0;
605 char * string_arg;
606
607 SL_ENTER(_("sl_printf_count"));
608
609 if (fmt == NULL)
610 SL_IRETURN(SL_ENULL, _("sl_printf_count"));
611
612 while (*fmt) {
613
614 if ( (*fmt) == '%' ) { /* a format specifier */
615
616 fmt++; /* point to first char after '%' */
617
618 fini = 0;
619 islong = 0;
620 islongdouble = 0;
621
622 while (*fmt && (fini == 0) ) {
623
624 switch (*fmt) {
625
626 case '*': /* field width supplied by an integer */
627 length = length + va_arg (vl, int);
628 ++fmt;
629 break;
630 case '1':
631 case '2':
632 case '3':
633 case '4':
634 case '5':
635 case '6':
636 case '7':
637 case '8':
638 case '9':
639 length = length + strtol (fmt, (char**) &fmt, 10);
640 /* strtol makes FastForward to first invalid char */
641 break;
642
643 case 'l': /* 'long' modifier */
644 if (islong == 0)
645 islong = 1;
646 else
647 {
648 islonglong = 1;
649 islong = 0;
650 }
651 ++fmt;
652 break;
653
654 case 'L': /* 'long double' modifier */
655#ifdef HAVE_LONG_DOUBLE
656 islongdouble = 1;
657#else
658 islong = 1;
659#endif
660 ++fmt;
661 break;
662
663 case 'd':
664 case 'i':
665 case 'o':
666 case 'u':
667 case 'x':
668 case 'X':
669 if (islonglong == 1)
670#ifdef HAVE_LONG_LONG
671 (void) va_arg (vl, long long);
672#else
673 (void) va_arg (vl, long);
674#endif
675 else if (islong == 1)
676 (void) va_arg (vl, long);
677 else
678 (void) va_arg (vl, int);
679 islong = 0;
680 islonglong = 0;
681 length = length + 24;
682 ++fmt;
683 fini = 1;
684 break;
685
686 case 'D':
687 case 'O':
688 case 'U':
689 (void) va_arg (vl, long);
690 length = length + 24;
691 fmt++;
692 fini = 1;
693 break;
694
695 case 'e':
696 case 'E':
697 case 'f':
698 case 'g':
699#ifdef HAVE_LONG_DOUBLE
700 if (islongdouble == 1) {
701 (void) va_arg (vl, long double);
702 islongdouble = 0;
703 length = length + 20;
704 }
705 else
706#endif
707 (void) va_arg (vl, double);
708 length = length + 20;
709 fini = 1;
710 ++fmt;
711 break;
712
713 case 's':
714 string_arg = va_arg (vl, char *);
715 if (string_arg != NULL)
716 length = length + sl_strlen (string_arg);
717 else
718 length = length + 16;
719 fini = 1;
720 ++fmt;
721 break;
722
723 case 'c':
724 (void) va_arg (vl, int);
725 length = length + 1;
726 fini = 1;
727 ++fmt;
728 break;
729
730 case 'p':
731 case 'n':
732 (void) va_arg (vl, void * );
733 length = length + 32;
734 fini = 1;
735 ++fmt;
736 break;
737
738 case '%': /* %% will print '%' */
739 length = length + 1;
740 fini = 1;
741 ++fmt;
742 break;
743
744 default:
745 length = length + 1;
746 ++fmt;
747 break;
748
749 } /* end switch */
750 }
751 /* end parsing a single format specifier */
752 } else {
753 length = length + 1;
754 fmt++;
755 }
756 }
757 SL_IRETURN(length, _("sl_printf_count"));
758}
759#endif /* #ifndef HAVE_VSNPRINTF */
760
761/*
762 * An implementation of vsnprintf. va_start/va_end are in the caller
763 * function.
764 * Returns C99 (#bytes that would heve been written) on success.
765 */
766int sl_vsnprintf(char *str, size_t n,
767 const char *format, va_list vl )
768{
769 int len = 0;
770#if !defined(HAVE_VSNPRINTF) || defined(HAVE_BROKEN_VSNPRINTF)
771 size_t total;
772 va_list vl2;
773#endif
774
775 SL_ENTER(_("sl_vsnprintf"));
776 if (str == NULL || format == NULL)
777 SL_IRETURN(0, _("sl_vsnprintf"));
778
779#if defined(HAVE_VSNPRINTF) && !defined(HAVE_BROKEN_VSNPRINTF)
780 len = vsnprintf (str, n, format, vl); /* flawfinder: ignore */
781 str[n-1] = '\0';
782#else
783 VA_COPY (vl2, vl); /* save the argument list */
784 total = sl_printf_count (format, vl);
785 len = (int) total;
786 if (total < n)
787 {
788 /* flawfinder: ignore */
789 vsprintf (str, format, vl2); /* program has checked that it fits */
790 str[n-1] = '\0';
791 }
792 else
793 {
794 sl_strlcpy (str, format, n);
795 va_end(vl2);
796 SL_IRETURN(len, _("sl_vsnprintf"));
797 }
798 va_end(vl2);
799#endif
800 SL_IRETURN(len, _("sl_vsnprintf"));
801}
802
803/*
804 * An implementation of snprintf.
805 * Returns SL_ENONE on success.
806 * ENULL: src || format == NULL
807 * ERANGE: n out of range
808 * ETRUNC: truncated (unimplemented)
809 */
810int sl_snprintf(char *str, size_t n,
811 const char *format, ... )
812{
813 va_list vl;
814#if !defined(HAVE_VSNPRINTF) || defined(HAVE_BROKEN_VSNPRINTF)
815 size_t total = 0;
816 va_list vl2;
817#endif
818
819 SL_ENTER(_("sl_snprintf"));
820 if (str == NULL || format == NULL)
821 SL_IRETURN(SL_ENULL, _("sl_snprintf"));
822
823 va_start (vl, format);
824#if defined(HAVE_VSNPRINTF) && !defined(HAVE_BROKEN_VSNPRINTF)
825 /* flawfinder: ignore */
826 vsnprintf (str, n, format, vl);
827 str[n-1] = '\0';
828#else
829 VA_COPY (vl2, vl); /* save the argument list */
830 total = sl_printf_count (format, vl);
831 if (total < n)
832 {
833 /* flawfinder: ignore */
834 vsprintf (str, format, vl2); /* program has checked that it fits */
835 str[n-1] = '\0';
836 }
837 else
838 {
839 sl_strlcpy (str, format, n);
840 va_end(vl2);
841 va_end(vl);
842 SL_IRETURN(SL_ETRUNC, _("sl_snprintf"));
843 }
844 va_end(vl2);
845#endif
846 va_end(vl);
847 SL_IRETURN(SL_ENONE, _("sl_snprintf"));
848}
849
850/*
851 * Appends src to string dst of size siz (unlike strncat, siz is the
852 * full size of dst, not space left). At most siz-1 characters
853 * will be copied. Always NUL terminates (unless siz == 0).
854 * Returns SL_NONE on success, errcode on failure.
855 *
856 * ENULL: dst == NULL
857 * ERANGE: siz out of range
858 * ETRUNC: src truncated
859 */
860int sl_strlcat(char * dst, /*@null@*/const char *src, size_t siz)
861{
862 register size_t dst_end;
863 register size_t dst_free;
864
865 register char * p;
866 register const char * q;
867
868 if (dst == NULL)
869 return SL_ENONE;
870 if (src == NULL || *src == '\0')
871 return SL_ENONE;
872
873 if (siz > 0) {
874
875 /* How much free space do we have ?
876 */
877 dst_end = strlen(dst);
878 dst_free = siz - dst_end - 1;
879
880 p = &dst[dst_end];
881 q = src;
882
883 while (dst_free > 0 && *q != '\0')
884 {
885 *p++ = *q++;
886 --dst_free;
887 }
888
889 /* NULL terminate dst.
890 */
891 *p = '\0';
892
893 if (*q != '\0')
894 return SL_ETRUNC;
895 }
896
897 return SL_ENONE;
898}
899
900/*
901 * An alternative implementation of the OpenBSD strlcpy() function.
902 *
903 * Copy src to string dst of size siz. At most siz-1 characters
904 * will be copied. Always NUL terminates (unless siz == 0).
905 * Returns SL_NONE on success, errcode on failure.
906 *
907 * ENULL: dst == NULL
908 * ERANGE: siz out of range
909 * ETRUNC: src truncated
910 */
911int sl_strlcpy(char * dst, /*@null@*/const char * src, size_t siz)
912{
913 /* SL_ENTER(_("sl_strlcpy")); */
914
915 if (dst == NULL)
916 return SL_ENULL;
917 if (src == NULL)
918 {
919 if (siz > 0)
920 dst[0] = '\0';
921 return SL_ENONE;
922 }
923
924
925 if (siz > 0) {
926 /* copy siz-1 characters
927 */
928 (void) strncpy(dst, src, siz-1);
929
930 /* NULL terminate
931 */
932 dst[siz-1] = '\0';
933 }
934 return SL_ENONE;
935}
936
937/*
938 * A robust drop-in replacement of strncpy. strlcpy is preferable.
939 */
940char * sl_strncpy(char *dst, const char *src, size_t size)
941{
942
943#ifdef SL_FAIL_ON_ERROR
944 SL_REQUIRE(dst != NULL, _("dst != NULL"));
945 SL_REQUIRE(src != NULL, _("src != NULL"));
946 SL_REQUIRE(size > 0, _("size > 0"));
947#endif
948
949 if (dst == NULL)
950 {
951 sl_errno = SL_ENULL;
952 return (NULL);
953 }
954 if (size < 1)
955 {
956 sl_errno = SL_ERANGE;
957 return (dst);
958 }
959 if (!src)
960 {
961 sl_errno = SL_ENULL;
962 dst[0] = '\0';
963 }
964 else if (src[0] == '\0')
965 dst[0] = '\0';
966 else
967 strncpy(dst, src, size);
968
969 if (sl_strlen(src) >= size)
970 {
971 errno = ENOSPC;
972 dst[size-1] = '\0';
973 }
974 return (dst);
975}
976
977/*
978 * A robust drop-in replacement of strncat. strlcat is preferable.
979 */
980char * sl_strncat(char *dst, const char *src, size_t n)
981{
982#ifdef SL_FAIL_ON_ERROR
983 SL_REQUIRE(dst != NULL, _("dst != NULL"));
984 SL_REQUIRE(src != NULL, _("src != NULL"));
985 SL_REQUIRE(n > 0, _("n > 0"));
986#endif
987
988 if (dst == NULL)
989 {
990 sl_errno = SL_ENULL;
991 return (NULL);
992 }
993 if (n < 1)
994 {
995 sl_errno = SL_ERANGE;
996 return (dst);
997 }
998 if (!src)
999 {
1000 sl_errno = SL_ENULL;
1001 return (dst);
1002 }
1003 else if (src[0] == '\0')
1004 dst[0] = '\0';
1005 else
1006 strncat(dst, src, n);
1007
1008 return (dst);
1009}
1010
1011
1012int sl_strcmp(const char * a, const char * b)
1013{
1014#ifdef SL_FAIL_ON_ERROR
1015 SL_REQUIRE (a != NULL, _("a != NULL"));
1016 SL_REQUIRE (b != NULL, _("b != NULL"));
1017#endif
1018
1019 if (a != NULL && b != NULL)
1020 return (strcmp(a, b));
1021 else if (a == NULL && b != NULL)
1022 return (-1);
1023 else if (a != NULL && b == NULL)
1024 return (1);
1025 else
1026 return (-7); /* arbitrary */
1027}
1028
1029int sl_strncmp(const char * a, const char * b, size_t n)
1030{
1031#ifdef SL_FAIL_ON_ERROR
1032 SL_REQUIRE (a != NULL, _("a != NULL"));
1033 SL_REQUIRE (b != NULL, _("b != NULL"));
1034 SL_REQUIRE (n > 0, _("n > 0"));
1035#endif
1036
1037 if (a != NULL && b != NULL)
1038 return (strncmp(a, b, n));
1039 else if (a == NULL && b != NULL)
1040 return (-1);
1041 else if (a != NULL && b == NULL)
1042 return (1);
1043 else
1044 return (-7); /* arbitrary */
1045}
1046
1047/* string searching
1048 */
1049
1050char * sl_strstr (const char * haystack, const char * needle)
1051{
1052#ifndef HAVE_STRSTR
1053 int i;
1054 size_t needle_len;
1055 size_t haystack_len;
1056#endif
1057
1058 if (haystack == NULL || needle == NULL)
1059 return NULL;
1060 if (*needle == '\0' || *haystack == '\0')
1061 return NULL;
1062
1063#if defined(HAVE_STRSTR)
1064 return (strstr(haystack, needle));
1065#else
1066 needle_len = strlen(needle);
1067 haystack_len = strlen(haystack);
1068
1069 for (i = 0; i <= (haystack_len-needle_len); ++i)
1070 if (0 == sl_strncmp(&haystack[i], needle, needle_len))
1071 return (needle);
1072 return NULL;
1073#endif
1074}
1075
1076
1077/* ----------------------------------------------------------------
1078 *
1079 * Privilege handling routines
1080 *
1081 * ---------------------------------------------------------------- */
1082
1083
1084
1085static uid_t euid;
1086static uid_t ruid;
1087static uid_t ruid_orig;
1088static gid_t egid;
1089static gid_t rgid;
1090static gid_t rgid_orig;
1091
1092static int uids_are_stored = SL_FALSE;
1093static int suid_is_set = SL_TRUE;
1094
1095#ifdef HAVE_SETRESUID
1096extern int setresuid (uid_t truid, uid_t teuid, uid_t tsuid);
1097extern int setresgid (gid_t trgid, gid_t tegid, gid_t tsgid);
1098#endif
1099
1100
1101/*
1102 * This function returns true if the program is SUID.
1103 * It calls abort() if the uid's are not saved already.
1104 */
1105int sl_is_suid()
1106{
1107 if (uids_are_stored == SL_FALSE)
1108 {
1109 if (getuid() == geteuid() && getgid() == getegid())
1110 return (0); /* FALSE */
1111 else
1112 return (1); /* TRUE */
1113 }
1114 else
1115 {
1116 if (euid == ruid && egid == rgid)
1117 return (0); /* FALSE */
1118 else
1119 return (1); /* TRUE */
1120 }
1121}
1122
1123/*
1124 * This function returns the saved euid.
1125 * It calls abort() if the uid's are not saved already.
1126 */
1127int sl_get_euid(uid_t * ret)
1128{
1129 SL_ENTER(_("sl_get_euid"));
1130 /* SL_REQUIRE(uids_are_stored == SL_TRUE, _("uids_are_stored == SL_TRUE"));*/
1131 if (uids_are_stored == SL_TRUE)
1132 *ret = euid;
1133 else
1134 *ret = geteuid();
1135 SL_IRETURN (SL_ENONE, _("sl_get_euid"));
1136}
1137
1138uid_t sl_ret_euid()
1139{
1140 /* SL_REQUIRE(uids_are_stored == SL_TRUE, _("uids_are_stored == SL_TRUE"));*/
1141 if (uids_are_stored == SL_TRUE)
1142 return (euid);
1143 else
1144 return (geteuid());
1145}
1146
1147/*
1148 * This function returns the saved egid.
1149 * It calls abort() if the uid's are not saved already.
1150 */
1151int sl_get_egid(gid_t * ret)
1152{
1153 SL_ENTER(_("sl_get_egid"));
1154 /* SL_REQUIRE(uids_are_stored == SL_TRUE, _("uids_are_stored == SL_TRUE"));*/
1155 if (uids_are_stored == SL_TRUE)
1156 *ret = egid;
1157 else
1158 *ret = getegid();
1159 SL_IRETURN (SL_ENONE, _("sl_get_egid"));
1160}
1161
1162/*
1163 * This function returns the saved ruid.
1164 * It calls abort() if the uid's are not saved already.
1165 */
1166int sl_get_ruid(uid_t * ret)
1167{
1168 SL_ENTER(_("sl_get_ruid"));
1169 /* SL_REQUIRE(uids_are_stored == SL_TRUE, _("uids_are_stored == SL_TRUE"));*/
1170 if (uids_are_stored == SL_TRUE)
1171 *ret = ruid;
1172 else
1173 *ret = getuid();
1174 SL_IRETURN (SL_ENONE, _("sl_get_ruid"));
1175}
1176
1177/*
1178 * This function returns the saved rgid.
1179 * It calls abort() if the uid's are not saved already.
1180 */
1181int sl_get_rgid(gid_t * ret)
1182{
1183 SL_ENTER(_("sl_get_rgid"));
1184 /* SL_REQUIRE(uids_are_stored == SL_TRUE, _("uids_are_stored == SL_TRUE"));*/
1185 if (uids_are_stored == SL_TRUE)
1186 *ret = rgid;
1187 else
1188 *ret = getgid();
1189 SL_IRETURN (SL_ENONE, _("sl_get_rgid"));
1190}
1191
1192/*
1193 * This function returns the saved original ruid.
1194 * It calls abort() if the uid's are not saved already.
1195 */
1196int sl_get_ruid_orig(uid_t * ret)
1197{
1198 SL_ENTER(_("sl_get_ruid_orig"));
1199 /* SL_REQUIRE(uids_are_stored == SL_TRUE, _("uids_are_stored == SL_TRUE"));*/
1200 if (uids_are_stored == SL_TRUE)
1201 *ret = ruid_orig;
1202 else
1203 *ret = getuid();
1204 SL_IRETURN (SL_ENONE, _("sl_get_ruid_orig"));
1205}
1206
1207/*
1208 * This function returns the saved original rgid.
1209 * It calls abort() if the uid's are not saved already.
1210 */
1211int sl_get_rgid_orig(gid_t * ret)
1212{
1213 SL_ENTER(_("sl_get_rgid_orig"));
1214 /* SL_REQUIRE(uids_are_stored == SL_TRUE, _("uids_are_stored == SL_TRUE"));*/
1215 if (uids_are_stored == SL_TRUE)
1216 *ret = rgid_orig;
1217 else
1218 *ret = getgid();
1219 SL_IRETURN (SL_ENONE, _("sl_get_rgid_orig"));
1220}
1221
1222static int suid_warn_flag = 1;
1223static void suid_warn(int a)
1224{
1225 fprintf(stderr, _("ERROR: open set/unset suid !!! %d\n"), a);
1226 return;
1227}
1228
1229/*
1230 * This function sets the effective uid
1231 * to the saved effective uid.
1232 * It will abort on failure.
1233 */
1234int sl_set_suid ()
1235{
1236 int retval;
1237
1238 SL_ENTER(_("sl_set_suid"));
1239
1240 if (uids_are_stored == SL_FALSE)
1241 {
1242 SL_IRETURN(SL_ENONE, _("sl_set_suid"));
1243 }
1244
1245 SL_REQUIRE(uids_are_stored == SL_TRUE, _("uids_are_stored == SL_TRUE"));
1246
1247 if (ruid == euid && rgid == egid)
1248 {
1249 suid_is_set = SL_TRUE;
1250 SL_IRETURN(SL_ENONE, _("sl_set_suid"));
1251 }
1252 SL_REQUIRE(suid_is_set == SL_FALSE, _("suid_is_set == SL_FALSE"));
1253
1254#if defined(HAVE_SETRESUID)
1255 retval = setresuid (sh_uid_neg, euid, sh_uid_neg);
1256 if (retval == 0)
1257 retval = setresgid (sh_gid_neg, egid, sh_gid_neg);
1258
1259#elif defined(HAVE_SETEUID)
1260 retval = seteuid (egid);
1261 if (retval == 0)
1262 retval = setegid (euid);
1263
1264 /* on AIX, setreuid does not behave well for non-root users.
1265 */
1266#elif defined(HAVE_SETREUID)
1267 retval = setreuid (ruid, euid);
1268 if (retval == 0)
1269 retval = setregid (rgid, egid);
1270
1271#else
1272 retval = setuid (euid);
1273 if (retval == 0)
1274 retval = setgid (egid);
1275#endif
1276 if (suid_warn_flag == 1)
1277 suid_warn(1);
1278 suid_warn_flag = 1;
1279
1280 SL_REQUIRE(retval == 0, _("retval == 0"));
1281 suid_is_set = SL_TRUE;
1282 SL_IRETURN(SL_ENONE, _("sl_set_suid"));
1283}
1284
1285/*
1286 * This function sets the effective uid to the real uid.
1287 * It will abort on failure.
1288 */
1289int sl_unset_suid ()
1290{
1291 register int retval;
1292
1293 SL_ENTER(_("sl_unset_suid"));
1294
1295 if (uids_are_stored == SL_FALSE)
1296 {
1297 SL_IRETURN(SL_ENONE, _("sl_unset_suid"));
1298 }
1299
1300 SL_REQUIRE(uids_are_stored == SL_TRUE, _("uids_are_stored == SL_TRUE"));
1301
1302 if (ruid == euid && rgid == egid)
1303 {
1304 suid_is_set = SL_FALSE;
1305 SL_IRETURN(SL_ENONE, _("sl_unset_suid"));
1306 }
1307 SL_REQUIRE(suid_is_set == SL_TRUE, _("suid_is_set == SL_TRUE"));
1308
1309#if defined(HAVE_SETRESUID)
1310 retval = setresgid (sh_gid_neg, rgid, sh_gid_neg);
1311 if (retval == 0)
1312 retval = setresuid (sh_uid_neg, ruid, sh_uid_neg);
1313
1314#elif defined(HAVE_SETEUID)
1315 retval = setegid (rgid);
1316 if (retval == 0)
1317 retval = seteuid (ruid);
1318
1319#elif defined(HAVE_SETREUID)
1320 retval = setregid (egid, rgid);
1321 if (retval == 0)
1322 retval = setreuid (euid, ruid);
1323
1324#else
1325 retval = setgid (rgid);
1326 if (retval == 0)
1327 retval = setuid (ruid);
1328#endif
1329
1330 if (suid_warn_flag == 0)
1331 suid_warn(0);
1332 suid_warn_flag = 0;
1333
1334 SL_REQUIRE(retval == 0, _("retval == 0"));
1335 suid_is_set = SL_FALSE;
1336 SL_IRETURN(SL_ENONE, _("sl_unset_suid"));
1337}
1338
1339
1340/*
1341 * This function saves the uid's.
1342 */
1343int sl_save_uids()
1344{
1345 SL_ENTER(_("sl_save_uids"));
1346 if (uids_are_stored == SL_TRUE)
1347 SL_IRETURN(SL_EREPEAT, _("sl_save_uids"));
1348
1349 ruid_orig = getuid();
1350 rgid_orig = getgid();
1351 egid = getegid();
1352 euid = geteuid();
1353 ruid = ruid_orig;
1354 rgid = rgid_orig;
1355 uids_are_stored = SL_TRUE;
1356
1357 SL_IRETURN(SL_ENONE, _("sl_save_uids"));
1358}
1359
1360/*
1361 * This function drops SUID privileges irrevocably.
1362 * It set the effective uid to the original real uid.
1363 */
1364extern int sh_unix_initgroups2 (uid_t in_pid, gid_t in_gid);
1365int sl_drop_privileges()
1366{
1367 SL_ENTER(_("sl_drop_privileges"));
1368 SL_REQUIRE(uids_are_stored == SL_TRUE, _("uids_are_stored == SL_TRUE"));
1369
1370 SL_REQUIRE(setgid(rgid_orig) == 0, _("setgid(rgid_orig) == 0"));
1371 SL_REQUIRE(sh_unix_initgroups2(ruid_orig, rgid_orig) == 0, _("sh_unix_initgroups2(ruid_orig,rgid_orig) == 0"));
1372 SL_REQUIRE(setuid(ruid_orig) == 0, _("setuid(ruid_orig) == 0"));
1373
1374 /* make sure that setuid(0) fails
1375 */
1376 SL_REQUIRE(setuid(0) < 0, _("setuid(0) < 0"));
1377
1378 euid = ruid_orig;
1379 egid = rgid_orig;
1380 ruid = ruid_orig;
1381 rgid = rgid_orig;
1382
1383 SL_IRETURN(SL_ENONE, _("sl_drop_privileges"));
1384}
1385
1386/*
1387 * Define a policy: Stay root.
1388 * Do nothing if not SUID.
1389 */
1390int sl_policy_get_root()
1391{
1392 SL_ENTER(_("sl_policy_get_root"));
1393 SL_REQUIRE(uids_are_stored == SL_FALSE, _("uids_are_stored == SL_FALSE"));
1394
1395 SL_REQUIRE (sl_save_uids() == SL_ENONE, _("sl_save_uids() == SL_ENONE"));
1396
1397 if (euid != ruid || egid != rgid)
1398 {
1399 SL_REQUIRE(setgid(egid) == 0, _("setgid(egid) == 0"));
1400 SL_REQUIRE(setuid(euid) == 0, _("setuid(euid) == 0"));
1401 SL_REQUIRE(ruid == getuid() && rgid == getgid(),
1402 _("ruid == getuid() && rgid == getgid()"));
1403 ruid = euid;
1404 rgid = egid;
1405 }
1406 suid_is_set = SL_TRUE;
1407 if (euid == 0)
1408 {
1409 SL_REQUIRE(sh_unix_initgroups2(euid, egid) == 0, _("sh_unix_initgroups2(euid,egid) == 0"));
1410 }
1411 SL_IRETURN(SL_ENONE, _("sl_policy_get_root"));
1412}
1413
1414#include <pwd.h>
1415
1416/*
1417 * Define a policy: Get real (irrevocably).
1418 * This function drops SUID privileges irrevocably.
1419 * Do nothing if not SUID (? not true - drops if root).
1420 */
1421
1422int sl_policy_get_real(char * user)
1423{
1424 struct passwd * tempres;
1425
1426 SL_ENTER(_("sl_policy_get_real"));
1427 SL_REQUIRE(uids_are_stored == SL_FALSE, _("uids_are_stored == SL_FALSE"));
1428 SL_REQUIRE (sl_save_uids() == SL_ENONE, _("sl_save_uids() == SL_ENONE"));
1429
1430 if (euid == 0 || ruid == 0)
1431 {
1432 tempres = sh_getpwnam(user);
1433
1434 SL_REQUIRE (NULL != tempres, _("tempres != NULL"));
1435
1436 rgid_orig = tempres->pw_gid;
1437 ruid_orig = tempres->pw_uid;
1438 }
1439 else
1440 {
1441 rgid_orig = rgid;
1442 ruid_orig = ruid;
1443 }
1444
1445 SL_REQUIRE (sl_drop_privileges() == SL_ENONE,
1446 _("sl_drop_privileges() == SL_ENONE"));
1447
1448 suid_is_set = SL_TRUE;
1449 SL_IRETURN(SL_ENONE, _("sl_policy_get_real"));
1450}
1451
1452
1453/*
1454 * Define a policy: Get user.
1455 * Drops privileges.
1456 * Do nothing if not SUID.
1457 */
1458int sl_policy_get_user(char * user)
1459{
1460 struct passwd * tempres;
1461
1462 SL_ENTER(_("sl_policy_get_user"));
1463
1464 SL_REQUIRE(user != NULL, _("user != NULL"));
1465 SL_REQUIRE(uids_are_stored == SL_FALSE, _("uids_are_stored == SL_FALSE"));
1466 SL_REQUIRE (sl_save_uids() == SL_ENONE, _("sl_save_uids() == SL_ENONE"));
1467
1468 if (euid != ruid || egid != rgid)
1469 {
1470 tempres = sh_getpwnam(user);
1471
1472 SL_REQUIRE (NULL != tempres, _("tempres != NULL"));
1473
1474#if 0
1475 rgid = tempres->pw_gid;
1476 ruid = tempres->pw_uid;
1477 SL_REQUIRE(sl_unset_suid() == SL_ENONE,
1478 _("sl_unset_suid() == SL_ENONE"));
1479#endif
1480 SL_REQUIRE (sl_drop_privileges() == SL_ENONE,
1481 _("sl_drop_privileges() == SL_ENONE"));
1482 }
1483 SL_IRETURN(SL_ENONE, _("sl_policy_get_user"));
1484}
1485
1486
1487
1488/* ----------------------------------------------------------------
1489 *
1490 * File access routines
1491 *
1492 * ---------------------------------------------------------------- */
1493
1494#define TOFFSET 0x1234
1495
1496/* this would prevent opening files if the first 16 fds are open :( */
1497/* #define MAXFD FOPEN_MAX */
1498
1499#define MAXFD 1024
1500
1501typedef struct openfiles {
1502 SL_TICKET ticket; /* The unique ID. */
1503 int fd; /* The file descriptor. */
1504 char * path; /* The file path. */
1505} SL_OFILE;
1506
1507static SL_OFILE * ofiles[MAXFD];
1508
1509
1510static unsigned int nonce_counter = TOFFSET;
1511
1512static
1513SL_TICKET sl_create_ticket (unsigned int myindex)
1514{
1515 unsigned int high; /* index */
1516 unsigned int low; /* nonce */
1517
1518 SL_ENTER(_("sl_create_ticket"));
1519
1520 if (myindex >= MAXFD)
1521 SL_IRETURN (SL_EINTERNAL, _("sl_create_ticket"));
1522
1523 /* mask out the high bit and check that it is not used
1524 * -> verify that it fits into 16 bits as positive
1525 */
1526 high = (myindex + TOFFSET) & 0x7fff;
1527
1528 if (high != myindex + TOFFSET)
1529 SL_IRETURN (SL_EINTERNAL, _("sl_create_ticket"));
1530
1531 low = nonce_counter & 0xffff;
1532
1533 /* Overflow -> nonce too big.
1534 */
1535 if ((low != nonce_counter++) || low == 0)
1536 SL_IRETURN (SL_EINTERNAL, _("sl_create_ticket"));
1537
1538 /* Wrap around the nonce counter.
1539 * This is a dirty trick.
1540 */
1541 if (nonce_counter > 0x7fff)
1542 nonce_counter = TOFFSET;
1543
1544 SL_RETURN ((SL_TICKET) ((high << 16) | low), _("sl_create_ticket"));
1545}
1546
1547static
1548int sl_read_ticket (SL_TICKET fno)
1549{
1550 register unsigned myindex;
1551 register SL_OFILE *of;
1552
1553 myindex = ((fno >> 16) & 0xffff) - TOFFSET;
1554 if (myindex >= MAXFD)
1555 return (SL_ETICKET);
1556
1557 if (ofiles[myindex] == NULL)
1558 return (SL_ETICKET);
1559
1560 if (ofiles[myindex]->ticket != fno)
1561 return (SL_ETICKET);
1562
1563 if ((of = ofiles[myindex])->fd < 0 || of->fd >= MAXFD )
1564 return (SL_EINTERNAL);
1565
1566 if (((of->ticket) & 0xffff) == 0)
1567 return (SL_EINTERNAL);
1568
1569 return (myindex);
1570}
1571
1572SL_TICKET sl_make_ticket (int fd, char * filename)
1573{
1574 size_t len;
1575 SL_TICKET ticket;
1576 SL_ENTER(_("sl_make_ticket"));
1577 /* Make entry.
1578 */
1579 if (fd >= MAXFD || fd < 0)
1580 {
1581 SL_IRETURN(SL_TOOMANY, _("sl_make_ticket"));
1582 }
1583
1584 if (ofiles[fd] != NULL)
1585 {
1586 SL_IRETURN(SL_EINTERNAL, _("sl_make_ticket"));
1587 }
1588
1589 if ( (ofiles[fd] = (SL_OFILE *) malloc(sizeof(SL_OFILE))) == NULL)
1590 {
1591 SL_IRETURN(SL_EMEM, _("sl_make_ticket"));
1592 }
1593
1594 len = sl_strlen(filename)+1;
1595
1596 if ( (ofiles[fd]->path = (char *) malloc(len) ) == NULL)
1597 {
1598 free(ofiles[fd]);
1599 ofiles[fd] = NULL;
1600 SL_IRETURN(SL_EMEM, _("sl_make_ticket"));
1601 }
1602
1603 /* Get a ticket.
1604 */
1605 ticket = sl_create_ticket((unsigned int)fd);
1606
1607 if (SL_ISERROR(ticket))
1608 {
1609 (void) free (ofiles[fd]->path);
1610 (void) free (ofiles[fd]);
1611 SL_IRETURN(ticket, _("sl_make_ticket"));
1612 }
1613
1614 sl_strlcpy (ofiles[fd]->path, filename, len);
1615 ofiles[fd]->ticket = ticket;
1616 ofiles[fd]->fd = fd;
1617
1618 SL_IRETURN(ticket, _("sl_make_ticket"));
1619}
1620
1621#define SL_OPEN_MIN 113
1622#define SL_OPEN_FOR_READ 113
1623#define SL_OPEN_FOR_WRITE 114
1624#define SL_OPEN_FOR_RDWR 115
1625#define SL_OPEN_FOR_WTRUNC 116
1626#define SL_OPEN_FOR_RWTRUNC 117
1627#define SL_OPEN_SAFE_RDWR 118
1628#define SL_OPEN_FOR_FASTREAD 119
1629#define SL_OPEN_MAX 119
1630
1631#if !defined(O_NOATIME)
1632#if defined(__linux__) && (defined(__i386__) || defined(__PPC__))
1633#define O_NOATIME 01000000
1634#else
1635 /*
1636 * bitwise 'or' with zero does not modify any bit
1637 */
1638#define O_NOATIME 0
1639#endif
1640#endif
1641
1642static int o_noatime = O_NOATIME;
1643static mode_t open_mode = (S_IWUSR|S_IRUSR|S_IRGRP);
1644
1645
1646static
1647int sl_open_file (const char *filename, int mode, int priv)
1648{
1649 struct stat lbuf;
1650 struct stat buf;
1651 int lstat_return;
1652 int stat_return;
1653 int fd;
1654 int sflags;
1655 size_t len;
1656 SL_TICKET ticket;
1657
1658#if !defined(O_NONBLOCK)
1659#if defined(O_NDELAY)
1660#define O_NONBLOCK O_NDELAY
1661#else
1662#define O_NONBLOCK 0
1663#endif
1664#endif
1665
1666 SL_ENTER(_("sl_open_file"));
1667
1668 if (filename == NULL)
1669 SL_IRETURN(SL_ENULL, _("sl_open_file"));
1670 if (mode < SL_OPEN_MIN || mode > SL_OPEN_MAX)
1671 SL_IRETURN(SL_EINTERNAL, _("sl_open_file"));
1672
1673 /* "This system call always succeeds and the previous value of
1674 * the mask is returned."
1675 */
1676 (void) umask (0);
1677
1678 if (mode == SL_OPEN_FOR_FASTREAD)
1679 {
1680 fd = aud_open_noatime (FIL__, __LINE__, priv, filename,
1681 O_RDONLY|O_NONBLOCK, 0, &o_noatime);
1682 /*
1683 if (fd >= 0) {
1684 sflags = retry_fcntl(FIL__, __LINE__, fd, F_GETFL, 0);
1685 retry_fcntl(FIL__, __LINE__, fd, F_SETFL, sflags & ~O_NONBLOCK);
1686 }
1687 */
1688 if (fd < 0)
1689 SL_IRETURN(SL_EBADFILE, _("sl_open_file"));
1690 goto createTicket;
1691 }
1692
1693#ifdef USE_SUID
1694 if (priv == SL_YESPRIV)
1695 sl_set_suid();
1696#endif
1697 if (mode == SL_OPEN_FOR_READ)
1698 lstat_return = retry_stat (FIL__, __LINE__, filename, &lbuf);
1699 else
1700 lstat_return = retry_lstat(FIL__, __LINE__, filename, &lbuf);
1701#ifdef USE_SUID
1702 if (priv == SL_YESPRIV)
1703 sl_unset_suid();
1704#endif
1705
1706 if (lstat_return == -1)
1707 {
1708 lstat_return = ENOENT;
1709 if ( (mode == SL_OPEN_FOR_READ && lstat_return == ENOENT) ||
1710 (errno != ENOENT))
1711 {
1712 TPT(( 0, FIL__, __LINE__, _("msg=<lstat: %s> errno=<%d>\n"),
1713 filename, errno));
1714 SL_IRETURN(SL_EBADFILE, _("sl_open_file"));
1715 }
1716 }
1717
1718 if ( (mode != SL_OPEN_FOR_READ) && (lstat_return != ENOENT) &&
1719 ( S_ISDIR(lbuf.st_mode) || (S_IWOTH & lbuf.st_mode) )
1720 )
1721 SL_IRETURN(SL_EBADFILE, _("sl_open_file"));
1722
1723
1724 /* O_NOATIME has an effect for read(). But write() ?.
1725 */
1726 switch (mode)
1727 {
1728 case SL_OPEN_FOR_READ:
1729 fd = aud_open_noatime (FIL__, __LINE__, priv, filename,
1730 O_RDONLY|O_NONBLOCK, 0, &o_noatime);
1731 if (fd >= 0) {
1732 sflags = retry_fcntl(FIL__, __LINE__, fd, F_GETFL, 0);
1733 retry_fcntl(FIL__, __LINE__, fd, F_SETFL, sflags & ~O_NONBLOCK);
1734 }
1735 break;
1736 case SL_OPEN_FOR_WRITE:
1737 if (lstat_return == ENOENT)
1738 fd = aud_open (FIL__, __LINE__, priv, filename,
1739 O_WRONLY|O_CREAT|O_EXCL, open_mode);
1740 else
1741 fd = aud_open (FIL__, __LINE__, priv, filename,
1742 O_WRONLY, open_mode);
1743 break;
1744 case SL_OPEN_SAFE_RDWR:
1745 if (lstat_return == ENOENT)
1746 fd = aud_open (FIL__, __LINE__, priv, filename,
1747 O_RDWR|O_CREAT|O_EXCL, open_mode);
1748 else
1749 SL_IRETURN(SL_EBADFILE, _("sl_open_file"));
1750 break;
1751 case SL_OPEN_FOR_RDWR:
1752 if (lstat_return == ENOENT)
1753 fd = aud_open (FIL__, __LINE__, priv, filename,
1754 O_RDWR|O_CREAT|O_EXCL, open_mode);
1755 else
1756 fd = aud_open (FIL__, __LINE__, priv, filename,
1757 O_RDWR, open_mode);
1758 break;
1759 case SL_OPEN_FOR_WTRUNC:
1760 if (lstat_return == ENOENT)
1761 fd = aud_open (FIL__, __LINE__, priv, filename,
1762 O_WRONLY|O_CREAT|O_EXCL, open_mode);
1763 else
1764 fd = aud_open (FIL__, __LINE__, priv, filename,
1765 O_WRONLY|O_TRUNC, open_mode);
1766 break;
1767 case SL_OPEN_FOR_RWTRUNC:
1768 if (lstat_return == ENOENT)
1769 fd = aud_open (FIL__, __LINE__, priv, filename,
1770 O_RDWR|O_CREAT|O_EXCL, open_mode);
1771 else
1772 fd = aud_open (FIL__, __LINE__, priv, filename,
1773 O_RDWR|O_TRUNC, open_mode);
1774 break;
1775 default:
1776 SL_IRETURN(SL_EINTERNAL, _("sl_open_file"));
1777 }
1778
1779 if (fd < 0)
1780 {
1781 TPT(( 0, FIL__, __LINE__, _("msg=<Error opening: %s> errno=<%d>\n"),
1782 filename, errno));
1783 SL_IRETURN(SL_EBADFILE, _("sl_open_file"));
1784 }
1785
1786#ifdef USE_SUID
1787 if (priv == SL_YESPRIV)
1788 sl_set_suid();
1789#endif
1790 stat_return = retry_fstat(FIL__, __LINE__, fd, &buf);
1791#ifdef USE_SUID
1792 if (priv == SL_YESPRIV)
1793 sl_unset_suid();
1794#endif
1795
1796 if (stat_return < 0)
1797 {
1798 close (fd);
1799 SL_IRETURN(SL_EBADFILE, _("sl_open_file"));
1800 }
1801
1802 if (lstat_return != ENOENT && buf.st_ino != lbuf.st_ino)
1803 {
1804 close (fd);
1805 SL_IRETURN(SL_EBOGUS, _("sl_open_file"));
1806 }
1807
1808 createTicket:
1809
1810 /* Make entry.
1811 */
1812 if (fd >= MAXFD)
1813 {
1814 close(fd);
1815 SL_IRETURN(SL_TOOMANY, _("sl_open_file"));
1816 }
1817
1818 if (ofiles[fd] != NULL)
1819 {
1820 close(fd);
1821 SL_IRETURN(SL_EINTERNAL, _("sl_open_file"));
1822 }
1823
1824 if ( (ofiles[fd] = (SL_OFILE *) malloc(sizeof(SL_OFILE))) == NULL)
1825 {
1826 close(fd);
1827 SL_IRETURN(SL_EMEM, _("sl_open_file"));
1828 }
1829
1830 len = sl_strlen(filename)+1;
1831
1832 if ( (ofiles[fd]->path = (char *) malloc(len) ) == NULL)
1833 {
1834 free(ofiles[fd]);
1835 ofiles[fd] = NULL;
1836 close(fd);
1837 SL_IRETURN(SL_EMEM, _("sl_open_file"));
1838 }
1839
1840 /* Get a ticket.
1841 */
1842 ticket = sl_create_ticket(fd);
1843
1844 if (SL_ISERROR(ticket))
1845 {
1846 (void) free (ofiles[fd]->path);
1847 (void) free (ofiles[fd]);
1848 close(fd);
1849 SL_IRETURN(ticket, _("sl_open_file"));
1850 }
1851
1852 sl_strlcpy (ofiles[fd]->path, filename, len);
1853 ofiles[fd]->ticket = ticket;
1854 ofiles[fd]->fd = fd;
1855
1856 SL_IRETURN(ticket, _("sl_open_file"));
1857}
1858
1859static
1860int check_fname_priv (const char * fname, int priv)
1861{
1862 SL_ENTER(_("check_fname_priv"));
1863 if (fname == NULL)
1864 SL_IRETURN(SL_ENULL, _("check_fname_priv"));
1865 if (priv != SL_YESPRIV && priv != SL_NOPRIV)
1866 SL_IRETURN(SL_EINTERNAL, _("check_fname_priv"));
1867 SL_IRETURN(SL_ENONE, _("check_fname_priv"));
1868}
1869
1870SL_TICKET sl_open_write (const char * fname, int priv)
1871{
1872 long status;
1873 SL_ENTER(_("sl_open_write"));
1874
1875 if (SL_ENONE != (status = check_fname_priv (fname, priv)))
1876 SL_IRETURN(status, _("sl_open_write"));
1877
1878 status = sl_open_file(fname, SL_OPEN_FOR_WRITE, priv);
1879 SL_IRETURN(status, _("sl_open_write"));
1880}
1881
1882SL_TICKET sl_open_read (const char * fname, int priv)
1883{
1884 long status;
1885 SL_ENTER(_("sl_open_read"));
1886
1887 if (SL_ENONE != (status = check_fname_priv (fname, priv)))
1888 {
1889 TPT(( 0, FIL__, __LINE__,
1890 _("msg=<Error in check_fname_priv.> status=<%ld>\n"),
1891 status));
1892 SL_IRETURN(status, _("sl_open_read"));
1893 }
1894
1895 status = sl_open_file(fname, SL_OPEN_FOR_READ, priv);
1896 SL_IRETURN(status, _("sl_open_read"));
1897}
1898
1899SL_TICKET sl_open_fastread (const char * fname, int priv)
1900{
1901 long status;
1902 SL_ENTER(_("sl_open_fastread"));
1903
1904 if (SL_ENONE != (status = check_fname_priv (fname, priv)))
1905 SL_IRETURN(status, _("sl_open_read"));
1906
1907 status = sl_open_file(fname, SL_OPEN_FOR_FASTREAD, priv);
1908 SL_IRETURN(status, _("sl_open_fastread"));
1909}
1910
1911SL_TICKET sl_open_rdwr (const char * fname, int priv)
1912{
1913 long status;
1914 SL_ENTER(_("sl_open_rdwr"));
1915
1916 if (SL_ENONE != (status = check_fname_priv (fname, priv)))
1917 SL_IRETURN(status, _("sl_open_rdwr"));
1918
1919 status = sl_open_file(fname, SL_OPEN_FOR_RDWR, priv);
1920 SL_IRETURN(status, _("sl_open_rdwr"));
1921}
1922
1923SL_TICKET sl_open_safe_rdwr (const char * fname, int priv)
1924{
1925 long status;
1926 SL_ENTER(_("sl_open_safe_rdwr"));
1927
1928 if (SL_ENONE != (status = check_fname_priv (fname, priv)))
1929 SL_IRETURN(status, _("sl_open_safe_rdwr"));
1930
1931 status = sl_open_file(fname, SL_OPEN_SAFE_RDWR, priv);
1932 SL_IRETURN(status, _("sl_open_safe_rdwr"));
1933}
1934
1935SL_TICKET sl_open_write_trunc (const char * fname, int priv)
1936{
1937 long status;
1938 SL_ENTER(_("sl_open_write_trunc"));
1939
1940 if (SL_ENONE != (status = check_fname_priv (fname, priv)))
1941 SL_IRETURN(status, _("sl_open_write_trunc"));
1942
1943 status = sl_open_file(fname, SL_OPEN_FOR_WTRUNC, priv);
1944 SL_IRETURN(status, _("sl_open_write_trunc"));
1945}
1946
1947SL_TICKET sl_open_rdwr_trunc (const char * fname, int priv)
1948{
1949 long status;
1950 SL_ENTER(_("sl_open_rdwr_trunc"));
1951
1952 if (SL_ENONE != (status = check_fname_priv (fname, priv)))
1953 SL_IRETURN(status, _("sl_open_rdwr_trunc"));
1954
1955 status = sl_open_file(fname, SL_OPEN_FOR_RWTRUNC, priv);
1956 SL_IRETURN(status, _("sl_open_rdwr_trunc"));
1957}
1958
1959
1960int get_the_fd (SL_TICKET ticket)
1961{
1962 int fd;
1963
1964 if (SL_ISERROR(fd = sl_read_ticket(ticket)))
1965 return (fd);
1966
1967 if (ofiles[fd] == NULL || fd != ofiles[fd]->fd || fd < 0)
1968 return (SL_EINTERNAL);
1969 return (fd);
1970}
1971
1972int sl_close (SL_TICKET ticket)
1973{
1974 register int fd;
1975
1976 SL_ENTER(_("sl_close"));
1977
1978 if (SL_ISERROR(fd = get_the_fd (ticket)))
1979 SL_IRETURN(fd, _("sl_close"));
1980
1981 /* This may fail, but what to do then ?
1982 */
1983 if (0 != close(fd) && ofiles[fd] != NULL)
1984 {
1985 TPT((0, FIL__, __LINE__,
1986 _("msg=<Error closing file.>, path=<%s>, fd=<%d>, err=<%s>\n"),
1987 ofiles[fd]->path, fd, strerror(errno)));
1988 }
1989
1990 if (ofiles[fd] != NULL)
1991 {
1992 (void) free(ofiles[fd]->path);
1993 (void) free(ofiles[fd]);
1994 ofiles[fd] = NULL;
1995 }
1996
1997 SL_IRETURN(SL_ENONE, _("sl_close"));
1998}
1999
2000int sl_dropall(int fd, int except)
2001{
2002 while (fd < MAXFD)
2003 {
2004 if (ofiles[fd] != NULL && fd != except)
2005 {
2006 if (ofiles[fd]->path != NULL)
2007 (void) free(ofiles[fd]->path);
2008 (void) free(ofiles[fd]);
2009 ofiles[fd] = NULL;
2010 }
2011 ++fd;
2012 }
2013 return 0;
2014}
2015
2016
2017int sl_unlink (SL_TICKET ticket)
2018{
2019 register int fd;
2020
2021 SL_ENTER(_("sl_unlink"));
2022
2023 if (SL_ISERROR(fd = get_the_fd(ticket)))
2024 SL_IRETURN(fd, _("sl_unlink"));
2025
2026 if (retry_aud_unlink(FIL__, __LINE__, ofiles[fd]->path) < 0)
2027 SL_IRETURN(SL_EUNLINK, _("sl_unlink"));
2028
2029 SL_IRETURN(SL_ENONE, _("sl_unlink"));
2030}
2031
2032
2033int sl_seek (SL_TICKET ticket, off_t off_data)
2034{
2035 register int fd;
2036
2037 SL_ENTER(_("sl_seek"));
2038
2039 if (SL_ISERROR(fd = get_the_fd(ticket)))
2040 SL_IRETURN(fd, _("sl_seek"));
2041
2042 if (lseek(fd, off_data, SEEK_SET) == (off_t)-1)
2043 SL_IRETURN(SL_EREWIND, _("sl_seek"));
2044
2045 SL_IRETURN(SL_ENONE, _("sl_seek"));
2046}
2047
2048int sl_rewind (SL_TICKET ticket)
2049{
2050 register int fd;
2051
2052 SL_ENTER(_("sl_rewind"));
2053
2054 if (SL_ISERROR(fd = get_the_fd(ticket)))
2055 SL_IRETURN(fd, _("sl_rewind"));
2056
2057 if (lseek (fd, 0L, SEEK_SET) == (off_t)-1)
2058 SL_IRETURN(SL_EREWIND, _("sl_rewind"));
2059
2060 SL_IRETURN(SL_ENONE, _("sl_rewind"));
2061}
2062
2063int sl_forward (SL_TICKET ticket)
2064{
2065 register int fd;
2066
2067 SL_ENTER(_("sl_forward"));
2068
2069 if (SL_ISERROR(fd = get_the_fd(ticket)))
2070 SL_IRETURN(fd, _("sl_forward"));
2071
2072 if (lseek (fd, 0L, SEEK_END) == (off_t)-1)
2073 SL_IRETURN(SL_EFORWARD, _("sl_forward"));
2074
2075 SL_IRETURN(SL_ENONE, _("sl_forward"));
2076}
2077
2078
2079int sl_sync (SL_TICKET ticket)
2080{
2081 register int fd;
2082
2083 SL_ENTER(_("sl_sync"));
2084
2085 if (SL_ISERROR(fd = get_the_fd(ticket)))
2086 SL_IRETURN(fd, _("sl_sync"));
2087
2088 if (fsync (fd) == -1)
2089 SL_IRETURN(SL_ESYNC, _("sl_sync"));
2090
2091 SL_IRETURN(SL_ENONE, _("sl_sync"));
2092}
2093
2094int sl_read_timeout_prep (SL_TICKET ticket)
2095{
2096 int fd;
2097 int sflags;
2098
2099 SL_ENTER(_("sl_read_timeout_prep"));
2100
2101 if (SL_ISERROR(fd = get_the_fd(ticket)))
2102 {
2103 TPT(( 0, FIL__, __LINE__, _("msg=<ticket error> errno=<%d>"), fd));
2104 SL_IRETURN(fd, _("sl_read_timeout_prep"));
2105 }
2106
2107 /* set to non-blocking mode
2108 */
2109 sflags = retry_fcntl(FIL__, __LINE__, fd, F_GETFL, 0);
2110 retry_fcntl(FIL__, __LINE__, fd, F_SETFL, sflags | O_NONBLOCK);
2111
2112 SL_IRETURN(SL_ENONE, _("sl_read_timeout_prep"));
2113}
2114
2115
2116int sl_read_timeout (SL_TICKET ticket, void * buf_in, size_t count,
2117 int timeout)
2118{
2119 fd_set readfds;
2120 struct timeval tv;
2121 /* int sflags; */
2122 int retval;
2123
2124 int fd;
2125 int byteread = 0;
2126 int bytes = 0;
2127 char * buf;
2128
2129 time_t tnow;
2130 time_t tstart;
2131 time_t tdiff;
2132 extern volatile int sig_termfast;
2133
2134 if (buf_in == NULL || SL_ISERROR(fd = get_the_fd(ticket)))
2135 {
2136 if (buf_in == NULL)
2137 {
2138 TPT(( 0, FIL__, __LINE__, _("msg=<null buffer>")));
2139 return (SL_ENULL);
2140 }
2141 if (SL_ISERROR(fd = get_the_fd(ticket)))
2142 {
2143 TPT(( 0, FIL__, __LINE__, _("msg=<ticket error> errno=<%d>"), fd));
2144 return (fd);
2145 }
2146 }
2147
2148 buf = (char *) buf_in;
2149
2150 tstart = time(NULL);
2151 tdiff = 0;
2152
2153 while (count > 0)
2154 {
2155 FD_ZERO(&readfds);
2156 FD_SET(fd, &readfds);
2157
2158 tv.tv_sec = timeout - tdiff;
2159 tv.tv_usec = 0;
2160
2161 retval = select (fd+1, &readfds, NULL, NULL, &tv);
2162
2163 if (retval > 0)
2164 {
2165 byteread = read (fd, buf, count);
2166
2167 if (byteread > 0)
2168 {
2169 bytes += byteread; count -= byteread;
2170 buf += byteread;
2171 if (count == 0)
2172 break;
2173 }
2174 else if (byteread == 0)
2175 {
2176 break;
2177 }
2178 else
2179 {
2180 if (errno == EINTR || errno == EAGAIN)
2181 {
2182 retry_msleep(1, 0);
2183 tnow = time(NULL);
2184 tdiff = tnow - tstart;
2185 continue;
2186 }
2187 else
2188 {
2189 return (SL_EREAD);
2190 }
2191 }
2192 }
2193 else if ((retval == -1) && (errno == EINTR || errno == EAGAIN))
2194 {
2195 retry_msleep(1, 0);
2196 tnow = time(NULL);
2197 tdiff = tnow - tstart;
2198 continue;
2199 }
2200 else if (retval == 0)
2201 {
2202 return (SL_TIMEOUT);
2203 }
2204 else
2205 {
2206 return (SL_EREAD);
2207 }
2208
2209 if (sig_termfast == 1)
2210 {
2211 return (SL_EREAD);
2212 }
2213
2214 tnow = time(NULL);
2215 tdiff = tnow - tstart;
2216
2217 if (tdiff > timeout)
2218 {
2219 return (SL_TIMEOUT);
2220 }
2221 }
2222
2223 return ((int) bytes);
2224}
2225
2226
2227int sl_read (SL_TICKET ticket, void * buf_in, size_t count)
2228{
2229 int fd;
2230 int byteread = 0;
2231 int bytes = 0;
2232
2233 char * buf;
2234
2235 if (count < 1)
2236 {
2237 TPT(( 0, FIL__, __LINE__, _("msg=<range error>")));
2238 return(SL_ERANGE);
2239 }
2240 if (buf_in == NULL)
2241 {
2242 TPT(( 0, FIL__, __LINE__, _("msg=<null buffer>")));
2243 return (SL_ENULL);
2244 }
2245
2246 if (SL_ISERROR(fd = get_the_fd(ticket)))
2247 {
2248 TPT(( 0, FIL__, __LINE__, _("msg=<ticket error> errno=<%d>"), fd));
2249 return (fd);
2250 }
2251
2252 buf = (char *) buf_in;
2253
2254 do
2255 {
2256 byteread = read (fd, buf, count);
2257 if (byteread > 0)
2258 {
2259 bytes += byteread; count -= byteread;
2260 buf += byteread;
2261 }
2262 } while ( byteread > 0 ||
2263 ( byteread == -1 && (errno == EINTR || errno == EAGAIN))
2264 );
2265
2266
2267 if (byteread == (-1))
2268 {
2269 TPT(( 0, FIL__, __LINE__, _("msg=<read error> errno=<%d>\n"), errno));
2270 return (SL_EREAD);
2271 }
2272 return (bytes);
2273}
2274
2275int sl_read_fast (SL_TICKET ticket, void * buf_in, size_t count)
2276{
2277 int fd;
2278 int byteread = 0;
2279
2280 char * buf;
2281
2282 if (count < 1)
2283 {
2284 TPT(( 0, FIL__, __LINE__, _("msg=<range error>")));
2285 return(SL_ERANGE);
2286 }
2287 if (buf_in == NULL)
2288 {
2289 TPT(( 0, FIL__, __LINE__, _("msg=<null buffer>")));
2290 return (SL_ENULL);
2291 }
2292
2293 if (SL_ISERROR(fd = get_the_fd(ticket)))
2294 {
2295 TPT(( 0, FIL__, __LINE__, _("msg=<ticket error> errno=<%d>"), fd));
2296 return (fd);
2297 }
2298
2299 buf = (char *) buf_in;
2300
2301 do
2302 {
2303 byteread = read (fd, buf, count);
2304 if (byteread >= 0)
2305 {
2306 return (byteread);
2307 }
2308 } while ( byteread == -1 && (errno == EINTR || errno == EAGAIN));
2309
2310
2311 if (byteread == (-1))
2312 {
2313 TPT(( 0, FIL__, __LINE__, _("msg=<read error> errno=<%d>\n"), errno));
2314 return (SL_EREAD);
2315 }
2316 return (0);
2317}
2318
2319
2320int sl_write (SL_TICKET ticket, void * msg_in, long nbytes)
2321{
2322 long bytewritten;
2323 long bytecount;
2324 int fd;
2325
2326 char * msg;
2327
2328 SL_ENTER(_("sl_write"));
2329
2330 if (nbytes < 1)
2331 SL_IRETURN(SL_ERANGE, _("sl_write"));
2332 if (msg_in == NULL)
2333 SL_IRETURN(SL_ENULL, _("sl_write"));
2334 if (SL_ISERROR(fd = get_the_fd(ticket)))
2335 SL_IRETURN(fd, _("sl_write"));
2336
2337 msg = (char *) msg_in;
2338
2339 /* write
2340 */
2341 bytecount = 0;
2342 bytewritten = 0;
2343 while (bytecount < nbytes)
2344 {
2345 if ((bytewritten = write (fd, msg, nbytes-bytecount)) > 0)
2346 {
2347 bytecount += bytewritten;
2348 msg += bytewritten; /* move buffer pointer forward */
2349 }
2350 else if (bytewritten <= 0)
2351 {
2352 if ( errno == EINTR || errno == EAGAIN) /* try again */
2353 continue;
2354 else
2355 SL_IRETURN(SL_EWRITE, _("sl_write"));
2356 }
2357 }
2358 SL_IRETURN(SL_ENONE, _("sl_write"));
2359}
2360
2361int sl_write_line (SL_TICKET ticket, void * msg, long nbytes)
2362{
2363 int status;
2364
2365 SL_ENTER(_("sl_write_line"));
2366
2367 status = sl_write(ticket, msg, nbytes);
2368 if (!SL_ISERROR(status))
2369 status = sl_write(ticket, "\n", 1);
2370
2371 SL_IRETURN(status, _("sl_write_line"));
2372}
2373
2374
2375/* ----------------------------------------------------------------
2376 *
2377 * Trustfile interface
2378 *
2379 * ---------------------------------------------------------------- */
2380
2381extern uid_t rootonly[];
2382extern int EUIDSLOT;
2383extern int ORIG_EUIDSLOT;
2384
2385extern char tf_path[MAXFILENAME]; /* Error path for trust function. */
2386extern uid_t tf_euid; /* Space for EUID of process. */
2387
2388
2389char * sl_error_string(int errorcode)
2390{
2391 switch (errorcode)
2392 {
2393 case SL_EBOGUS:
2394 return _("Bogus file. Modified during access.");
2395 case SL_EWRITE:
2396 return _("Write error.");
2397 case SL_EREAD:
2398 return _("Read error.");
2399 case SL_ESYNC:
2400 return _("Error in fsync().");
2401 case SL_EFORWARD:
2402 return _("Error in lseek().");
2403 case SL_EREWIND:
2404 return _("Error in lseek().");
2405 case SL_EUNLINK:
2406 return _("Error in unlink().");
2407 case SL_EMEM:
2408 return _("Out of memory.");
2409 case SL_EINTERNAL:
2410 return _("Internal error.");
2411 case SL_ETICKET:
2412 return _("Bad ticket.");
2413 case SL_EREPEAT:
2414 return _("Illegal repeated use of function.");
2415 case SL_ERANGE:
2416 return _("Argument out of range.");
2417 case SL_ENULL:
2418 return _("Dereferenced NULL pointer.");
2419
2420 case SL_EBADUID:
2421 return _("Owner not trustworthy.");
2422 case SL_EBADGID:
2423 return _("Group writeable and member not trustworthy.");
2424 case SL_EBADOTH:
2425 return _("World writeable.");
2426 case SL_EBADFILE:
2427 return _("File access error.");
2428 case SL_EBADNAME:
2429 return _("Invalid filename (prob. too long or null).");
2430
2431 case SL_ETRUNC:
2432 return _("Truncation occured.");
2433 case SL_ESTAT:
2434 return _("stat() failed.");
2435 default:
2436 return _("Unknown error.");
2437 }
2438}
2439
2440
2441
2442char * sl_trust_errfile()
2443{
2444 return &tf_path[0];
2445}
2446
2447extern uid_t tf_baduid;
2448uid_t sl_trust_baduid()
2449{
2450 return tf_baduid;
2451}
2452
2453extern gid_t tf_badgid;
2454gid_t sl_trust_badgid()
2455{
2456 return tf_badgid;
2457}
2458
2459
2460static int trust_count = 0;
2461
2462int sl_trust_purge_user ()
2463{
2464 int i;
2465
2466 EUIDSLOT = ORIG_EUIDSLOT;
2467 trust_count = 0;
2468
2469 for (i = EUIDSLOT; i < (EUIDSLOT + 15); ++i)
2470 rootonly[i] = sh_uid_neg;
2471 return 0;
2472}
2473
2474int sl_trust_add_user (uid_t pwid)
2475{
2476 SL_ENTER(_("sl_trust_add_user"));
2477
2478 if (trust_count == 15)
2479 SL_IRETURN(SL_ERANGE, _("sl_trust_add_user"));
2480
2481 rootonly[EUIDSLOT] = pwid;
2482 ++EUIDSLOT;
2483 ++trust_count;
2484
2485 SL_IRETURN(SL_ENONE, _("sl_trust_add_user"));
2486}
2487
2488int sl_trustfile_euid(char * filename, uid_t teuid)
2489{
2490 long status;
2491 SL_ENTER(_("sl_trustfile_euid"));
2492
2493 tf_path[0] = '\0';
2494 if (filename == NULL || filename[0] == '\0')
2495 SL_IRETURN(SL_EBADNAME, _("sl_trustfile_euid"));
2496
2497 tf_euid = teuid;
2498 status = sl_trustfile(filename, NULL, NULL);
2499 SL_IRETURN(status, _("sl_trustfile_euid"));
2500}
2501
2502/* ----------------------------------------------------------------
2503 *
2504 * Overflow tests
2505 *
2506 * ---------------------------------------------------------------- */
2507
2508int sl_ok_muli (int a, int b) /* a*b */
2509{
2510 if (a >= (INT_MIN / b) && a <= (INT_MAX / b))
2511 return SL_TRUE; /* no overflow */
2512 return SL_FALSE;
2513}
2514
2515int sl_ok_divi (int a, int b) /* a/b */
2516{
2517 (void) a;
2518 if (b != 0)
2519 return SL_TRUE; /* no overflow */
2520 return SL_FALSE;
2521}
2522
2523int sl_ok_addi (int a, int b) /* a+b */
2524{
2525 if (a >= 0 && b >= 0)
2526 {
2527 if (a <= (INT_MAX - b))
2528 return SL_TRUE; /* no overflow */
2529 else
2530 return SL_FALSE;
2531 }
2532 else if (a < 0 && b < 0)
2533 {
2534 if (a >= (INT_MIN - b))
2535 return SL_TRUE; /* no overflow */
2536 else
2537 return SL_FALSE;
2538 }
2539 return SL_TRUE;
2540}
2541
2542int sl_ok_subi (int a, int b) /* a-b */
2543{
2544 if (a >= 0 && b < 0)
2545 {
2546 if (a <= (INT_MAX + b))
2547 return SL_TRUE; /* no overflow */
2548 else
2549 return SL_FALSE;
2550 }
2551 else if (a < 0 && b >= 0)
2552 {
2553 if (a >= (INT_MIN + b))
2554 return SL_TRUE; /* no overflow */
2555 else
2556 return SL_FALSE;
2557 }
2558 return SL_TRUE;
2559}
Note: See TracBrowser for help on using the repository browser.