xref: /freebsd/contrib/sendmail/src/alias.c (revision 2774f206809b8fd3a4904fe945f029a414fbc642)
1 /*
2  * Copyright (c) 1998-2003 Proofpoint, 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.221 2013-11-22 20:51:54 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
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 *
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
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
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 (SM_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
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
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
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
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
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
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)) >= 0)
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)) < 0)
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 (SM_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 ((SM_ISSPACE(*p)) || *p == ',')
758 						p++;
759 					if (*p == '\0')
760 						break;
761 					if (parseaddr(p, &bl, RF_COPYNONE, ',',
762 						      &delimptr, CurEnv, true)
763 					    == NULL)
764 						usrerr("553 5.3.5 %s... bad address", p);
765 					p = delimptr;
766 				}
767 			}
768 			else
769 			{
770 				p = nlp;
771 			}
772 
773 			/* see if there should be a continuation line */
774 			c = sm_io_getc(af, SM_TIME_DEFAULT);
775 			if (!sm_io_eof(af))
776 				(void) sm_io_ungetc(af, SM_TIME_DEFAULT, c);
777 			if (c != ' ' && c != '\t')
778 				break;
779 
780 			/* read continuation line */
781 			if (sm_io_fgets(af, SM_TIME_DEFAULT, p,
782 					sizeof(line) - (p-line)) < 0)
783 				break;
784 			LineNumber++;
785 
786 			/* check for line overflow */
787 			if (strchr(p, '\n') == NULL && !sm_io_eof(af))
788 			{
789 				usrerr("554 5.3.5 alias too long");
790 				while ((c = sm_io_getc(af, SM_TIME_DEFAULT))
791 				       != SM_IO_EOF && c != '\n')
792 					continue;
793 				skipping = true;
794 				break;
795 			}
796 		}
797 
798 		if (skipping)
799 			continue;
800 
801 		if (!bitnset(M_ALIASABLE, al.q_mailer->m_flags))
802 		{
803 			syserr("554 5.3.5 %s... cannot alias non-local names",
804 				al.q_paddr);
805 			continue;
806 		}
807 
808 		/*
809 		**  Insert alias into symbol table or database file.
810 		**
811 		**	Special case pOStmaStER -- always make it lower case.
812 		*/
813 
814 		if (sm_strcasecmp(al.q_user, "postmaster") == 0)
815 			makelower(al.q_user);
816 
817 		lhssize = strlen(al.q_user);
818 		rhssize = strlen(rhs);
819 		if (rhssize > 0)
820 		{
821 			/* is RHS empty (just spaces)? */
822 			p = rhs;
823 			while (SM_ISSPACE(*p))
824 				p++;
825 		}
826 		if (rhssize == 0 || *p == '\0')
827 		{
828 			syserr("554 5.3.5 %.40s... missing value for alias",
829 			       line);
830 
831 		}
832 		else
833 		{
834 			map->map_class->map_store(map, al.q_user, rhs);
835 
836 			/* statistics */
837 			naliases++;
838 			bytes += lhssize + rhssize;
839 			if (rhssize > longest)
840 				longest = rhssize;
841 		}
842 	}
843 
844 	CurEnv->e_to = NULL;
845 	FileName = NULL;
846 	if (Verbose || announcestats)
847 		message("%s: %ld aliases, longest %ld bytes, %ld bytes total",
848 			map->map_file, naliases, longest, bytes);
849 	if (LogLevel > 7 && logstats)
850 		sm_syslog(LOG_INFO, NOQID,
851 			"%s: %ld aliases, longest %ld bytes, %ld bytes total",
852 			map->map_file, naliases, longest, bytes);
853 }
854 /*
855 **  FORWARD -- Try to forward mail
856 **
857 **	This is similar but not identical to aliasing.
858 **
859 **	Parameters:
860 **		user -- the name of the user who's mail we would like
861 **			to forward to.  It must have been verified --
862 **			i.e., the q_home field must have been filled
863 **			in.
864 **		sendq -- a pointer to the head of the send queue to
865 **			put this user's aliases in.
866 **		aliaslevel -- the current alias nesting depth.
867 **		e -- the current envelope.
868 **
869 **	Returns:
870 **		none.
871 **
872 **	Side Effects:
873 **		New names are added to send queues.
874 */
875 
876 void
877 forward(user, sendq, aliaslevel, e)
878 	ADDRESS *user;
879 	ADDRESS **sendq;
880 	int aliaslevel;
881 	register ENVELOPE *e;
882 {
883 	char *pp;
884 	char *ep;
885 	bool got_transient;
886 
887 	if (tTd(27, 1))
888 		sm_dprintf("forward(%s)\n", user->q_paddr);
889 
890 	if (!bitnset(M_HASPWENT, user->q_mailer->m_flags) ||
891 	    !QS_IS_OK(user->q_state))
892 		return;
893 	if (ForwardPath != NULL && *ForwardPath == '\0')
894 		return;
895 	if (user->q_home == NULL)
896 	{
897 		syserr("554 5.3.0 forward: no home");
898 		user->q_home = "/no/such/directory";
899 	}
900 
901 	/* good address -- look for .forward file in home */
902 	macdefine(&e->e_macro, A_PERM, 'z', user->q_home);
903 	macdefine(&e->e_macro, A_PERM, 'u', user->q_user);
904 	macdefine(&e->e_macro, A_PERM, 'h', user->q_host);
905 	if (ForwardPath == NULL)
906 		ForwardPath = newstr("\201z/.forward");
907 
908 	got_transient = false;
909 	for (pp = ForwardPath; pp != NULL; pp = ep)
910 	{
911 		int err;
912 		char buf[MAXPATHLEN];
913 		struct stat st;
914 
915 		ep = strchr(pp, SEPARATOR);
916 		if (ep != NULL)
917 			*ep = '\0';
918 		expand(pp, buf, sizeof(buf), e);
919 		if (ep != NULL)
920 			*ep++ = SEPARATOR;
921 		if (buf[0] == '\0')
922 			continue;
923 		if (tTd(27, 3))
924 			sm_dprintf("forward: trying %s\n", buf);
925 
926 		err = include(buf, true, user, sendq, aliaslevel, e);
927 		if (err == 0)
928 			break;
929 		else if (transienterror(err))
930 		{
931 			/* we may have to suspend this message */
932 			got_transient = true;
933 			if (tTd(27, 2))
934 				sm_dprintf("forward: transient error on %s\n",
935 					   buf);
936 			if (LogLevel > 2)
937 			{
938 				char *curhost = CurHostName;
939 
940 				CurHostName = NULL;
941 				sm_syslog(LOG_ERR, e->e_id,
942 					  "forward %s: transient error: %s",
943 					  buf, sm_errstring(err));
944 				CurHostName = curhost;
945 			}
946 
947 		}
948 		else
949 		{
950 			switch (err)
951 			{
952 			  case ENOENT:
953 				break;
954 
955 			  case E_SM_WWDIR:
956 			  case E_SM_GWDIR:
957 				/* check if it even exists */
958 				if (stat(buf, &st) < 0 && errno == ENOENT)
959 				{
960 					if (bitnset(DBS_DONTWARNFORWARDFILEINUNSAFEDIRPATH,
961 						    DontBlameSendmail))
962 						break;
963 				}
964 				/* FALLTHROUGH */
965 
966 #if _FFR_FORWARD_SYSERR
967 			  case E_SM_NOSLINK:
968 			  case E_SM_NOHLINK:
969 			  case E_SM_REGONLY:
970 			  case E_SM_ISEXEC:
971 			  case E_SM_WWFILE:
972 			  case E_SM_GWFILE:
973 				syserr("forward: %s: %s", buf, sm_errstring(err));
974 				break;
975 #endif /* _FFR_FORWARD_SYSERR */
976 
977 			  default:
978 				if (LogLevel > (RunAsUid == 0 ? 2 : 10))
979 					sm_syslog(LOG_WARNING, e->e_id,
980 						  "forward %s: %s", buf,
981 						  sm_errstring(err));
982 				if (Verbose)
983 					message("forward: %s: %s",
984 						buf, sm_errstring(err));
985 				break;
986 			}
987 		}
988 	}
989 	if (pp == NULL && got_transient)
990 	{
991 		/*
992 		**  There was no successful .forward open and at least one
993 		**  transient open.  We have to defer this address for
994 		**  further delivery.
995 		*/
996 
997 		message("transient .forward open error: message queued");
998 		user->q_state = QS_QUEUEUP;
999 		return;
1000 	}
1001 }
1002