xref: /csrg-svn/usr.sbin/sendmail/src/conf.c (revision 4081)
1294Seric # include <stdio.h>
2294Seric # include <pwd.h>
33309Seric # include "sendmail.h"
4404Seric 
5294Seric /*
63309Seric **  CONF.C -- Sendmail Configuration Tables.
7294Seric **
8294Seric **	Defines the configuration of this installation.
9294Seric **
101388Seric **	Compilation Flags:
111388Seric **		NETV6MAIL -- set if you want to use "v6mail" that
121388Seric **			comes with the Berkeley network.  Normally
131388Seric **			/bin/mail will work fine, but around Berkeley
141388Seric **			we use v6mail because it is a "fixed target".
152355Seric **			Also, only v6mail has the "/dev/mail" stuff
162355Seric **			in it (for biff(1)).
171388Seric **		V6 -- running on a version 6 system.  This determines
181388Seric **			whether to define certain routines between
191388Seric **			the two systems.  If you are running a funny
201388Seric **			system, e.g., V6 with long tty names, this
211388Seric **			should be checked carefully.
22294Seric **
231388Seric **	Configuration Variables:
241388Seric **		Mailer -- a table of mailers known to the system.
253438Seric **			This should be fairly static.  The fields are:
261388Seric **			- the pathname of the mailer.
271388Seric **			- a list of flags describing the properties
281388Seric **			  of this mailer:
291388Seric **			   M_FOPT -- if set, the mailer has a picky "-f"
301388Seric **				option.  In this mode, the mailer will
311388Seric **				only accept the "-f" option if the
321388Seric **				sender is actually "root", "network",
331388Seric **				and possibly (but not necessarily) if
341388Seric **				the -f argument matches the real sender.
351388Seric **				The effect is that if the "-f" option
363309Seric **				is given to sendmail then it will be
371388Seric **				passed through (as arguments 1 & 2) to
381388Seric **				the mailer.
391388Seric **			   M_ROPT -- identical to M_FOPT, except uses
401388Seric **				-r instead.
411388Seric **			   M_QUIET -- if set, don't print a message if
421388Seric **				the mailer returns bad status.
431388Seric **			   M_RESTR -- if set, this mailer is restricted
441388Seric **				to use by "daemon"; otherwise, we do a
451388Seric **				setuid(getuid()) before calling the
461388Seric **				mailer.
473185Seric **			   M_NHDR -- if set, the mailer doesn't want us
483185Seric **				to insert a UNIX "From" line before
491388Seric **				outputing.
501388Seric **			   M_NOHOST -- if set, this mailer doesn't care
511388Seric **				about the host part (e.g., the local
521388Seric **				mailer).
531388Seric **			   M_STRIPQ -- if set, strip quote (`"')
541388Seric **				characters out of parameters as you
551388Seric **				transliterate them into the argument
561388Seric **				vector.  For example, the local mailer
571388Seric **				is called directly, so these should be
581388Seric **				stripped, but the program-mailer (i.e.,
591388Seric **				csh) should leave them in.
602897Seric **			   M_NEEDDATE -- this mailer requires a Date:
612897Seric **				field in the message.
622897Seric **			   M_NEEDFROM -- this mailer requires a From:
632897Seric **				field in the message.
642897Seric **			   M_MSGID -- this mailer requires a Message-Id
652897Seric **				field in the message.
663185Seric **			   M_ARPAFMT == M_NEEDDATE|M_NEEDFROM|M_MSGID.
671388Seric **			- an exit status to use as the code for the
681388Seric **			  error message print if the mailer returns
691388Seric **			  something we don't understand.
701388Seric **			- A list of names that are to be considered
711388Seric **			  "local" (and hence are stripped off) for
721388Seric **			  this mailer.
731388Seric **			- An argument vector to be passed to the
743438Seric **			  mailer; this is macro substituted.
751388Seric **			>>>>>>>>>> Entry zero must be for the local
761388Seric **			>> NOTE >> mailer and entry one must be for
771388Seric **			>>>>>>>>>> the shell.
782897Seric **		HdrInfo -- a table describing well-known header fields.
792897Seric **			Each entry has the field name and some flags,
802897Seric **			which can be:
813057Seric **			- H_EOH -- this field is equivalent to a blank
823057Seric **			  line; i.e., it signifies end of header.
833057Seric **			- H_DELETE -- delete this field.
843057Seric **			There is also a field pointing to a pointer
853057Seric **			that should be set to point to this header.
86294Seric */
87294Seric 
88294Seric 
89294Seric 
90294Seric 
91*4081Seric static char SccsId[] = "@(#)conf.c	3.15	08/09/81";
92294Seric 
931388Seric 
941388Seric # include <whoami.h>		/* definitions of machine id's at berkeley */
951388Seric 
961573Seric # ifdef BERKELEY
972355Seric # define NETV6MAIL		/* use /usr/net/bin/v6mail for local delivery */
983061Seric # endif BERKELEY
993061Seric 
1003061Seric 
1013061Seric 
1023046Seric /* local mail -- must be #0 */
1033046Seric static char	*LocalArgv[] =
104294Seric {
1053046Seric 	"...local%mail",
1063046Seric 	"-d",
1073046Seric 	"$u",
1083046Seric 	NULL
1093046Seric };
1103046Seric 
1113046Seric static struct mailer	LocalMailer =
1123046Seric {
113294Seric # ifdef NETV6MAIL
1143185Seric 	"local",	"/usr/net/bin/v6mail",
115294Seric # else
1163185Seric 	"local",	"/bin/mail",
117294Seric # endif
1183185Seric 	M_ROPT|M_NOHOST|M_STRIPQ|M_ARPAFMT|M_MUSER|M_NHDR,
1193185Seric 	EX_NOUSER,	"$f",		LocalArgv,	NULL,
1203046Seric };
1213046Seric 
1223185Seric /* pipes through programs -- must be #1 -- also used for files */
1233046Seric static char	*ProgArgv[] =
1243046Seric {
1253046Seric 	"...prog%mail",
1263046Seric 	"-fc",
1273046Seric 	"$u",
1283046Seric 	NULL
1293046Seric };
1303046Seric 
1313046Seric static struct mailer	ProgMailer =
1323046Seric {
1333185Seric 	"prog",		"/bin/csh",
1343185Seric 	M_NOHOST|M_ARPAFMT,
1353185Seric 	EX_UNAVAILABLE, "$f",		ProgArgv,	NULL,
1363046Seric };
1373046Seric 
1384078Seric /* user-private mailers -- must be #2 */
1394078Seric static char	*PrivArgv[] =
1404078Seric {
1414078Seric 	"...priv%mail",
1424078Seric 	"$u",
1434078Seric 	NULL
1444078Seric };
1454078Seric 
1464078Seric static struct mailer	PrivMailer =
1474078Seric {
1484078Seric 	"priv",		NULL,
1494078Seric 	M_ROPT|M_NOHOST|M_STRIPQ|M_ARPAFMT,
1504078Seric 	EX_UNAVAILABLE,	"$f",		PrivArgv,	NULL,
1514078Seric };
1524078Seric 
1533046Seric /* local berkeley mail */
1543046Seric static char	*BerkArgv[] =
1553046Seric {
1563046Seric 	"...berk%mail",
1573046Seric 	"-m",
1583046Seric 	"$h",
1593232Seric 	"-h",
1603232Seric 	"$c",
1613046Seric 	"-t",
1623046Seric 	"$u",
1633046Seric 	NULL
1643046Seric };
1653046Seric 
1663046Seric static struct mailer	BerkMailer =
1673046Seric {
1683185Seric 	"berk",		"/usr/net/bin/sendberkmail",
1693388Seric 	M_FOPT|M_NEEDDATE|M_FULLNAME|M_STRIPQ,
1703185Seric 	EX_UNAVAILABLE,	"$B:$f",	BerkArgv,	NULL,
1713046Seric };
1723046Seric 
1733046Seric /* arpanet mail */
1743046Seric static char	*ArpaArgv[] =
1753046Seric {
1763046Seric 	"...arpa%mail",
1773046Seric 	"$f",
1783046Seric 	"$h",
1793046Seric 	"$u",
1803046Seric 	NULL
1813046Seric };
1823046Seric 
1833046Seric static struct mailer	ArpaMailer =
1843046Seric {
1853185Seric 	"arpa",		"/usr/lib/mailers/arpa",
1863185Seric 	M_STRIPQ|M_ARPAFMT|M_USR_UPPER,
1873185Seric 	0,		"$f@$A",	ArpaArgv,	NULL,
1883046Seric };
1893046Seric 
1903046Seric /* uucp mail (cheat & use Bell's v7 mail) */
1913046Seric static char	*UucpArgv[] =
1923046Seric {
1933046Seric 	"...uucp%mail",
1943232Seric 	"-",
1953232Seric 	"$h!rmail",
1963232Seric 	"($u)",
1973046Seric 	NULL
198294Seric };
199294Seric 
2003046Seric static struct mailer	UucpMailer =
2013046Seric {
2023232Seric 	"uucp",		"/usr/bin/uux",
2033388Seric 	M_ROPT|M_STRIPQ|M_NEEDDATE|M_FULLNAME|M_MUSER,
2043185Seric 	EX_NOUSER,	"$U!$f",	UucpArgv,	NULL,
2053046Seric };
2063046Seric 
2073046Seric struct mailer	*Mailer[] =
2083046Seric {
2093046Seric 	&LocalMailer,		/* 0 -- must be 0 */
2103046Seric 	&ProgMailer,		/* 1 -- must be 1 */
2114078Seric 	&PrivMailer,		/* 2 -- must be 2 */
2124078Seric 	&BerkMailer,		/* 3 */
2134078Seric 	&ArpaMailer,		/* 4 */
2144078Seric 	&UucpMailer,		/* 5 */
2153144Seric 	NULL
2163046Seric };
2173046Seric 
2184078Seric /* offsets for arbitrary mailers */
2194078Seric # define M_BERK		2	/* berknet */
2204078Seric # define M_ARPA		3	/* arpanet */
2214078Seric # define M_UUCP		4	/* UUCPnet */
222294Seric 
223294Seric 
224294Seric 
2253046Seric 
2262897Seric 
2272897Seric /*
2282897Seric **  Header info table
2293057Seric **	Final (null) entry contains the flags used for any other field.
2302897Seric */
2312897Seric 
2322897Seric struct hdrinfo	HdrInfo[] =
2332897Seric {
2343384Seric 	"date",		H_CHECK,		M_NEEDDATE,
2353384Seric 	"from",		H_CHECK,		M_NEEDFROM,
2363388Seric 	"full-name",	H_ACHECK,		M_FULLNAME,
2373057Seric 	"to",		0,			NULL,
2383057Seric 	"cc",		0,			NULL,
2393057Seric 	"subject",	0,			NULL,
2403384Seric 	"message-id",	H_CHECK,		M_MSGID,
2413057Seric 	"message",	H_EOH,			NULL,
2423057Seric 	NULL,		0,			NULL,
2432897Seric };
244294Seric 
245294Seric # ifdef V6
246294Seric /*
247294Seric **  TTYPATH -- Get the path of the user's tty -- Version 6 version.
248294Seric **
249294Seric **	Returns the pathname of the user's tty.  Returns NULL if
250294Seric **	the user is not logged in or if s/he has write permission
251294Seric **	denied.
252294Seric **
253294Seric **	Parameters:
254294Seric **		none
255294Seric **
256294Seric **	Returns:
257294Seric **		pathname of the user's tty.
258294Seric **		NULL if not logged in or write permission denied.
259294Seric **
260294Seric **	Side Effects:
261294Seric **		none.
262294Seric **
263294Seric **	WARNING:
264294Seric **		Return value is in a local buffer.
265294Seric **
266294Seric **	Called By:
267294Seric **		savemail
268294Seric */
269294Seric 
270294Seric # include <sys/types.h>
271294Seric # include <sys/stat.h>
272294Seric 
273294Seric char *
274294Seric ttypath()
275294Seric {
276294Seric 	struct stat stbuf;
277294Seric 	register int i;
278294Seric 	static char pathn[] = "/dev/ttyx";
279294Seric 
280294Seric 	/* compute the pathname of the controlling tty */
281294Seric 	if ((i = ttyn(2)) == 'x' && (i = ttyn(1)) == 'x' && (i = ttyn(0)) == 'x')
282294Seric 	{
283294Seric 		errno = 0;
284294Seric 		return (NULL);
285294Seric 	}
286294Seric 	pathn[8] = i;
287294Seric 
288294Seric 	/* see if we have write permission */
2892967Seric 	if (stat(pathn, &stbuf) < 0 || !bitset(02, stbuf.st_mode))
290294Seric 	{
291294Seric 		errno = 0;
292294Seric 		return (NULL);
293294Seric 	}
294294Seric 
295294Seric 	/* see if the user is logged in */
296294Seric 	if (getlogin() == NULL)
297294Seric 		return (NULL);
298294Seric 
299294Seric 	/* looks good */
300294Seric 	return (pathn);
301294Seric }
302294Seric /*
303294Seric **  FDOPEN -- Open a stdio file given an open file descriptor.
304294Seric **
305294Seric **	This is included here because it is standard in v7, but we
306294Seric **	need it in v6.
307294Seric **
308294Seric **	Algorithm:
309294Seric **		Open /dev/null to create a descriptor.
310294Seric **		Close that descriptor.
311294Seric **		Copy the existing fd into the descriptor.
312294Seric **
313294Seric **	Parameters:
314294Seric **		fd -- the open file descriptor.
315294Seric **		type -- "r", "w", or whatever.
316294Seric **
317294Seric **	Returns:
318294Seric **		The file descriptor it creates.
319294Seric **
320294Seric **	Side Effects:
321294Seric **		none
322294Seric **
323294Seric **	Called By:
324294Seric **		deliver
325294Seric **
326294Seric **	Notes:
327294Seric **		The mode of fd must match "type".
328294Seric */
329294Seric 
330294Seric FILE *
331294Seric fdopen(fd, type)
332294Seric 	int fd;
333294Seric 	char *type;
334294Seric {
335294Seric 	register FILE *f;
336294Seric 
337294Seric 	f = fopen("/dev/null", type);
338*4081Seric 	(void) close(fileno(f));
339294Seric 	fileno(f) = fd;
340294Seric 	return (f);
341294Seric }
342294Seric /*
343294Seric **  INDEX -- Return pointer to character in string
344294Seric **
345294Seric **	For V7 compatibility.
346294Seric **
347294Seric **	Parameters:
348294Seric **		s -- a string to scan.
349294Seric **		c -- a character to look for.
350294Seric **
351294Seric **	Returns:
352294Seric **		If c is in s, returns the address of the first
353294Seric **			instance of c in s.
354294Seric **		NULL if c is not in s.
355294Seric **
356294Seric **	Side Effects:
357294Seric **		none.
358294Seric */
359294Seric 
360294Seric index(s, c)
361294Seric 	register char *s;
362294Seric 	register char c;
363294Seric {
364294Seric 	while (*s != '\0')
365294Seric 	{
366294Seric 		if (*s++ == c)
367294Seric 			return (--s);
368294Seric 	}
369294Seric 	return (NULL);
370294Seric }
371294Seric # endif V6
372294Seric 
373294Seric # ifndef V6
374294Seric /*
375294Seric **  TTYPATH -- Get the path of the user's tty -- Version 7 version.
376294Seric **
377294Seric **	Returns the pathname of the user's tty.  Returns NULL if
378294Seric **	the user is not logged in or if s/he has write permission
379294Seric **	denied.
380294Seric **
381294Seric **	Parameters:
382294Seric **		none
383294Seric **
384294Seric **	Returns:
385294Seric **		pathname of the user's tty.
386294Seric **		NULL if not logged in or write permission denied.
387294Seric **
388294Seric **	Side Effects:
389294Seric **		none.
390294Seric **
391294Seric **	WARNING:
392294Seric **		Return value is in a local buffer.
393294Seric **
394294Seric **	Called By:
395294Seric **		savemail
396294Seric */
397294Seric 
398294Seric # include <sys/types.h>
399294Seric # include <sys/stat.h>
400294Seric 
401294Seric char *
402294Seric ttypath()
403294Seric {
404294Seric 	struct stat stbuf;
405294Seric 	register char *pathn;
406294Seric 	extern char *ttyname();
407*4081Seric 	extern char *getlogin();
408294Seric 
409294Seric 	/* compute the pathname of the controlling tty */
410294Seric 	if ((pathn = ttyname(2)) == NULL && (pathn = ttyname(1)) == NULL && (pathn = ttyname(0)) == NULL)
411294Seric 	{
412294Seric 		errno = 0;
413294Seric 		return (NULL);
414294Seric 	}
415294Seric 
416294Seric 	/* see if we have write permission */
4172967Seric 	if (stat(pathn, &stbuf) < 0 || !bitset(02, stbuf.st_mode))
418294Seric 	{
419294Seric 		errno = 0;
420294Seric 		return (NULL);
421294Seric 	}
422294Seric 
423294Seric 	/* see if the user is logged in */
424294Seric 	if (getlogin() == NULL)
425294Seric 		return (NULL);
426294Seric 
427294Seric 	/* looks good */
428294Seric 	return (pathn);
429294Seric }
430294Seric # endif V6
4312967Seric /*
4322967Seric **  CHECKCOMPAT -- check for From and To person compatible.
4332967Seric **
4342967Seric **	This routine can be supplied on a per-installation basis
4352967Seric **	to determine whether a person is allowed to send a message.
4362967Seric **	This allows restriction of certain types of internet
4372967Seric **	forwarding or registration of users.
4382967Seric **
4392967Seric **	If the hosts are found to be incompatible, an error
4402967Seric **	message should be given using "usrerr" and FALSE should
4412967Seric **	be returned.
4422967Seric **
4432967Seric **	Parameters:
4442967Seric **		to -- the person being sent to.
4452967Seric **
4462967Seric **	Returns:
4472967Seric **		TRUE -- ok to send.
4482967Seric **		FALSE -- not ok.
4492967Seric **
4502967Seric **	Side Effects:
4512967Seric **		none (unless you include the usrerr stuff)
4522967Seric */
4532967Seric 
4542967Seric bool
4552967Seric checkcompat(to)
4562967Seric 	register ADDRESS *to;
4572967Seric {
458*4081Seric # ifdef lint
459*4081Seric 	ADDRESS *x = to;
460*4081Seric 
461*4081Seric 	to = x;
462*4081Seric # endif lint
463*4081Seric 
4642967Seric 	return (TRUE);
4652967Seric }
466