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.6 (Berkeley) 01/09/93"; 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 /* |H_RECEIPTTO */, 63 "errors-to", H_FROM|H_ERRORSTO, 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 SpaceSub = ' '; /* option B */ 134 QueueLA = 8; /* option x */ 135 RefuseLA = 12; /* option X */ 136 WkRecipFact = 30000L; /* option y */ 137 WkClassFact = 1800L; /* option z */ 138 WkTimeFact = 90000L; /* option Z */ 139 QueueFactor = WkRecipFact * 20; /* option q */ 140 FileMode = (getuid() != geteuid()) ? 0644 : 0600; 141 /* option F */ 142 DefUid = 1; /* option u */ 143 DefGid = 1; /* option g */ 144 CheckpointInterval = 10; /* option C */ 145 MaxHopCount = 25; /* option h */ 146 SendMode = SM_FORK; /* option d */ 147 ErrorMode = EM_PRINT; /* option e */ 148 EightBit = FALSE; /* option 8 */ 149 MaxMciCache = 1; /* option k */ 150 MciCacheTimeout = 300; /* option K */ 151 LogLevel = 9; /* option L */ 152 ReadTimeout = 2 * 60 * 60; /* option r */ 153 TimeOut = 3 * 24 * 60 * 60; /* option T */ 154 setdefuser(); 155 setupmaps(); 156 setupmailers(); 157 } 158 159 160 /* 161 ** SETDEFUSER -- set/reset DefUser using DefUid (for initgroups()) 162 */ 163 164 setdefuser() 165 { 166 struct passwd *defpwent; 167 static char defuserbuf[40]; 168 169 DefUser = defuserbuf; 170 if ((defpwent = getpwuid(DefUid)) != NULL) 171 strcpy(defuserbuf, defpwent->pw_name); 172 else 173 strcpy(defuserbuf, "nobody"); 174 } 175 /* 176 ** SETUPMAPS -- set up map classes 177 ** 178 ** Since these are compiled in, they cannot be in the config file. 179 ** 180 */ 181 182 setupmaps() 183 { 184 register STAB *s; 185 extern bool host_map_init(); 186 extern char *maphostname(); 187 188 /* set up host name lookup map */ 189 s = stab("host", ST_MAPCLASS, ST_ENTER); 190 s->s_mapclass.map_init = host_map_init; 191 s->s_mapclass.map_lookup = maphostname; 192 193 /* 194 ** Set up other map classes. 195 */ 196 197 # ifdef DBM_MAP 198 /* dbm file access */ 199 { 200 extern bool dbm_map_init(); 201 extern char *dbm_map_lookup(); 202 203 s = stab("dbm", ST_MAPCLASS, ST_ENTER); 204 s->s_mapclass.map_init = dbm_map_init; 205 s->s_mapclass.map_lookup = dbm_map_lookup; 206 } 207 # endif 208 209 # ifdef BTREE_MAP 210 /* new database file access -- btree files */ 211 { 212 extern bool bt_map_init(); 213 extern char *db_map_lookup(); 214 215 s = stab("btree", ST_MAPCLASS, ST_ENTER); 216 s->s_mapclass.map_init = bt_map_init; 217 s->s_mapclass.map_lookup = db_map_lookup; 218 } 219 # endif 220 221 # ifdef HASH_MAP 222 /* new database file access -- hash files */ 223 { 224 extern bool hash_map_init(); 225 extern char *db_map_lookup(); 226 227 s = stab("hash", ST_MAPCLASS, ST_ENTER); 228 s->s_mapclass.map_init = hash_map_init; 229 s->s_mapclass.map_lookup = db_map_lookup; 230 } 231 # endif 232 233 # ifdef NIS_MAP 234 /* NIS map access */ 235 { 236 extern bool nis_map_init(); 237 extern char *nis_map_lookup(); 238 239 s = stab("nis", ST_MAPCLASS, ST_ENTER); 240 s->s_mapclass.map_init = nis_map_init; 241 s->s_mapclass.map_lookup = nis_map_lookup; 242 } 243 # endif 244 245 # ifdef USERDB_MAP 246 /* user database */ 247 { 248 extern bool udb_map_init(); 249 extern char *udb_map_lookup(); 250 251 s = stab("udb", ST_MAPCLASS, ST_ENTER); 252 s->s_mapclass.map_init = udb_map_init; 253 s->s_mapclass.map_lookup = udb_map_lookup; 254 } 255 # endif 256 } 257 /* 258 ** HOST_MAP_INIT -- initialize host class structures 259 */ 260 261 bool 262 host_map_init(map, mapname, args) 263 MAP *map; 264 char *mapname; 265 char *args; 266 { 267 register char *p = args; 268 269 for (;;) 270 { 271 while (isspace(*p)) 272 p++; 273 if (*p != '-') 274 break; 275 switch (*++p) 276 { 277 case 'a': 278 map->map_app = ++p; 279 break; 280 } 281 while (*p != '\0' && !isspace(*p)) 282 p++; 283 if (*p != '\0') 284 *p++ = '\0'; 285 } 286 if (map->map_app != NULL) 287 map->map_app = newstr(map->map_app); 288 return TRUE; 289 } 290 /* 291 ** SETUPMAILERS -- initialize default mailers 292 */ 293 294 setupmailers() 295 { 296 char buf[100]; 297 298 strcpy(buf, "prog, P=/bin/sh, F=lsD, A=sh -c $u"); 299 makemailer(buf); 300 301 strcpy(buf, "*file*, P=/dev/null, F=lsDEu, A=FILE"); 302 makemailer(buf); 303 304 strcpy(buf, "*include*, P=/dev/null, F=su, A=INCLUDE"); 305 makemailer(buf); 306 } 307 /* 308 ** GETRUID -- get real user id (V7) 309 */ 310 311 getruid() 312 { 313 if (OpMode == MD_DAEMON) 314 return (RealUid); 315 else 316 return (getuid()); 317 } 318 319 320 /* 321 ** GETRGID -- get real group id (V7). 322 */ 323 324 getrgid() 325 { 326 if (OpMode == MD_DAEMON) 327 return (RealGid); 328 else 329 return (getgid()); 330 } 331 /* 332 ** USERNAME -- return the user id of the logged in user. 333 ** 334 ** Parameters: 335 ** none. 336 ** 337 ** Returns: 338 ** The login name of the logged in user. 339 ** 340 ** Side Effects: 341 ** none. 342 ** 343 ** Notes: 344 ** The return value is statically allocated. 345 */ 346 347 char * 348 username() 349 { 350 static char *myname = NULL; 351 extern char *getlogin(); 352 register struct passwd *pw; 353 354 /* cache the result */ 355 if (myname == NULL) 356 { 357 myname = getlogin(); 358 if (myname == NULL || myname[0] == '\0') 359 { 360 361 pw = getpwuid(getruid()); 362 if (pw != NULL) 363 myname = newstr(pw->pw_name); 364 } 365 else 366 { 367 368 myname = newstr(myname); 369 if ((pw = getpwnam(myname)) == NULL || 370 getuid() != pw->pw_uid) 371 { 372 pw = getpwuid(getuid()); 373 if (pw != NULL) 374 myname = newstr(pw->pw_name); 375 } 376 } 377 if (myname == NULL || myname[0] == '\0') 378 { 379 syserr("Who are you?"); 380 myname = "postmaster"; 381 } 382 } 383 384 return (myname); 385 } 386 /* 387 ** TTYPATH -- Get the path of the user's tty 388 ** 389 ** Returns the pathname of the user's tty. Returns NULL if 390 ** the user is not logged in or if s/he has write permission 391 ** denied. 392 ** 393 ** Parameters: 394 ** none 395 ** 396 ** Returns: 397 ** pathname of the user's tty. 398 ** NULL if not logged in or write permission denied. 399 ** 400 ** Side Effects: 401 ** none. 402 ** 403 ** WARNING: 404 ** Return value is in a local buffer. 405 ** 406 ** Called By: 407 ** savemail 408 */ 409 410 # include <sys/stat.h> 411 412 char * 413 ttypath() 414 { 415 struct stat stbuf; 416 register char *pathn; 417 extern char *ttyname(); 418 extern char *getlogin(); 419 420 /* compute the pathname of the controlling tty */ 421 if ((pathn = ttyname(2)) == NULL && (pathn = ttyname(1)) == NULL && 422 (pathn = ttyname(0)) == NULL) 423 { 424 errno = 0; 425 return (NULL); 426 } 427 428 /* see if we have write permission */ 429 if (stat(pathn, &stbuf) < 0 || !bitset(02, stbuf.st_mode)) 430 { 431 errno = 0; 432 return (NULL); 433 } 434 435 /* see if the user is logged in */ 436 if (getlogin() == NULL) 437 return (NULL); 438 439 /* looks good */ 440 return (pathn); 441 } 442 /* 443 ** CHECKCOMPAT -- check for From and To person compatible. 444 ** 445 ** This routine can be supplied on a per-installation basis 446 ** to determine whether a person is allowed to send a message. 447 ** This allows restriction of certain types of internet 448 ** forwarding or registration of users. 449 ** 450 ** If the hosts are found to be incompatible, an error 451 ** message should be given using "usrerr" and FALSE should 452 ** be returned. 453 ** 454 ** 'NoReturn' can be set to suppress the return-to-sender 455 ** function; this should be done on huge messages. 456 ** 457 ** Parameters: 458 ** to -- the person being sent to. 459 ** 460 ** Returns: 461 ** TRUE -- ok to send. 462 ** FALSE -- not ok. 463 ** 464 ** Side Effects: 465 ** none (unless you include the usrerr stuff) 466 */ 467 468 bool 469 checkcompat(to, e) 470 register ADDRESS *to; 471 register ENVELOPE *e; 472 { 473 # ifdef lint 474 if (to == NULL) 475 to++; 476 # endif lint 477 # ifdef EXAMPLE_CODE 478 /* this code is intended as an example only */ 479 register STAB *s; 480 481 s = stab("arpa", ST_MAILER, ST_FIND); 482 if (s != NULL && e->e_from.q_mailer != LocalMailer && 483 to->q_mailer == s->s_mailer) 484 { 485 usrerr("No ARPA mail through this machine: see your system administration"); 486 /* NoReturn = TRUE; to supress return copy */ 487 return (FALSE); 488 } 489 # endif /* EXAMPLE_CODE */ 490 return (TRUE); 491 } 492 /* 493 ** HOLDSIGS -- arrange to hold all signals 494 ** 495 ** Parameters: 496 ** none. 497 ** 498 ** Returns: 499 ** none. 500 ** 501 ** Side Effects: 502 ** Arranges that signals are held. 503 */ 504 505 holdsigs() 506 { 507 } 508 /* 509 ** RLSESIGS -- arrange to release all signals 510 ** 511 ** This undoes the effect of holdsigs. 512 ** 513 ** Parameters: 514 ** none. 515 ** 516 ** Returns: 517 ** none. 518 ** 519 ** Side Effects: 520 ** Arranges that signals are released. 521 */ 522 523 rlsesigs() 524 { 525 } 526 /* 527 ** GETLA -- get the current load average 528 ** 529 ** This code stolen from la.c. 530 ** 531 ** Parameters: 532 ** none. 533 ** 534 ** Returns: 535 ** The current load average as an integer. 536 ** 537 ** Side Effects: 538 ** none. 539 */ 540 541 /* try to guess what style of load average we have */ 542 #define LA_ZERO 1 /* always return load average as zero */ 543 #define LA_INT 2 /* read kmem for avenrun; interpret as int */ 544 #define LA_FLOAT 3 /* read kmem for avenrun; interpret as float */ 545 #define LA_SUBR 4 /* call getloadavg */ 546 547 #ifndef LA_TYPE 548 # if defined(sun) 549 # define LA_TYPE LA_INT 550 # endif 551 # if defined(mips) 552 /* Ultrix or RISC/os */ 553 # define LA_TYPE LA_INT 554 # define LA_AVENRUN "avenrun" 555 # endif 556 # if defined(hpux) 557 # define LA_TYPE LA_FLOAT 558 # endif 559 # if defined(BSD) 560 # define LA_TYPE LA_SUBR 561 # endif 562 563 # ifndef LA_TYPE 564 # define LA_TYPE LA_ZERO 565 # endif 566 #endif 567 568 #if (LA_TYPE == LA_INT) || (LA_TYPE == LA_FLOAT) 569 570 #include <nlist.h> 571 #include <fcntl.h> 572 573 #ifndef LA_AVENRUN 574 #define LA_AVENRUN "_avenrun" 575 #endif 576 577 /* _PATH_UNIX should be defined in <paths.h> */ 578 #ifndef _PATH_UNIX 579 # if defined(hpux) 580 # define _PATH_UNIX "/hp-ux" 581 # endif 582 # if defined(mips) && !defined(ultrix) 583 /* powerful RISC/os */ 584 # define _PATH_UNIX "/unix" 585 # endif 586 # ifndef _PATH_UNIX 587 # define _PATH_UNIX "/vmunix" 588 # endif 589 #endif 590 591 struct nlist Nl[] = 592 { 593 { LA_AVENRUN }, 594 #define X_AVENRUN 0 595 { 0 }, 596 }; 597 598 #if (LA_TYPE == LA_INT) && !defined(FSHIFT) 599 # define FSHIFT 8 600 # define FSCALE (1 << FSHIFT) 601 #endif 602 603 getla() 604 { 605 static int kmem = -1; 606 #if LA_TYPE == LA_INT 607 long avenrun[3]; 608 #else 609 double avenrun[3]; 610 #endif 611 extern off_t lseek(); 612 613 if (kmem < 0) 614 { 615 kmem = open("/dev/kmem", 0, 0); 616 if (kmem < 0) 617 return (-1); 618 (void) fcntl(kmem, F_SETFD, 1); 619 nlist(_PATH_UNIX, Nl); 620 if (Nl[0].n_type == 0) 621 return (-1); 622 } 623 if (lseek(kmem, (off_t) Nl[X_AVENRUN].n_value, 0) == -1 || 624 read(kmem, (char *) avenrun, sizeof(avenrun)) < sizeof(avenrun)) 625 { 626 /* thank you Ian */ 627 return (-1); 628 } 629 #if LA_TYPE == LA_INT 630 return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT); 631 #else 632 return ((int) (avenrun[0] + 0.5)); 633 #endif 634 } 635 636 #else 637 #if LA_TYPE == LA_SUBR 638 639 getla() 640 { 641 double avenrun[3]; 642 643 if (getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0])) < 0) 644 return (-1); 645 return ((int) (avenrun[0] + 0.5)); 646 } 647 648 #else 649 650 getla() 651 { 652 return (0); 653 } 654 655 #endif 656 #endif 657 /* 658 ** SHOULDQUEUE -- should this message be queued or sent? 659 ** 660 ** Compares the message cost to the load average to decide. 661 ** 662 ** Parameters: 663 ** pri -- the priority of the message in question. 664 ** ctime -- the message creation time. 665 ** 666 ** Returns: 667 ** TRUE -- if this message should be queued up for the 668 ** time being. 669 ** FALSE -- if the load is low enough to send this message. 670 ** 671 ** Side Effects: 672 ** none. 673 */ 674 675 bool 676 shouldqueue(pri, ctime) 677 long pri; 678 time_t ctime; 679 { 680 if (CurrentLA < QueueLA) 681 return (FALSE); 682 return (pri > (QueueFactor / (CurrentLA - QueueLA + 1))); 683 } 684 /* 685 ** REFUSECONNECTIONS -- decide if connections should be refused 686 ** 687 ** Parameters: 688 ** none. 689 ** 690 ** Returns: 691 ** TRUE if incoming SMTP connections should be refused 692 ** (for now). 693 ** FALSE if we should accept new work. 694 ** 695 ** Side Effects: 696 ** none. 697 */ 698 699 bool 700 refuseconnections() 701 { 702 /* this is probably too simplistic */ 703 return (CurrentLA > RefuseLA); 704 } 705 /* 706 ** SETPROCTITLE -- set process title for ps 707 ** 708 ** Parameters: 709 ** fmt -- a printf style format string. 710 ** a, b, c -- possible parameters to fmt. 711 ** 712 ** Returns: 713 ** none. 714 ** 715 ** Side Effects: 716 ** Clobbers argv of our main procedure so ps(1) will 717 ** display the title. 718 */ 719 720 /*VARARGS1*/ 721 setproctitle(fmt VA_ARG_FORMAL) 722 char *fmt; 723 VA_ARG_DECL 724 { 725 # ifdef SETPROCTITLE 726 register char *p; 727 register int i; 728 char buf[MAXLINE]; 729 VA_LOCAL_DECL 730 extern char **Argv; 731 extern char *LastArgv; 732 733 p = buf; 734 735 /* print sendmail: heading for grep */ 736 (void) strcpy(p, "sendmail: "); 737 p += strlen(p); 738 739 /* print the argument string */ 740 VA_START(fmt); 741 (void) vsprintf(p, fmt, ap); 742 VA_END; 743 744 i = strlen(buf); 745 if (i > LastArgv - Argv[0] - 2) 746 { 747 i = LastArgv - Argv[0] - 2; 748 buf[i] = '\0'; 749 } 750 (void) strcpy(Argv[0], buf); 751 p = &Argv[0][i]; 752 while (p < LastArgv) 753 *p++ = ' '; 754 # endif /* SETPROCTITLE */ 755 } 756 /* 757 ** REAPCHILD -- pick up the body of my child, lest it become a zombie 758 ** 759 ** Parameters: 760 ** none. 761 ** 762 ** Returns: 763 ** none. 764 ** 765 ** Side Effects: 766 ** Picks up extant zombies. 767 */ 768 769 # include <sys/wait.h> 770 771 void 772 reapchild() 773 { 774 # ifdef WNOHANG 775 union wait status; 776 777 while (wait3((int *)&status, WNOHANG, (struct rusage *) NULL) > 0) 778 continue; 779 # else /* WNOHANG */ 780 auto int status; 781 782 while (wait((int *)&status) > 0) 783 continue; 784 # endif /* WNOHANG */ 785 } 786 /* 787 ** UNSETENV -- remove a variable from the environment 788 ** 789 ** Not needed on newer systems. 790 ** 791 ** Parameters: 792 ** name -- the string name of the environment variable to be 793 ** deleted from the current environment. 794 ** 795 ** Returns: 796 ** none. 797 ** 798 ** Globals: 799 ** environ -- a pointer to the current environment. 800 ** 801 ** Side Effects: 802 ** Modifies environ. 803 */ 804 805 #ifdef UNSETENV 806 807 void 808 unsetenv(name) 809 char *name; 810 { 811 extern char **environ; 812 register char **pp; 813 int len = strlen(name); 814 815 for (pp = environ; *pp != NULL; pp++) 816 { 817 if (strncmp(name, *pp, len) == 0 && 818 ((*pp)[len] == '=' || (*pp)[len] == '\0')) 819 break; 820 } 821 822 for (; *pp != NULL; pp++) 823 *pp = pp[1]; 824 } 825 826 #endif /* UNSETENV */ 827 /* 828 ** GETDTABLESIZE -- return number of file descriptors 829 ** 830 ** Only on non-BSD systems 831 ** 832 ** Parameters: 833 ** none 834 ** 835 ** Returns: 836 ** size of file descriptor table 837 ** 838 ** Side Effects: 839 ** none 840 */ 841 842 #ifdef SYSTEM5 843 844 int 845 getdtablesize() 846 { 847 return NOFILE; 848 } 849 850 #endif 851