1 /* --------------------------------------------------------------
2  *
3  * The developement of this library has been stimulated by reading
4  * a paper on 'Robust Programming' by Matt Bishop, although
5  * not all of his ideas might be implemented in the same
6  * strictness as discussed in the paper.
7  *
8  * --------------------------------------------------------------
9  */
10 
11 #ifndef SL_SLIB_H
12 #define SL_SLIB_H
13 
14 #include <errno.h>
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <stdarg.h>
18 #include <sys/types.h>
19 
20 #include "config_xor.h"
21 
22 #ifdef HAVE_UNISTD_H
23 #include <unistd.h>
24 #endif
25 
26 #include "sh_string.h"
27 
28 /****************
29 
30 		 -- Defined in config.h. --
31 
32 		 #ifndef _(string)
33 		 #define _(string) string
34 		 #endif
35 
36 		 #ifndef N_(string)
37 		 #define N_(string) string
38 		 #endif
39 
40 *****************/
41 
42 
43 /* --------------------------------------------------------------
44  *
45  * Typedefs, global variables, macros.
46  *
47  * --------------------------------------------------------------
48  */
49 
50 extern  long int sl_errno;              /* Global error variable.         */
51 
52 
53 /* The ticketing system; used to hide internals from the
54  * programmer.
55  */
56 typedef long int SL_TICKET;             /* Unique ID for opened files.    */
57 
58 
59 /*
60  * TRUE, FALSE
61  */
62 #if !defined(S_TRUE)
63 #define S_TRUE  1
64 #define S_FALSE 0
65 #endif
66 
67 #define SH_GRBUF_SIZE   4096
68 #define SH_PWBUF_SIZE  32768
69 
70 
71 #if defined(__GNUC__) && (__GNUC__ >= 3)
72 #undef  SL_GNUC_CONST
73 #define SL_GNUC_CONST   __attribute__((const))
74 #else
75 #undef  SL_GNUC_CONST
76 #define SL_GNUC_CONST
77 #endif
78 
79 /*
80  *  The following macros are provided:
81  *
82  *  SL_ISERROR(x)       TRUE if return status of 'x' is an error code.
83  *  SL_REQUIRE(x, xstr) Abort if 'x' is false.
84  *  SL_ENTER(s)         Trace entry in    function 's'.
85  *  SL_RETURN(x, s)     Trace return from function 's'.
86  */
87 
88 
89 /*
90  * The error codes.
91  */
92 #define SL_ENONE         0
93 
94 #define SL_ENULL     -1024     /* Invalid use of NULL pointer.         */
95 #define SL_ERANGE    -1025     /* Argument out of range.               */
96 #define SL_ETRUNC    -1026     /* Result truncated.                    */
97 #define SL_EREPEAT   -1027     /* Illegal repeated use of function.    */
98 
99 #define SL_EINTERNAL -1028     /* Internal error.                      */
100 #define SL_ETICKET   -1029     /* Bad ticket.                          */
101 #define SL_EBADFILE  -1030     /* File access error. Check errno.      */
102 #define SL_EBOGUS    -1031     /* Bogus file.                          */
103 #define SL_EMEM      -1032     /* Out of memory.                       */
104 #define SL_EUNLINK   -1033     /* Unlink error. Check errno.           */
105 #define SL_EREWIND   -1034     /* Rewind error. Check errno.           */
106 #define SL_EFORWARD  -1035     /* Forward error. Check errno.          */
107 #define SL_EREAD     -1036     /* Read error. Check errno.             */
108 #define SL_EWRITE    -1037     /* Write error. Check errno.            */
109 #define SL_ESYNC     -1038     /* Write error. Check errno.            */
110 #define SL_ECLOSE    -1039     /* Close error. Check errno.            */
111 
112 #define SL_EBADNAME  -1040     /* Invalid name.                        */
113 #define SL_ESTAT     -1041     /* stat of file failed. Check errno.    */
114 #define SL_EFSTAT    -1042     /* fstat of file failed. Check errno.   */
115 
116 #define SL_EBADUID   -1050	/* Owner not trustworthy.              */
117 #define SL_EBADGID   -1051	/* Group writeable and not trustworthy.*/
118 #define SL_EBADOTH   -1052	/* World writeable.                    */
119 
120 #define SL_TOOMANY   -1053      /* Too many open files                 */
121 #define SL_TIMEOUT   -1054      /* Timeout in read                     */
122 
123 #define SL_EISDIR    -1055      /* Is a directory                      */
124 
125 #define SL_EINTERNAL01 -1061    /* Internal error.                      */
126 #define SL_EINTERNAL02 -1062    /* Internal error.                      */
127 #define SL_EINTERNAL03 -1063    /* Internal error.                      */
128 #define SL_EINTERNAL04 -1064    /* Internal error.                      */
129 #define SL_EINTERNAL05 -1065    /* Internal error.                      */
130 #define SL_EINTERNAL06 -1066    /* Internal error.                      */
131 #define SL_EINTERNAL07 -1067    /* Internal error.                      */
132 #define SL_EINTERNAL08 -1068    /* Internal error.                      */
133 #define SL_EINTERNAL09 -1069    /* Internal error.                      */
134 #define SL_EINTERNAL10 -1070    /* Internal error.                      */
135 #define SL_EINTERNAL11 -1071    /* Internal error.                      */
136 #define SL_EINTERNAL12 -1072    /* Internal error.                      */
137 
138 /*
139  * All int functions return SL_NONE on success.
140  */
141 
142 #ifdef  __cplusplus
143 extern "C" {
144 #endif
145 
146   int dlog (int flag, const char * file, int line, const char *fmt, ...);
147 
148   char * sl_get_errmsg(void);
149 
150   /* ----------------------------------------------------------------
151    *
152    *    Heap consistency routines
153    *
154    * ---------------------------------------------------------------- */
155 
156   int sl_test_heap(void);
157 
158   /* ----------------------------------------------------------------
159    *
160    *    Capability routines
161    *
162    * ---------------------------------------------------------------- */
163 
164   extern int sl_useCaps;
165 
166   int sl_drop_cap (void);
167   int sl_drop_cap_sub(void);
168   int sl_get_cap_sub(void);
169   int sl_drop_cap_qdel(void);
170   int sl_get_cap_qdel(void);
171 
172   /* ----------------------------------------------------------------
173    *
174    *    String handling routines
175    *
176    * ---------------------------------------------------------------- */
177 
178   /*
179    * A memset that does not get optimized away
180    */
181   void *sl_memset(void *s, int c, size_t n);
182 #if !defined(SH_REAL_SET)
183 #undef  memset
184 #define memset sl_memset
185 #endif
186 
187   /*
188    * Copy src to dst. siz is the length of dst.
189    */
190   int sl_strlcpy(char * dst, /*@null@*/const char * src, size_t siz);
191 
192   /*
193    * Append src to dst. siz is the length of dst.
194    */
195   int sl_strlcat(char * dst, /*@null@*/const char *src,  size_t siz);
196 
197   /*
198    * An implementation of vsnprintf. va_start/va_end are in the caller
199    * function.
200    */
201   int sl_vsnprintf(char *str, size_t n,
202 		   const char *format, va_list vl );
203 
204   /*
205    * An implementation of snprintf.
206    */
207   int sl_snprintf(char *str, size_t n,
208 		  const char *format, ... );
209 
210   /*
211    * A robust drop-in replacement of strncpy. strlcpy is preferable.
212    */
213   char * sl_strncpy(/*@out@*/char *dst, const char *src, size_t size);
214 
215   /*
216    * Robust strncat.
217    */
218   char * sl_strncat(char *dst, const char *src, size_t n);
219 
220   /*
221    * strstr
222    */
223   char * sl_strstr (const char * haystack, const char * needle);
224 
225   /*
226    * robust strn[case]cmp replacement
227    */
228   int sl_strncmp(const char * a, const char * b, size_t n);
229   int sl_ts_strncmp(const char * a, const char * b, size_t n);
230 
231   int sl_strncasecmp(const char * a, const char * b, size_t n);
232 
233   /*
234    * robust strcmp replacement
235    */
236   int sl_strcmp(const char * a, const char * b);
237 
238   /*
239    * robust strcasecmp replacement
240    */
241   int sl_strcasecmp(const char * one, const char * two);
242 
243   /*
244    * robust strlen replacement
245    */
246 #define sl_strlen(arg) ((arg == NULL) ? 0 : (strlen(arg)))
247 
248   /* ----------------------------------------------------------------
249    *
250    *    Privilege handling routines
251    *
252    * ---------------------------------------------------------------- */
253 
254   /*
255    * ONE OF THE FOLLOWING THREE FUNCTIONS
256    * SHOULD BE CALLED BEFORE ANY OTHER OF THE
257    * UID HANDLING FUNCTIONS.
258    */
259   int sl_policy_get_user(const char *username);  /* drop SUID to <username>  */
260   int sl_policy_get_real(char *username);  /* drop privs to <username> */
261   int sl_policy_get_root(void);            /* drop SUID to root        */
262 
263   /*
264    * If not using one of the above, use this function,
265    * and then call sh_unset_suid().
266    * This function saves the uid's.
267    * It calls abort() on error.
268    */
269   int sl_save_uids(void);
270 
271   /*
272    * This function returns the saved euid.
273    * It calls abort() if the uid's are not saved already.
274    */
275   int sl_get_euid(/*@out@*/uid_t * ret);
276   uid_t sl_ret_euid(void);
277 
278   /*
279    * This function returns the saved egid.
280    * It calls abort() if the uid's are not saved already.
281    */
282   int sl_get_egid(/*@out@*/gid_t * ret);
283 
284   /*
285    * This function returns the saved current ruid.
286    * It calls abort() if the uid's are not saved already.
287    */
288   int sl_get_ruid(/*@out@*/uid_t * ret);
289 
290   /*
291    * This function returns the saved current rgid.
292    * It calls abort() if the uid's are not saved already.
293    */
294   int sl_get_rgid(gid_t * ret);
295 
296   /*
297    * This function returns the saved original ruid.
298    * It calls abort() if the uid's are not saved already.
299    */
300   int sl_get_ruid_orig(uid_t * ret);
301 
302   /*
303    * This function returns the saved original rgid.
304    * It calls abort() if the uid's are not saved already.
305    */
306   int sl_get_rgid_orig(gid_t * ret);
307 
308   /*
309    * This function returns true if the program is SUID.
310    * It calls abort() if the uid's are not saved already.
311    */
312   int sl_is_suid(void);
313 
314   /*
315    * This function sets the effective uid
316    * to the saved effective uid.
317    */
318   int sl_set_suid (void);
319 
320   /*
321    * This function sets the effective uid to the real uid.
322    */
323   int sl_unset_suid (void);
324 
325   /*
326    * This function drops SUID privileges irrevocably.
327    */
328   int sl_drop_privileges(void);
329 
330   /* ----------------------------------------------------------------
331    *
332    *    File handling routines
333    *
334    * ---------------------------------------------------------------- */
335 
336 #define SL_OFILE_SIZE 32
337 
338   char * sl_check_badfd();
339   char * sl_check_stale();
340 
341   /* Create a file record for an open file
342    */
343   SL_TICKET sl_make_ticket (const char * ofile, int oline,
344 			    int fd, const char * filename, FILE * stream);
345 
346   /* Get the pointer to a stream. If none exists yet, open it
347    */
348   FILE * sl_stream (SL_TICKET ticket, char * mode);
349 
350   /* Open for writing.
351    */
352   SL_TICKET  sl_open_write       (const char * ofile, int oline,
353 				  const char * fname, int priviledge_mode);
354 
355   /* Open for reading.
356    */
357   SL_TICKET  sl_open_read        (const char * ofile, int oline,
358 				  const char * fname, int priviledge_mode);
359 
360   /* Drop from cach when closing
361    */
362   int sl_set_drop_cache(const char * str);
363 
364   /* Open for reading w/minimum checking.
365    */
366   SL_TICKET  sl_open_fastread    (const char * ofile, int oline,
367 				  const char * fname, int priviledge_mode);
368 
369   /* Open for read and write.
370    */
371   SL_TICKET  sl_open_rdwr        (const char * ofile, int oline,
372 				  const char * fname, int priviledge_mode);
373 
374   /* Open for read and write, fail if file exists.
375    */
376   SL_TICKET sl_open_safe_rdwr    (const char * ofile, int oline,
377 				  const char * fname, int priv);
378 
379   /* Open for write, truncate.
380    */
381   SL_TICKET  sl_open_write_trunc (const char * ofile, int oline,
382 				  const char * fname, int priviledge_mode);
383 
384   /* Open for read and write, truncate.
385    */
386   SL_TICKET  sl_open_rdwr_trunc  (const char * ofile, int oline,
387 				  const char * fname, int priviledge_mode);
388 
389   /* Initialize the content sh_string.
390    */
391   int sl_init_content (SL_TICKET ticket, size_t size);
392 
393   /* Get the (pointer to) the content sh_string.
394    */
395   sh_string * sl_get_content (SL_TICKET ticket);
396 
397   /* Lock file (uses fcntl F_SETLK).
398    */
399   int sl_lock (SL_TICKET ticket);
400 
401   /* Close file.
402    */
403   int sl_close (SL_TICKET ticket);
404 
405   /* Close file descriptor.
406    */
407   int sl_close_fd (const char * file, int line, int fd);
408 
409   /* Close stream.
410    */
411   int sl_fclose (const char * file, int line, FILE * fp);
412 
413   /* Unlink file.
414    */
415   int sl_unlink (SL_TICKET ticket);
416 
417   /* Rewind file.
418    */
419   int sl_rewind (SL_TICKET ticket);
420 
421   /* Seek file.
422    */
423   int sl_seek (SL_TICKET ticket, off_t off_data);
424 
425   /* Forward file.
426    */
427   int sl_forward (SL_TICKET ticket);
428 
429   /* Sync file.
430    */
431   int sl_sync (SL_TICKET ticket);
432 
433   /* Read file.
434    */
435   int sl_read (SL_TICKET ticket, void * buf, size_t count);
436 
437   int sl_read_timeout_prep (SL_TICKET ticket);
438 
439   int sl_read_timeout_fd (int fd, void * buf,
440 			  size_t count, int timeout, int is_nonblocking);
441 
442   int sl_read_timeout (SL_TICKET ticket, void * buf,
443 		       size_t count, int timeout, int is_nonblocking);
444 
445   int sl_read_fast (SL_TICKET ticket, void * buf_in, size_t count);
446 
447   /* Write file.
448    */
449   int sl_write (SL_TICKET ticket, const void * msg, long nbytes);
450 
451   /* Write file, terminate with newline.
452    */
453   int sl_write_line (SL_TICKET ticket, const void * msg, long nbytes);
454 
455   /* As above, but only for non-constant strings.
456    */
457   int sl_write_line_fast (SL_TICKET ticket, void * msg, long nbytes);
458 
459   /* Drop all metadata for file descriptors >= fd.
460    */
461   int sl_dropall(int fd, int except);
462   int sl_dropall_dirty(int fd, int except); /* don't deallocate */
463 
464   /* Check whether file is trustworthy.
465    */
466   int sl_trustfile(const char * path, uid_t * ok, uid_t * bad);
467 
468   /* Check whether file is trustworthy.
469    */
470   int sl_trustfile_euid(const char * filename, uid_t euid);
471 
472   /* purge list of trusted users
473    */
474   int  sl_trust_purge_user (void);
475 
476   /* Add a trusted user.
477    */
478   int  sl_trust_add_user (uid_t pwid);
479 
480   /* Get error string.
481    */
482   char * sl_error_string(int errorcode);
483 
484   /* Get error file.
485    */
486   char * sl_trust_errfile(void);
487 
488   /* Overflow tests
489    */
490   int sl_ok_muli (int a, int b) SL_GNUC_CONST;
491   int sl_ok_divi (int a, int b) SL_GNUC_CONST;
492   int sl_ok_addi (int a, int b) SL_GNUC_CONST;
493   int sl_ok_subi (int a, int b) SL_GNUC_CONST;
494 
495   int sl_ok_muls (size_t a, size_t b) SL_GNUC_CONST;
496   int sl_ok_adds (size_t a, size_t b) SL_GNUC_CONST;
497 
498 
499 #ifdef  __cplusplus
500 }
501 #endif
502 
503 /* Privilege modes for file access.
504  */
505 #define SL_YESPRIV 0x33
506 #define SL_NOPRIV  0x34
507 
508 /* Suitable for Linux
509  */
510 #define MAXFILENAME	4096
511 
512 
513 /*
514  * This macro is TRUE if (x) < 0.
515  */
516 #define SL_ISERROR(x) ((long)(x) < 0)
517 
518 #if defined(WITH_TPT)
519 #define TPT(arg) dlog arg ;
520 #else
521 #define TPT(arg)
522 #endif
523 
524 
525 /*
526  * The 'require' macro.
527  */
528 #define SL_REQUIRE(assertion, astext)                  \
529 do {                                                   \
530     /*@i@*/ if (assertion) ;                           \
531     else {                                             \
532         dlog(0, FIL__, __LINE__, SDG_AFAIL,            \
533                  FIL__, __LINE__, astext);             \
534         _exit(EXIT_FAILURE);                           \
535     }                                                  \
536 } while (0)
537 
538 
539 /*
540  * The enter macro. Prints the trace if TRACE is on.
541  */
542 extern int slib_do_trace;
543 extern int slib_trace_fd;
544 
545 #if defined(SL_DEBUG)
546 #define SL_ENTER(s)  sl_stack_push(s, FIL__, __LINE__);
547 #else
548 #define SL_ENTER(s)  if (slib_do_trace != 0) sl_trace_in(s, FIL__, __LINE__);
549 #endif
550 
551 /*
552  * The return macro.
553  */
554 #if defined(SL_DEBUG)
555 #ifndef S_SPLINT_S
556 #define SL_RETURN(x, s)   \
557 do {                      \
558    sl_stack_pop(s, FIL__, __LINE__);       \
559    return(x);      \
560 } while(0)
561 #else
562 /*@notfunction@*/
563 #define SL_RETURN(x, s) return(x);
564 #endif  /* S_SPLINT_S */
565 #else
566 #ifndef S_SPLINT_S
567 #define SL_RETURN(x, s)   \
568 do {                      \
569    if (slib_do_trace != 0)     \
570      sl_trace_out(s, FIL__, __LINE__);     \
571    return(x);      \
572 } while(0)
573 #else
574 /*@notfunction@*/
575 #define SL_RETURN(x, s) return(x);
576 #endif  /* S_SPLINT_S */
577 #endif  /* SL_RETURN macro */
578 
579 #if defined(SL_DEBUG)
580 #define SL_RET0(s)      \
581 do {                    \
582       sl_stack_pop(s, FIL__, __LINE__);  \
583       return;    \
584 } while(0)
585 #else
586 #ifndef S_SPLINT_S
587 #define SL_RET0(s)      \
588 do {                    \
589    if (slib_do_trace != 0)   \
590      sl_trace_out(s, FIL__, __LINE__);   \
591    return;       \
592 } while(0)
593 #else
594 /*@notfunction@*/
595 #define SL_RET0(s) return;
596 #endif  /* S_SPLINT_S */
597 #endif  /* SL_RETURN macro */
598 
599 #if defined(SL_DEBUG)
600 void sl_stack_push(char * c, char * file, int line);
601 void sl_stack_pop(char * c, char * file, int line);
602 void sl_stack_print(void);
603 #endif
604 void sl_trace_in   (const char * str, const char * file, int line);
605 void sl_trace_out  (const char * str, const char * file, int line);
606 int  sl_trace_file (const char * str);
607 int  sl_trace_use  (const char * str);
608 
609 
610 
611 
612 /*
613  * The internal return macro. Sets sl_errno to the return value.
614  */
615 
616 #if defined(SL_DEBUG)
617 #define SL_IRETURN(x, s)                                            \
618 do {                                                                \
619    if((long)(x) < 0) {                                              \
620       TPT((0,    FIL__, __LINE__, SDG_ERROR, (long)(x)))            \
621       sl_errno=(x);                                                 \
622     }                                                               \
623    sl_stack_pop(s, FIL__, __LINE__);                              \
624    if (1) return(x);                                                \
625 } while(0)
626 #else
627 #define SL_IRETURN(x, s)             \
628 do {                                 \
629    if ((long)(x) < 0) sl_errno=(x);  \
630    if (slib_do_trace)                \
631      sl_trace_out(s, FIL__, __LINE__);   \
632    if (1) return(x);                 \
633 } while(0)
634 
635 #endif  /* SL_IRETURN macro */
636 
637 
638 
639 /* slib.h */
640 #endif
641 
642 
643 
644 
645