xref: /illumos-gate/usr/src/cmd/sendmail/src/alias.c (revision fec46055)
1 /*
2  * Copyright (c) 1998-2003 Sendmail, Inc. and its suppliers.
3  *	All rights reserved.
4  * Copyright (c) 1983, 1995-1997 Eric P. Allman.  All rights reserved.
5  * Copyright (c) 1988, 1993
6  *	The Regents of the University of California.  All rights reserved.
7  *
8  * By using this file, you agree to the terms and conditions set
9  * forth in the LICENSE file which can be found at the top level of
10  * the sendmail distribution.
11  *
12  */
13 
14 #include <sendmail.h>
15 
16 SM_RCSID("@(#)$Id: alias.c,v 8.219 2006/10/24 18:04:09 ca Exp $")
17 
18 #define SEPARATOR ':'
19 # define ALIAS_SPEC_SEPARATORS	" ,/:"
20 
21 static MAP	*AliasFileMap = NULL;	/* the actual aliases.files map */
22 static int	NAliasFileMaps;	/* the number of entries in AliasFileMap */
23 
24 static char	*aliaslookup __P((char *, int *, char *));
25 
26 /*
27 **  ALIAS -- Compute aliases.
28 **
29 **	Scans the alias file for an alias for the given address.
30 **	If found, it arranges to deliver to the alias list instead.
31 **	Uses libdbm database if -DDBM.
32 **
33 **	Parameters:
34 **		a -- address to alias.
35 **		sendq -- a pointer to the head of the send queue
36 **			to put the aliases in.
37 **		aliaslevel -- the current alias nesting depth.
38 **		e -- the current envelope.
39 **
40 **	Returns:
41 **		none
42 **
43 **	Side Effects:
44 **		Aliases found are expanded.
45 **
46 **	Deficiencies:
47 **		It should complain about names that are aliased to
48 **			nothing.
49 */
50 
51 void
alias(a,sendq,aliaslevel,e)52 alias(a, sendq, aliaslevel, e)
53 	register ADDRESS *a;
54 	ADDRESS **sendq;
55 	int aliaslevel;
56 	register ENVELOPE *e;
57 {
58 	register char *p;
59 	char *owner;
60 	auto int status = EX_OK;
61 	char obuf[MAXNAME + 7];
62 
63 	if (tTd(27, 1))
64 		sm_dprintf("alias(%s)\n", a->q_user);
65 
66 	/* don't realias already aliased names */
67 	if (!QS_IS_OK(a->q_state))
68 		return;
69 
70 	if (NoAlias)
71 		return;
72 
73 	e->e_to = a->q_paddr;
74 
75 	/*
76 	**  Look up this name.
77 	**
78 	**	If the map was unavailable, we will queue this message
79 	**	until the map becomes available; otherwise, we could
80 	**	bounce messages inappropriately.
81 	*/
82 
83 #if _FFR_REDIRECTEMPTY
84 	/*
85 	**  envelope <> can't be sent to mailing lists, only owner-
86 	**  send spam of this type to owner- of the list
87 	**  ----  to stop spam from going to mailing lists!
88 	*/
89 
90 	if (e->e_sender != NULL && *e->e_sender == '\0')
91 	{
92 		/* Look for owner of alias */
93 		(void) sm_strlcpyn(obuf, sizeof(obuf), 2, "owner-", a->q_user);
94 		if (aliaslookup(obuf, &status, a->q_host) != NULL)
95 		{
96 			if (LogLevel > 8)
97 				sm_syslog(LOG_WARNING, e->e_id,
98 				       "possible spam from <> to list: %s, redirected to %s\n",
99 				       a->q_user, obuf);
100 			a->q_user = sm_rpool_strdup_x(e->e_rpool, obuf);
101 		}
102 	}
103 #endif /* _FFR_REDIRECTEMPTY */
104 
105 	p = aliaslookup(a->q_user, &status, a->q_host);
106 	if (status == EX_TEMPFAIL || status == EX_UNAVAILABLE)
107 	{
108 		a->q_state = QS_QUEUEUP;
109 		if (e->e_message == NULL)
110 			e->e_message = sm_rpool_strdup_x(e->e_rpool,
111 						"alias database unavailable");
112 
113 		/* XXX msg only per recipient? */
114 		if (a->q_message == NULL)
115 			a->q_message = "alias database unavailable";
116 		return;
117 	}
118 	if (p == NULL)
119 		return;
120 
121 	/*
122 	**  Match on Alias.
123 	**	Deliver to the target list.
124 	*/
125 
126 	if (tTd(27, 1))
127 		sm_dprintf("%s (%s, %s) aliased to %s\n",
128 			   a->q_paddr, a->q_host, a->q_user, p);
129 	if (bitset(EF_VRFYONLY, e->e_flags))
130 	{
131 		a->q_state = QS_VERIFIED;
132 		return;
133 	}
134 	message("aliased to %s", shortenstring(p, MAXSHORTSTR));
135 	if (LogLevel > 10)
136 		sm_syslog(LOG_INFO, e->e_id,
137 			  "alias %.100s => %s",
138 			  a->q_paddr, shortenstring(p, MAXSHORTSTR));
139 	a->q_flags &= ~QSELFREF;
140 	if (tTd(27, 5))
141 	{
142 		sm_dprintf("alias: QS_EXPANDED ");
143 		printaddr(sm_debug_file(), a, false);
144 	}
145 	a->q_state = QS_EXPANDED;
146 
147 	/*
148 	**  Always deliver aliased items as the default user.
149 	**  Setting q_gid to 0 forces deliver() to use DefUser
150 	**  instead of the alias name for the call to initgroups().
151 	*/
152 
153 	a->q_uid = DefUid;
154 	a->q_gid = 0;
155 	a->q_fullname = NULL;
156 	a->q_flags |= QGOODUID|QALIAS;
157 
158 	(void) sendtolist(p, a, sendq, aliaslevel + 1, e);
159 
160 	if (bitset(QSELFREF, a->q_flags) && QS_IS_EXPANDED(a->q_state))
161 		a->q_state = QS_OK;
162 
163 	/*
164 	**  Look for owner of alias
165 	*/
166 
167 	if (strncmp(a->q_user, "owner-", 6) == 0 ||
168 	    strlen(a->q_user) > sizeof(obuf) - 7)
169 		(void) sm_strlcpy(obuf, "owner-owner", sizeof(obuf));
170 	else
171 		(void) sm_strlcpyn(obuf, sizeof(obuf), 2, "owner-", a->q_user);
172 	owner = aliaslookup(obuf, &status, a->q_host);
173 	if (owner == NULL)
174 		return;
175 
176 	/* reflect owner into envelope sender */
177 	if (strpbrk(owner, ",:/|\"") != NULL)
178 		owner = obuf;
179 	a->q_owner = sm_rpool_strdup_x(e->e_rpool, owner);
180 
181 	/* announce delivery to this alias; NORECEIPT bit set later */
182 	if (e->e_xfp != NULL)
183 		(void) sm_io_fprintf(e->e_xfp, SM_TIME_DEFAULT,
184 				"Message delivered to mailing list %s\n",
185 				a->q_paddr);
186 	e->e_flags |= EF_SENDRECEIPT;
187 	a->q_flags |= QDELIVERED|QEXPANDED;
188 }
189 /*
190 **  ALIASLOOKUP -- look up a name in the alias file.
191 **
192 **	Parameters:
193 **		name -- the name to look up.
194 **		pstat -- a pointer to a place to put the status.
195 **		av -- argument for %1 expansion.
196 **
197 **	Returns:
198 **		the value of name.
199 **		NULL if unknown.
200 **
201 **	Side Effects:
202 **		none.
203 **
204 **	Warnings:
205 **		The return value will be trashed across calls.
206 */
207 
208 static char *
aliaslookup(name,pstat,av)209 aliaslookup(name, pstat, av)
210 	char *name;
211 	int *pstat;
212 	char *av;
213 {
214 	static MAP *map = NULL;
215 #if _FFR_ALIAS_DETAIL
216 	int i;
217 	char *argv[4];
218 #endif /* _FFR_ALIAS_DETAIL */
219 
220 	if (map == NULL)
221 	{
222 		STAB *s = stab("aliases", ST_MAP, ST_FIND);
223 
224 		if (s == NULL)
225 			return NULL;
226 		map = &s->s_map;
227 	}
228 	DYNOPENMAP(map);
229 
230 	/* special case POstMastER -- always use lower case */
231 	if (sm_strcasecmp(name, "postmaster") == 0)
232 		name = "postmaster";
233 
234 #if _FFR_ALIAS_DETAIL
235 	i = 0;
236 	argv[i++] = name;
237 	argv[i++] = av;
238 
239 	/* XXX '+' is hardwired here as delimiter! */
240 	if (av != NULL && *av == '+')
241 		argv[i++] = av + 1;
242 	argv[i++] = NULL;
243 	return (*map->map_class->map_lookup)(map, name, argv, pstat);
244 #else /* _FFR_ALIAS_DETAIL */
245 	return (*map->map_class->map_lookup)(map, name, NULL, pstat);
246 #endif /* _FFR_ALIAS_DETAIL */
247 }
248 /*
249 **  SETALIAS -- set up an alias map
250 **
251 **	Called when reading configuration file.
252 **
253 **	Parameters:
254 **		spec -- the alias specification
255 **
256 **	Returns:
257 **		none.
258 */
259 
260 void
setalias(spec)261 setalias(spec)
262 	char *spec;
263 {
264 	register char *p;
265 	register MAP *map;
266 	char *class;
267 	STAB *s;
268 
269 	if (tTd(27, 8))
270 		sm_dprintf("setalias(%s)\n", spec);
271 
272 	for (p = spec; p != NULL; )
273 	{
274 		char buf[50];
275 
276 		while (isascii(*p) && isspace(*p))
277 			p++;
278 		if (*p == '\0')
279 			break;
280 		spec = p;
281 
282 		if (NAliasFileMaps >= MAXMAPSTACK)
283 		{
284 			syserr("Too many alias databases defined, %d max",
285 				MAXMAPSTACK);
286 			return;
287 		}
288 		if (AliasFileMap == NULL)
289 		{
290 			(void) sm_strlcpy(buf, "aliases.files sequence",
291 					  sizeof(buf));
292 			AliasFileMap = makemapentry(buf);
293 			if (AliasFileMap == NULL)
294 			{
295 				syserr("setalias: cannot create aliases.files map");
296 				return;
297 			}
298 		}
299 		(void) sm_snprintf(buf, sizeof(buf), "Alias%d", NAliasFileMaps);
300 		s = stab(buf, ST_MAP, ST_ENTER);
301 		map = &s->s_map;
302 		memset(map, '\0', sizeof(*map));
303 		map->map_mname = s->s_name;
304 		p = strpbrk(p, ALIAS_SPEC_SEPARATORS);
305 		if (p != NULL && *p == SEPARATOR)
306 		{
307 			/* map name */
308 			*p++ = '\0';
309 			class = spec;
310 			spec = p;
311 		}
312 		else
313 		{
314 			class = "implicit";
315 			map->map_mflags = MF_INCLNULL;
316 		}
317 
318 		/* find end of spec */
319 		if (p != NULL)
320 		{
321 			bool quoted = false;
322 
323 			for (; *p != '\0'; p++)
324 			{
325 				/*
326 				**  Don't break into a quoted string.
327 				**  Needed for ldap maps which use
328 				**  commas in their specifications.
329 				*/
330 
331 				if (*p == '"')
332 					quoted = !quoted;
333 				else if (*p == ',' && !quoted)
334 					break;
335 			}
336 
337 			/* No more alias specifications follow */
338 			if (*p == '\0')
339 				p = NULL;
340 		}
341 		if (p != NULL)
342 			*p++ = '\0';
343 
344 		if (tTd(27, 20))
345 			sm_dprintf("  map %s:%s %s\n", class, s->s_name, spec);
346 
347 		/* look up class */
348 		s = stab(class, ST_MAPCLASS, ST_FIND);
349 		if (s == NULL)
350 		{
351 			syserr("setalias: unknown alias class %s", class);
352 		}
353 		else if (!bitset(MCF_ALIASOK, s->s_mapclass.map_cflags))
354 		{
355 			syserr("setalias: map class %s can't handle aliases",
356 				class);
357 		}
358 		else
359 		{
360 			map->map_class = &s->s_mapclass;
361 			map->map_mflags |= MF_ALIAS;
362 			if (map->map_class->map_parse(map, spec))
363 			{
364 				map->map_mflags |= MF_VALID;
365 				AliasFileMap->map_stack[NAliasFileMaps++] = map;
366 			}
367 		}
368 	}
369 }
370 /*
371 **  ALIASWAIT -- wait for distinguished @:@ token to appear.
372 **
373 **	This can decide to reopen or rebuild the alias file
374 **
375 **	Parameters:
376 **		map -- a pointer to the map descriptor for this alias file.
377 **		ext -- the filename extension (e.g., ".db") for the
378 **			database file.
379 **		isopen -- if set, the database is already open, and we
380 **			should check for validity; otherwise, we are
381 **			just checking to see if it should be created.
382 **
383 **	Returns:
384 **		true -- if the database is open when we return.
385 **		false -- if the database is closed when we return.
386 */
387 
388 bool
aliaswait(map,ext,isopen)389 aliaswait(map, ext, isopen)
390 	MAP *map;
391 	char *ext;
392 	bool isopen;
393 {
394 	bool attimeout = false;
395 	time_t mtime;
396 	struct stat stb;
397 	char buf[MAXPATHLEN];
398 
399 	if (tTd(27, 3))
400 		sm_dprintf("aliaswait(%s:%s)\n",
401 			   map->map_class->map_cname, map->map_file);
402 	if (bitset(MF_ALIASWAIT, map->map_mflags))
403 		return isopen;
404 	map->map_mflags |= MF_ALIASWAIT;
405 
406 	if (SafeAlias > 0)
407 	{
408 		auto int st;
409 		unsigned int sleeptime = 2;
410 		unsigned int loopcount = 0;	/* only used for debugging */
411 		time_t toolong = curtime() + SafeAlias;
412 
413 		while (isopen &&
414 		       map->map_class->map_lookup(map, "@", NULL, &st) == NULL)
415 		{
416 			if (curtime() > toolong)
417 			{
418 				/* we timed out */
419 				attimeout = true;
420 				break;
421 			}
422 
423 			/*
424 			**  Close and re-open the alias database in case
425 			**  the one is mv'ed instead of cp'ed in.
426 			*/
427 
428 			if (tTd(27, 2))
429 			{
430 				loopcount++;
431 				sm_dprintf("aliaswait: sleeping for %u seconds (loopcount = %u)\n",
432 					   sleeptime, loopcount);
433 			}
434 
435 			map->map_mflags |= MF_CLOSING;
436 			map->map_class->map_close(map);
437 			map->map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_CLOSING);
438 			(void) sleep(sleeptime);
439 			sleeptime *= 2;
440 			if (sleeptime > 60)
441 				sleeptime = 60;
442 			isopen = map->map_class->map_open(map, O_RDONLY);
443 		}
444 	}
445 
446 	/* see if we need to go into auto-rebuild mode */
447 	if (!bitset(MCF_REBUILDABLE, map->map_class->map_cflags))
448 	{
449 		if (tTd(27, 3))
450 			sm_dprintf("aliaswait: not rebuildable\n");
451 		map->map_mflags &= ~MF_ALIASWAIT;
452 		return isopen;
453 	}
454 	if (stat(map->map_file, &stb) < 0)
455 	{
456 		if (tTd(27, 3))
457 			sm_dprintf("aliaswait: no source file\n");
458 		map->map_mflags &= ~MF_ALIASWAIT;
459 		return isopen;
460 	}
461 	mtime = stb.st_mtime;
462 	if (sm_strlcpyn(buf, sizeof(buf), 2,
463 			map->map_file, ext == NULL ? "" : ext) >= sizeof(buf))
464 	{
465 		if (LogLevel > 3)
466 			sm_syslog(LOG_INFO, NOQID,
467 				  "alias database %s%s name too long",
468 				  map->map_file, ext == NULL ? "" : ext);
469 		message("alias database %s%s name too long",
470 			map->map_file, ext == NULL ? "" : ext);
471 	}
472 
473 	if (stat(buf, &stb) < 0 || stb.st_mtime < mtime || attimeout)
474 	{
475 		if (LogLevel > 3)
476 			sm_syslog(LOG_INFO, NOQID,
477 				  "alias database %s out of date", buf);
478 		message("Warning: alias database %s out of date", buf);
479 	}
480 	map->map_mflags &= ~MF_ALIASWAIT;
481 	return isopen;
482 }
483 /*
484 **  REBUILDALIASES -- rebuild the alias database.
485 **
486 **	Parameters:
487 **		map -- the database to rebuild.
488 **		automatic -- set if this was automatically generated.
489 **
490 **	Returns:
491 **		true if successful; false otherwise.
492 **
493 **	Side Effects:
494 **		Reads the text version of the database, builds the
495 **		DBM or DB version.
496 */
497 
498 bool
rebuildaliases(map,automatic)499 rebuildaliases(map, automatic)
500 	register MAP *map;
501 	bool automatic;
502 {
503 	SM_FILE_T *af;
504 	bool nolock = false;
505 	bool success = false;
506 	long sff = SFF_OPENASROOT|SFF_REGONLY|SFF_NOLOCK;
507 	sigfunc_t oldsigint, oldsigquit;
508 #ifdef SIGTSTP
509 	sigfunc_t oldsigtstp;
510 #endif /* SIGTSTP */
511 
512 	if (!bitset(MCF_REBUILDABLE, map->map_class->map_cflags))
513 		return false;
514 
515 	if (!bitnset(DBS_LINKEDALIASFILEINWRITABLEDIR, DontBlameSendmail))
516 		sff |= SFF_NOWLINK;
517 	if (!bitnset(DBS_GROUPWRITABLEALIASFILE, DontBlameSendmail))
518 		sff |= SFF_NOGWFILES;
519 	if (!bitnset(DBS_WORLDWRITABLEALIASFILE, DontBlameSendmail))
520 		sff |= SFF_NOWWFILES;
521 
522 	/* try to lock the source file */
523 	if ((af = safefopen(map->map_file, O_RDWR, 0, sff)) == NULL)
524 	{
525 		struct stat stb;
526 
527 		if ((errno != EACCES && errno != EROFS) || automatic ||
528 		    (af = safefopen(map->map_file, O_RDONLY, 0, sff)) == NULL)
529 		{
530 			int saveerr = errno;
531 
532 			if (tTd(27, 1))
533 				sm_dprintf("Can't open %s: %s\n",
534 					map->map_file, sm_errstring(saveerr));
535 			if (!automatic && !bitset(MF_OPTIONAL, map->map_mflags))
536 				message("newaliases: cannot open %s: %s",
537 					map->map_file, sm_errstring(saveerr));
538 			errno = 0;
539 			return false;
540 		}
541 		nolock = true;
542 		if (tTd(27, 1) ||
543 		    fstat(sm_io_getinfo(af, SM_IO_WHAT_FD, NULL), &stb) < 0 ||
544 		    bitset(S_IWUSR|S_IWGRP|S_IWOTH, stb.st_mode))
545 			message("warning: cannot lock %s: %s",
546 				map->map_file, sm_errstring(errno));
547 	}
548 
549 	/* see if someone else is rebuilding the alias file */
550 	if (!nolock &&
551 	    !lockfile(sm_io_getinfo(af, SM_IO_WHAT_FD, NULL), map->map_file,
552 		      NULL, LOCK_EX|LOCK_NB))
553 	{
554 		/* yes, they are -- wait until done */
555 		message("Alias file %s is locked (maybe being rebuilt)",
556 			map->map_file);
557 		if (OpMode != MD_INITALIAS)
558 		{
559 			/* wait for other rebuild to complete */
560 			(void) lockfile(sm_io_getinfo(af, SM_IO_WHAT_FD, NULL),
561 					map->map_file, NULL, LOCK_EX);
562 		}
563 		(void) sm_io_close(af, SM_TIME_DEFAULT);
564 		errno = 0;
565 		return false;
566 	}
567 
568 	oldsigint = sm_signal(SIGINT, SIG_IGN);
569 	oldsigquit = sm_signal(SIGQUIT, SIG_IGN);
570 #ifdef SIGTSTP
571 	oldsigtstp = sm_signal(SIGTSTP, SIG_IGN);
572 #endif /* SIGTSTP */
573 
574 	if (map->map_class->map_open(map, O_RDWR))
575 	{
576 		if (LogLevel > 7)
577 		{
578 			sm_syslog(LOG_NOTICE, NOQID,
579 				"alias database %s %srebuilt by %s",
580 				map->map_file, automatic ? "auto" : "",
581 				username());
582 		}
583 		map->map_mflags |= MF_OPEN|MF_WRITABLE;
584 		map->map_pid = CurrentPid;
585 		readaliases(map, af, !automatic, true);
586 		success = true;
587 	}
588 	else
589 	{
590 		if (tTd(27, 1))
591 			sm_dprintf("Can't create database for %s: %s\n",
592 				map->map_file, sm_errstring(errno));
593 		if (!automatic)
594 			syserr("Cannot create database for alias file %s",
595 				map->map_file);
596 	}
597 
598 	/* close the file, thus releasing locks */
599 	(void) sm_io_close(af, SM_TIME_DEFAULT);
600 
601 	/* add distinguished entries and close the database */
602 	if (bitset(MF_OPEN, map->map_mflags))
603 	{
604 		map->map_mflags |= MF_CLOSING;
605 		map->map_class->map_close(map);
606 		map->map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_CLOSING);
607 	}
608 
609 	/* restore the old signals */
610 	(void) sm_signal(SIGINT, oldsigint);
611 	(void) sm_signal(SIGQUIT, oldsigquit);
612 #ifdef SIGTSTP
613 	(void) sm_signal(SIGTSTP, oldsigtstp);
614 #endif /* SIGTSTP */
615 	return success;
616 }
617 /*
618 **  READALIASES -- read and process the alias file.
619 **
620 **	This routine implements the part of initaliases that occurs
621 **	when we are not going to use the DBM stuff.
622 **
623 **	Parameters:
624 **		map -- the alias database descriptor.
625 **		af -- file to read the aliases from.
626 **		announcestats -- announce statistics regarding number of
627 **			aliases, longest alias, etc.
628 **		logstats -- lot the same info.
629 **
630 **	Returns:
631 **		none.
632 **
633 **	Side Effects:
634 **		Reads aliasfile into the symbol table.
635 **		Optionally, builds the .dir & .pag files.
636 */
637 
638 void
readaliases(map,af,announcestats,logstats)639 readaliases(map, af, announcestats, logstats)
640 	register MAP *map;
641 	SM_FILE_T *af;
642 	bool announcestats;
643 	bool logstats;
644 {
645 	register char *p;
646 	char *rhs;
647 	bool skipping;
648 	long naliases, bytes, longest;
649 	ADDRESS al, bl;
650 	char line[BUFSIZ];
651 
652 	/*
653 	**  Read and interpret lines
654 	*/
655 
656 	FileName = map->map_file;
657 	LineNumber = 0;
658 	naliases = bytes = longest = 0;
659 	skipping = false;
660 	while (sm_io_fgets(af, SM_TIME_DEFAULT, line, sizeof(line)) != NULL)
661 	{
662 		int lhssize, rhssize;
663 		int c;
664 
665 		LineNumber++;
666 		p = strchr(line, '\n');
667 
668 		/* XXX what if line="a\\" ? */
669 		while (p != NULL && p > line && p[-1] == '\\')
670 		{
671 			p--;
672 			if (sm_io_fgets(af, SM_TIME_DEFAULT, p,
673 					SPACELEFT(line, p)) == NULL)
674 				break;
675 			LineNumber++;
676 			p = strchr(p, '\n');
677 		}
678 		if (p != NULL)
679 			*p = '\0';
680 		else if (!sm_io_eof(af))
681 		{
682 			errno = 0;
683 			syserr("554 5.3.0 alias line too long");
684 
685 			/* flush to end of line */
686 			while ((c = sm_io_getc(af, SM_TIME_DEFAULT)) !=
687 				SM_IO_EOF && c != '\n')
688 				continue;
689 
690 			/* skip any continuation lines */
691 			skipping = true;
692 			continue;
693 		}
694 		switch (line[0])
695 		{
696 		  case '#':
697 		  case '\0':
698 			skipping = false;
699 			continue;
700 
701 		  case ' ':
702 		  case '\t':
703 			if (!skipping)
704 				syserr("554 5.3.5 Non-continuation line starts with space");
705 			skipping = true;
706 			continue;
707 		}
708 		skipping = false;
709 
710 		/*
711 		**  Process the LHS
712 		**	Find the colon separator, and parse the address.
713 		**	It should resolve to a local name -- this will
714 		**	be checked later (we want to optionally do
715 		**	parsing of the RHS first to maximize error
716 		**	detection).
717 		*/
718 
719 		for (p = line; *p != '\0' && *p != ':' && *p != '\n'; p++)
720 			continue;
721 		if (*p++ != ':')
722 		{
723 			syserr("554 5.3.5 missing colon");
724 			continue;
725 		}
726 		if (parseaddr(line, &al, RF_COPYALL, ':', NULL, CurEnv, true)
727 		    == NULL)
728 		{
729 			syserr("554 5.3.5 %.40s... illegal alias name", line);
730 			continue;
731 		}
732 
733 		/*
734 		**  Process the RHS.
735 		**	'al' is the internal form of the LHS address.
736 		**	'p' points to the text of the RHS.
737 		*/
738 
739 		while (isascii(*p) && isspace(*p))
740 			p++;
741 		rhs = p;
742 		for (;;)
743 		{
744 			register char *nlp;
745 
746 			nlp = &p[strlen(p)];
747 			if (nlp > p && nlp[-1] == '\n')
748 				*--nlp = '\0';
749 
750 			if (CheckAliases)
751 			{
752 				/* do parsing & compression of addresses */
753 				while (*p != '\0')
754 				{
755 					auto char *delimptr;
756 
757 					while ((isascii(*p) && isspace(*p)) ||
758 								*p == ',')
759 						p++;
760 					if (*p == '\0')
761 						break;
762 					if (parseaddr(p, &bl, RF_COPYNONE, ',',
763 						      &delimptr, CurEnv, true)
764 					    == NULL)
765 						usrerr("553 5.3.5 %s... bad address", p);
766 					p = delimptr;
767 				}
768 			}
769 			else
770 			{
771 				p = nlp;
772 			}
773 
774 			/* see if there should be a continuation line */
775 			c = sm_io_getc(af, SM_TIME_DEFAULT);
776 			if (!sm_io_eof(af))
777 				(void) sm_io_ungetc(af, SM_TIME_DEFAULT, c);
778 			if (c != ' ' && c != '\t')
779 				break;
780 
781 			/* read continuation line */
782 			if (sm_io_fgets(af, SM_TIME_DEFAULT, p,
783 					sizeof(line) - (p-line)) == NULL)
784 				break;
785 			LineNumber++;
786 
787 			/* check for line overflow */
788 			if (strchr(p, '\n') == NULL && !sm_io_eof(af))
789 			{
790 				usrerr("554 5.3.5 alias too long");
791 				while ((c = sm_io_getc(af, SM_TIME_DEFAULT))
792 				       != SM_IO_EOF && c != '\n')
793 					continue;
794 				skipping = true;
795 				break;
796 			}
797 		}
798 
799 		if (skipping)
800 			continue;
801 
802 		if (!bitnset(M_ALIASABLE, al.q_mailer->m_flags))
803 		{
804 			syserr("554 5.3.5 %s... cannot alias non-local names",
805 				al.q_paddr);
806 			continue;
807 		}
808 
809 		/*
810 		**  Insert alias into symbol table or database file.
811 		**
812 		**	Special case pOStmaStER -- always make it lower case.
813 		*/
814 
815 		if (sm_strcasecmp(al.q_user, "postmaster") == 0)
816 			makelower(al.q_user);
817 
818 		lhssize = strlen(al.q_user);
819 		rhssize = strlen(rhs);
820 		if (rhssize > 0)
821 		{
822 			/* is RHS empty (just spaces)? */
823 			p = rhs;
824 			while (isascii(*p) && isspace(*p))
825 				p++;
826 		}
827 		if (rhssize == 0 || *p == '\0')
828 		{
829 			syserr("554 5.3.5 %.40s... missing value for alias",
830 			       line);
831 
832 		}
833 		else
834 		{
835 			map->map_class->map_store(map, al.q_user, rhs);
836 
837 			/* statistics */
838 			naliases++;
839 			bytes += lhssize + rhssize;
840 			if (rhssize > longest)
841 				longest = rhssize;
842 		}
843 
844 #if 0
845 	/*
846 	**  address strings are now stored in the envelope rpool,
847 	**  and therefore cannot be freed.
848 	*/
849 		if (al.q_paddr != NULL)
850 			sm_free(al.q_paddr);  /* disabled */
851 		if (al.q_host != NULL)
852 			sm_free(al.q_host);  /* disabled */
853 		if (al.q_user != NULL)
854 			sm_free(al.q_user);  /* disabled */
855 #endif /* 0 */
856 	}
857 
858 	CurEnv->e_to = NULL;
859 	FileName = NULL;
860 	if (Verbose || announcestats)
861 		message("%s: %ld aliases, longest %ld bytes, %ld bytes total",
862 			map->map_file, naliases, longest, bytes);
863 	if (LogLevel > 7 && logstats)
864 		sm_syslog(LOG_INFO, NOQID,
865 			"%s: %ld aliases, longest %ld bytes, %ld bytes total",
866 			map->map_file, naliases, longest, bytes);
867 }
868 /*
869 **  FORWARD -- Try to forward mail
870 **
871 **	This is similar but not identical to aliasing.
872 **
873 **	Parameters:
874 **		user -- the name of the user who's mail we would like
875 **			to forward to.  It must have been verified --
876 **			i.e., the q_home field must have been filled
877 **			in.
878 **		sendq -- a pointer to the head of the send queue to
879 **			put this user's aliases in.
880 **		aliaslevel -- the current alias nesting depth.
881 **		e -- the current envelope.
882 **
883 **	Returns:
884 **		none.
885 **
886 **	Side Effects:
887 **		New names are added to send queues.
888 */
889 
890 void
forward(user,sendq,aliaslevel,e)891 forward(user, sendq, aliaslevel, e)
892 	ADDRESS *user;
893 	ADDRESS **sendq;
894 	int aliaslevel;
895 	register ENVELOPE *e;
896 {
897 	char *pp;
898 	char *ep;
899 	bool got_transient;
900 
901 	if (tTd(27, 1))
902 		sm_dprintf("forward(%s)\n", user->q_paddr);
903 
904 	if (!bitnset(M_HASPWENT, user->q_mailer->m_flags) ||
905 	    !QS_IS_OK(user->q_state))
906 		return;
907 	if (ForwardPath != NULL && *ForwardPath == '\0')
908 		return;
909 	if (user->q_home == NULL)
910 	{
911 		syserr("554 5.3.0 forward: no home");
912 		user->q_home = "/no/such/directory";
913 	}
914 
915 	/* good address -- look for .forward file in home */
916 	macdefine(&e->e_macro, A_PERM, 'z', user->q_home);
917 	macdefine(&e->e_macro, A_PERM, 'u', user->q_user);
918 	macdefine(&e->e_macro, A_PERM, 'h', user->q_host);
919 	if (ForwardPath == NULL)
920 		ForwardPath = newstr("\201z/.forward");
921 
922 	got_transient = false;
923 	for (pp = ForwardPath; pp != NULL; pp = ep)
924 	{
925 		int err;
926 		char buf[MAXPATHLEN];
927 		struct stat st;
928 
929 		ep = strchr(pp, SEPARATOR);
930 		if (ep != NULL)
931 			*ep = '\0';
932 		expand(pp, buf, sizeof(buf), e);
933 		if (ep != NULL)
934 			*ep++ = SEPARATOR;
935 		if (buf[0] == '\0')
936 			continue;
937 		if (tTd(27, 3))
938 			sm_dprintf("forward: trying %s\n", buf);
939 
940 		err = include(buf, true, user, sendq, aliaslevel, e);
941 		if (err == 0)
942 			break;
943 		else if (transienterror(err))
944 		{
945 			/* we may have to suspend this message */
946 			got_transient = true;
947 			if (tTd(27, 2))
948 				sm_dprintf("forward: transient error on %s\n",
949 					   buf);
950 			if (LogLevel > 2)
951 			{
952 				char *curhost = CurHostName;
953 
954 				CurHostName = NULL;
955 				sm_syslog(LOG_ERR, e->e_id,
956 					  "forward %s: transient error: %s",
957 					  buf, sm_errstring(err));
958 				CurHostName = curhost;
959 			}
960 
961 		}
962 		else
963 		{
964 			switch (err)
965 			{
966 			  case ENOENT:
967 				break;
968 
969 			  case E_SM_WWDIR:
970 			  case E_SM_GWDIR:
971 				/* check if it even exists */
972 				if (stat(buf, &st) < 0 && errno == ENOENT)
973 				{
974 					if (bitnset(DBS_DONTWARNFORWARDFILEINUNSAFEDIRPATH,
975 						    DontBlameSendmail))
976 						break;
977 				}
978 				/* FALLTHROUGH */
979 
980 #if _FFR_FORWARD_SYSERR
981 			  case E_SM_NOSLINK:
982 			  case E_SM_NOHLINK:
983 			  case E_SM_REGONLY:
984 			  case E_SM_ISEXEC:
985 			  case E_SM_WWFILE:
986 			  case E_SM_GWFILE:
987 				syserr("forward: %s: %s", buf, sm_errstring(err));
988 				break;
989 #endif /* _FFR_FORWARD_SYSERR */
990 
991 				/* FALLTHROUGH */
992 			  default:
993 				if (LogLevel > (RunAsUid == 0 ? 2 : 10))
994 					sm_syslog(LOG_WARNING, e->e_id,
995 						  "forward %s: %s", buf,
996 						  sm_errstring(err));
997 				if (Verbose)
998 					message("forward: %s: %s",
999 						buf, sm_errstring(err));
1000 				break;
1001 			}
1002 		}
1003 	}
1004 	if (pp == NULL && got_transient)
1005 	{
1006 		/*
1007 		**  There was no successful .forward open and at least one
1008 		**  transient open.  We have to defer this address for
1009 		**  further delivery.
1010 		*/
1011 
1012 		message("transient .forward open error: message queued");
1013 		user->q_state = QS_QUEUEUP;
1014 		return;
1015 	}
1016 }
1017