xref: /csrg-svn/usr.sbin/sendmail/src/conf.c (revision 25008)
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*25008Seric static char	SccsId[] = "@(#)conf.c	5.8 (Berkeley) 09/21/85";
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,
699055Seric 	"sender",		H_FROM,
709055Seric 	"from",			H_FROM,
719055Seric 	"full-name",		H_ACHECK,
729055Seric 	"return-receipt-to",	H_FROM,
739055Seric 	"errors-to",		H_FROM,
748060Seric 		/* destination fields */
759055Seric 	"to",			H_RCPT,
7611417Seric 	"resent-to",		H_RCPT|H_RESENT,
779055Seric 	"cc",			H_RCPT,
7811417Seric 	"resent-cc",		H_RCPT|H_RESENT,
799055Seric 	"bcc",			H_RCPT|H_ACHECK,
8011417Seric 	"resent-bcc",		H_RCPT|H_ACHECK|H_RESENT,
818060Seric 		/* message identification and control */
8211417Seric 	"message-id",		0,
8311417Seric 	"resent-message-id",	H_RESENT,
849055Seric 	"message",		H_EOH,
859055Seric 	"text",			H_EOH,
8611417Seric 		/* date fields */
8711417Seric 	"date",			0,
8811417Seric 	"resent-date",		H_RESENT,
898060Seric 		/* trace fields */
909055Seric 	"received",		H_TRACE|H_FORCE,
919055Seric 	"via",			H_TRACE|H_FORCE,
929055Seric 	"mail-from",		H_TRACE|H_FORCE,
938060Seric 
949055Seric 	NULL,			0,
952897Seric };
964166Seric 
974166Seric 
984166Seric /*
994166Seric **  ARPANET error message numbers.
1004166Seric */
1014166Seric 
1027956Seric char	Arpa_Info[] =		"050";	/* arbitrary info */
1037956Seric char	Arpa_TSyserr[] =	"451";	/* some (transient) system error */
1047956Seric char	Arpa_PSyserr[] =	"554";	/* some (permanent) system error */
1057956Seric char	Arpa_Usrerr[] =		"554";	/* some (fatal) user error */
1064282Seric 
1074282Seric 
1084282Seric 
1094282Seric /*
1104282Seric **  Location of system files/databases/etc.
1114282Seric */
1124282Seric 
1134282Seric char	*ConfFile =	"/usr/lib/sendmail.cf";	/* runtime configuration */
1149064Seric char	*FreezeFile =	"/usr/lib/sendmail.fc";	/* frozen version of above */
1159039Seric 
1169064Seric 
1179064Seric 
1189039Seric /*
11924943Seric **  Miscellaneous stuff.
1209039Seric */
1219039Seric 
12224943Seric int	DtableSize =	50;		/* max open files; reset in 4.2bsd */
12324943Seric /*
12424943Seric **  SETDEFAULTS -- set default values
12524943Seric **
12624943Seric **	Because of the way freezing is done, these must be initialized
12724943Seric **	using direct code.
12824943Seric **
12924943Seric **	Parameters:
13024943Seric **		none.
13124943Seric **
13224943Seric **	Returns:
13324943Seric **		none.
13424943Seric **
13524943Seric **	Side Effects:
13624943Seric **		Initializes a bunch of global variables to their
13724943Seric **		default values.
13824943Seric */
13924943Seric 
14024943Seric setdefaults()
14124943Seric {
14224943Seric 	QueueLA = 8;
14324943Seric 	QueueFactor = 10000;
14424943Seric 	RefuseLA = 12;
14524943Seric 	SpaceSub = ' ';
14624981Seric 	WkRecipFact = 1000;
14724981Seric 	WkClassFact = 1800;
148*25008Seric 	WkTimeFact = 600;
14924981Seric 	FileMode = 0644;
15024981Seric 	DefUid = 1;
15124981Seric 	DefGid = 1;
15224943Seric }
153294Seric 
154294Seric # ifdef V6
155294Seric /*
1564190Seric **  TTYNAME -- return name of terminal.
157294Seric **
158294Seric **	Parameters:
1594190Seric **		fd -- file descriptor to check.
160294Seric **
161294Seric **	Returns:
1624190Seric **		pointer to full path of tty.
1634190Seric **		NULL if no tty.
164294Seric **
165294Seric **	Side Effects:
166294Seric **		none.
167294Seric */
168294Seric 
169294Seric char *
1704190Seric ttyname(fd)
1714190Seric 	int fd;
172294Seric {
1734190Seric 	register char tn;
174294Seric 	static char pathn[] = "/dev/ttyx";
175294Seric 
176294Seric 	/* compute the pathname of the controlling tty */
1774190Seric 	if ((tn = ttyn(fd)) == NULL)
178294Seric 	{
179294Seric 		errno = 0;
180294Seric 		return (NULL);
181294Seric 	}
1824190Seric 	pathn[8] = tn;
183294Seric 	return (pathn);
184294Seric }
185294Seric /*
186294Seric **  FDOPEN -- Open a stdio file given an open file descriptor.
187294Seric **
188294Seric **	This is included here because it is standard in v7, but we
189294Seric **	need it in v6.
190294Seric **
191294Seric **	Algorithm:
192294Seric **		Open /dev/null to create a descriptor.
193294Seric **		Close that descriptor.
194294Seric **		Copy the existing fd into the descriptor.
195294Seric **
196294Seric **	Parameters:
197294Seric **		fd -- the open file descriptor.
198294Seric **		type -- "r", "w", or whatever.
199294Seric **
200294Seric **	Returns:
201294Seric **		The file descriptor it creates.
202294Seric **
203294Seric **	Side Effects:
204294Seric **		none
205294Seric **
206294Seric **	Called By:
207294Seric **		deliver
208294Seric **
209294Seric **	Notes:
210294Seric **		The mode of fd must match "type".
211294Seric */
212294Seric 
213294Seric FILE *
214294Seric fdopen(fd, type)
215294Seric 	int fd;
216294Seric 	char *type;
217294Seric {
218294Seric 	register FILE *f;
219294Seric 
220294Seric 	f = fopen("/dev/null", type);
2214081Seric 	(void) close(fileno(f));
222294Seric 	fileno(f) = fd;
223294Seric 	return (f);
224294Seric }
225294Seric /*
226294Seric **  INDEX -- Return pointer to character in string
227294Seric **
228294Seric **	For V7 compatibility.
229294Seric **
230294Seric **	Parameters:
231294Seric **		s -- a string to scan.
232294Seric **		c -- a character to look for.
233294Seric **
234294Seric **	Returns:
235294Seric **		If c is in s, returns the address of the first
236294Seric **			instance of c in s.
237294Seric **		NULL if c is not in s.
238294Seric **
239294Seric **	Side Effects:
240294Seric **		none.
241294Seric */
242294Seric 
2434437Seric char *
244294Seric index(s, c)
245294Seric 	register char *s;
246294Seric 	register char c;
247294Seric {
248294Seric 	while (*s != '\0')
249294Seric 	{
250294Seric 		if (*s++ == c)
251294Seric 			return (--s);
252294Seric 	}
253294Seric 	return (NULL);
254294Seric }
2554326Seric /*
2564326Seric **  UMASK -- fake the umask system call.
2574326Seric **
2584326Seric **	Since V6 always acts like the umask is zero, we will just
2594326Seric **	assume the same thing.
2604326Seric */
2614326Seric 
2624326Seric /*ARGSUSED*/
2634326Seric umask(nmask)
2644326Seric {
2654326Seric 	return (0);
2664326Seric }
2674326Seric 
2684326Seric 
2694326Seric /*
2704326Seric **  GETRUID -- get real user id.
2714326Seric */
2724326Seric 
2734326Seric getruid()
2744326Seric {
2754326Seric 	return (getuid() & 0377);
2764326Seric }
2774326Seric 
2784326Seric 
2794326Seric /*
2804326Seric **  GETRGID -- get real group id.
2814326Seric */
2824326Seric 
2834326Seric getrgid()
2844326Seric {
2854326Seric 	return (getgid() & 0377);
2864326Seric }
2874326Seric 
2884326Seric 
2894326Seric /*
2904326Seric **  GETEUID -- get effective user id.
2914326Seric */
2924326Seric 
2934326Seric geteuid()
2944326Seric {
2954326Seric 	return ((getuid() >> 8) & 0377);
2964326Seric }
2974326Seric 
2984326Seric 
2994326Seric /*
3004326Seric **  GETEGID -- get effective group id.
3014326Seric */
3024326Seric 
3034326Seric getegid()
3044326Seric {
3054326Seric 	return ((getgid() >> 8) & 0377);
3064326Seric }
3074326Seric 
308294Seric # endif V6
3094326Seric 
3104326Seric # ifndef V6
3114326Seric 
3124326Seric /*
3134326Seric **  GETRUID -- get real user id (V7)
3144326Seric */
3154326Seric 
3164326Seric getruid()
3174326Seric {
3189274Seric 	if (OpMode == MD_DAEMON)
3194536Seric 		return (RealUid);
3204536Seric 	else
3214536Seric 		return (getuid());
3224326Seric }
3234326Seric 
3244326Seric 
3254326Seric /*
3264326Seric **  GETRGID -- get real group id (V7).
3274326Seric */
3284326Seric 
3294326Seric getrgid()
3304326Seric {
3319274Seric 	if (OpMode == MD_DAEMON)
3324536Seric 		return (RealGid);
3334536Seric 	else
3344536Seric 		return (getgid());
3354326Seric }
3364326Seric 
3374326Seric # endif V6
3384190Seric /*
3399369Seric **  USERNAME -- return the user id of the logged in user.
3409369Seric **
3419369Seric **	Parameters:
3429369Seric **		none.
3439369Seric **
3449369Seric **	Returns:
3459369Seric **		The login name of the logged in user.
3469369Seric **
3479369Seric **	Side Effects:
3489369Seric **		none.
3499369Seric **
3509369Seric **	Notes:
3519369Seric **		The return value is statically allocated.
3529369Seric */
3539369Seric 
3549369Seric char *
3559369Seric username()
3569369Seric {
35717469Seric 	static char *myname = NULL;
3589369Seric 	extern char *getlogin();
35919904Smiriam 	register struct passwd *pw;
36019904Smiriam 	extern struct passwd *getpwuid();
3619369Seric 
36217469Seric 	/* cache the result */
36317469Seric 	if (myname == NULL)
36417469Seric 	{
36517469Seric 		myname = getlogin();
36617469Seric 		if (myname == NULL || myname[0] == '\0')
36717469Seric 		{
36817469Seric 
36917469Seric 			pw = getpwuid(getruid());
37017469Seric 			if (pw != NULL)
37117469Seric 				myname = pw->pw_name;
37217469Seric 		}
37319904Smiriam 		else
37419904Smiriam 		{
37519873Smiriam 
37619873Smiriam 			pw = getpwnam(myname);
37719904Smiriam 			if(getuid() != pw->pw_uid)
37819904Smiriam 			{
37919873Smiriam 				pw = getpwuid(getuid());
38024945Seric 				if (pw != NULL)
38124945Seric 					myname = pw->pw_name;
38219873Smiriam 			}
38319873Smiriam 		}
38417469Seric 		if (myname == NULL || myname[0] == '\0')
38517469Seric 		{
38617469Seric 			syserr("Who are you?");
38717469Seric 			myname = "postmaster";
38817469Seric 		}
38917469Seric 	}
39017469Seric 
39117469Seric 	return (myname);
3929369Seric }
3939369Seric /*
3944190Seric **  TTYPATH -- Get the path of the user's tty
395294Seric **
396294Seric **	Returns the pathname of the user's tty.  Returns NULL if
397294Seric **	the user is not logged in or if s/he has write permission
398294Seric **	denied.
399294Seric **
400294Seric **	Parameters:
401294Seric **		none
402294Seric **
403294Seric **	Returns:
404294Seric **		pathname of the user's tty.
405294Seric **		NULL if not logged in or write permission denied.
406294Seric **
407294Seric **	Side Effects:
408294Seric **		none.
409294Seric **
410294Seric **	WARNING:
411294Seric **		Return value is in a local buffer.
412294Seric **
413294Seric **	Called By:
414294Seric **		savemail
415294Seric */
416294Seric 
417294Seric # include <sys/stat.h>
418294Seric 
419294Seric char *
420294Seric ttypath()
421294Seric {
422294Seric 	struct stat stbuf;
423294Seric 	register char *pathn;
424294Seric 	extern char *ttyname();
4254081Seric 	extern char *getlogin();
426294Seric 
427294Seric 	/* compute the pathname of the controlling tty */
4289369Seric 	if ((pathn = ttyname(2)) == NULL && (pathn = ttyname(1)) == NULL &&
4299369Seric 	    (pathn = ttyname(0)) == NULL)
430294Seric 	{
431294Seric 		errno = 0;
432294Seric 		return (NULL);
433294Seric 	}
434294Seric 
435294Seric 	/* see if we have write permission */
4362967Seric 	if (stat(pathn, &stbuf) < 0 || !bitset(02, stbuf.st_mode))
437294Seric 	{
438294Seric 		errno = 0;
439294Seric 		return (NULL);
440294Seric 	}
441294Seric 
442294Seric 	/* see if the user is logged in */
443294Seric 	if (getlogin() == NULL)
444294Seric 		return (NULL);
445294Seric 
446294Seric 	/* looks good */
447294Seric 	return (pathn);
448294Seric }
4492967Seric /*
4502967Seric **  CHECKCOMPAT -- check for From and To person compatible.
4512967Seric **
4522967Seric **	This routine can be supplied on a per-installation basis
4532967Seric **	to determine whether a person is allowed to send a message.
4542967Seric **	This allows restriction of certain types of internet
4552967Seric **	forwarding or registration of users.
4562967Seric **
4572967Seric **	If the hosts are found to be incompatible, an error
4582967Seric **	message should be given using "usrerr" and FALSE should
4592967Seric **	be returned.
4602967Seric **
4614288Seric **	'NoReturn' can be set to suppress the return-to-sender
4624288Seric **	function; this should be done on huge messages.
4634288Seric **
4642967Seric **	Parameters:
4652967Seric **		to -- the person being sent to.
4662967Seric **
4672967Seric **	Returns:
4682967Seric **		TRUE -- ok to send.
4692967Seric **		FALSE -- not ok.
4702967Seric **
4712967Seric **	Side Effects:
4722967Seric **		none (unless you include the usrerr stuff)
4732967Seric */
4742967Seric 
4752967Seric bool
4762967Seric checkcompat(to)
4772967Seric 	register ADDRESS *to;
4782967Seric {
47912133Seric # ifdef lint
48012133Seric 	if (to == NULL)
48112133Seric 		to++;
48212133Seric # endif lint
48310698Seric # ifdef EXAMPLE_CODE
48410698Seric 	/* this code is intended as an example only */
4854437Seric 	register STAB *s;
4864437Seric 
4874437Seric 	s = stab("arpa", ST_MAILER, ST_FIND);
4889369Seric 	if (s != NULL && CurEnv->e_from.q_mailer != LocalMailer &&
4899369Seric 	    to->q_mailer == s->s_mailer)
4904437Seric 	{
4914437Seric 		usrerr("No ARPA mail through this machine: see your system administration");
49210698Seric 		/* NoReturn = TRUE; to supress return copy */
4934437Seric 		return (FALSE);
4944437Seric 	}
49510698Seric # endif EXAMPLE_CODE
4962967Seric 	return (TRUE);
4972967Seric }
4989369Seric /*
4999369Seric **  HOLDSIGS -- arrange to hold all signals
5009369Seric **
5019369Seric **	Parameters:
5029369Seric **		none.
5039369Seric **
5049369Seric **	Returns:
5059369Seric **		none.
5069369Seric **
5079369Seric **	Side Effects:
5089369Seric **		Arranges that signals are held.
5099369Seric */
5109369Seric 
5119369Seric holdsigs()
5129369Seric {
5139369Seric }
5149369Seric /*
5159369Seric **  RLSESIGS -- arrange to release all signals
5169369Seric **
5179369Seric **	This undoes the effect of holdsigs.
5189369Seric **
5199369Seric **	Parameters:
5209369Seric **		none.
5219369Seric **
5229369Seric **	Returns:
5239369Seric **		none.
5249369Seric **
5259369Seric **	Side Effects:
5269369Seric **		Arranges that signals are released.
5279369Seric */
5289369Seric 
5299369Seric rlsesigs()
5309369Seric {
5319369Seric }
53214872Seric /*
53314872Seric **  GETLA -- get the current load average
53414872Seric **
53514881Seric **	This code stolen from la.c.
53614881Seric **
53714872Seric **	Parameters:
53814872Seric **		none.
53914872Seric **
54014872Seric **	Returns:
54114872Seric **		The current load average as an integer.
54214872Seric **
54314872Seric **	Side Effects:
54414872Seric **		none.
54514872Seric */
54614872Seric 
54714872Seric #ifdef VMUNIX
54814872Seric 
54914872Seric #include <nlist.h>
55014872Seric 
55114872Seric struct	nlist Nl[] =
55214872Seric {
55314872Seric 	{ "_avenrun" },
55414872Seric #define	X_AVENRUN	0
55514872Seric 	{ 0 },
55614872Seric };
55714872Seric 
55814872Seric getla()
55914872Seric {
56014872Seric 	static int kmem = -1;
56124943Seric # ifdef sun
56224943Seric 	long avenrun[3];
56324943Seric # else
56414872Seric 	double avenrun[3];
56524943Seric # endif
56614872Seric 
56714872Seric 	if (kmem < 0)
56814872Seric 	{
56924945Seric 		kmem = open("/dev/kmem", 0, 0);
57014872Seric 		if (kmem < 0)
57114872Seric 			return (-1);
57223118Seric 		(void) ioctl(kmem, (int) FIOCLEX, (char *) 0);
57314872Seric 		nlist("/vmunix", Nl);
57414872Seric 		if (Nl[0].n_type == 0)
57514872Seric 			return (-1);
57614872Seric 	}
57724945Seric 	if (lseek(kmem, (off_t) Nl[X_AVENRUN].n_value, 0) == -1 ||
57823118Seric 	    read(kmem, (char *) avenrun, sizeof(avenrun)) < sizeof(avenrun))
57919967Seric 	{
58019967Seric 		/* thank you Ian */
58119967Seric 		return (-1);
58219967Seric 	}
58324943Seric # ifdef sun
58424943Seric 	return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT);
58524943Seric # else
58614872Seric 	return ((int) (avenrun[0] + 0.5));
58724943Seric # endif
58814872Seric }
58914872Seric 
59014872Seric #else VMUNIX
59114872Seric 
59214872Seric getla()
59314872Seric {
59414872Seric 	return (0);
59514872Seric }
59614872Seric 
59714872Seric #endif VMUNIX
59824943Seric /*
59924943Seric **  SHOULDQUEUE -- should this message be queued or sent?
60024943Seric **
60124943Seric **	Compares the message cost to the load average to decide.
60224943Seric **
60324943Seric **	Parameters:
60424943Seric **		pri -- the priority of the message in question.
60524943Seric **
60624943Seric **	Returns:
60724943Seric **		TRUE -- if this message should be queued up for the
60824943Seric **			time being.
60924943Seric **		FALSE -- if the load is low enough to send this message.
61024943Seric **
61124943Seric **	Side Effects:
61224943Seric **		none.
61324943Seric */
61424943Seric 
61524943Seric bool
61624943Seric shouldqueue(pri)
61724943Seric 	long pri;
61824943Seric {
61924943Seric 	int la;
62024943Seric 
62124943Seric 	la = getla();
62224943Seric 	if (la < QueueLA)
62324943Seric 		return (FALSE);
62424943Seric 	return (pri > (QueueFactor / (la - QueueLA + 1)));
62524943Seric }
62624943Seric /*
62724943Seric **  SETPROCTITLE -- set process title for ps
62824943Seric **
62924943Seric **	Parameters:
63024943Seric **		fmt -- a printf style format string.
63124943Seric **		a, b, c -- possible parameters to fmt.
63224943Seric **
63324943Seric **	Returns:
63424943Seric **		none.
63524943Seric **
63624943Seric **	Side Effects:
63724943Seric **		Clobbers argv of our main procedure so ps(1) will
63824943Seric **		display the title.
63924943Seric */
64024943Seric 
64124943Seric /*VARARGS1*/
64224943Seric setproctitle(fmt, a, b, c)
64324943Seric 	char *fmt;
64424943Seric {
64524943Seric # ifdef SETPROCTITLE
64624943Seric 	register char *p;
64724943Seric 	extern char **Argv;
64824943Seric 	extern char *LastArgv;
64924943Seric 
65024943Seric 	p = Argv[0];
65124943Seric 
65224943Seric 	/* make ps print "(sendmail)" */
65324943Seric 	*p++ = '-';
65424943Seric 
65524943Seric 	(void) sprintf(p, fmt, a, b, c);
65624943Seric 	p += strlen(p);
65724943Seric 
65824943Seric 	/* avoid confusing ps */
65924943Seric 	while (p < LastArgv)
66024943Seric 		*p++ = ' ';
66124943Seric # endif SETPROCTITLE
66224943Seric }
663