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