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