This is sendmail version 8.6.3.
[unix-history] / usr.sbin / sendmail / src / recipient.c
CommitLineData
15637ed4
RG
1/*
2 * Copyright (c) 1983 Eric P. Allman
6f14531a
RG
3 * Copyright (c) 1988, 1993
4 * The Regents of the University of California. All rights reserved.
15637ed4
RG
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed by the University of
17 * California, Berkeley and its contributors.
18 * 4. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35#ifndef lint
d747e748 36static char sccsid[] = "@(#)recipient.c 8.19 (Berkeley) 9/29/93";
15637ed4
RG
37#endif /* not lint */
38
15637ed4 39# include "sendmail.h"
6f14531a 40# include <pwd.h>
15637ed4
RG
41
42/*
43** SENDTOLIST -- Designate a send list.
44**
45** The parameter is a comma-separated list of people to send to.
46** This routine arranges to send to all of them.
47**
48** Parameters:
49** list -- the send list.
50** ctladdr -- the address template for the person to
51** send to -- effective uid/gid are important.
52** This is typically the alias that caused this
53** expansion.
54** sendq -- a pointer to the head of a queue to put
55** these people into.
6f14531a 56** e -- the envelope in which to add these recipients.
15637ed4
RG
57**
58** Returns:
6f14531a 59** The number of addresses actually on the list.
15637ed4
RG
60**
61** Side Effects:
62** none.
63*/
64
65# define MAXRCRSN 10
66
6f14531a 67sendtolist(list, ctladdr, sendq, e)
15637ed4
RG
68 char *list;
69 ADDRESS *ctladdr;
70 ADDRESS **sendq;
6f14531a 71 register ENVELOPE *e;
15637ed4
RG
72{
73 register char *p;
74 register ADDRESS *al; /* list of addresses to send to */
75 bool firstone; /* set on first address sent */
15637ed4 76 char delimiter; /* the address delimiter */
6f14531a 77 int naddrs;
d747e748
JH
78 char *oldto = e->e_to;
79
80 if (list == NULL)
81 {
82 syserr("sendtolist: null list");
83 return 0;
84 }
15637ed4
RG
85
86 if (tTd(25, 1))
87 {
88 printf("sendto: %s\n ctladdr=", list);
89 printaddr(ctladdr, FALSE);
90 }
91
92 /* heuristic to determine old versus new style addresses */
93 if (ctladdr == NULL &&
6f14531a
RG
94 (strchr(list, ',') != NULL || strchr(list, ';') != NULL ||
95 strchr(list, '<') != NULL || strchr(list, '(') != NULL))
96 e->e_flags &= ~EF_OLDSTYLE;
15637ed4 97 delimiter = ' ';
6f14531a 98 if (!bitset(EF_OLDSTYLE, e->e_flags) || ctladdr != NULL)
15637ed4
RG
99 delimiter = ',';
100
101 firstone = TRUE;
15637ed4 102 al = NULL;
6f14531a 103 naddrs = 0;
15637ed4
RG
104
105 for (p = list; *p != '\0'; )
106 {
6f14531a 107 auto char *delimptr;
15637ed4 108 register ADDRESS *a;
15637ed4
RG
109
110 /* parse the address */
6f14531a 111 while ((isascii(*p) && isspace(*p)) || *p == ',')
15637ed4 112 p++;
d747e748 113 a = parseaddr(p, NULLADDR, RF_COPYALL, delimiter, &delimptr, e);
6f14531a 114 p = delimptr;
15637ed4
RG
115 if (a == NULL)
116 continue;
117 a->q_next = al;
118 a->q_alias = ctladdr;
119
120 /* see if this should be marked as a primary address */
121 if (ctladdr == NULL ||
122 (firstone && *p == '\0' && bitset(QPRIMARY, ctladdr->q_flags)))
123 a->q_flags |= QPRIMARY;
124
15637ed4 125 if (ctladdr != NULL && sameaddr(ctladdr, a))
6f14531a
RG
126 ctladdr->q_flags |= QSELFREF;
127 al = a;
15637ed4
RG
128 firstone = FALSE;
129 }
130
15637ed4
RG
131 /* arrange to send to everyone on the local send list */
132 while (al != NULL)
133 {
134 register ADDRESS *a = al;
15637ed4
RG
135
136 al = a->q_next;
6f14531a 137 a = recipient(a, sendq, e);
15637ed4
RG
138
139 /* arrange to inherit full name */
140 if (a->q_fullname == NULL && ctladdr != NULL)
141 a->q_fullname = ctladdr->q_fullname;
6f14531a 142 naddrs++;
15637ed4
RG
143 }
144
d747e748 145 e->e_to = oldto;
6f14531a 146 return (naddrs);
15637ed4
RG
147}
148\f/*
149** RECIPIENT -- Designate a message recipient
150**
151** Saves the named person for future mailing.
152**
153** Parameters:
154** a -- the (preparsed) address header for the recipient.
155** sendq -- a pointer to the head of a queue to put the
156** recipient in. Duplicate supression is done
157** in this queue.
6f14531a 158** e -- the current envelope.
15637ed4
RG
159**
160** Returns:
161** The actual address in the queue. This will be "a" if
162** the address is not a duplicate, else the original address.
163**
164** Side Effects:
165** none.
166*/
167
15637ed4 168ADDRESS *
6f14531a 169recipient(a, sendq, e)
15637ed4
RG
170 register ADDRESS *a;
171 register ADDRESS **sendq;
6f14531a 172 register ENVELOPE *e;
15637ed4
RG
173{
174 register ADDRESS *q;
175 ADDRESS **pq;
176 register struct mailer *m;
177 register char *p;
178 bool quoted = FALSE; /* set if the addr has a quote bit */
6f14531a 179 int findusercount = 0;
15637ed4 180 char buf[MAXNAME]; /* unquoted image of the user name */
6f14531a 181 extern int safefile();
15637ed4 182
6f14531a 183 e->e_to = a->q_paddr;
15637ed4
RG
184 m = a->q_mailer;
185 errno = 0;
186 if (tTd(26, 1))
187 {
188 printf("\nrecipient: ");
189 printaddr(a, FALSE);
190 }
191
d747e748
JH
192 /* if this is primary, add it to the original recipient list */
193 if (a->q_alias == NULL)
194 {
195 if (e->e_origrcpt == NULL)
196 e->e_origrcpt = a->q_paddr;
197 else if (e->e_origrcpt != a->q_paddr)
198 e->e_origrcpt = "";
199 }
200
15637ed4
RG
201 /* break aliasing loops */
202 if (AliasLevel > MAXRCRSN)
203 {
6f14531a 204 usrerr("554 aliasing/forwarding loop broken");
15637ed4
RG
205 return (a);
206 }
207
208 /*
209 ** Finish setting up address structure.
210 */
211
212 /* set the queue timeout */
6f14531a 213 a->q_timeout = TimeOuts.to_q_return;
15637ed4
RG
214
215 /* get unquoted user for file, program or user.name check */
216 (void) strcpy(buf, a->q_user);
217 for (p = buf; *p != '\0' && !quoted; p++)
218 {
6f14531a 219 if (*p == '\\')
15637ed4
RG
220 quoted = TRUE;
221 }
6f14531a 222 stripquotes(buf);
15637ed4 223
6f14531a
RG
224 /* check for direct mailing to restricted mailers */
225 if (a->q_alias == NULL && m == ProgMailer &&
226 !bitset(EF_QUEUERUN, e->e_flags))
15637ed4 227 {
6f14531a 228 a->q_flags |= QBADADDR;
d747e748 229 usrerr("550 Cannot mail directly to programs");
15637ed4
RG
230 }
231
232 /*
233 ** Look up this person in the recipient list.
234 ** If they are there already, return, otherwise continue.
235 ** If the list is empty, just add it. Notice the cute
236 ** hack to make from addresses suppress things correctly:
237 ** the QDONTSEND bit will be set in the send list.
238 ** [Please note: the emphasis is on "hack."]
239 */
240
241 for (pq = sendq; (q = *pq) != NULL; pq = &q->q_next)
242 {
6f14531a 243 if (sameaddr(q, a))
15637ed4
RG
244 {
245 if (tTd(26, 1))
246 {
247 printf("%s in sendq: ", a->q_paddr);
248 printaddr(q, FALSE);
249 }
15637ed4 250 if (!bitset(QPRIMARY, q->q_flags))
6f14531a
RG
251 {
252 if (!bitset(QDONTSEND, a->q_flags))
253 message("duplicate suppressed");
15637ed4 254 q->q_flags |= a->q_flags;
6f14531a 255 }
d747e748
JH
256 a = q;
257 goto testselfdestruct;
15637ed4
RG
258 }
259 }
260
261 /* add address on list */
262 *pq = a;
263 a->q_next = NULL;
15637ed4
RG
264
265 /*
6f14531a 266 ** Alias the name and handle special mailer types.
15637ed4
RG
267 */
268
6f14531a
RG
269 trylocaluser:
270 if (tTd(29, 7))
271 printf("at trylocaluser %s\n", a->q_user);
272
273 if (bitset(QDONTSEND|QBADADDR|QVERIFIED, a->q_flags))
d747e748 274 goto testselfdestruct;
6f14531a
RG
275
276 if (m == InclMailer)
15637ed4 277 {
6f14531a
RG
278 a->q_flags |= QDONTSEND;
279 if (a->q_alias == NULL && !bitset(EF_QUEUERUN, e->e_flags))
15637ed4 280 {
6f14531a
RG
281 a->q_flags |= QBADADDR;
282 usrerr("550 Cannot mail directly to :include:s");
283 }
284 else
285 {
286 int ret;
287
288 message("including file %s", a->q_user);
289 ret = include(a->q_user, FALSE, a, sendq, e);
290 if (transienterror(ret))
15637ed4 291 {
6f14531a
RG
292#ifdef LOG
293 if (LogLevel > 2)
294 syslog(LOG_ERR, "%s: include %s: transient error: %e",
295 e->e_id, a->q_user, errstring(ret));
296#endif
d747e748 297 a->q_flags |= QQUEUEUP;
6f14531a
RG
298 usrerr("451 Cannot open %s: %s",
299 a->q_user, errstring(ret));
15637ed4 300 }
6f14531a 301 else if (ret != 0)
15637ed4 302 {
d747e748 303 a->q_flags |= QBADADDR;
6f14531a
RG
304 usrerr("550 Cannot open %s: %s",
305 a->q_user, errstring(ret));
15637ed4
RG
306 }
307 }
15637ed4 308 }
6f14531a
RG
309 else if (m == FileMailer)
310 {
311 struct stat stb;
312 extern bool writable();
313
314 p = strrchr(buf, '/');
315 /* check if writable or creatable */
316 if (a->q_alias == NULL && !bitset(EF_QUEUERUN, e->e_flags))
317 {
318 a->q_flags |= QBADADDR;
319 usrerr("550 Cannot mail directly to files");
320 }
321 else if ((stat(buf, &stb) >= 0) ? (!writable(&stb)) :
d747e748 322 (*p = '\0', safefile(buf, RealUid, RealGid, NULL, TRUE, S_IWRITE|S_IEXEC) != 0))
6f14531a
RG
323 {
324 a->q_flags |= QBADADDR;
325 giveresponse(EX_CANTCREAT, m, NULL, e);
326 }
327 }
328
329 if (m != LocalMailer)
330 {
331 if (!bitset(QDONTSEND, a->q_flags))
332 e->e_nrcpts++;
d747e748 333 goto testselfdestruct;
6f14531a
RG
334 }
335
336 /* try aliasing */
337 alias(a, sendq, e);
338
339# ifdef USERDB
340 /* if not aliased, look it up in the user database */
341 if (!bitset(QDONTSEND|QNOTREMOTE|QVERIFIED, a->q_flags))
342 {
343 extern int udbexpand();
344 extern int errno;
345
346 if (udbexpand(a, sendq, e) == EX_TEMPFAIL)
347 {
d747e748 348 a->q_flags |= QQUEUEUP;
6f14531a
RG
349 if (e->e_message == NULL)
350 e->e_message = newstr("Deferred: user database error");
351# ifdef LOG
352 if (LogLevel > 8)
353 syslog(LOG_INFO, "%s: deferred: udbexpand: %s",
354 e->e_id, errstring(errno));
355# endif
356 message("queued (user database error): %s",
357 errstring(errno));
358 e->e_nrcpts++;
d747e748 359 goto testselfdestruct;
6f14531a
RG
360 }
361 }
362# endif
363
364 /* if it was an alias or a UDB expansion, just return now */
365 if (bitset(QDONTSEND|QQUEUEUP|QVERIFIED, a->q_flags))
d747e748 366 goto testselfdestruct;
15637ed4
RG
367
368 /*
6f14531a
RG
369 ** If we have a level two config file, then pass the name through
370 ** Ruleset 5 before sending it off. Ruleset 5 has the right
371 ** to send rewrite it to another mailer. This gives us a hook
372 ** after local aliasing has been done.
15637ed4
RG
373 */
374
6f14531a 375 if (tTd(29, 5))
15637ed4 376 {
6f14531a
RG
377 printf("recipient: testing local? cl=%d, rr5=%x\n\t",
378 ConfigLevel, RewriteRules[5]);
379 printaddr(a, FALSE);
380 }
381 if (!bitset(QNOTREMOTE, a->q_flags) && ConfigLevel >= 2 &&
382 RewriteRules[5] != NULL)
383 {
384 maplocaluser(a, sendq, e);
385 }
386
387 /*
388 ** If it didn't get rewritten to another mailer, go ahead
389 ** and deliver it.
390 */
391
392 if (!bitset(QDONTSEND|QQUEUEUP, a->q_flags))
393 {
394 auto bool fuzzy;
395 register struct passwd *pw;
396 extern struct passwd *finduser();
15637ed4 397
6f14531a
RG
398 /* warning -- finduser may trash buf */
399 pw = finduser(buf, &fuzzy);
400 if (pw == NULL)
15637ed4 401 {
6f14531a
RG
402 a->q_flags |= QBADADDR;
403 giveresponse(EX_NOUSER, m, NULL, e);
15637ed4
RG
404 }
405 else
406 {
6f14531a 407 char nbuf[MAXNAME];
15637ed4 408
6f14531a 409 if (fuzzy)
15637ed4 410 {
6f14531a
RG
411 /* name was a fuzzy match */
412 a->q_user = newstr(pw->pw_name);
413 if (findusercount++ > 3)
15637ed4 414 {
6f14531a
RG
415 a->q_flags |= QBADADDR;
416 usrerr("554 aliasing/forwarding loop for %s broken",
417 pw->pw_name);
418 return (a);
15637ed4 419 }
6f14531a
RG
420
421 /* see if it aliases */
422 (void) strcpy(buf, pw->pw_name);
423 goto trylocaluser;
15637ed4 424 }
6f14531a
RG
425 a->q_home = newstr(pw->pw_dir);
426 a->q_uid = pw->pw_uid;
427 a->q_gid = pw->pw_gid;
428 a->q_ruser = newstr(pw->pw_name);
429 a->q_flags |= QGOODUID;
430 buildfname(pw->pw_gecos, pw->pw_name, nbuf);
431 if (nbuf[0] != '\0')
432 a->q_fullname = newstr(nbuf);
433 if (!quoted)
434 forward(a, sendq, e);
15637ed4
RG
435 }
436 }
6f14531a
RG
437 if (!bitset(QDONTSEND, a->q_flags))
438 e->e_nrcpts++;
d747e748
JH
439
440 testselfdestruct:
441 if (tTd(26, 8))
442 {
443 printf("testselfdestruct: ");
444 printaddr(a, TRUE);
445 }
446 if (a->q_alias == NULL && a != &e->e_from &&
447 bitset(QDONTSEND, a->q_flags))
448 {
449 q = *sendq;
450 while (q != NULL && bitset(QDONTSEND, q->q_flags))
451 q = q->q_next;
452 if (q == NULL)
453 {
454 a->q_flags |= QBADADDR;
455 usrerr("554 aliasing/forwarding loop broken");
456 }
457 }
15637ed4
RG
458 return (a);
459}
460\f/*
461** FINDUSER -- find the password entry for a user.
462**
463** This looks a lot like getpwnam, except that it may want to
464** do some fancier pattern matching in /etc/passwd.
465**
466** This routine contains most of the time of many sendmail runs.
467** It deserves to be optimized.
468**
469** Parameters:
470** name -- the name to match against.
6f14531a
RG
471** fuzzyp -- an outarg that is set to TRUE if this entry
472** was found using the fuzzy matching algorithm;
473** set to FALSE otherwise.
15637ed4
RG
474**
475** Returns:
476** A pointer to a pw struct.
477** NULL if name is unknown or ambiguous.
478**
479** Side Effects:
480** may modify name.
481*/
482
483struct passwd *
6f14531a 484finduser(name, fuzzyp)
15637ed4 485 char *name;
6f14531a 486 bool *fuzzyp;
15637ed4
RG
487{
488 register struct passwd *pw;
489 register char *p;
490 extern struct passwd *getpwent();
491 extern struct passwd *getpwnam();
492
6f14531a
RG
493 if (tTd(29, 4))
494 printf("finduser(%s): ", name);
495
496 *fuzzyp = FALSE;
15637ed4 497
d747e748
JH
498 /* DEC Hesiod getpwnam accepts numeric strings -- short circuit it */
499 for (p = name; *p != '\0'; p++)
500 if (!isascii(*p) || !isdigit(*p))
501 break;
502 if (*p == '\0')
503 {
504 if (tTd(29, 4))
505 printf("failed (numeric input)\n");
506 return NULL;
507 }
508
15637ed4
RG
509 /* look up this login name using fast path */
510 if ((pw = getpwnam(name)) != NULL)
6f14531a
RG
511 {
512 if (tTd(29, 4))
513 printf("found (non-fuzzy)\n");
15637ed4 514 return (pw);
6f14531a
RG
515 }
516
517#ifdef MATCHGECOS
518 /* see if fuzzy matching allowed */
519 if (!MatchGecos)
520 {
521 if (tTd(29, 4))
522 printf("not found (fuzzy disabled)\n");
523 return NULL;
524 }
15637ed4
RG
525
526 /* search for a matching full name instead */
527 for (p = name; *p != '\0'; p++)
528 {
529 if (*p == (SpaceSub & 0177) || *p == '_')
530 *p = ' ';
531 }
532 (void) setpwent();
533 while ((pw = getpwent()) != NULL)
534 {
535 char buf[MAXNAME];
536
537 buildfname(pw->pw_gecos, pw->pw_name, buf);
6f14531a 538 if (strchr(buf, ' ') != NULL && !strcasecmp(buf, name))
15637ed4 539 {
6f14531a
RG
540 if (tTd(29, 4))
541 printf("fuzzy matches %s\n", pw->pw_name);
542 message("sending to login name %s", pw->pw_name);
543 *fuzzyp = TRUE;
15637ed4
RG
544 return (pw);
545 }
546 }
6f14531a
RG
547 if (tTd(29, 4))
548 printf("no fuzzy match found\n");
549#else
550 if (tTd(29, 4))
551 printf("not found (fuzzy disabled)\n");
552#endif
15637ed4
RG
553 return (NULL);
554}
555\f/*
556** WRITABLE -- predicate returning if the file is writable.
557**
558** This routine must duplicate the algorithm in sys/fio.c.
559** Unfortunately, we cannot use the access call since we
560** won't necessarily be the real uid when we try to
561** actually open the file.
562**
563** Notice that ANY file with ANY execute bit is automatically
564** not writable. This is also enforced by mailfile.
565**
566** Parameters:
567** s -- pointer to a stat struct for the file.
568**
569** Returns:
570** TRUE -- if we will be able to write this file.
571** FALSE -- if we cannot write this file.
572**
573** Side Effects:
574** none.
575*/
576
577bool
578writable(s)
579 register struct stat *s;
580{
6f14531a
RG
581 uid_t euid;
582 gid_t egid;
15637ed4
RG
583 int bits;
584
585 if (bitset(0111, s->st_mode))
586 return (FALSE);
3a363396
NW
587 euid = RealUid;
588 egid = RealGid;
15637ed4
RG
589 if (geteuid() == 0)
590 {
591 if (bitset(S_ISUID, s->st_mode))
592 euid = s->st_uid;
593 if (bitset(S_ISGID, s->st_mode))
594 egid = s->st_gid;
595 }
596
597 if (euid == 0)
598 return (TRUE);
599 bits = S_IWRITE;
600 if (euid != s->st_uid)
601 {
602 bits >>= 3;
603 if (egid != s->st_gid)
604 bits >>= 3;
605 }
606 return ((s->st_mode & bits) != 0);
607}
608\f/*
609** INCLUDE -- handle :include: specification.
610**
611** Parameters:
612** fname -- filename to include.
6f14531a
RG
613** forwarding -- if TRUE, we are reading a .forward file.
614** if FALSE, it's a :include: file.
15637ed4
RG
615** ctladdr -- address template to use to fill in these
616** addresses -- effective user/group id are
617** the important things.
618** sendq -- a pointer to the head of the send queue
619** to put these addresses in.
620**
621** Returns:
6f14531a 622** open error status
15637ed4
RG
623**
624** Side Effects:
625** reads the :include: file and sends to everyone
626** listed in that file.
627*/
628
6f14531a 629static jmp_buf CtxIncludeTimeout;
d747e748 630static int includetimeout();
6f14531a
RG
631
632int
633include(fname, forwarding, ctladdr, sendq, e)
15637ed4 634 char *fname;
6f14531a 635 bool forwarding;
15637ed4
RG
636 ADDRESS *ctladdr;
637 ADDRESS **sendq;
6f14531a 638 ENVELOPE *e;
15637ed4 639{
d747e748 640 register FILE *fp = NULL;
6f14531a 641 char *oldto = e->e_to;
15637ed4
RG
642 char *oldfilename = FileName;
643 int oldlinenumber = LineNumber;
6f14531a
RG
644 register EVENT *ev = NULL;
645 int nincludes;
d747e748
JH
646 register ADDRESS *ca;
647 uid_t saveduid, uid;
648 gid_t savedgid, gid;
649 char *uname;
650 int rval = 0;
6f14531a 651 char buf[MAXLINE];
6f14531a
RG
652
653 if (tTd(27, 2))
654 printf("include(%s)\n", fname);
d747e748
JH
655 if (tTd(27, 4))
656 printf(" ruid=%d euid=%d\n", getuid(), geteuid());
6f14531a
RG
657 if (tTd(27, 14))
658 {
659 printf("ctladdr ");
660 printaddr(ctladdr, FALSE);
661 }
662
d747e748
JH
663 if (tTd(27, 9))
664 printf("include: old uid = %d/%d\n", getuid(), geteuid());
6f14531a
RG
665
666 ca = getctladdr(ctladdr);
667 if (ca == NULL)
d747e748 668 {
6f14531a 669 uid = 0;
d747e748
JH
670 gid = 0;
671 uname = NULL;
672 saveduid = -1;
673 }
6f14531a 674 else
d747e748 675 {
6f14531a 676 uid = ca->q_uid;
d747e748
JH
677 gid = ca->q_gid;
678 uname = ca->q_user;
679#ifdef HASSETREUID
680 saveduid = geteuid();
681 savedgid = getegid();
682 if (saveduid == 0)
683 {
684 initgroups(uname, gid);
685 if (uid != 0)
686 (void) setreuid(0, uid);
687 }
688#endif
689 }
690
691 if (tTd(27, 9))
692 printf("include: new uid = %d/%d\n", getuid(), geteuid());
693
694 /*
695 ** If home directory is remote mounted but server is down,
696 ** this can hang or give errors; use a timeout to avoid this
697 */
6f14531a
RG
698
699 if (setjmp(CtxIncludeTimeout) != 0)
700 {
d747e748 701 ctladdr->q_flags |= QQUEUEUP;
6f14531a
RG
702 errno = 0;
703 usrerr("451 open timeout on %s", fname);
d747e748
JH
704
705 /* return pseudo-error code */
706 rval = EOPENTIMEOUT;
707 goto resetuid;
6f14531a
RG
708 }
709 ev = setevent((time_t) 60, includetimeout, 0);
710
711 /* the input file must be marked safe */
d747e748
JH
712 rval = safefile(fname, uid, gid, uname, forwarding, S_IREAD);
713 if (rval != 0)
6f14531a 714 {
d747e748 715 /* don't use this :include: file */
6f14531a
RG
716 clrevent(ev);
717 if (tTd(27, 4))
718 printf("include: not safe (uid=%d): %s\n",
d747e748
JH
719 uid, errstring(rval));
720 goto resetuid;
6f14531a 721 }
15637ed4
RG
722
723 fp = fopen(fname, "r");
724 if (fp == NULL)
725 {
d747e748
JH
726 rval = errno;
727 if (tTd(27, 4))
728 printf("include: open: %s\n", errstring(rval));
15637ed4 729 }
d747e748 730 else if (ca == NULL)
15637ed4
RG
731 {
732 struct stat st;
733
734 if (fstat(fileno(fp), &st) < 0)
6f14531a 735 {
d747e748 736 rval = errno;
15637ed4 737 syserr("Cannot fstat %s!", fname);
6f14531a 738 }
d747e748
JH
739 else
740 {
741 ctladdr->q_uid = st.st_uid;
742 ctladdr->q_gid = st.st_gid;
743 ctladdr->q_flags |= QGOODUID;
744 }
15637ed4
RG
745 }
746
6f14531a
RG
747 clrevent(ev);
748
d747e748
JH
749resetuid:
750
751#ifdef HASSETREUID
752 if (saveduid == 0)
753 {
754 if (uid != 0)
755 if (setreuid(-1, 0) < 0 || setreuid(RealUid, 0) < 0)
756 syserr("setreuid(%d, 0) failure (real=%d, eff=%d)",
757 RealUid, getuid(), geteuid());
758 setgid(savedgid);
759 }
760#endif
761
762 if (tTd(27, 9))
763 printf("include: reset uid = %d/%d\n", getuid(), geteuid());
764
765 if (fp == NULL)
766 return rval;
767
6f14531a
RG
768 if (bitset(EF_VRFYONLY, e->e_flags))
769 {
770 /* don't do any more now */
771 ctladdr->q_flags |= QVERIFIED;
772 e->e_nrcpts++;
773 xfclose(fp, "include", fname);
d747e748 774 return rval;
6f14531a
RG
775 }
776
15637ed4
RG
777 /* read the file -- each line is a comma-separated list. */
778 FileName = fname;
779 LineNumber = 0;
6f14531a
RG
780 ctladdr->q_flags &= ~QSELFREF;
781 nincludes = 0;
15637ed4
RG
782 while (fgets(buf, sizeof buf, fp) != NULL)
783 {
6f14531a 784 register char *p = strchr(buf, '\n');
15637ed4
RG
785
786 LineNumber++;
787 if (p != NULL)
788 *p = '\0';
6f14531a 789 if (buf[0] == '#' || buf[0] == '\0')
15637ed4 790 continue;
6f14531a
RG
791 e->e_to = NULL;
792 message("%s to %s",
793 forwarding ? "forwarding" : "sending", buf);
794#ifdef LOG
795 if (forwarding && LogLevel > 9)
796 syslog(LOG_INFO, "%s: forward %s => %s",
797 e->e_id, oldto, buf);
798#endif
799
15637ed4 800 AliasLevel++;
6f14531a 801 nincludes += sendtolist(buf, ctladdr, sendq, e);
15637ed4
RG
802 AliasLevel--;
803 }
d747e748
JH
804
805 if (ferror(fp) && tTd(27, 3))
806 printf("include: read error: %s\n", errstring(errno));
6f14531a
RG
807 if (nincludes > 0 && !bitset(QSELFREF, ctladdr->q_flags))
808 {
809 if (tTd(27, 5))
810 {
811 printf("include: QDONTSEND ");
812 printaddr(ctladdr, FALSE);
813 }
814 ctladdr->q_flags |= QDONTSEND;
815 }
15637ed4 816
6f14531a 817 (void) xfclose(fp, "include", fname);
15637ed4
RG
818 FileName = oldfilename;
819 LineNumber = oldlinenumber;
d747e748
JH
820 e->e_to = oldto;
821 return rval;
6f14531a
RG
822}
823
824static
825includetimeout()
826{
827 longjmp(CtxIncludeTimeout, 1);
15637ed4
RG
828}
829\f/*
830** SENDTOARGV -- send to an argument vector.
831**
832** Parameters:
833** argv -- argument vector to send to.
6f14531a 834** e -- the current envelope.
15637ed4
RG
835**
836** Returns:
837** none.
838**
839** Side Effects:
840** puts all addresses on the argument vector onto the
841** send queue.
842*/
843
6f14531a 844sendtoargv(argv, e)
15637ed4 845 register char **argv;
6f14531a 846 register ENVELOPE *e;
15637ed4
RG
847{
848 register char *p;
849
850 while ((p = *argv++) != NULL)
851 {
d747e748 852 (void) sendtolist(p, NULLADDR, &e->e_sendqueue, e);
15637ed4
RG
853 }
854}
855\f/*
856** GETCTLADDR -- get controlling address from an address header.
857**
858** If none, get one corresponding to the effective userid.
859**
860** Parameters:
861** a -- the address to find the controller of.
862**
863** Returns:
864** the controlling address.
865**
866** Side Effects:
867** none.
868*/
869
870ADDRESS *
871getctladdr(a)
872 register ADDRESS *a;
873{
874 while (a != NULL && !bitset(QGOODUID, a->q_flags))
875 a = a->q_alias;
876 return (a);
877}