1 /* 2 * Copyright (c) 1983 Eric P. Allman 3 * Copyright (c) 1988 Regents of the University of California. 4 * All rights reserved. 5 * 6 * %sccs.include.redist.c% 7 */ 8 9 #ifndef lint 10 static char sccsid[] = "@(#)conf.c 6.1 (Berkeley) 12/21/92"; 11 #endif /* not lint */ 12 13 # include <sys/ioctl.h> 14 # include <pwd.h> 15 # include "sendmail.h" 16 # include "pathnames.h" 17 18 /* 19 ** CONF.C -- Sendmail Configuration Tables. 20 ** 21 ** Defines the configuration of this installation. 22 ** 23 ** Configuration Variables: 24 ** HdrInfo -- a table describing well-known header fields. 25 ** Each entry has the field name and some flags, 26 ** which are described in sendmail.h. 27 ** 28 ** Notes: 29 ** I have tried to put almost all the reasonable 30 ** configuration information into the configuration 31 ** file read at runtime. My intent is that anything 32 ** here is a function of the version of UNIX you 33 ** are running, or is really static -- for example 34 ** the headers are a superset of widely used 35 ** protocols. If you find yourself playing with 36 ** this file too much, you may be making a mistake! 37 */ 38 39 40 41 42 /* 43 ** Header info table 44 ** Final (null) entry contains the flags used for any other field. 45 ** 46 ** Not all of these are actually handled specially by sendmail 47 ** at this time. They are included as placeholders, to let 48 ** you know that "someday" I intend to have sendmail do 49 ** something with them. 50 */ 51 52 struct hdrinfo HdrInfo[] = 53 { 54 /* originator fields, most to least significant */ 55 "resent-sender", H_FROM|H_RESENT, 56 "resent-from", H_FROM|H_RESENT, 57 "resent-reply-to", H_FROM|H_RESENT, 58 "sender", H_FROM, 59 "from", H_FROM, 60 "reply-to", H_FROM, 61 "full-name", H_ACHECK, 62 "return-receipt-to", H_FROM, 63 "errors-to", H_FROM, 64 /* destination fields */ 65 "to", H_RCPT, 66 "resent-to", H_RCPT|H_RESENT, 67 "cc", H_RCPT, 68 "resent-cc", H_RCPT|H_RESENT, 69 "bcc", H_RCPT|H_ACHECK, 70 "resent-bcc", H_RCPT|H_ACHECK|H_RESENT, 71 "apparently-to", H_RCPT, 72 /* message identification and control */ 73 "message-id", 0, 74 "resent-message-id", H_RESENT, 75 "message", H_EOH, 76 "text", H_EOH, 77 /* date fields */ 78 "date", 0, 79 "resent-date", H_RESENT, 80 /* trace fields */ 81 "received", H_TRACE|H_FORCE, 82 "via", H_TRACE|H_FORCE, 83 "mail-from", H_TRACE|H_FORCE, 84 85 NULL, 0, 86 }; 87 88 89 /* 90 ** ARPANET error message numbers. 91 */ 92 93 char Arpa_Info[] = "050"; /* arbitrary info */ 94 char Arpa_TSyserr[] = "451"; /* some (transient) system error */ 95 char Arpa_PSyserr[] = "554"; /* some (permanent) system error */ 96 char Arpa_Usrerr[] = "554"; /* some (fatal) user error */ 97 98 99 100 /* 101 ** Location of system files/databases/etc. 102 */ 103 104 char *ConfFile = _PATH_SENDMAILCF; /* runtime configuration */ 105 char *FreezeFile = _PATH_SENDMAILFC; /* frozen version of above */ 106 107 108 109 /* 110 ** Miscellaneous stuff. 111 */ 112 113 int DtableSize = 50; /* max open files; reset in 4.2bsd */ 114 /* 115 ** SETDEFAULTS -- set default values 116 ** 117 ** Because of the way freezing is done, these must be initialized 118 ** using direct code. 119 ** 120 ** Parameters: 121 ** none. 122 ** 123 ** Returns: 124 ** none. 125 ** 126 ** Side Effects: 127 ** Initializes a bunch of global variables to their 128 ** default values. 129 */ 130 131 setdefaults() 132 { 133 QueueLA = 8; 134 QueueFactor = 10000; 135 RefuseLA = 12; 136 SpaceSub = ' '; 137 WkRecipFact = 1000; 138 WkClassFact = 1800; 139 WkTimeFact = 9000; 140 FileMode = (getuid() != geteuid()) ? 0644 : 0600; 141 DefUid = 1; 142 DefGid = 1; 143 CheckpointInterval = 10; 144 MaxHopCount = 17; 145 SendMode = SM_FORK; 146 ErrorMode = EM_PRINT; 147 EightBit = FALSE; 148 MaxMciCache = 1; 149 MciCacheTimeout = 300; 150 setdefuser(); 151 setupmaps(); 152 } 153 154 155 /* 156 ** SETDEFUSER -- set/reset DefUser using DefUid (for initgroups()) 157 */ 158 159 setdefuser() 160 { 161 struct passwd *defpwent; 162 163 if (DefUser != NULL) 164 free(DefUser); 165 if ((defpwent = getpwuid(DefUid)) != NULL) 166 DefUser = newstr(defpwent->pw_name); 167 else 168 DefUser = newstr("nobody"); 169 } 170 /* 171 ** SETUPMAPS -- set up map classes 172 ** 173 ** Since these are compiled in, they cannot be in the config file. 174 ** 175 */ 176 177 setupmaps() 178 { 179 register STAB *s; 180 extern bool host_map_init(); 181 extern char *maphostname(); 182 183 /* set up host name lookup map */ 184 s = stab("host", ST_MAPCLASS, ST_ENTER); 185 s->s_mapclass.map_init = host_map_init; 186 s->s_mapclass.map_lookup = maphostname; 187 188 /* 189 ** Set up other map classes. 190 */ 191 192 # ifdef DBM_MAP 193 /* dbm file access */ 194 { 195 extern bool dbm_map_init(); 196 extern char *dbm_map_lookup(); 197 198 s = stab("dbm", ST_MAPCLASS, ST_ENTER); 199 s->s_mapclass.map_init = dbm_map_init; 200 s->s_mapclass.map_lookup = dbm_map_lookup; 201 } 202 # endif 203 204 # ifdef BTREE_MAP 205 /* new database file access -- btree files */ 206 { 207 extern bool bt_map_init(); 208 extern char *db_map_lookup(); 209 210 s = stab("btree", ST_MAPCLASS, ST_ENTER); 211 s->s_mapclass.map_init = bt_map_init; 212 s->s_mapclass.map_lookup = db_map_lookup; 213 } 214 # endif 215 216 # ifdef HASH_MAP 217 /* new database file access -- hash files */ 218 { 219 extern bool hash_map_init(); 220 extern char *db_map_lookup(); 221 222 s = stab("hash", ST_MAPCLASS, ST_ENTER); 223 s->s_mapclass.map_init = hash_map_init; 224 s->s_mapclass.map_lookup = db_map_lookup; 225 } 226 # endif 227 228 # ifdef NIS_MAP 229 /* NIS map access */ 230 { 231 extern bool nis_map_init(); 232 extern char *nis_map_lookup(); 233 234 s = stab("nis", ST_MAPCLASS, ST_ENTER); 235 s->s_mapclass.map_init = nis_map_init; 236 s->s_mapclass.map_lookup = nis_map_lookup; 237 } 238 # endif 239 240 # ifdef USERDB_MAP 241 /* user database */ 242 { 243 extern bool udb_map_init(); 244 extern char *udb_map_lookup(); 245 246 s = stab("udb", ST_MAPCLASS, ST_ENTER); 247 s->s_mapclass.map_init = udb_map_init; 248 s->s_mapclass.map_lookup = udb_map_lookup; 249 } 250 # endif 251 } 252 /* 253 ** HOST_MAP_INIT -- initialize host class structures 254 */ 255 256 bool 257 host_map_init(map, mapname, args) 258 MAP *map; 259 char *mapname; 260 char *args; 261 { 262 register char *p = args; 263 264 for (;;) 265 { 266 while (isspace(*p)) 267 p++; 268 if (*p != '-') 269 break; 270 switch (*++p) 271 { 272 case 'a': 273 map->map_app = ++p; 274 break; 275 } 276 while (*p != '\0' && !isspace(*p)) 277 p++; 278 if (*p != '\0') 279 *p++ = '\0'; 280 } 281 if (map->map_app != NULL) 282 map->map_app = newstr(map->map_app); 283 return TRUE; 284 } 285 286 /* 287 ** GETRUID -- get real user id (V7) 288 */ 289 290 getruid() 291 { 292 if (OpMode == MD_DAEMON) 293 return (RealUid); 294 else 295 return (getuid()); 296 } 297 298 299 /* 300 ** GETRGID -- get real group id (V7). 301 */ 302 303 getrgid() 304 { 305 if (OpMode == MD_DAEMON) 306 return (RealGid); 307 else 308 return (getgid()); 309 } 310 /* 311 ** USERNAME -- return the user id of the logged in user. 312 ** 313 ** Parameters: 314 ** none. 315 ** 316 ** Returns: 317 ** The login name of the logged in user. 318 ** 319 ** Side Effects: 320 ** none. 321 ** 322 ** Notes: 323 ** The return value is statically allocated. 324 */ 325 326 char * 327 username() 328 { 329 static char *myname = NULL; 330 extern char *getlogin(); 331 register struct passwd *pw; 332 333 /* cache the result */ 334 if (myname == NULL) 335 { 336 myname = getlogin(); 337 if (myname == NULL || myname[0] == '\0') 338 { 339 340 pw = getpwuid(getruid()); 341 if (pw != NULL) 342 myname = newstr(pw->pw_name); 343 } 344 else 345 { 346 347 myname = newstr(myname); 348 if ((pw = getpwnam(myname)) == NULL || 349 getuid() != pw->pw_uid) 350 { 351 pw = getpwuid(getuid()); 352 if (pw != NULL) 353 myname = newstr(pw->pw_name); 354 } 355 } 356 if (myname == NULL || myname[0] == '\0') 357 { 358 syserr("Who are you?"); 359 myname = "postmaster"; 360 } 361 } 362 363 return (myname); 364 } 365 /* 366 ** TTYPATH -- Get the path of the user's tty 367 ** 368 ** Returns the pathname of the user's tty. Returns NULL if 369 ** the user is not logged in or if s/he has write permission 370 ** denied. 371 ** 372 ** Parameters: 373 ** none 374 ** 375 ** Returns: 376 ** pathname of the user's tty. 377 ** NULL if not logged in or write permission denied. 378 ** 379 ** Side Effects: 380 ** none. 381 ** 382 ** WARNING: 383 ** Return value is in a local buffer. 384 ** 385 ** Called By: 386 ** savemail 387 */ 388 389 # include <sys/stat.h> 390 391 char * 392 ttypath() 393 { 394 struct stat stbuf; 395 register char *pathn; 396 extern char *ttyname(); 397 extern char *getlogin(); 398 399 /* compute the pathname of the controlling tty */ 400 if ((pathn = ttyname(2)) == NULL && (pathn = ttyname(1)) == NULL && 401 (pathn = ttyname(0)) == NULL) 402 { 403 errno = 0; 404 return (NULL); 405 } 406 407 /* see if we have write permission */ 408 if (stat(pathn, &stbuf) < 0 || !bitset(02, stbuf.st_mode)) 409 { 410 errno = 0; 411 return (NULL); 412 } 413 414 /* see if the user is logged in */ 415 if (getlogin() == NULL) 416 return (NULL); 417 418 /* looks good */ 419 return (pathn); 420 } 421 /* 422 ** CHECKCOMPAT -- check for From and To person compatible. 423 ** 424 ** This routine can be supplied on a per-installation basis 425 ** to determine whether a person is allowed to send a message. 426 ** This allows restriction of certain types of internet 427 ** forwarding or registration of users. 428 ** 429 ** If the hosts are found to be incompatible, an error 430 ** message should be given using "usrerr" and FALSE should 431 ** be returned. 432 ** 433 ** 'NoReturn' can be set to suppress the return-to-sender 434 ** function; this should be done on huge messages. 435 ** 436 ** Parameters: 437 ** to -- the person being sent to. 438 ** 439 ** Returns: 440 ** TRUE -- ok to send. 441 ** FALSE -- not ok. 442 ** 443 ** Side Effects: 444 ** none (unless you include the usrerr stuff) 445 */ 446 447 bool 448 checkcompat(to, e) 449 register ADDRESS *to; 450 register ENVELOPE *e; 451 { 452 # ifdef lint 453 if (to == NULL) 454 to++; 455 # endif lint 456 # ifdef EXAMPLE_CODE 457 /* this code is intended as an example only */ 458 register STAB *s; 459 460 s = stab("arpa", ST_MAILER, ST_FIND); 461 if (s != NULL && e->e_from.q_mailer != LocalMailer && 462 to->q_mailer == s->s_mailer) 463 { 464 usrerr("No ARPA mail through this machine: see your system administration"); 465 /* NoReturn = TRUE; to supress return copy */ 466 return (FALSE); 467 } 468 # endif /* EXAMPLE_CODE */ 469 return (TRUE); 470 } 471 /* 472 ** HOLDSIGS -- arrange to hold all signals 473 ** 474 ** Parameters: 475 ** none. 476 ** 477 ** Returns: 478 ** none. 479 ** 480 ** Side Effects: 481 ** Arranges that signals are held. 482 */ 483 484 holdsigs() 485 { 486 } 487 /* 488 ** RLSESIGS -- arrange to release all signals 489 ** 490 ** This undoes the effect of holdsigs. 491 ** 492 ** Parameters: 493 ** none. 494 ** 495 ** Returns: 496 ** none. 497 ** 498 ** Side Effects: 499 ** Arranges that signals are released. 500 */ 501 502 rlsesigs() 503 { 504 } 505 /* 506 ** GETLA -- get the current load average 507 ** 508 ** This code stolen from la.c. 509 ** 510 ** Parameters: 511 ** none. 512 ** 513 ** Returns: 514 ** The current load average as an integer. 515 ** 516 ** Side Effects: 517 ** none. 518 */ 519 520 /* try to guess what style of load average we have */ 521 #define LA_ZERO 1 /* always return load average as zero */ 522 #define LA_INT 2 /* read kmem for avenrun; interpret as int */ 523 #define LA_FLOAT 3 /* read kmem for avenrun; interpret as float */ 524 #define LA_SUBR 4 /* call getloadavg */ 525 526 #ifndef LA_TYPE 527 # if defined(sun) 528 # define LA_TYPE LA_INT 529 # endif 530 # if defined(mips) 531 /* Ultrix or RISC/os */ 532 # define LA_TYPE LA_INT 533 # define LA_AVENRUN "avenrun" 534 # endif 535 # if defined(hpux) 536 # define LA_TYPE LA_FLOAT 537 # endif 538 # if defined(BSD) 539 # define LA_TYPE LA_SUBR 540 # endif 541 542 # ifndef LA_TYPE 543 # define LA_TYPE LA_ZERO 544 # endif 545 #endif 546 547 #if (LA_TYPE == LA_INT) || (LA_TYPE == LA_FLOAT) 548 549 #include <nlist.h> 550 #include <fcntl.h> 551 552 #ifndef LA_AVENRUN 553 #define LA_AVENRUN "_avenrun" 554 #endif 555 556 /* _PATH_UNIX should be defined in <paths.h> */ 557 #ifndef _PATH_UNIX 558 # if defined(hpux) 559 # define _PATH_UNIX "/hp-ux" 560 # endif 561 # if defined(mips) && !defined(ultrix) 562 /* powerful RISC/os */ 563 # define _PATH_UNIX "/unix" 564 # endif 565 # ifndef _PATH_UNIX 566 # define _PATH_UNIX "/vmunix" 567 # endif 568 #endif 569 570 struct nlist Nl[] = 571 { 572 { LA_AVENRUN }, 573 #define X_AVENRUN 0 574 { 0 }, 575 }; 576 577 #if (LA_TYPE == LA_INT) && !defined(FSHIFT) 578 # define FSHIFT 8 579 # define FSCALE (1 << FSHIFT) 580 #endif 581 582 getla() 583 { 584 static int kmem = -1; 585 #if LA_TYPE == LA_INT 586 long avenrun[3]; 587 #else 588 double avenrun[3]; 589 #endif 590 extern off_t lseek(); 591 592 if (kmem < 0) 593 { 594 kmem = open("/dev/kmem", 0, 0); 595 if (kmem < 0) 596 return (-1); 597 (void) fcntl(kmem, F_SETFD, 1); 598 nlist(_PATH_UNIX, Nl); 599 if (Nl[0].n_type == 0) 600 return (-1); 601 } 602 if (lseek(kmem, (off_t) Nl[X_AVENRUN].n_value, 0) == -1 || 603 read(kmem, (char *) avenrun, sizeof(avenrun)) < sizeof(avenrun)) 604 { 605 /* thank you Ian */ 606 return (-1); 607 } 608 #if LA_TYPE == LA_INT 609 return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT); 610 #else 611 return ((int) (avenrun[0] + 0.5)); 612 #endif 613 } 614 615 #else 616 #if LA_TYPE == LA_SUBR 617 618 getla() 619 { 620 double avenrun[3]; 621 622 if (getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0])) < 0) 623 return (-1); 624 return ((int) (avenrun[0] + 0.5)); 625 } 626 627 #else 628 629 getla() 630 { 631 return (0); 632 } 633 634 #endif 635 #endif 636 /* 637 ** SHOULDQUEUE -- should this message be queued or sent? 638 ** 639 ** Compares the message cost to the load average to decide. 640 ** 641 ** Parameters: 642 ** pri -- the priority of the message in question. 643 ** 644 ** Returns: 645 ** TRUE -- if this message should be queued up for the 646 ** time being. 647 ** FALSE -- if the load is low enough to send this message. 648 ** 649 ** Side Effects: 650 ** none. 651 */ 652 653 bool 654 shouldqueue(pri) 655 long pri; 656 { 657 if (CurrentLA < QueueLA) 658 return (FALSE); 659 return (pri > (QueueFactor / (CurrentLA - QueueLA + 1))); 660 } 661 /* 662 ** REFUSECONNECTIONS -- decide if connections should be refused 663 ** 664 ** Parameters: 665 ** none. 666 ** 667 ** Returns: 668 ** TRUE if incoming SMTP connections should be refused 669 ** (for now). 670 ** FALSE if we should accept new work. 671 ** 672 ** Side Effects: 673 ** none. 674 */ 675 676 bool 677 refuseconnections() 678 { 679 /* this is probably too simplistic */ 680 return (CurrentLA > RefuseLA); 681 } 682 /* 683 ** SETPROCTITLE -- set process title for ps 684 ** 685 ** Parameters: 686 ** fmt -- a printf style format string. 687 ** a, b, c -- possible parameters to fmt. 688 ** 689 ** Returns: 690 ** none. 691 ** 692 ** Side Effects: 693 ** Clobbers argv of our main procedure so ps(1) will 694 ** display the title. 695 */ 696 697 /*VARARGS1*/ 698 setproctitle(fmt VA_ARG_FORMAL) 699 char *fmt; 700 VA_ARG_DECL 701 { 702 # ifdef SETPROCTITLE 703 register char *p; 704 register int i; 705 char buf[MAXLINE]; 706 VA_LOCAL_DECL 707 extern char **Argv; 708 extern char *LastArgv; 709 710 p = buf; 711 712 /* print sendmail: heading for grep */ 713 (void) strcpy(p, "sendmail: "); 714 p += strlen(p); 715 716 /* print the argument string */ 717 VA_START(fmt); 718 (void) vsprintf(p, fmt, ap); 719 VA_END; 720 721 i = strlen(buf); 722 if (i > LastArgv - Argv[0] - 2) 723 { 724 i = LastArgv - Argv[0] - 2; 725 buf[i] = '\0'; 726 } 727 (void) strcpy(Argv[0], buf); 728 p = &Argv[0][i]; 729 while (p < LastArgv) 730 *p++ = ' '; 731 # endif /* SETPROCTITLE */ 732 } 733 /* 734 ** REAPCHILD -- pick up the body of my child, lest it become a zombie 735 ** 736 ** Parameters: 737 ** none. 738 ** 739 ** Returns: 740 ** none. 741 ** 742 ** Side Effects: 743 ** Picks up extant zombies. 744 */ 745 746 # include <sys/wait.h> 747 748 void 749 reapchild() 750 { 751 # ifdef WNOHANG 752 union wait status; 753 754 while (wait3((int *)&status, WNOHANG, (struct rusage *) NULL) > 0) 755 continue; 756 # else /* WNOHANG */ 757 auto int status; 758 759 while (wait((int *)&status) > 0) 760 continue; 761 # endif /* WNOHANG */ 762 } 763 /* 764 ** UNSETENV -- remove a variable from the environment 765 ** 766 ** Not needed on newer systems. 767 ** 768 ** Parameters: 769 ** name -- the string name of the environment variable to be 770 ** deleted from the current environment. 771 ** 772 ** Returns: 773 ** none. 774 ** 775 ** Globals: 776 ** environ -- a pointer to the current environment. 777 ** 778 ** Side Effects: 779 ** Modifies environ. 780 */ 781 782 #ifdef UNSETENV 783 784 void 785 unsetenv(name) 786 char *name; 787 { 788 extern char **environ; 789 register char **pp; 790 int len = strlen(name); 791 792 for (pp = environ; *pp != NULL; pp++) 793 { 794 if (strncmp(name, *pp, len) == 0 && 795 ((*pp)[len] == '=' || (*pp)[len] == '\0')) 796 break; 797 } 798 799 for (; *pp != NULL; pp++) 800 *pp = pp[1]; 801 } 802 803 #endif /* UNSETENV */ 804 /* 805 ** GETDTABLESIZE -- return number of file descriptors 806 ** 807 ** Only on non-BSD systems 808 ** 809 ** Parameters: 810 ** none 811 ** 812 ** Returns: 813 ** size of file descriptor table 814 ** 815 ** Side Effects: 816 ** none 817 */ 818 819 #ifdef SYSTEM5 820 821 int 822 getdtablesize() 823 { 824 return NOFILE; 825 } 826 827 #endif 828