xref: /csrg-svn/usr.sbin/sendmail/src/conf.c (revision 25686)
122698Sdist /*
222698Sdist **  Sendmail
322698Sdist **  Copyright (c) 1983  Eric P. Allman
422698Sdist **  Berkeley, California
522698Sdist **
622698Sdist **  Copyright (c) 1983 Regents of the University of California.
722698Sdist **  All rights reserved.  The Berkeley software License Agreement
822698Sdist **  specifies the terms and conditions for redistribution.
922698Sdist */
1022698Sdist 
1122698Sdist #ifndef lint
12*25686Seric static char	SccsId[] = "@(#)conf.c	5.12 (Berkeley) 01/05/86";
1322698Sdist #endif not lint
1422698Sdist 
15294Seric # include <pwd.h>
1614881Seric # include <sys/ioctl.h>
1724943Seric # ifdef sun
1824943Seric # include <sys/param.h>
1924943Seric # endif sun
203309Seric # include "sendmail.h"
21404Seric 
22294Seric /*
233309Seric **  CONF.C -- Sendmail Configuration Tables.
24294Seric **
25294Seric **	Defines the configuration of this installation.
26294Seric **
271388Seric **	Compilation Flags:
281388Seric **		V6 -- running on a version 6 system.  This determines
291388Seric **			whether to define certain routines between
301388Seric **			the two systems.  If you are running a funny
311388Seric **			system, e.g., V6 with long tty names, this
321388Seric **			should be checked carefully.
3314872Seric **		VMUNIX -- running on a Berkeley UNIX system.
34294Seric **
351388Seric **	Configuration Variables:
362897Seric **		HdrInfo -- a table describing well-known header fields.
372897Seric **			Each entry has the field name and some flags,
384147Seric **			which are described in sendmail.h.
394093Seric **
404093Seric **	Notes:
414093Seric **		I have tried to put almost all the reasonable
424093Seric **		configuration information into the configuration
434093Seric **		file read at runtime.  My intent is that anything
444093Seric **		here is a function of the version of UNIX you
454093Seric **		are running, or is really static -- for example
464093Seric **		the headers are a superset of widely used
474093Seric **		protocols.  If you find yourself playing with
484093Seric **		this file too much, you may be making a mistake!
49294Seric */
50294Seric 
51294Seric 
52294Seric 
53294Seric 
544437Seric /*
552897Seric **  Header info table
563057Seric **	Final (null) entry contains the flags used for any other field.
574147Seric **
584147Seric **	Not all of these are actually handled specially by sendmail
594147Seric **	at this time.  They are included as placeholders, to let
604147Seric **	you know that "someday" I intend to have sendmail do
614147Seric **	something with them.
622897Seric */
632897Seric 
642897Seric struct hdrinfo	HdrInfo[] =
652897Seric {
668060Seric 		/* originator fields, most to least significant  */
6711417Seric 	"resent-sender",	H_FROM|H_RESENT,
6811417Seric 	"resent-from",		H_FROM|H_RESENT,
69*25686Seric 	"resent-reply-to",	H_FROM|H_RESENT,
709055Seric 	"sender",		H_FROM,
719055Seric 	"from",			H_FROM,
72*25686Seric 	"reply-to",		H_FROM,
739055Seric 	"full-name",		H_ACHECK,
749055Seric 	"return-receipt-to",	H_FROM,
759055Seric 	"errors-to",		H_FROM,
768060Seric 		/* destination fields */
779055Seric 	"to",			H_RCPT,
7811417Seric 	"resent-to",		H_RCPT|H_RESENT,
799055Seric 	"cc",			H_RCPT,
8011417Seric 	"resent-cc",		H_RCPT|H_RESENT,
819055Seric 	"bcc",			H_RCPT|H_ACHECK,
8211417Seric 	"resent-bcc",		H_RCPT|H_ACHECK|H_RESENT,
838060Seric 		/* message identification and control */
8411417Seric 	"message-id",		0,
8511417Seric 	"resent-message-id",	H_RESENT,
869055Seric 	"message",		H_EOH,
879055Seric 	"text",			H_EOH,
8811417Seric 		/* date fields */
8911417Seric 	"date",			0,
9011417Seric 	"resent-date",		H_RESENT,
918060Seric 		/* trace fields */
929055Seric 	"received",		H_TRACE|H_FORCE,
939055Seric 	"via",			H_TRACE|H_FORCE,
949055Seric 	"mail-from",		H_TRACE|H_FORCE,
958060Seric 
969055Seric 	NULL,			0,
972897Seric };
984166Seric 
994166Seric 
1004166Seric /*
1014166Seric **  ARPANET error message numbers.
1024166Seric */
1034166Seric 
1047956Seric char	Arpa_Info[] =		"050";	/* arbitrary info */
1057956Seric char	Arpa_TSyserr[] =	"451";	/* some (transient) system error */
1067956Seric char	Arpa_PSyserr[] =	"554";	/* some (permanent) system error */
1077956Seric char	Arpa_Usrerr[] =		"554";	/* some (fatal) user error */
1084282Seric 
1094282Seric 
1104282Seric 
1114282Seric /*
1124282Seric **  Location of system files/databases/etc.
1134282Seric */
1144282Seric 
1154282Seric char	*ConfFile =	"/usr/lib/sendmail.cf";	/* runtime configuration */
1169064Seric char	*FreezeFile =	"/usr/lib/sendmail.fc";	/* frozen version of above */
1179039Seric 
1189064Seric 
1199064Seric 
1209039Seric /*
12124943Seric **  Miscellaneous stuff.
1229039Seric */
1239039Seric 
12424943Seric int	DtableSize =	50;		/* max open files; reset in 4.2bsd */
12524943Seric /*
12624943Seric **  SETDEFAULTS -- set default values
12724943Seric **
12824943Seric **	Because of the way freezing is done, these must be initialized
12924943Seric **	using direct code.
13024943Seric **
13124943Seric **	Parameters:
13224943Seric **		none.
13324943Seric **
13424943Seric **	Returns:
13524943Seric **		none.
13624943Seric **
13724943Seric **	Side Effects:
13824943Seric **		Initializes a bunch of global variables to their
13924943Seric **		default values.
14024943Seric */
14124943Seric 
14224943Seric setdefaults()
14324943Seric {
14424943Seric 	QueueLA = 8;
14524943Seric 	QueueFactor = 10000;
14624943Seric 	RefuseLA = 12;
14724943Seric 	SpaceSub = ' ';
14824981Seric 	WkRecipFact = 1000;
14924981Seric 	WkClassFact = 1800;
15025008Seric 	WkTimeFact = 600;
15124981Seric 	FileMode = 0644;
15224981Seric 	DefUid = 1;
15324981Seric 	DefGid = 1;
15424943Seric }
155294Seric 
156294Seric # ifdef V6
157294Seric /*
1584190Seric **  TTYNAME -- return name of terminal.
159294Seric **
160294Seric **	Parameters:
1614190Seric **		fd -- file descriptor to check.
162294Seric **
163294Seric **	Returns:
1644190Seric **		pointer to full path of tty.
1654190Seric **		NULL if no tty.
166294Seric **
167294Seric **	Side Effects:
168294Seric **		none.
169294Seric */
170294Seric 
171294Seric char *
1724190Seric ttyname(fd)
1734190Seric 	int fd;
174294Seric {
1754190Seric 	register char tn;
176294Seric 	static char pathn[] = "/dev/ttyx";
177294Seric 
178294Seric 	/* compute the pathname of the controlling tty */
1794190Seric 	if ((tn = ttyn(fd)) == NULL)
180294Seric 	{
181294Seric 		errno = 0;
182294Seric 		return (NULL);
183294Seric 	}
1844190Seric 	pathn[8] = tn;
185294Seric 	return (pathn);
186294Seric }
187294Seric /*
188294Seric **  FDOPEN -- Open a stdio file given an open file descriptor.
189294Seric **
190294Seric **	This is included here because it is standard in v7, but we
191294Seric **	need it in v6.
192294Seric **
193294Seric **	Algorithm:
194294Seric **		Open /dev/null to create a descriptor.
195294Seric **		Close that descriptor.
196294Seric **		Copy the existing fd into the descriptor.
197294Seric **
198294Seric **	Parameters:
199294Seric **		fd -- the open file descriptor.
200294Seric **		type -- "r", "w", or whatever.
201294Seric **
202294Seric **	Returns:
203294Seric **		The file descriptor it creates.
204294Seric **
205294Seric **	Side Effects:
206294Seric **		none
207294Seric **
208294Seric **	Called By:
209294Seric **		deliver
210294Seric **
211294Seric **	Notes:
212294Seric **		The mode of fd must match "type".
213294Seric */
214294Seric 
215294Seric FILE *
216294Seric fdopen(fd, type)
217294Seric 	int fd;
218294Seric 	char *type;
219294Seric {
220294Seric 	register FILE *f;
221294Seric 
222294Seric 	f = fopen("/dev/null", type);
2234081Seric 	(void) close(fileno(f));
224294Seric 	fileno(f) = fd;
225294Seric 	return (f);
226294Seric }
227294Seric /*
228294Seric **  INDEX -- Return pointer to character in string
229294Seric **
230294Seric **	For V7 compatibility.
231294Seric **
232294Seric **	Parameters:
233294Seric **		s -- a string to scan.
234294Seric **		c -- a character to look for.
235294Seric **
236294Seric **	Returns:
237294Seric **		If c is in s, returns the address of the first
238294Seric **			instance of c in s.
239294Seric **		NULL if c is not in s.
240294Seric **
241294Seric **	Side Effects:
242294Seric **		none.
243294Seric */
244294Seric 
2454437Seric char *
246294Seric index(s, c)
247294Seric 	register char *s;
248294Seric 	register char c;
249294Seric {
250294Seric 	while (*s != '\0')
251294Seric 	{
252294Seric 		if (*s++ == c)
253294Seric 			return (--s);
254294Seric 	}
255294Seric 	return (NULL);
256294Seric }
2574326Seric /*
2584326Seric **  UMASK -- fake the umask system call.
2594326Seric **
2604326Seric **	Since V6 always acts like the umask is zero, we will just
2614326Seric **	assume the same thing.
2624326Seric */
2634326Seric 
2644326Seric /*ARGSUSED*/
2654326Seric umask(nmask)
2664326Seric {
2674326Seric 	return (0);
2684326Seric }
2694326Seric 
2704326Seric 
2714326Seric /*
2724326Seric **  GETRUID -- get real user id.
2734326Seric */
2744326Seric 
2754326Seric getruid()
2764326Seric {
2774326Seric 	return (getuid() & 0377);
2784326Seric }
2794326Seric 
2804326Seric 
2814326Seric /*
2824326Seric **  GETRGID -- get real group id.
2834326Seric */
2844326Seric 
2854326Seric getrgid()
2864326Seric {
2874326Seric 	return (getgid() & 0377);
2884326Seric }
2894326Seric 
2904326Seric 
2914326Seric /*
2924326Seric **  GETEUID -- get effective user id.
2934326Seric */
2944326Seric 
2954326Seric geteuid()
2964326Seric {
2974326Seric 	return ((getuid() >> 8) & 0377);
2984326Seric }
2994326Seric 
3004326Seric 
3014326Seric /*
3024326Seric **  GETEGID -- get effective group id.
3034326Seric */
3044326Seric 
3054326Seric getegid()
3064326Seric {
3074326Seric 	return ((getgid() >> 8) & 0377);
3084326Seric }
3094326Seric 
310294Seric # endif V6
3114326Seric 
3124326Seric # ifndef V6
3134326Seric 
3144326Seric /*
3154326Seric **  GETRUID -- get real user id (V7)
3164326Seric */
3174326Seric 
3184326Seric getruid()
3194326Seric {
3209274Seric 	if (OpMode == MD_DAEMON)
3214536Seric 		return (RealUid);
3224536Seric 	else
3234536Seric 		return (getuid());
3244326Seric }
3254326Seric 
3264326Seric 
3274326Seric /*
3284326Seric **  GETRGID -- get real group id (V7).
3294326Seric */
3304326Seric 
3314326Seric getrgid()
3324326Seric {
3339274Seric 	if (OpMode == MD_DAEMON)
3344536Seric 		return (RealGid);
3354536Seric 	else
3364536Seric 		return (getgid());
3374326Seric }
3384326Seric 
3394326Seric # endif V6
3404190Seric /*
3419369Seric **  USERNAME -- return the user id of the logged in user.
3429369Seric **
3439369Seric **	Parameters:
3449369Seric **		none.
3459369Seric **
3469369Seric **	Returns:
3479369Seric **		The login name of the logged in user.
3489369Seric **
3499369Seric **	Side Effects:
3509369Seric **		none.
3519369Seric **
3529369Seric **	Notes:
3539369Seric **		The return value is statically allocated.
3549369Seric */
3559369Seric 
3569369Seric char *
3579369Seric username()
3589369Seric {
35917469Seric 	static char *myname = NULL;
3609369Seric 	extern char *getlogin();
36119904Smiriam 	register struct passwd *pw;
36219904Smiriam 	extern struct passwd *getpwuid();
3639369Seric 
36417469Seric 	/* cache the result */
36517469Seric 	if (myname == NULL)
36617469Seric 	{
36717469Seric 		myname = getlogin();
36817469Seric 		if (myname == NULL || myname[0] == '\0')
36917469Seric 		{
37017469Seric 
37117469Seric 			pw = getpwuid(getruid());
37217469Seric 			if (pw != NULL)
37317469Seric 				myname = pw->pw_name;
37417469Seric 		}
37519904Smiriam 		else
37619904Smiriam 		{
37719873Smiriam 
37819873Smiriam 			pw = getpwnam(myname);
37919904Smiriam 			if(getuid() != pw->pw_uid)
38019904Smiriam 			{
38119873Smiriam 				pw = getpwuid(getuid());
38224945Seric 				if (pw != NULL)
38324945Seric 					myname = pw->pw_name;
38419873Smiriam 			}
38519873Smiriam 		}
38617469Seric 		if (myname == NULL || myname[0] == '\0')
38717469Seric 		{
38817469Seric 			syserr("Who are you?");
38917469Seric 			myname = "postmaster";
39017469Seric 		}
39117469Seric 	}
39217469Seric 
39317469Seric 	return (myname);
3949369Seric }
3959369Seric /*
3964190Seric **  TTYPATH -- Get the path of the user's tty
397294Seric **
398294Seric **	Returns the pathname of the user's tty.  Returns NULL if
399294Seric **	the user is not logged in or if s/he has write permission
400294Seric **	denied.
401294Seric **
402294Seric **	Parameters:
403294Seric **		none
404294Seric **
405294Seric **	Returns:
406294Seric **		pathname of the user's tty.
407294Seric **		NULL if not logged in or write permission denied.
408294Seric **
409294Seric **	Side Effects:
410294Seric **		none.
411294Seric **
412294Seric **	WARNING:
413294Seric **		Return value is in a local buffer.
414294Seric **
415294Seric **	Called By:
416294Seric **		savemail
417294Seric */
418294Seric 
419294Seric # include <sys/stat.h>
420294Seric 
421294Seric char *
422294Seric ttypath()
423294Seric {
424294Seric 	struct stat stbuf;
425294Seric 	register char *pathn;
426294Seric 	extern char *ttyname();
4274081Seric 	extern char *getlogin();
428294Seric 
429294Seric 	/* compute the pathname of the controlling tty */
4309369Seric 	if ((pathn = ttyname(2)) == NULL && (pathn = ttyname(1)) == NULL &&
4319369Seric 	    (pathn = ttyname(0)) == NULL)
432294Seric 	{
433294Seric 		errno = 0;
434294Seric 		return (NULL);
435294Seric 	}
436294Seric 
437294Seric 	/* see if we have write permission */
4382967Seric 	if (stat(pathn, &stbuf) < 0 || !bitset(02, stbuf.st_mode))
439294Seric 	{
440294Seric 		errno = 0;
441294Seric 		return (NULL);
442294Seric 	}
443294Seric 
444294Seric 	/* see if the user is logged in */
445294Seric 	if (getlogin() == NULL)
446294Seric 		return (NULL);
447294Seric 
448294Seric 	/* looks good */
449294Seric 	return (pathn);
450294Seric }
4512967Seric /*
4522967Seric **  CHECKCOMPAT -- check for From and To person compatible.
4532967Seric **
4542967Seric **	This routine can be supplied on a per-installation basis
4552967Seric **	to determine whether a person is allowed to send a message.
4562967Seric **	This allows restriction of certain types of internet
4572967Seric **	forwarding or registration of users.
4582967Seric **
4592967Seric **	If the hosts are found to be incompatible, an error
4602967Seric **	message should be given using "usrerr" and FALSE should
4612967Seric **	be returned.
4622967Seric **
4634288Seric **	'NoReturn' can be set to suppress the return-to-sender
4644288Seric **	function; this should be done on huge messages.
4654288Seric **
4662967Seric **	Parameters:
4672967Seric **		to -- the person being sent to.
4682967Seric **
4692967Seric **	Returns:
4702967Seric **		TRUE -- ok to send.
4712967Seric **		FALSE -- not ok.
4722967Seric **
4732967Seric **	Side Effects:
4742967Seric **		none (unless you include the usrerr stuff)
4752967Seric */
4762967Seric 
4772967Seric bool
4782967Seric checkcompat(to)
4792967Seric 	register ADDRESS *to;
4802967Seric {
48112133Seric # ifdef lint
48212133Seric 	if (to == NULL)
48312133Seric 		to++;
48412133Seric # endif lint
48510698Seric # ifdef EXAMPLE_CODE
48610698Seric 	/* this code is intended as an example only */
4874437Seric 	register STAB *s;
4884437Seric 
4894437Seric 	s = stab("arpa", ST_MAILER, ST_FIND);
4909369Seric 	if (s != NULL && CurEnv->e_from.q_mailer != LocalMailer &&
4919369Seric 	    to->q_mailer == s->s_mailer)
4924437Seric 	{
4934437Seric 		usrerr("No ARPA mail through this machine: see your system administration");
49410698Seric 		/* NoReturn = TRUE; to supress return copy */
4954437Seric 		return (FALSE);
4964437Seric 	}
49710698Seric # endif EXAMPLE_CODE
4982967Seric 	return (TRUE);
4992967Seric }
5009369Seric /*
5019369Seric **  HOLDSIGS -- arrange to hold all signals
5029369Seric **
5039369Seric **	Parameters:
5049369Seric **		none.
5059369Seric **
5069369Seric **	Returns:
5079369Seric **		none.
5089369Seric **
5099369Seric **	Side Effects:
5109369Seric **		Arranges that signals are held.
5119369Seric */
5129369Seric 
5139369Seric holdsigs()
5149369Seric {
5159369Seric }
5169369Seric /*
5179369Seric **  RLSESIGS -- arrange to release all signals
5189369Seric **
5199369Seric **	This undoes the effect of holdsigs.
5209369Seric **
5219369Seric **	Parameters:
5229369Seric **		none.
5239369Seric **
5249369Seric **	Returns:
5259369Seric **		none.
5269369Seric **
5279369Seric **	Side Effects:
5289369Seric **		Arranges that signals are released.
5299369Seric */
5309369Seric 
5319369Seric rlsesigs()
5329369Seric {
5339369Seric }
53414872Seric /*
53514872Seric **  GETLA -- get the current load average
53614872Seric **
53714881Seric **	This code stolen from la.c.
53814881Seric **
53914872Seric **	Parameters:
54014872Seric **		none.
54114872Seric **
54214872Seric **	Returns:
54314872Seric **		The current load average as an integer.
54414872Seric **
54514872Seric **	Side Effects:
54614872Seric **		none.
54714872Seric */
54814872Seric 
54914872Seric #ifdef VMUNIX
55014872Seric 
55114872Seric #include <nlist.h>
55214872Seric 
55314872Seric struct	nlist Nl[] =
55414872Seric {
55514872Seric 	{ "_avenrun" },
55614872Seric #define	X_AVENRUN	0
55714872Seric 	{ 0 },
55814872Seric };
55914872Seric 
56014872Seric getla()
56114872Seric {
56214872Seric 	static int kmem = -1;
56324943Seric # ifdef sun
56424943Seric 	long avenrun[3];
56524943Seric # else
56614872Seric 	double avenrun[3];
56724943Seric # endif
56825615Seric 	extern off_t lseek();
56914872Seric 
57014872Seric 	if (kmem < 0)
57114872Seric 	{
57224945Seric 		kmem = open("/dev/kmem", 0, 0);
57314872Seric 		if (kmem < 0)
57414872Seric 			return (-1);
57523118Seric 		(void) ioctl(kmem, (int) FIOCLEX, (char *) 0);
57614872Seric 		nlist("/vmunix", Nl);
57714872Seric 		if (Nl[0].n_type == 0)
57814872Seric 			return (-1);
57914872Seric 	}
58024945Seric 	if (lseek(kmem, (off_t) Nl[X_AVENRUN].n_value, 0) == -1 ||
58123118Seric 	    read(kmem, (char *) avenrun, sizeof(avenrun)) < sizeof(avenrun))
58219967Seric 	{
58319967Seric 		/* thank you Ian */
58419967Seric 		return (-1);
58519967Seric 	}
58624943Seric # ifdef sun
58724943Seric 	return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT);
58824943Seric # else
58914872Seric 	return ((int) (avenrun[0] + 0.5));
59024943Seric # endif
59114872Seric }
59214872Seric 
59314872Seric #else VMUNIX
59414872Seric 
59514872Seric getla()
59614872Seric {
59714872Seric 	return (0);
59814872Seric }
59914872Seric 
60014872Seric #endif VMUNIX
60124943Seric /*
60224943Seric **  SHOULDQUEUE -- should this message be queued or sent?
60324943Seric **
60424943Seric **	Compares the message cost to the load average to decide.
60524943Seric **
60624943Seric **	Parameters:
60724943Seric **		pri -- the priority of the message in question.
60824943Seric **
60924943Seric **	Returns:
61024943Seric **		TRUE -- if this message should be queued up for the
61124943Seric **			time being.
61224943Seric **		FALSE -- if the load is low enough to send this message.
61324943Seric **
61424943Seric **	Side Effects:
61524943Seric **		none.
61624943Seric */
61724943Seric 
61824943Seric bool
61924943Seric shouldqueue(pri)
62024943Seric 	long pri;
62124943Seric {
62224943Seric 	int la;
62324943Seric 
62424943Seric 	la = getla();
62524943Seric 	if (la < QueueLA)
62624943Seric 		return (FALSE);
62724943Seric 	return (pri > (QueueFactor / (la - QueueLA + 1)));
62824943Seric }
62924943Seric /*
63024943Seric **  SETPROCTITLE -- set process title for ps
63124943Seric **
63224943Seric **	Parameters:
63324943Seric **		fmt -- a printf style format string.
63424943Seric **		a, b, c -- possible parameters to fmt.
63524943Seric **
63624943Seric **	Returns:
63724943Seric **		none.
63824943Seric **
63924943Seric **	Side Effects:
64024943Seric **		Clobbers argv of our main procedure so ps(1) will
64124943Seric **		display the title.
64224943Seric */
64324943Seric 
64424943Seric /*VARARGS1*/
64524943Seric setproctitle(fmt, a, b, c)
64624943Seric 	char *fmt;
64724943Seric {
64824943Seric # ifdef SETPROCTITLE
64924943Seric 	register char *p;
65025049Seric 	register int i;
65124943Seric 	extern char **Argv;
65224943Seric 	extern char *LastArgv;
65325049Seric 	char buf[MAXLINE];
65424943Seric 
65525049Seric 	(void) sprintf(buf, fmt, a, b, c);
65624943Seric 
65724943Seric 	/* make ps print "(sendmail)" */
65825049Seric 	p = Argv[0];
65924943Seric 	*p++ = '-';
66024943Seric 
66125049Seric 	i = strlen(buf);
66225049Seric 	if (i > LastArgv - p - 2)
66325049Seric 	{
66425049Seric 		i = LastArgv - p - 2;
66525049Seric 		buf[i] = '\0';
66625049Seric 	}
66725049Seric 	(void) strcpy(p, buf);
66825049Seric 	p += i;
66924943Seric 	while (p < LastArgv)
67024943Seric 		*p++ = ' ';
67124943Seric # endif SETPROCTITLE
67224943Seric }
673