1 /*
2  * Copyright (c) 1983 Eric P. Allman
3  * Copyright (c) 1988 Regents of the University of California.
4  * All rights reserved.
5  *
6  * %sccs.include.redist.c%
7  */
8 
9 #ifndef lint
10 static char sccsid[] = "@(#)recipient.c	6.13 (Berkeley) 02/20/93";
11 #endif /* not lint */
12 
13 # include <sys/types.h>
14 # include <sys/stat.h>
15 # include <fcntl.h>
16 # include <pwd.h>
17 # include "sendmail.h"
18 
19 /*
20 **  SENDTOLIST -- Designate a send list.
21 **
22 **	The parameter is a comma-separated list of people to send to.
23 **	This routine arranges to send to all of them.
24 **
25 **	Parameters:
26 **		list -- the send list.
27 **		ctladdr -- the address template for the person to
28 **			send to -- effective uid/gid are important.
29 **			This is typically the alias that caused this
30 **			expansion.
31 **		sendq -- a pointer to the head of a queue to put
32 **			these people into.
33 **
34 **	Returns:
35 **		The number of addresses actually on the list.
36 **
37 **	Side Effects:
38 **		none.
39 */
40 
41 # define MAXRCRSN	10
42 
43 sendtolist(list, ctladdr, sendq, e)
44 	char *list;
45 	ADDRESS *ctladdr;
46 	ADDRESS **sendq;
47 	register ENVELOPE *e;
48 {
49 	register char *p;
50 	register ADDRESS *al;	/* list of addresses to send to */
51 	bool firstone;		/* set on first address sent */
52 	char delimiter;		/* the address delimiter */
53 	int naddrs;
54 
55 	if (tTd(25, 1))
56 	{
57 		printf("sendto: %s\n   ctladdr=", list);
58 		printaddr(ctladdr, FALSE);
59 	}
60 
61 	/* heuristic to determine old versus new style addresses */
62 	if (ctladdr == NULL &&
63 	    (strchr(list, ',') != NULL || strchr(list, ';') != NULL ||
64 	     strchr(list, '<') != NULL || strchr(list, '(') != NULL))
65 		e->e_flags &= ~EF_OLDSTYLE;
66 	delimiter = ' ';
67 	if (!bitset(EF_OLDSTYLE, e->e_flags) || ctladdr != NULL)
68 		delimiter = ',';
69 
70 	firstone = TRUE;
71 	al = NULL;
72 	naddrs = 0;
73 
74 	for (p = list; *p != '\0'; )
75 	{
76 		register ADDRESS *a;
77 		extern char *DelimChar;		/* defined in prescan */
78 
79 		/* parse the address */
80 		while ((isascii(*p) && isspace(*p)) || *p == ',')
81 			p++;
82 		a = parseaddr(p, (ADDRESS *) NULL, 1, delimiter, e);
83 		p = DelimChar;
84 		if (a == NULL)
85 			continue;
86 		a->q_next = al;
87 		a->q_alias = ctladdr;
88 
89 		/* see if this should be marked as a primary address */
90 		if (ctladdr == NULL ||
91 		    (firstone && *p == '\0' && bitset(QPRIMARY, ctladdr->q_flags)))
92 			a->q_flags |= QPRIMARY;
93 
94 		if (ctladdr != NULL && sameaddr(ctladdr, a))
95 			ctladdr->q_flags |= QSELFREF;
96 		al = a;
97 		firstone = FALSE;
98 	}
99 
100 	/* arrange to send to everyone on the local send list */
101 	while (al != NULL)
102 	{
103 		register ADDRESS *a = al;
104 		extern ADDRESS *recipient();
105 
106 		al = a->q_next;
107 		a = recipient(a, sendq, e);
108 
109 		/* arrange to inherit full name */
110 		if (a->q_fullname == NULL && ctladdr != NULL)
111 			a->q_fullname = ctladdr->q_fullname;
112 		naddrs++;
113 	}
114 
115 	e->e_to = NULL;
116 	return (naddrs);
117 }
118 /*
119 **  RECIPIENT -- Designate a message recipient
120 **
121 **	Saves the named person for future mailing.
122 **
123 **	Parameters:
124 **		a -- the (preparsed) address header for the recipient.
125 **		sendq -- a pointer to the head of a queue to put the
126 **			recipient in.  Duplicate supression is done
127 **			in this queue.
128 **		e -- the current envelope.
129 **
130 **	Returns:
131 **		The actual address in the queue.  This will be "a" if
132 **		the address is not a duplicate, else the original address.
133 **
134 **	Side Effects:
135 **		none.
136 */
137 
138 extern ADDRESS *getctladdr();
139 extern char	*RcptLogFile;
140 
141 ADDRESS *
142 recipient(a, sendq, e)
143 	register ADDRESS *a;
144 	register ADDRESS **sendq;
145 	register ENVELOPE *e;
146 {
147 	register ADDRESS *q;
148 	ADDRESS **pq;
149 	register struct mailer *m;
150 	register char *p;
151 	bool quoted = FALSE;		/* set if the addr has a quote bit */
152 	int findusercount = 0;
153 	char buf[MAXNAME];		/* unquoted image of the user name */
154 	extern bool safefile();
155 
156 	e->e_to = a->q_paddr;
157 	m = a->q_mailer;
158 	errno = 0;
159 	if (tTd(26, 1))
160 	{
161 		printf("\nrecipient: ");
162 		printaddr(a, FALSE);
163 	}
164 
165 	/* break aliasing loops */
166 	if (AliasLevel > MAXRCRSN)
167 	{
168 		usrerr("aliasing/forwarding loop broken");
169 		return (a);
170 	}
171 
172 	/*
173 	**  Finish setting up address structure.
174 	*/
175 
176 	/* set the queue timeout */
177 	a->q_timeout = TimeOut;
178 
179 	/* map user & host to lower case if requested on non-aliases */
180 	if (a->q_alias == NULL)
181 		loweraddr(a);
182 
183 	/* get unquoted user for file, program or user.name check */
184 	(void) strcpy(buf, a->q_user);
185 	for (p = buf; *p != '\0' && !quoted; p++)
186 	{
187 		if (*p == '\\')
188 			quoted = TRUE;
189 	}
190 	stripquotes(buf);
191 
192 	/* check for direct mailing to restricted mailers */
193 	if (a->q_alias == NULL && m == ProgMailer)
194 	{
195 		a->q_flags |= QDONTSEND|QBADADDR;
196 		usrerr("Cannot mail directly to programs", m->m_name);
197 	}
198 
199 	/*
200 	**  Look up this person in the recipient list.
201 	**	If they are there already, return, otherwise continue.
202 	**	If the list is empty, just add it.  Notice the cute
203 	**	hack to make from addresses suppress things correctly:
204 	**	the QDONTSEND bit will be set in the send list.
205 	**	[Please note: the emphasis is on "hack."]
206 	*/
207 
208 	for (pq = sendq; (q = *pq) != NULL; pq = &q->q_next)
209 	{
210 		if (!ForceMail && sameaddr(q, a))
211 		{
212 			if (tTd(26, 1))
213 			{
214 				printf("%s in sendq: ", a->q_paddr);
215 				printaddr(q, FALSE);
216 			}
217 			if (!bitset(QPRIMARY, q->q_flags))
218 			{
219 				if (!bitset(QDONTSEND, a->q_flags))
220 					message(Arpa_Info, "duplicate suppressed");
221 				q->q_flags |= a->q_flags;
222 			}
223 			return (q);
224 		}
225 	}
226 
227 	/* add address on list */
228 	*pq = a;
229 	a->q_next = NULL;
230 
231 	if (a->q_alias == NULL && RcptLogFile != NULL &&
232 	    !bitset(QDONTSEND, a->q_flags))
233 	{
234 		static int RcptLogFd = -1;
235 
236 		/*
237 		**  Log the incoming recipient name before aliasing,
238 		**  expanding, forwarding, rewriting, and all that jazz.
239 		**  We'll use this to track down out-of-date aliases,
240 		**  host names, and so forth.
241 		*/
242 
243 		if (RcptLogFd < 0)
244 		{
245 			/* try to open the log file */
246 			RcptLogFd = open(RcptLogFile, O_WRONLY|O_APPEND|O_CREAT, 0666);
247 			if (RcptLogFd >= 0)
248 				(void) fcntl(RcptLogFd, F_SETFD, 1);
249 		}
250 		if (RcptLogFd >= 0)
251 		{
252 			int l = strlen(a->q_paddr);
253 
254 			a->q_paddr[l] = '\n';
255 			if (write(RcptLogFd, a->q_paddr, l + 1) < 0)
256 			{
257 				(void) close(RcptLogFd);
258 				RcptLogFd = -1;
259 			}
260 			a->q_paddr[l] = '\0';
261 		}
262 	}
263 
264 	/*
265 	**  Alias the name and handle special mailer types.
266 	*/
267 
268   trylocaluser:
269 	if (tTd(29, 7))
270 		printf("at trylocaluser %s\n", a->q_user);
271 
272 	if (bitset(QDONTSEND, a->q_flags))
273 		return (a);
274 
275 	if (m == InclMailer)
276 	{
277 		a->q_flags |= QDONTSEND;
278 		if (a->q_alias == NULL)
279 		{
280 			a->q_flags |= QBADADDR;
281 			usrerr("Cannot mail directly to :include:s");
282 		}
283 		else
284 		{
285 			message(Arpa_Info, "including file %s", a->q_user);
286 			(void) include(a->q_user, FALSE, a, sendq, e);
287 		}
288 	}
289 	else if (m == FileMailer)
290 	{
291 		struct stat stb;
292 		extern bool writable();
293 
294 		p = strrchr(buf, '/');
295 		/* check if writable or creatable */
296 		if (a->q_alias == NULL && !QueueRun)
297 		{
298 			a->q_flags |= QDONTSEND|QBADADDR;
299 			usrerr("Cannot mail directly to files");
300 		}
301 		else if ((stat(buf, &stb) >= 0) ? (!writable(&stb)) :
302 		    (*p = '\0', !safefile(buf, getruid(), S_IWRITE|S_IEXEC)))
303 		{
304 			a->q_flags |= QBADADDR;
305 			giveresponse(EX_CANTCREAT, m, e);
306 		}
307 	}
308 
309 	if (m != LocalMailer)
310 	{
311 		if (!bitset(QDONTSEND, a->q_flags))
312 			e->e_nrcpts++;
313 		return (a);
314 	}
315 
316 	/* try aliasing */
317 	alias(a, sendq, e);
318 
319 # ifdef USERDB
320 	/* if not aliased, look it up in the user database */
321 	if (!bitset(QDONTSEND|QNOTREMOTE, a->q_flags))
322 	{
323 		extern int udbexpand();
324 
325 		if (udbexpand(a, sendq, e) == EX_TEMPFAIL)
326 		{
327 			a->q_flags |= QQUEUEUP;
328 			if (e->e_message == NULL)
329 				e->e_message = newstr("Deferred: user database error");
330 # ifdef LOG
331 			if (LogLevel > 8)
332 				syslog(LOG_INFO, "%s: deferred: udbexpand",
333 					e->e_id);
334 # endif
335 			message(Arpa_Info, "queued (user database error)");
336 			e->e_nrcpts++;
337 			return (a);
338 		}
339 	}
340 # endif
341 
342 	/* if it was an alias or a UDB expansion, just return now */
343 	if (bitset(QDONTSEND, a->q_flags))
344 		return (a);
345 
346 	/*
347 	**  If we have a level two config file, then pass the name through
348 	**  Ruleset 5 before sending it off.  Ruleset 5 has the right
349 	**  to send rewrite it to another mailer.  This gives us a hook
350 	**  after local aliasing has been done.
351 	*/
352 
353 	if (tTd(29, 5))
354 	{
355 		printf("recipient: testing local?  cl=%d, rr5=%x\n\t",
356 			ConfigLevel, RewriteRules[5]);
357 		printaddr(a, FALSE);
358 	}
359 	if (!bitset(QNOTREMOTE, a->q_flags) && ConfigLevel >= 2 &&
360 	    RewriteRules[5] != NULL)
361 	{
362 		maplocaluser(a, sendq, e);
363 	}
364 
365 	/*
366 	**  If it didn't get rewritten to another mailer, go ahead
367 	**  and deliver it.
368 	*/
369 
370 	if (!bitset(QDONTSEND, a->q_flags))
371 	{
372 		auto bool fuzzy;
373 		register struct passwd *pw;
374 		extern struct passwd *finduser();
375 
376 		/* warning -- finduser may trash buf */
377 		pw = finduser(buf, &fuzzy);
378 		if (pw == NULL)
379 		{
380 			a->q_flags |= QBADADDR;
381 			giveresponse(EX_NOUSER, m, e);
382 		}
383 		else
384 		{
385 			char nbuf[MAXNAME];
386 
387 			if (fuzzy)
388 			{
389 				/* name was a fuzzy match */
390 				a->q_user = newstr(pw->pw_name);
391 				if (findusercount++ > 3)
392 				{
393 					usrerr("aliasing/forwarding loop for %s broken",
394 						pw->pw_name);
395 					return (a);
396 				}
397 
398 				/* see if it aliases */
399 				(void) strcpy(buf, pw->pw_name);
400 				goto trylocaluser;
401 			}
402 			a->q_home = newstr(pw->pw_dir);
403 			a->q_uid = pw->pw_uid;
404 			a->q_gid = pw->pw_gid;
405 			a->q_flags |= QGOODUID;
406 			buildfname(pw->pw_gecos, pw->pw_name, nbuf);
407 			if (nbuf[0] != '\0')
408 				a->q_fullname = newstr(nbuf);
409 			if (!quoted)
410 				forward(a, sendq, e);
411 		}
412 	}
413 	if (!bitset(QDONTSEND, a->q_flags))
414 		e->e_nrcpts++;
415 	return (a);
416 }
417 /*
418 **  FINDUSER -- find the password entry for a user.
419 **
420 **	This looks a lot like getpwnam, except that it may want to
421 **	do some fancier pattern matching in /etc/passwd.
422 **
423 **	This routine contains most of the time of many sendmail runs.
424 **	It deserves to be optimized.
425 **
426 **	Parameters:
427 **		name -- the name to match against.
428 **		fuzzyp -- an outarg that is set to TRUE if this entry
429 **			was found using the fuzzy matching algorithm;
430 **			set to FALSE otherwise.
431 **
432 **	Returns:
433 **		A pointer to a pw struct.
434 **		NULL if name is unknown or ambiguous.
435 **
436 **	Side Effects:
437 **		may modify name.
438 */
439 
440 struct passwd *
441 finduser(name, fuzzyp)
442 	char *name;
443 	bool *fuzzyp;
444 {
445 	register struct passwd *pw;
446 	register char *p;
447 	extern struct passwd *getpwent();
448 	extern struct passwd *getpwnam();
449 
450 	if (tTd(29, 4))
451 		printf("finduser(%s): ", name);
452 
453 	/* map upper => lower case */
454 	for (p = name; *p != '\0'; p++)
455 	{
456 		if (isascii(*p) && isupper(*p))
457 			*p = tolower(*p);
458 	}
459 	*fuzzyp = FALSE;
460 
461 	/* look up this login name using fast path */
462 	if ((pw = getpwnam(name)) != NULL)
463 	{
464 		if (tTd(29, 4))
465 			printf("found (non-fuzzy)\n");
466 		return (pw);
467 	}
468 
469 #ifdef MATCHGECOS
470 	/* see if fuzzy matching allowed */
471 	if (!MatchGecos)
472 	{
473 		if (tTd(29, 4))
474 			printf("not found (fuzzy disabled)\n");
475 		return NULL;
476 	}
477 
478 	/* search for a matching full name instead */
479 	for (p = name; *p != '\0'; p++)
480 	{
481 		if (*p == (SpaceSub & 0177) || *p == '_')
482 			*p = ' ';
483 	}
484 	(void) setpwent();
485 	while ((pw = getpwent()) != NULL)
486 	{
487 		char buf[MAXNAME];
488 
489 		buildfname(pw->pw_gecos, pw->pw_name, buf);
490 		if (strchr(buf, ' ') != NULL && !strcasecmp(buf, name))
491 		{
492 			if (tTd(29, 4))
493 				printf("fuzzy matches %s\n", pw->pw_name);
494 			message(Arpa_Info, "sending to login name %s", pw->pw_name);
495 			*fuzzyp = TRUE;
496 			return (pw);
497 		}
498 	}
499 #endif
500 	if (tTd(29, 4))
501 		printf("no fuzzy match found\n");
502 	return (NULL);
503 }
504 /*
505 **  WRITABLE -- predicate returning if the file is writable.
506 **
507 **	This routine must duplicate the algorithm in sys/fio.c.
508 **	Unfortunately, we cannot use the access call since we
509 **	won't necessarily be the real uid when we try to
510 **	actually open the file.
511 **
512 **	Notice that ANY file with ANY execute bit is automatically
513 **	not writable.  This is also enforced by mailfile.
514 **
515 **	Parameters:
516 **		s -- pointer to a stat struct for the file.
517 **
518 **	Returns:
519 **		TRUE -- if we will be able to write this file.
520 **		FALSE -- if we cannot write this file.
521 **
522 **	Side Effects:
523 **		none.
524 */
525 
526 bool
527 writable(s)
528 	register struct stat *s;
529 {
530 	uid_t euid;
531 	gid_t egid;
532 	int bits;
533 
534 	if (bitset(0111, s->st_mode))
535 		return (FALSE);
536 	euid = getruid();
537 	egid = getrgid();
538 	if (geteuid() == 0)
539 	{
540 		if (bitset(S_ISUID, s->st_mode))
541 			euid = s->st_uid;
542 		if (bitset(S_ISGID, s->st_mode))
543 			egid = s->st_gid;
544 	}
545 
546 	if (euid == 0)
547 		return (TRUE);
548 	bits = S_IWRITE;
549 	if (euid != s->st_uid)
550 	{
551 		bits >>= 3;
552 		if (egid != s->st_gid)
553 			bits >>= 3;
554 	}
555 	return ((s->st_mode & bits) != 0);
556 }
557 /*
558 **  INCLUDE -- handle :include: specification.
559 **
560 **	Parameters:
561 **		fname -- filename to include.
562 **		forwarding -- if TRUE, we are reading a .forward file.
563 **			if FALSE, it's a :include: file.
564 **		ctladdr -- address template to use to fill in these
565 **			addresses -- effective user/group id are
566 **			the important things.
567 **		sendq -- a pointer to the head of the send queue
568 **			to put these addresses in.
569 **
570 **	Returns:
571 **		open error status
572 **
573 **	Side Effects:
574 **		reads the :include: file and sends to everyone
575 **		listed in that file.
576 */
577 
578 static jmp_buf	CtxIncludeTimeout;
579 
580 int
581 include(fname, forwarding, ctladdr, sendq, e)
582 	char *fname;
583 	bool forwarding;
584 	ADDRESS *ctladdr;
585 	ADDRESS **sendq;
586 	ENVELOPE *e;
587 {
588 	register FILE *fp;
589 	char *oldto = e->e_to;
590 	char *oldfilename = FileName;
591 	int oldlinenumber = LineNumber;
592 	register EVENT *ev = NULL;
593 	int nincludes;
594 	char buf[MAXLINE];
595 	static int includetimeout();
596 
597 	if (tTd(27, 2))
598 		printf("include(%s)\n", fname);
599 
600 	/*
601 	**  If home directory is remote mounted but server is down,
602 	**  this can hang or give errors; use a timeout to avoid this
603 	*/
604 
605 	if (setjmp(CtxIncludeTimeout) != 0)
606 	{
607 		ctladdr->q_flags |= QQUEUEUP|QDONTSEND;
608 		errno = 0;
609 		usrerr("451 open timeout on %s", fname);
610 		return ETIMEDOUT;
611 	}
612 	ev = setevent((time_t) 60, includetimeout, 0);
613 
614 	/* if forwarding, the input file must be marked safe */
615 	if (forwarding && !safefile(fname, ctladdr->q_uid, S_IREAD))
616 	{
617 		/* don't use this .forward file */
618 		clrevent(ev);
619 		if (tTd(27, 4))
620 			printf("include: not safe (uid=%d)\n", ctladdr->q_uid);
621 		return EPERM;
622 	}
623 
624 	fp = fopen(fname, "r");
625 	if (fp == NULL)
626 	{
627 		int ret = errno;
628 
629 		clrevent(ev);
630 		usrerr("Cannot open %s", fname);
631 		return ret;
632 	}
633 
634 	if (getctladdr(ctladdr) == NULL)
635 	{
636 		struct stat st;
637 
638 		if (fstat(fileno(fp), &st) < 0)
639 		{
640 			int ret = errno;
641 
642 			clrevent(ev);
643 			syserr("Cannot fstat %s!", fname);
644 			return ret;
645 		}
646 		ctladdr->q_uid = st.st_uid;
647 		ctladdr->q_gid = st.st_gid;
648 		ctladdr->q_flags |= QGOODUID;
649 	}
650 
651 	clrevent(ev);
652 
653 	/* read the file -- each line is a comma-separated list. */
654 	FileName = fname;
655 	LineNumber = 0;
656 	ctladdr->q_flags &= ~QSELFREF;
657 	nincludes = 0;
658 	while (fgets(buf, sizeof buf, fp) != NULL)
659 	{
660 		register char *p = strchr(buf, '\n');
661 
662 		LineNumber++;
663 		if (p != NULL)
664 			*p = '\0';
665 		if (buf[0] == '#' || buf[0] == '\0')
666 			continue;
667 		e->e_to = NULL;
668 		message(Arpa_Info, "%s to %s",
669 			forwarding ? "forwarding" : "sending", buf);
670 #ifdef LOG
671 		if (forwarding && LogLevel > 9)
672 			syslog(LOG_INFO, "%s: forward %s => %s",
673 				e->e_id, oldto, buf);
674 #endif
675 
676 		AliasLevel++;
677 		nincludes += sendtolist(buf, ctladdr, sendq, e);
678 		AliasLevel--;
679 	}
680 	if (nincludes > 0 && !bitset(QSELFREF, ctladdr->q_flags))
681 	{
682 		if (tTd(27, 5))
683 		{
684 			printf("include: QDONTSEND ");
685 			printaddr(ctladdr, FALSE);
686 		}
687 		ctladdr->q_flags |= QDONTSEND;
688 	}
689 
690 	(void) fclose(fp);
691 	FileName = oldfilename;
692 	LineNumber = oldlinenumber;
693 	return 0;
694 }
695 
696 static
697 includetimeout()
698 {
699 	longjmp(CtxIncludeTimeout, 1);
700 }
701 /*
702 **  SENDTOARGV -- send to an argument vector.
703 **
704 **	Parameters:
705 **		argv -- argument vector to send to.
706 **
707 **	Returns:
708 **		none.
709 **
710 **	Side Effects:
711 **		puts all addresses on the argument vector onto the
712 **			send queue.
713 */
714 
715 sendtoargv(argv, e)
716 	register char **argv;
717 	register ENVELOPE *e;
718 {
719 	register char *p;
720 
721 	while ((p = *argv++) != NULL)
722 	{
723 		if (argv[0] != NULL && argv[1] != NULL && !strcasecmp(argv[0], "at"))
724 		{
725 			char nbuf[MAXNAME];
726 
727 			if (strlen(p) + strlen(argv[1]) + 2 > sizeof nbuf)
728 				usrerr("address overflow");
729 			else
730 			{
731 				(void) strcpy(nbuf, p);
732 				(void) strcat(nbuf, "@");
733 				(void) strcat(nbuf, argv[1]);
734 				p = newstr(nbuf);
735 				argv += 2;
736 			}
737 		}
738 		(void) sendtolist(p, (ADDRESS *) NULL, &e->e_sendqueue, e);
739 	}
740 }
741 /*
742 **  GETCTLADDR -- get controlling address from an address header.
743 **
744 **	If none, get one corresponding to the effective userid.
745 **
746 **	Parameters:
747 **		a -- the address to find the controller of.
748 **
749 **	Returns:
750 **		the controlling address.
751 **
752 **	Side Effects:
753 **		none.
754 */
755 
756 ADDRESS *
757 getctladdr(a)
758 	register ADDRESS *a;
759 {
760 	while (a != NULL && !bitset(QGOODUID, a->q_flags))
761 		a = a->q_alias;
762 	return (a);
763 }
764