[net.bugs.4bsd] flaw in sendmail

piet@mcvax.UUCP (Piet Beertema) (01/21/86)

Consider the following cases of a class definition in sendmail.cf:

1) CLxxx yyy zzz
2) FLfoo %[xyz ]

where file "foo" contains "xxx yyy zzz".

In case 1) class L contains members xxx, yyy and zzz. In case 2) however
class L will *not* contain those separate members; instead it contains
only one member "xxx yyy zzz" (which is according to the manual). But it
turns out that in the course of the rewriting the class is treated as
containing only "xxx" (which the manual does not say).
Intuitively though, you would expect both cases to yield the same class.

An example of when this comes to hand is when you use your /etc/hosts file
to define a class of LAN hosts, *including* all their nicknames, so you
don't have to enter each of them in your sendmail.cf (and perhaps change
it time and again). E.g. assuming your local network number is 99:

FL/etc/hosts 99.%*s %[	 -1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz]

will do the job.


The fix for making it work as expected is easy: in readcf.c replace the
routine fileclass() with the following code:

fileclass(class, filename, fmt)
	int class;
	char *filename;
	char *fmt;
{
	register char *p;
	register FILE *f;
	char buf[MAXLINE], wordbuf[MAXLINE];

	f = fopen(filename, "r");
	if (f == NULL)
	{
		syserr("cannot open %s", filename);
		return;
	}

	while (fgets(buf, sizeof buf, f) != NULL)
	{
		if (sscanf(buf, fmt, wordbuf) != 1)
			continue;
		/* scan possible list of words and set class for all */
		for (p = wordbuf; *p != '\0'; )
		{
			register char *wd;
			char delim;

			while (*p != '\0' && isspace(*p))
				p++;
			wd = p;
			while (*p != '\0' && !isspace(*p))
				p++;
			delim = *p;
			*p = '\0';
			if (wd[0] != '\0')
				setclass(class, wd);
			*p = delim;
		}
	}

	(void) fclose(f);
}


-- 
	Piet Beertema, CWI, Amsterdam
	(piet@mcvax.UUCP)