source: trunk/src/slib.c@ 6

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

Fixed a stupid bug in sh_files.c; released as 2.1.1a

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