1 # include <pwd.h>
2 # include <sys/types.h>
3 # include <sys/stat.h>
4 # include "sendmail.h"
5 
6 static char SccsId[] = "@(#)recipient.c	3.13	09/12/81";
7 
8 /*
9 **  SENDTO -- Designate a send list.
10 **
11 **	The parameter is a comma-separated list of people to send to.
12 **	This routine arranges to send to all of them.
13 **
14 **	Parameters:
15 **		list -- the send list.
16 **		copyf -- the copy flag; passed to parse.
17 **
18 **	Returns:
19 **		none
20 **
21 **	Side Effects:
22 **		none.
23 */
24 
25 # define MAXRCRSN	10
26 
27 sendto(list, copyf)
28 	char *list;
29 	int copyf;
30 {
31 	register char *p;
32 	bool more;		/* set if more addresses to send to */
33 	ADDRESS *al;		/* list of addresses to send to */
34 
35 # ifdef DEBUG
36 	if (Debug > 1)
37 		printf("sendto: %s\n", list);
38 # endif DEBUG
39 
40 	more = TRUE;
41 	al = NULL;
42 	for (p = list; more; )
43 	{
44 		register char *q;
45 		register char c;
46 		ADDRESS *a;
47 
48 		/* find the end of this address */
49 		while (*p == ' ' || *p == '\t')
50 			p++;
51 		q = p;
52 		while ((c = *p++) != '\0' && c != ',' && c != '\n')
53 			continue;
54 		more = c != '\0';
55 		*--p = '\0';
56 		if (more)
57 			p++;
58 		if (*q == '\0')
59 			continue;
60 
61 		/* parse the address */
62 		if ((a = parse(q, (ADDRESS *) NULL, copyf)) == NULL)
63 			continue;
64 
65 		/* put it on the local send list */
66 		a->q_next = al;
67 		al = a;
68 	}
69 
70 	/* arrange to send to everyone on the local send list */
71 	while (al != NULL)
72 	{
73 		register ADDRESS *a = al;
74 
75 		al = a->q_next;
76 		recipient(a);
77 	}
78 
79 	To = NULL;
80 }
81 /*
82 **  RECIPIENT -- Designate a message recipient
83 **
84 **	Saves the named person for future mailing.
85 **
86 **	Parameters:
87 **		a -- the (preparsed) address header for the recipient.
88 **
89 **	Returns:
90 **		none.
91 **
92 **	Side Effects:
93 **		none.
94 */
95 
96 recipient(a)
97 	register ADDRESS *a;
98 {
99 	register ADDRESS *q;
100 	ADDRESS **pq;
101 	register struct mailer *m;
102 
103 	To = a->q_paddr;
104 	m = Mailer[a->q_mailer];
105 	errno = 0;
106 # ifdef DEBUG
107 	if (Debug)
108 		printf("recipient(%s)\n", To);
109 # endif DEBUG
110 
111 	/* break aliasing loops */
112 	if (AliasLevel > MAXRCRSN)
113 	{
114 		usrerr("aliasing/forwarding loop broken");
115 		return;
116 	}
117 
118 	/*
119 	**  Do sickly crude mapping for program mailing, etc.
120 	*/
121 
122 	if (a->q_mailer == MN_LOCAL)
123 	{
124 		if (a->q_user[0] == '|')
125 		{
126 			a->q_mailer = MN_PROG;
127 			m = Mailer[MN_PROG];
128 			a->q_user++;
129 # ifdef PARANOID
130 			if (AliasLevel <= 0)
131 			{
132 				usrerr("Cannot mail directly to programs");
133 				a->q_flags |= QDONTSEND;
134 			}
135 # endif PARANOID
136 		}
137 	}
138 
139 	/*
140 	**  Look up this person in the recipient list.  If they
141 	**  are there already, return, otherwise continue.
142 	**  If the list is empty, just add it.
143 	*/
144 
145 	for (pq = &m->m_sendq; (q = *pq) != NULL; pq = &q->q_next)
146 	{
147 		if (!ForceMail && sameaddr(q, a, FALSE))
148 		{
149 # ifdef DEBUG
150 			if (Debug)
151 				printf("(%s in sendq)\n", a->q_paddr);
152 # endif DEBUG
153 			if (Verbose && !bitset(QDONTSEND, a->q_flags))
154 				message(Arpa_Info, "duplicate suppressed");
155 			return;
156 		}
157 	}
158 
159 	/* add address on list */
160 	*pq = a;
161 	a->q_next = NULL;
162 	if (DontSend)
163 		a->q_flags |= QDONTSEND;
164 
165 	/*
166 	**  Alias the name and handle :include: specs.
167 	*/
168 
169 	if (a->q_mailer == MN_LOCAL)
170 	{
171 		if (strncmp(a->q_user, ":include:", 9) == 0)
172 		{
173 			a->q_flags |= QDONTSEND;
174 			if (Verbose)
175 				message(Arpa_Info, "including file %s", &a->q_user[9]);
176 			include(&a->q_user[9], " sending");
177 		}
178 		else
179 			alias(a);
180 	}
181 
182 	/*
183 	**  If the user is local and still being sent, verify that
184 	**  the address is good.  If it is, try to forward.
185 	**  If the address is already good, we have a forwarding
186 	**  loop.  This can be broken by just sending directly to
187 	**  the user (which is probably correct anyway).
188 	*/
189 
190 	if (!bitset(QDONTSEND, a->q_flags) && a->q_mailer == MN_LOCAL)
191 	{
192 		char buf[MAXNAME];
193 		register char *p;
194 		struct stat stb;
195 		extern bool writable();
196 
197 		strcpy(buf, a->q_user);
198 		stripquotes(buf, TRUE);
199 
200 		/* see if this is to a file */
201 		if ((p = rindex(buf, '/')) != NULL)
202 		{
203 			/* check if writable or creatable */
204 			if ((stat(buf, &stb) >= 0) ? (!writable(&stb)) :
205 			    (*p = '\0', access(buf, 3) < 0))
206 			{
207 				a->q_flags |= QBADADDR;
208 				giveresponse(EX_CANTCREAT, TRUE, m);
209 			}
210 		}
211 		else
212 		{
213 			register struct passwd *pw;
214 			extern struct passwd *finduser();
215 
216 			pw = finduser(buf);
217 			if (pw == NULL)
218 			{
219 				a->q_flags |= QBADADDR;
220 				giveresponse(EX_NOUSER, TRUE, m);
221 			}
222 			else
223 			{
224 				a->q_home = newstr(pw->pw_dir);
225 				a->q_uid = pw->pw_uid;
226 				if (strcmp(buf, a->q_user) == 0)
227 					forward(a);
228 			}
229 		}
230 	}
231 }
232 /*
233 **  FINDUSER -- find the password entry for a user.
234 **
235 **	This looks a lot like getpwnam, except that it may want to
236 **	do some fancier pattern matching in /etc/passwd.
237 **
238 **	Parameters:
239 **		name -- the name to match against.
240 **
241 **	Returns:
242 **		A pointer to a pw struct.
243 **		NULL if name is unknown or ambiguous.
244 **
245 **	Side Effects:
246 **		none.
247 */
248 
249 struct passwd *
250 finduser(name)
251 	char *name;
252 {
253 	extern struct passwd *getpwnam();
254 
255 	return (getpwnam(name));
256 }
257 /*
258 **  WRITABLE -- predicate returning if the file is writable.
259 **
260 **	This routine must duplicate the algorithm in sys/fio.c.
261 **	Unfortunately, we cannot use the access call since we
262 **	won't necessarily be the real uid when we try to
263 **	actually open the file.
264 **
265 **	Notice that ANY file with ANY execute bit is automatically
266 **	not writable.  This is also enforced by mailfile.
267 **
268 **	Parameters:
269 **		s -- pointer to a stat struct for the file.
270 **
271 **	Returns:
272 **		TRUE -- if we will be able to write this file.
273 **		FALSE -- if we cannot write this file.
274 **
275 **	Side Effects:
276 **		none.
277 */
278 
279 bool
280 writable(s)
281 	register struct stat *s;
282 {
283 	int euid, egid;
284 	int bits;
285 
286 	if (bitset(0111, s->st_mode))
287 		return (FALSE);
288 	euid = getruid();
289 	egid = getrgid();
290 	if (geteuid() == 0)
291 	{
292 		if (bitset(S_ISUID, s->st_mode))
293 			euid = s->st_uid;
294 		if (bitset(S_ISGID, s->st_mode))
295 			egid = s->st_gid;
296 	}
297 
298 	if (euid == 0)
299 		return (TRUE);
300 	bits = S_IWRITE;
301 	if (euid != s->st_uid)
302 	{
303 		bits >>= 3;
304 		if (egid != s->st_gid)
305 			bits >>= 3;
306 	}
307 	return ((s->st_mode & bits) != 0);
308 }
309 /*
310 **  INCLUDE -- handle :include: specification.
311 **
312 **	Parameters:
313 **		fname -- filename to include.
314 **		msg -- message to print in verbose mode.
315 **
316 **	Returns:
317 **		none.
318 **
319 **	Side Effects:
320 **		reads the :include: file and sends to everyone
321 **		listed in that file.
322 */
323 
324 include(fname, msg)
325 	char *fname;
326 	char *msg;
327 {
328 	char buf[MAXLINE];
329 	register FILE *fp;
330 	char *oldto = To;
331 
332 	fp = fopen(fname, "r");
333 	if (fp == NULL)
334 	{
335 		usrerr("Cannot open %s", fname);
336 		return;
337 	}
338 
339 	/* read the file -- each line is a comma-separated list. */
340 	while (fgets(buf, sizeof buf, fp) != NULL)
341 	{
342 		register char *p = index(buf, '\n');
343 
344 		if (p != NULL)
345 			*p = '\0';
346 		if (buf[0] == '\0')
347 			continue;
348 		To = oldto;
349 		if (Verbose)
350 			message(Arpa_Info, "%s to %s", msg, buf);
351 		AliasLevel++;
352 		sendto(buf, 1);
353 		AliasLevel--;
354 	}
355 
356 	(void) fclose(fp);
357 }
358 /*
359 **  SENDTOARGV -- send to an argument vector.
360 **
361 **	Parameters:
362 **		argv -- argument vector to send to.
363 **
364 **	Returns:
365 **		none.
366 **
367 **	Side Effects:
368 **		puts all addresses on the argument vector onto the
369 **			send queue.
370 */
371 
372 sendtoargv(argv)
373 	register char **argv;
374 {
375 	register char *p;
376 	extern bool sameword();
377 
378 	while ((p = *argv++) != NULL)
379 	{
380 		if (argv[0] != NULL && argv[1] != NULL && sameword(argv[0], "at"))
381 		{
382 			char nbuf[MAXNAME];
383 
384 			if (strlen(p) + strlen(argv[1]) + 2 > sizeof nbuf)
385 				usrerr("address overflow");
386 			else
387 			{
388 				(void) strcpy(nbuf, p);
389 				(void) strcat(nbuf, "@");
390 				(void) strcat(nbuf, argv[1]);
391 				p = newstr(nbuf);
392 				argv += 2;
393 			}
394 		}
395 		sendto(p, 0);
396 	}
397 }
398