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