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