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