1 # include <pwd.h>
2 # include "sendmail.h"
3 # include <sys/stat.h>
4 
5 static char SccsId[] = "@(#)recipient.c	3.28.1.1	11/21/81";
6 
7 /*
8 **  SENDTO -- Designate a send list.
9 **
10 **	The parameter is a comma-separated list of people to send to.
11 **	This routine arranges to send to all of them.
12 **
13 **	The `ctladdr' is the address that expanded to be this one,
14 **	e.g., in an alias expansion.  This is used for a number of
15 **	purposed, most notably inheritance of uid/gid for protection
16 **	purposes.  It is also used to detect self-reference in group
17 **	expansions and the like.
18 **
19 **	Parameters:
20 **		list -- the send list.
21 **		copyf -- the copy flag; passed to parse.
22 **		ctladdr -- the address template for the person to
23 **			send to -- effective uid/gid are important.
24 **		qflags -- special flags to set in the q_flags field.
25 **
26 **	Returns:
27 **		pointer to chain of addresses.
28 **
29 **	Side Effects:
30 **		none.
31 */
32 
33 # define MAXRCRSN	10
34 
35 ADDRESS *
36 sendto(list, copyf, ctladdr, qflags)
37 	char *list;
38 	int copyf;
39 	ADDRESS *ctladdr;
40 	u_short qflags;
41 {
42 	register char *p;
43 	bool more;		/* set if more addresses to send to */
44 	ADDRESS *al;		/* list of addresses to send to */
45 	bool firstone;		/* set on first address sent */
46 	bool selfref;		/* set if this list includes ctladdr */
47 	ADDRESS *sibl;		/* sibling pointer in tree */
48 	ADDRESS *prev;		/* previous sibling */
49 
50 # ifdef DEBUG
51 	if (Debug > 1)
52 	{
53 		printf("sendto: %s\n   ctladdr=", list);
54 		printaddr(ctladdr, FALSE);
55 	}
56 # endif DEBUG
57 
58 	more = TRUE;
59 	firstone = TRUE;
60 	selfref = FALSE;
61 	al = NULL;
62 	for (p = list; more; )
63 	{
64 		register char *q;
65 		register char c;
66 		ADDRESS *a;
67 
68 		/* find the end of this address */
69 		while (*p == ' ' || *p == '\t')
70 			p++;
71 		q = p;
72 		while ((c = *p++) != '\0' && c != ',' && c != '\n')
73 			continue;
74 		more = c != '\0';
75 		*--p = '\0';
76 		if (more)
77 			p++;
78 		if (*q == '\0')
79 			continue;
80 
81 		/* parse the address */
82 		if ((a = parse(q, (ADDRESS *) NULL, copyf)) == NULL)
83 			continue;
84 		a->q_next = al;
85 		a->q_alias = ctladdr;
86 		if (ctladdr != NULL)
87 			a->q_flags |= ctladdr->q_flags & ~QPRIMARY;
88 		a->q_flags |= qflags;
89 
90 		/* see if this should be marked as a primary address */
91 		if (ctladdr == NULL ||
92 		    (firstone && !more && bitset(QPRIMARY, ctladdr->q_flags)))
93 			a->q_flags |= QPRIMARY;
94 
95 		/* put on send queue or suppress self-reference */
96 		if (ctladdr != NULL && sameaddr(ctladdr, a, FALSE))
97 			selfref = TRUE;
98 		else
99 			al = a;
100 		firstone = FALSE;
101 	}
102 
103 	/* if this alias doesn't include itself, delete ctladdr */
104 	if (!selfref && ctladdr != NULL)
105 		ctladdr->q_flags |= QDONTSEND;
106 
107 	/* arrange to send to everyone on the local send list */
108 	prev = sibl = NULL;
109 	if (ctladdr != NULL)
110 		prev = ctladdr->q_child;
111 	while (al != NULL)
112 	{
113 		register ADDRESS *a = al;
114 		extern ADDRESS *recipient();
115 
116 		al = a->q_next;
117 		sibl = recipient(a);
118 		if (sibl != NULL)
119 		{
120 			extern ADDRESS *addrref();
121 
122 			/* inherit full name */
123 			if (sibl->q_fullname == NULL && ctladdr != NULL)
124 				sibl->q_fullname = ctladdr->q_fullname;
125 
126 			/* link tree together (but only if the node is new) */
127 			if (sibl == a)
128 			{
129 				sibl->q_sibling = prev;
130 				prev = sibl;
131 			}
132 		}
133 	}
134 
135 	To = NULL;
136 	if (ctladdr != NULL)
137 		ctladdr->q_child = prev;
138 	return (prev);
139 }
140 /*
141 **  ADDRREF -- return pointer to address that references another address.
142 **
143 **	Parameters:
144 **		a -- address to check.
145 **		r -- reference to find.
146 **
147 **	Returns:
148 **		address of node in tree rooted at 'a' that references
149 **			'r'.
150 **		NULL if no such node exists.
151 **
152 **	Side Effects:
153 **		none.
154 */
155 
156 ADDRESS *
157 addrref(a, r)
158 	register ADDRESS *a;
159 	register ADDRESS *r;
160 {
161 	register ADDRESS *q;
162 
163 	while (a != NULL)
164 	{
165 		if (a->q_child == r || a->q_sibling == r)
166 			return (a);
167 		q = addrref(a->q_child, r);
168 		if (q != NULL)
169 			return (q);
170 		a = a->q_sibling;
171 	}
172 	return (NULL);
173 }
174 /*
175 **  RECIPIENT -- Designate a message recipient
176 **
177 **	Saves the named person for future mailing.
178 **
179 **	Parameters:
180 **		a -- the (preparsed) address header for the recipient.
181 **
182 **	Returns:
183 **		pointer to address actually inserted in send list.
184 **
185 **	Side Effects:
186 **		none.
187 */
188 
189 ADDRESS *
190 recipient(a)
191 	register ADDRESS *a;
192 {
193 	register ADDRESS *q;
194 	ADDRESS **pq;
195 	register struct mailer *m;
196 	extern ADDRESS *getctladdr();
197 	extern bool safefile();
198 
199 	To = a->q_paddr;
200 	m = a->q_mailer;
201 	errno = 0;
202 # ifdef DEBUG
203 	if (Debug)
204 	{
205 		printf("\nrecipient: ");
206 		printaddr(a, FALSE);
207 	}
208 # endif DEBUG
209 
210 	/* break aliasing loops */
211 	if (AliasLevel > MAXRCRSN)
212 	{
213 		usrerr("aliasing/forwarding loop broken");
214 		return (NULL);
215 	}
216 
217 	/*
218 	**  Finish setting up address structure.
219 	*/
220 
221 	a->q_timeout = TimeOut;
222 
223 	/* do sickly crude mapping for program mailing, etc. */
224 	if (a->q_mailer == LocalMailer)
225 	{
226 		if (a->q_user[0] == '|')
227 		{
228 			a->q_mailer = m = ProgMailer;
229 			a->q_user++;
230 			if (a->q_alias == NULL && Debug == 0 && !QueueRun)
231 			{
232 				usrerr("Cannot mail directly to programs");
233 				a->q_flags |= QDONTSEND;
234 			}
235 		}
236 	}
237 
238 	/*
239 	**  Look up this person in the recipient list.
240 	**	If they are there already, return, otherwise continue.
241 	**	If the list is empty, just add it.  Notice the cute
242 	**	hack to make from addresses suppress things correctly:
243 	**	the QDONTSEND bit will be set in the send list.
244 	**	[Please note: the emphasis is on "hack."]
245 	*/
246 
247 	for (pq = &m->m_sendq; (q = *pq) != NULL; pq = &q->q_next)
248 	{
249 		if (!ForceMail && sameaddr(q, a, FALSE))
250 		{
251 # ifdef DEBUG
252 			if (Debug)
253 			{
254 				printf("%s in sendq: ", a->q_paddr);
255 				printaddr(q, FALSE);
256 			}
257 # endif DEBUG
258 			if (Verbose && !bitset(QDONTSEND|QPSEUDO, a->q_flags))
259 				message(Arpa_Info, "duplicate suppressed");
260 			if (!bitset(QPRIMARY, q->q_flags))
261 				q->q_flags |= a->q_flags;
262 			if (!bitset(QPSEUDO, a->q_flags))
263 				q->q_flags &= ~QPSEUDO;
264 			return (q);
265 		}
266 	}
267 
268 	/* add address on list */
269 	*pq = a;
270 	a->q_next = NULL;
271 	if (DontSend)
272 		a->q_flags |= QDONTSEND;
273 
274 	/*
275 	**  Alias the name and handle :include: specs.
276 	*/
277 
278 	if (a->q_mailer == LocalMailer)
279 	{
280 		if (strncmp(a->q_user, ":include:", 9) == 0)
281 		{
282 			a->q_flags |= QDONTSEND;
283 			if (a->q_alias == NULL && Debug == 0 && !QueueRun)
284 				usrerr("Cannot mail directly to :include:s");
285 			else
286 			{
287 				if (Verbose)
288 					message(Arpa_Info, "including file %s", &a->q_user[9]);
289 				include(&a->q_user[9], " sending", a);
290 			}
291 		}
292 		else
293 			alias(a);
294 	}
295 
296 	/*
297 	**  If the user is local and still being sent, verify that
298 	**  the address is good.  If it is, try to forward.
299 	**  If the address is already good, we have a forwarding
300 	**  loop.  This can be broken by just sending directly to
301 	**  the user (which is probably correct anyway).
302 	*/
303 
304 	if (!bitset(QDONTSEND, a->q_flags) && a->q_mailer == LocalMailer)
305 	{
306 		char buf[MAXNAME];
307 		register char *p;
308 		struct stat stb;
309 		extern bool writable();
310 		bool quoted = FALSE;
311 
312 		strcpy(buf, a->q_user);
313 		for (p = buf; *p != '\0' && !quoted; p++)
314 		{
315 			if (!isascii(*p) && (*p & 0377) != (SPACESUB) & 0377)
316 				quoted = TRUE;
317 		}
318 		stripquotes(buf, TRUE);
319 
320 		/* see if this is to a file */
321 		if ((p = rindex(buf, '/')) != NULL)
322 		{
323 			/* check if writable or creatable */
324 			if (a->q_alias == NULL && Debug == 0 && !QueueRun)
325 			{
326 				usrerr("Cannot mail directly to files");
327 				a->q_flags |= QDONTSEND;
328 			}
329 			else if ((stat(buf, &stb) >= 0) ? (!writable(&stb)) :
330 			    (*p = '\0', !safefile(buf, getruid(), S_IWRITE|S_IEXEC)))
331 			{
332 				a->q_flags |= QBADADDR;
333 				giveresponse(EX_CANTCREAT, TRUE, m);
334 			}
335 		}
336 		else
337 		{
338 			register struct passwd *pw;
339 			extern struct passwd *finduser();
340 
341 			/* warning -- finduser may trash buf */
342 			pw = finduser(buf);
343 			if (pw == NULL)
344 			{
345 				a->q_flags |= QBADADDR;
346 				giveresponse(EX_NOUSER, TRUE, m);
347 			}
348 			else
349 			{
350 				char nbuf[MAXNAME];
351 
352 				if (strcmp(a->q_user, pw->pw_name) != 0)
353 				{
354 					a->q_user = newstr(pw->pw_name);
355 					strcpy(buf, pw->pw_name);
356 				}
357 				a->q_home = newstr(pw->pw_dir);
358 				a->q_uid = pw->pw_uid;
359 				a->q_gid = pw->pw_gid;
360 				a->q_flags |= QGOODUID;
361 				fullname(pw, nbuf);
362 				if (nbuf[0] != '\0')
363 					a->q_fullname = newstr(nbuf);
364 				if (!quoted)
365 					forward(a);
366 			}
367 		}
368 	}
369 
370 	return (a);
371 }
372 /*
373 **  FINDUSER -- find the password entry for a user.
374 **
375 **	This looks a lot like getpwnam, except that it may want to
376 **	do some fancier pattern matching in /etc/passwd.
377 **
378 **	Parameters:
379 **		name -- the name to match against.
380 **
381 **	Returns:
382 **		A pointer to a pw struct.
383 **		NULL if name is unknown or ambiguous.
384 **
385 **	Side Effects:
386 **		may modify name.
387 */
388 
389 struct passwd *
390 finduser(name)
391 	char *name;
392 {
393 	extern struct passwd *getpwent();
394 	register struct passwd *pw;
395 	register char *p;
396 
397 	/*
398 	**  Make name canonical.
399 	*/
400 
401 	for (p = name; *p != '\0'; p++)
402 	{
403 		if (*p == (SPACESUB & 0177) || *p == '_')
404 			*p = ' ';
405 	}
406 
407 	setpwent();
408 	while ((pw = getpwent()) != NULL)
409 	{
410 		extern bool sameword();
411 		char buf[MAXNAME];
412 
413 		if (strcmp(pw->pw_name, name) == 0)
414 			return (pw);
415 		fullname(pw, buf);
416 		if (index(buf, ' ') != NULL && sameword(buf, name))
417 		{
418 			if (Verbose)
419 				message(Arpa_Info, "sending to %s <%s>",
420 				    buf, pw->pw_name);
421 			return (pw);
422 		}
423 	}
424 	return (NULL);
425 }
426 /*
427 **  WRITABLE -- predicate returning if the file is writable.
428 **
429 **	This routine must duplicate the algorithm in sys/fio.c.
430 **	Unfortunately, we cannot use the access call since we
431 **	won't necessarily be the real uid when we try to
432 **	actually open the file.
433 **
434 **	Notice that ANY file with ANY execute bit is automatically
435 **	not writable.  This is also enforced by mailfile.
436 **
437 **	Parameters:
438 **		s -- pointer to a stat struct for the file.
439 **
440 **	Returns:
441 **		TRUE -- if we will be able to write this file.
442 **		FALSE -- if we cannot write this file.
443 **
444 **	Side Effects:
445 **		none.
446 */
447 
448 bool
449 writable(s)
450 	register struct stat *s;
451 {
452 	int euid, egid;
453 	int bits;
454 
455 	if (bitset(0111, s->st_mode))
456 		return (FALSE);
457 	euid = getruid();
458 	egid = getrgid();
459 	if (geteuid() == 0)
460 	{
461 		if (bitset(S_ISUID, s->st_mode))
462 			euid = s->st_uid;
463 		if (bitset(S_ISGID, s->st_mode))
464 			egid = s->st_gid;
465 	}
466 
467 	if (euid == 0)
468 		return (TRUE);
469 	bits = S_IWRITE;
470 	if (euid != s->st_uid)
471 	{
472 		bits >>= 3;
473 		if (egid != s->st_gid)
474 			bits >>= 3;
475 	}
476 	return ((s->st_mode & bits) != 0);
477 }
478 /*
479 **  INCLUDE -- handle :include: specification.
480 **
481 **	Parameters:
482 **		fname -- filename to include.
483 **		msg -- message to print in verbose mode.
484 **		ctladdr -- address template to use to fill in these
485 **			addresses -- effective user/group id are
486 **			the important things.
487 **
488 **	Returns:
489 **		none.
490 **
491 **	Side Effects:
492 **		reads the :include: file and sends to everyone
493 **		listed in that file.
494 */
495 
496 include(fname, msg, ctladdr)
497 	char *fname;
498 	char *msg;
499 	ADDRESS *ctladdr;
500 {
501 	char buf[MAXLINE];
502 	register FILE *fp;
503 	char *oldto = To;
504 
505 	fp = fopen(fname, "r");
506 	if (fp == NULL)
507 	{
508 		usrerr("Cannot open %s", fname);
509 		return;
510 	}
511 	if (getctladdr(ctladdr) == NULL)
512 	{
513 		struct stat st;
514 
515 		if (fstat(fileno(fp), &st) < 0)
516 			syserr("Cannot fstat %s!", fname);
517 		ctladdr->q_uid = st.st_uid;
518 		ctladdr->q_gid = st.st_gid;
519 		ctladdr->q_flags |= QGOODUID;
520 	}
521 
522 	/* read the file -- each line is a comma-separated list. */
523 	while (fgets(buf, sizeof buf, fp) != NULL)
524 	{
525 		register char *p = index(buf, '\n');
526 
527 		if (p != NULL)
528 			*p = '\0';
529 		if (buf[0] == '\0')
530 			continue;
531 		To = oldto;
532 		if (Verbose)
533 			message(Arpa_Info, "%s to %s", msg, buf);
534 		AliasLevel++;
535 		sendto(buf, 1, ctladdr, 0);
536 		AliasLevel--;
537 	}
538 
539 	(void) fclose(fp);
540 }
541 /*
542 **  SENDTOARGV -- send to an argument vector.
543 **
544 **	Parameters:
545 **		argv -- argument vector to send to.
546 **
547 **	Returns:
548 **		none.
549 **
550 **	Side Effects:
551 **		puts all addresses on the argument vector onto the
552 **			send queue.
553 */
554 
555 sendtoargv(argv)
556 	register char **argv;
557 {
558 	register char *p;
559 	extern bool sameword();
560 
561 	while ((p = *argv++) != NULL)
562 	{
563 		if (argv[0] != NULL && argv[1] != NULL && sameword(argv[0], "at"))
564 		{
565 			char nbuf[MAXNAME];
566 
567 			if (strlen(p) + strlen(argv[1]) + 2 > sizeof nbuf)
568 				usrerr("address overflow");
569 			else
570 			{
571 				(void) strcpy(nbuf, p);
572 				(void) strcat(nbuf, "@");
573 				(void) strcat(nbuf, argv[1]);
574 				p = newstr(nbuf);
575 				argv += 2;
576 			}
577 		}
578 		sendto(p, 0, (ADDRESS *) NULL, 0);
579 	}
580 }
581 /*
582 **  GETCTLADDR -- get controlling address from an address header.
583 **
584 **	If none, get one corresponding to the effective userid.
585 **
586 **	Parameters:
587 **		a -- the address to find the controller of.
588 **
589 **	Returns:
590 **		the controlling address.
591 **
592 **	Side Effects:
593 **		none.
594 */
595 
596 ADDRESS *
597 getctladdr(a)
598 	register ADDRESS *a;
599 {
600 	while (a != NULL && !bitset(QGOODUID, a->q_flags))
601 		a = a->q_alias;
602 	return (a);
603 }
604