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