don't pass through NOTIFY= unless it was given in the SMTP RCPT
[unix-history] / usr / src / usr.sbin / sendmail / src / recipient.c
CommitLineData
b2a81223 1/*
dc45ba8c 2 * Copyright (c) 1983 Eric P. Allman
c1f0acb8
KB
3 * Copyright (c) 1988, 1993
4 * The Regents of the University of California. All rights reserved.
bee79b64 5 *
417f7a11 6 * %sccs.include.redist.c%
bee79b64 7 */
b2a81223
DF
8
9#ifndef lint
e1f691b3 10static char sccsid[] = "@(#)recipient.c 8.74 (Berkeley) %G%";
bee79b64 11#endif /* not lint */
b2a81223 12
72041f93 13# include "sendmail.h"
6eefe4f6 14# include <pwd.h>
6eefe4f6 15
6eefe4f6 16/*
811a6cf3 17** SENDTOLIST -- Designate a send list.
6eefe4f6
EA
18**
19** The parameter is a comma-separated list of people to send to.
20** This routine arranges to send to all of them.
21**
abae7b2d
EA
22** The `ctladdr' is the address that expanded to be this one,
23** e.g., in an alias expansion. This is used for a number of
24** purposed, most notably inheritance of uid/gid for protection
25** purposes. It is also used to detect self-reference in group
26** expansions and the like.
27**
6eefe4f6
EA
28** Parameters:
29** list -- the send list.
1bf7c76b
EA
30** ctladdr -- the address template for the person to
31** send to -- effective uid/gid are important.
d4f42161
EA
32** This is typically the alias that caused this
33** expansion.
34** sendq -- a pointer to the head of a queue to put
35** these people into.
f8c2f9fd
EA
36** aliaslevel -- the current alias nesting depth -- to
37** diagnose loops.
118e6693 38** e -- the envelope in which to add these recipients.
abae7b2d 39** qflags -- special flags to set in the q_flags field.
6eefe4f6
EA
40**
41** Returns:
abae7b2d 42** pointer to chain of addresses.
6eefe4f6
EA
43**
44** Side Effects:
45** none.
46*/
47
68d9129a
EA
48#define MAXRCRSN 10 /* maximum levels of alias recursion */
49
50/* q_flags bits inherited from ctladdr */
e1f691b3 51#define QINHERITEDBITS (QPINGONSUCCESS|QPINGONFAILURE|QPINGONDELAY|QHASNOTIFY)
6eefe4f6 52
d51d925d 53int
abae7b2d
EA
54ADDRESS *
55sendto(list, copyf, ctladdr, qflags)
6eefe4f6 56 char *list;
1bf7c76b 57 ADDRESS *ctladdr;
4e5e456f 58 ADDRESS **sendq;
f8c2f9fd 59 int aliaslevel;
a4076aed 60 register ENVELOPE *e;
abae7b2d 61 u_short qflags;
6eefe4f6
EA
62{
63 register char *p;
7b955214 64 register ADDRESS *al; /* list of addresses to send to */
92f12b98 65 bool firstone; /* set on first address sent */
d3f52e20 66 char delimiter; /* the address delimiter */
1c7897ef 67 int naddrs;
c6fde7ee 68 int i;
d1147db7 69 char *oldto = e->e_to;
c6fde7ee 70 char *bufp;
93df3047 71 char buf[MAXNAME + 1];
abae7b2d
EA
72 ADDRESS *sibl; /* sibling pointer in tree */
73 ADDRESS *prev; /* previous sibling */
d6b27179 74
5aec60fc
EA
75 if (list == NULL)
76 {
77 syserr("sendtolist: null list");
78 return 0;
79 }
80
9678c96d 81 if (tTd(25, 1))
331b7c9f
EA
82 {
83 printf("sendto: %s\n ctladdr=", list);
84 printaddr(ctladdr, FALSE);
85 }
6eefe4f6 86
7b955214 87 /* heuristic to determine old versus new style addresses */
a2983993 88 if (ctladdr == NULL &&
f3d8f6d6
EA
89 (strchr(list, ',') != NULL || strchr(list, ';') != NULL ||
90 strchr(list, '<') != NULL || strchr(list, '(') != NULL))
a4076aed 91 e->e_flags &= ~EF_OLDSTYLE;
d3f52e20 92 delimiter = ' ';
a4076aed 93 if (!bitset(EF_OLDSTYLE, e->e_flags) || ctladdr != NULL)
d3f52e20 94 delimiter = ',';
7b955214 95
92f12b98 96 firstone = TRUE;
d6b27179 97 al = NULL;
1c7897ef 98 naddrs = 0;
7b955214 99
c6fde7ee
EA
100 /* make sure we have enough space to copy the string */
101 i = strlen(list) + 1;
102 if (i <= sizeof buf)
93df3047 103 bufp = buf;
c6fde7ee
EA
104 else
105 bufp = xalloc(i);
dcf45886 106 strcpy(bufp, denlstring(list, FALSE, TRUE));
93df3047
EA
107
108 for (p = bufp; *p != '\0'; )
6eefe4f6 109 {
9e2cf26f 110 auto char *delimptr;
506fc377 111 register ADDRESS *a;
6eefe4f6
EA
112
113 /* parse the address */
2bee003d 114 while ((isascii(*p) && isspace(*p)) || *p == ',')
506fc377 115 p++;
28f94061 116 a = parseaddr(p, NULLADDR, RF_COPYALL, delimiter, &delimptr, e);
9e2cf26f 117 p = delimptr;
b9fadd5b
EA
118 if (a == NULL)
119 continue;
d6b27179 120 a->q_next = al;
1bf7c76b 121 a->q_alias = ctladdr;
abae7b2d
EA
122 if (ctladdr != NULL)
123 a->q_flags |= ctladdr->q_flags & ~QPRIMARY;
124 a->q_flags |= qflags;
331b7c9f
EA
125
126 /* see if this should be marked as a primary address */
92f12b98 127 if (ctladdr == NULL ||
506fc377 128 (firstone && *p == '\0' && bitset(QPRIMARY, ctladdr->q_flags)))
92f12b98 129 a->q_flags |= QPRIMARY;
331b7c9f 130
abae7b2d
EA
131 sibl = recipient(a);
132 if (sibl != NULL)
133 {
134 extern ADDRESS *addrref();
135
136 /* inherit full name */
137 if (sibl->q_fullname == NULL && ctladdr != NULL)
138 sibl->q_fullname = ctladdr->q_fullname;
139
140 /* link tree together (but only if the node is new) */
141 if (sibl == a)
142 {
143 sibl->q_sibling = prev;
144 prev = sibl;
145 }
146 }
6eefe4f6 147 }
d6b27179 148
d1147db7 149 e->e_to = oldto;
c6fde7ee
EA
150 if (bufp != buf)
151 free(bufp);
1c7897ef 152 return (naddrs);
abae7b2d
EA
153 if (ctladdr != NULL)
154 ctladdr->q_child = prev;
155 return (prev);
156}
157\f/*
158** ADDRREF -- return pointer to address that references another address.
159**
160** Parameters:
161** a -- address to check.
162** r -- reference to find.
163**
164** Returns:
165** address of node in tree rooted at 'a' that references
166** 'r'.
167** NULL if no such node exists.
168**
169** Side Effects:
170** none.
171*/
172
173ADDRESS *
174addrref(a, r)
175 register ADDRESS *a;
176 register ADDRESS *r;
177{
178 register ADDRESS *q;
179
180 while (a != NULL)
181 {
182 if (a->q_child == r || a->q_sibling == r)
183 return (a);
184 q = addrref(a->q_child, r);
185 if (q != NULL)
186 return (q);
187 a = a->q_sibling;
188 }
189 return (NULL);
6eefe4f6
EA
190}
191\f/*
192** RECIPIENT -- Designate a message recipient
193**
194** Saves the named person for future mailing.
195**
196** Parameters:
197** a -- the (preparsed) address header for the recipient.
d4f42161
EA
198** sendq -- a pointer to the head of a queue to put the
199** recipient in. Duplicate supression is done
200** in this queue.
f8c2f9fd 201** aliaslevel -- the current alias nesting depth.
78bbbc48 202** e -- the current envelope.
6eefe4f6
EA
203**
204** Returns:
abae7b2d 205** pointer to address actually inserted in send list.
6eefe4f6
EA
206**
207** Side Effects:
208** none.
209*/
210
d344c0b7 211ADDRESS *
abae7b2d 212ADDRESS *
f8c2f9fd 213recipient(a, sendq, aliaslevel, e)
6eefe4f6 214 register ADDRESS *a;
d4f42161 215 register ADDRESS **sendq;
f8c2f9fd 216 int aliaslevel;
a4076aed 217 register ENVELOPE *e;
6eefe4f6
EA
218{
219 register ADDRESS *q;
74c5fe7c 220 ADDRESS **pq;
6eefe4f6 221 register struct mailer *m;
98f46225
EA
222 register char *p;
223 bool quoted = FALSE; /* set if the addr has a quote bit */
7f0fd60b 224 int findusercount = 0;
f466bb18
EA
225 int i;
226 char *buf;
8446c922 227 char buf0[MAXNAME + 1]; /* unquoted image of the user name */
118e6693 228 extern int safefile();
6eefe4f6 229
a4076aed 230 e->e_to = a->q_paddr;
179c1218 231 m = a->q_mailer;
6eefe4f6 232 errno = 0;
9678c96d 233 if (tTd(26, 1))
331b7c9f
EA
234 {
235 printf("\nrecipient: ");
236 printaddr(a, FALSE);
237 }
6eefe4f6 238
e4a5cf08
EA
239 /* if this is primary, add it to the original recipient list */
240 if (a->q_alias == NULL)
241 {
242 if (e->e_origrcpt == NULL)
243 e->e_origrcpt = a->q_paddr;
244 else if (e->e_origrcpt != a->q_paddr)
245 e->e_origrcpt = "";
246 }
247
6eefe4f6 248 /* break aliasing loops */
f8c2f9fd 249 if (aliaslevel > MAXRCRSN)
6eefe4f6 250 {
d51d925d
EA
251 usrerr("554 aliasing/forwarding loop broken (%d aliases deep; %d max",
252 aliaslevel, MAXRCRSN);
abae7b2d 253 return (NULL);
6eefe4f6
EA
254 }
255
256 /*
ed45aae1 257 ** Finish setting up address structure.
6eefe4f6
EA
258 */
259
0fe3917f 260 /* get unquoted user for file, program or user.name check */
f466bb18 261 i = strlen(a->q_user);
8446c922 262 if (i >= sizeof buf0)
f466bb18
EA
263 buf = xalloc(i + 1);
264 else
265 buf = buf0;
98f46225
EA
266 (void) strcpy(buf, a->q_user);
267 for (p = buf; *p != '\0' && !quoted; p++)
268 {
3eb4fac4 269 if (*p == '\\')
98f46225
EA
270 quoted = TRUE;
271 }
85c61679 272 stripquotes(buf);
98f46225 273
98e5062b 274 /* check for direct mailing to restricted mailers */
78a504b0 275 if (m == ProgMailer)
6eefe4f6 276 {
78a504b0
EA
277 if (a->q_alias == NULL)
278 {
279 a->q_flags |= QBADADDR;
280 usrerr("550 Cannot mail directly to programs");
281 }
282 else if (bitset(QBOGUSSHELL, a->q_alias->q_flags))
283 {
284 a->q_flags |= QBADADDR;
285 usrerr("550 User %s@%s doesn't have a valid shell for mailing to programs",
286 a->q_alias->q_ruser, MyHostName);
287 }
288 else if (bitset(QUNSAFEADDR, a->q_alias->q_flags))
289 {
290 a->q_flags |= QBADADDR;
291 usrerr("550 Address %s is unsafe for mailing to programs",
292 a->q_alias->q_paddr);
293 }
6eefe4f6
EA
294 }
295
296 /*
b9ca6d11
EA
297 ** Look up this person in the recipient list.
298 ** If they are there already, return, otherwise continue.
299 ** If the list is empty, just add it. Notice the cute
300 ** hack to make from addresses suppress things correctly:
301 ** the QDONTSEND bit will be set in the send list.
302 ** [Please note: the emphasis is on "hack."]
6eefe4f6
EA
303 */
304
d4f42161 305 for (pq = sendq; (q = *pq) != NULL; pq = &q->q_next)
6eefe4f6 306 {
35943e55 307 if (sameaddr(q, a))
6eefe4f6 308 {
1d303d98
EA
309 /* if this is a reinsertion, just go ahead */
310 if (bitset(QVERIFIED, q->q_flags))
311 break;
312
9678c96d 313 if (tTd(26, 1))
331b7c9f
EA
314 {
315 printf("%s in sendq: ", a->q_paddr);
316 printaddr(q, FALSE);
317 }
34bc9a9c 318 if (!bitset(QPRIMARY, q->q_flags))
f7eca811 319 {
34bc9a9c 320 if (!bitset(QDONTSEND, a->q_flags))
b6edea3d 321 message("duplicate suppressed");
34bc9a9c 322 q->q_flags |= a->q_flags;
f7eca811 323 }
34bc9a9c
EA
324 else if (bitset(QSELFREF, q->q_flags))
325 q->q_flags |= a->q_flags & ~QDONTSEND;
abae7b2d
EA
326 if (!bitset(QPSEUDO, a->q_flags))
327 q->q_flags &= ~QPSEUDO;
328 return (q);
6eefe4f6 329 }
6eefe4f6 330 }
74c5fe7c
EA
331
332 /* add address on list */
1d303d98
EA
333 if (*pq != a)
334 {
335 *pq = a;
336 a->q_next = NULL;
337 }
338
339 a->q_flags &= ~QVERIFIED;
6eefe4f6
EA
340
341 /*
98e5062b 342 ** Alias the name and handle special mailer types.
6eefe4f6
EA
343 */
344
7f0fd60b 345 trylocaluser:
42450b5a
EA
346 if (tTd(29, 7))
347 printf("at trylocaluser %s\n", a->q_user);
348
bc854e30 349 if (bitset(QDONTSEND|QBADADDR|QVERIFIED, a->q_flags))
d1147db7 350 goto testselfdestruct;
98e5062b
EA
351
352 if (m == InclMailer)
6eefe4f6 353 {
98e5062b 354 a->q_flags |= QDONTSEND;
46361811 355 if (a->q_alias == NULL)
6eefe4f6 356 {
bc854e30 357 a->q_flags |= QBADADDR;
b6edea3d 358 usrerr("550 Cannot mail directly to :include:s");
6eefe4f6
EA
359 }
360 else
8a12fae4 361 {
d50bcc17 362 int ret;
118e6693 363
b6edea3d 364 message("including file %s", a->q_user);
f8c2f9fd 365 ret = include(a->q_user, FALSE, a, sendq, aliaslevel, e);
d50bcc17
EA
366 if (transienterror(ret))
367 {
368#ifdef LOG
369 if (LogLevel > 2)
24ba7f88 370 syslog(LOG_ERR, "%s: include %s: transient error: %s",
1db90aeb
EA
371 e->e_id == NULL ? "NOQUEUE" : e->e_id,
372 a->q_user, errstring(ret));
d50bcc17 373#endif
c069e0df 374 a->q_flags |= QQUEUEUP;
4281694e 375 a->q_flags &= ~QDONTSEND;
d50bcc17
EA
376 usrerr("451 Cannot open %s: %s",
377 a->q_user, errstring(ret));
378 }
379 else if (ret != 0)
380 {
32c83608 381 a->q_flags |= QBADADDR;
d50bcc17
EA
382 usrerr("550 Cannot open %s: %s",
383 a->q_user, errstring(ret));
d50bcc17 384 }
8a12fae4 385 }
98e5062b 386 }
6e99f903 387 else if (m == FileMailer)
6eefe4f6 388 {
a0554f81 389 extern bool writable();
6eefe4f6 390
d13779b1 391 /* check if writable or creatable */
46361811 392 if (a->q_alias == NULL)
6eefe4f6 393 {
bc854e30 394 a->q_flags |= QBADADDR;
b6edea3d 395 usrerr("550 Cannot mail directly to files");
d13779b1 396 }
78a504b0
EA
397 else if (bitset(QBOGUSSHELL, a->q_alias->q_flags))
398 {
399 a->q_flags |= QBADADDR;
400 usrerr("550 User %s@%s doesn't have a valid shell for mailing to files",
401 a->q_alias->q_ruser, MyHostName);
402 }
403 else if (bitset(QUNSAFEADDR, a->q_alias->q_flags))
404 {
405 a->q_flags |= QBADADDR;
406 usrerr("550 Address %s is unsafe for mailing to files",
407 a->q_alias->q_paddr);
408 }
d52f8819 409 else if (!writable(buf, getctladdr(a), SFF_CREAT))
d13779b1 410 {
bc854e30 411 a->q_flags |= QBADADDR;
3500a891
EA
412 giveresponse(EX_CANTCREAT, m, NULL, a->q_alias,
413 (time_t) 0, e);
d13779b1 414 }
d13779b1
EA
415 }
416
98e5062b 417 /* try aliasing */
2bade550 418 if (!bitset(QDONTSEND, a->q_flags) && bitnset(M_ALIASABLE, m->m_flags))
f8c2f9fd 419 alias(a, sendq, aliaslevel, e);
98e5062b
EA
420
421# ifdef USERDB
422 /* if not aliased, look it up in the user database */
2bade550
EA
423 if (!bitset(QDONTSEND|QNOTREMOTE|QVERIFIED, a->q_flags) &&
424 bitnset(M_CHECKUDB, m->m_flags))
98e5062b
EA
425 {
426 extern int udbexpand();
427
f8c2f9fd 428 if (udbexpand(a, sendq, aliaslevel, e) == EX_TEMPFAIL)
98e5062b 429 {
c069e0df 430 a->q_flags |= QQUEUEUP;
98e5062b
EA
431 if (e->e_message == NULL)
432 e->e_message = newstr("Deferred: user database error");
433# ifdef LOG
68f7099c 434 if (LogLevel > 8)
3f0792d1 435 syslog(LOG_INFO, "%s: deferred: udbexpand: %s",
1db90aeb
EA
436 e->e_id == NULL ? "NOQUEUE" : e->e_id,
437 errstring(errno));
98e5062b 438# endif
73f6752a
EA
439 message("queued (user database error): %s",
440 errstring(errno));
6e99f903 441 e->e_nrcpts++;
d1147db7 442 goto testselfdestruct;
98e5062b
EA
443 }
444 }
445# endif
446
d13779b1
EA
447 /*
448 ** If we have a level two config file, then pass the name through
449 ** Ruleset 5 before sending it off. Ruleset 5 has the right
450 ** to send rewrite it to another mailer. This gives us a hook
451 ** after local aliasing has been done.
452 */
453
454 if (tTd(29, 5))
455 {
456 printf("recipient: testing local? cl=%d, rr5=%x\n\t",
457 ConfigLevel, RewriteRules[5]);
458 printaddr(a, FALSE);
459 }
2bade550
EA
460 if (!bitset(QNOTREMOTE|QDONTSEND|QQUEUEUP|QVERIFIED, a->q_flags) &&
461 ConfigLevel >= 2 && RewriteRules[5] != NULL &&
462 bitnset(M_TRYRULESET5, m->m_flags))
d13779b1 463 {
f8c2f9fd 464 maplocaluser(a, sendq, aliaslevel, e);
d13779b1
EA
465 }
466
467 /*
468 ** If it didn't get rewritten to another mailer, go ahead
469 ** and deliver it.
470 */
471
2bade550
EA
472 if (!bitset(QDONTSEND|QQUEUEUP|QVERIFIED, a->q_flags) &&
473 bitnset(M_HASPWENT, m->m_flags))
d13779b1 474 {
42450b5a 475 auto bool fuzzy;
d13779b1
EA
476 register struct passwd *pw;
477 extern struct passwd *finduser();
478
479 /* warning -- finduser may trash buf */
42450b5a 480 pw = finduser(buf, &fuzzy);
d13779b1
EA
481 if (pw == NULL)
482 {
bc854e30 483 a->q_flags |= QBADADDR;
3500a891
EA
484 giveresponse(EX_NOUSER, m, NULL, a->q_alias,
485 (time_t) 0, e);
6eefe4f6
EA
486 }
487 else
488 {
8446c922 489 char nbuf[MAXNAME + 1];
ff3e3c1c 490
42450b5a 491 if (fuzzy)
6eefe4f6 492 {
7f0fd60b 493 /* name was a fuzzy match */
d13779b1 494 a->q_user = newstr(pw->pw_name);
7f0fd60b
EA
495 if (findusercount++ > 3)
496 {
bc854e30 497 a->q_flags |= QBADADDR;
b6edea3d 498 usrerr("554 aliasing/forwarding loop for %s broken",
7f0fd60b 499 pw->pw_name);
f466bb18 500 goto done;
7f0fd60b
EA
501 }
502
503 /* see if it aliases */
d13779b1 504 (void) strcpy(buf, pw->pw_name);
7f0fd60b 505 goto trylocaluser;
6eefe4f6 506 }
c841d671
EA
507 if (strcmp(pw->pw_dir, "/") == 0)
508 a->q_home = "";
509 else
510 a->q_home = newstr(pw->pw_dir);
d13779b1
EA
511 a->q_uid = pw->pw_uid;
512 a->q_gid = pw->pw_gid;
61cbea4c 513 a->q_ruser = newstr(pw->pw_name);
d13779b1
EA
514 a->q_flags |= QGOODUID;
515 buildfname(pw->pw_gecos, pw->pw_name, nbuf);
516 if (nbuf[0] != '\0')
517 a->q_fullname = newstr(nbuf);
1ee33f7d
EA
518 if (pw->pw_shell != NULL && pw->pw_shell[0] != '\0' &&
519 !usershellok(pw->pw_shell))
52d85a9d 520 {
1ee33f7d 521 a->q_flags |= QBOGUSSHELL;
52d85a9d 522 }
d13779b1 523 if (!quoted)
f8c2f9fd 524 forward(a, sendq, aliaslevel, e);
6eefe4f6
EA
525 }
526 }
6e99f903
EA
527 if (!bitset(QDONTSEND, a->q_flags))
528 e->e_nrcpts++;
d1147db7
EA
529
530 testselfdestruct:
cd361139 531 if (tTd(26, 8))
d1147db7 532 {
cd361139
EA
533 printf("testselfdestruct: ");
534 printaddr(a, TRUE);
535 }
536 if (a->q_alias == NULL && a != &e->e_from &&
537 bitset(QDONTSEND, a->q_flags))
538 {
539 q = *sendq;
0fc3fb21 540 while (q != NULL && bitset(QDONTSEND, q->q_flags))
d1147db7 541 q = q->q_next;
cd361139 542 if (q == NULL)
d1147db7
EA
543 {
544 a->q_flags |= QBADADDR;
545 usrerr("554 aliasing/forwarding loop broken");
546 }
547 }
f466bb18
EA
548
549 done:
550 if (buf != buf0)
551 free(buf);
d344c0b7 552 return (a);
abae7b2d
EA
553
554 return (a);
6eefe4f6
EA
555}
556\f/*
ff3e3c1c
EA
557** FINDUSER -- find the password entry for a user.
558**
559** This looks a lot like getpwnam, except that it may want to
560** do some fancier pattern matching in /etc/passwd.
561**
7338e3d4
EA
562** This routine contains most of the time of many sendmail runs.
563** It deserves to be optimized.
564**
ff3e3c1c
EA
565** Parameters:
566** name -- the name to match against.
42450b5a
EA
567** fuzzyp -- an outarg that is set to TRUE if this entry
568** was found using the fuzzy matching algorithm;
569** set to FALSE otherwise.
ff3e3c1c
EA
570**
571** Returns:
572** A pointer to a pw struct.
573** NULL if name is unknown or ambiguous.
574**
575** Side Effects:
29c33ff6 576** may modify name.
ff3e3c1c
EA
577*/
578
579struct passwd *
42450b5a 580finduser(name, fuzzyp)
ff3e3c1c 581 char *name;
42450b5a 582 bool *fuzzyp;
ff3e3c1c 583{
2b5e3c25 584 register struct passwd *pw;
29c33ff6 585 register char *p;
f74d8dce
EA
586 extern struct passwd *getpwent();
587 extern struct passwd *getpwnam();
29c33ff6 588
42450b5a
EA
589 if (tTd(29, 4))
590 printf("finduser(%s): ", name);
591
42450b5a 592 *fuzzyp = FALSE;
ff3e3c1c 593
e28a0bbb 594#ifdef HESIOD
06b7bf4a
EA
595 /* DEC Hesiod getpwnam accepts numeric strings -- short circuit it */
596 for (p = name; *p != '\0'; p++)
597 if (!isascii(*p) || !isdigit(*p))
598 break;
599 if (*p == '\0')
600 {
601 if (tTd(29, 4))
602 printf("failed (numeric input)\n");
603 return NULL;
604 }
e28a0bbb 605#endif
06b7bf4a 606
639d8b98 607 /* look up this login name using fast path */
77b16ff1 608 if ((pw = getpwnam(name)) != NULL)
42450b5a
EA
609 {
610 if (tTd(29, 4))
611 printf("found (non-fuzzy)\n");
77b16ff1 612 return (pw);
42450b5a 613 }
77b16ff1 614
7f0fd60b
EA
615#ifdef MATCHGECOS
616 /* see if fuzzy matching allowed */
617 if (!MatchGecos)
42450b5a
EA
618 {
619 if (tTd(29, 4))
620 printf("not found (fuzzy disabled)\n");
7f0fd60b 621 return NULL;
42450b5a 622 }
7f0fd60b 623
77b16ff1 624 /* search for a matching full name instead */
639d8b98
EA
625 for (p = name; *p != '\0'; p++)
626 {
627 if (*p == (SpaceSub & 0177) || *p == '_')
628 *p = ' ';
629 }
03388044 630 (void) setpwent();
2b5e3c25
EA
631 while ((pw = getpwent()) != NULL)
632 {
abae7b2d 633 char buf[MAXNAME];
2b5e3c25 634
abae7b2d 635 fullname(pw, buf);
f3d8f6d6 636 if (strchr(buf, ' ') != NULL && !strcasecmp(buf, name))
36292825 637 {
42450b5a
EA
638 if (tTd(29, 4))
639 printf("fuzzy matches %s\n", pw->pw_name);
abae7b2d
EA
640 message(Arpa_Info, "sending to %s <%s>",
641 buf, pw->pw_name);
2b5e3c25 642 return (pw);
36292825 643 }
2b5e3c25 644 }
42450b5a
EA
645 if (tTd(29, 4))
646 printf("no fuzzy match found\n");
70ce33b6
EA
647#else
648 if (tTd(29, 4))
649 printf("not found (fuzzy disabled)\n");
650#endif
2b5e3c25 651 return (NULL);
ff3e3c1c
EA
652}
653\f/*
a0554f81
EA
654** WRITABLE -- predicate returning if the file is writable.
655**
656** This routine must duplicate the algorithm in sys/fio.c.
657** Unfortunately, we cannot use the access call since we
658** won't necessarily be the real uid when we try to
659** actually open the file.
660**
661** Notice that ANY file with ANY execute bit is automatically
662** not writable. This is also enforced by mailfile.
663**
664** Parameters:
c9bddda6 665** filename -- the file name to check.
75cdfff0 666** ctladdr -- the controlling address for this file.
c9bddda6 667** flags -- SFF_* flags to control the function.
a0554f81
EA
668**
669** Returns:
670** TRUE -- if we will be able to write this file.
671** FALSE -- if we cannot write this file.
672**
673** Side Effects:
674** none.
675*/
676
677bool
75cdfff0 678writable(filename, ctladdr, flags)
793aec0f 679 char *filename;
75cdfff0 680 ADDRESS *ctladdr;
c9bddda6 681 int flags;
a0554f81 682{
44967af8
EA
683 uid_t euid;
684 gid_t egid;
a0554f81 685 int bits;
fce21cb9
EA
686 register char *p;
687 char *uname;
a0554f81 688
793aec0f 689 if (tTd(29, 5))
c9bddda6 690 printf("writable(%s, %x)\n", filename, flags);
fce21cb9 691
d2865fc3
EA
692#ifdef SUID_ROOT_FILES_OK
693 /* really ought to be passed down -- and not a good idea */
694 flags |= SFF_ROOTOK;
695#endif
696
fce21cb9
EA
697 /*
698 ** File does exist -- check that it is writable.
699 */
700
75cdfff0 701 if (ctladdr != NULL && geteuid() == 0)
fce21cb9 702 {
75cdfff0
EA
703 euid = ctladdr->q_uid;
704 egid = ctladdr->q_gid;
705 uname = ctladdr->q_user;
706 }
0c35b842 707#ifdef RUN_AS_REAL_UID
75cdfff0
EA
708 else
709 {
d52f8819
EA
710 extern char RealUserName[];
711
75cdfff0
EA
712 euid = RealUid;
713 egid = RealGid;
714 uname = RealUserName;
fce21cb9 715 }
0c35b842
EA
716#else
717 else if (FileMailer != NULL)
718 {
719 euid = FileMailer->m_uid;
720 egid = FileMailer->m_gid;
721 }
722 else
723 {
724 euid = egid = 0;
725 }
726#endif
0aa35b96
EA
727 if (euid == 0)
728 {
729 euid = DefUid;
730 uname = DefUser;
731 }
732 if (egid == 0)
733 egid = DefGid;
a0554f81 734 if (geteuid() == 0)
d52f8819 735 flags |= SFF_SETUIDOK;
a0554f81 736
d52f8819 737 errno = safefile(filename, euid, egid, uname, flags, S_IWRITE, NULL);
7763037f 738 return errno == 0;
a0554f81
EA
739}
740\f/*
6eefe4f6
EA
741** INCLUDE -- handle :include: specification.
742**
743** Parameters:
744** fname -- filename to include.
a90a7c55
EA
745** forwarding -- if TRUE, we are reading a .forward file.
746** if FALSE, it's a :include: file.
1bf7c76b
EA
747** ctladdr -- address template to use to fill in these
748** addresses -- effective user/group id are
749** the important things.
d4f42161
EA
750** sendq -- a pointer to the head of the send queue
751** to put these addresses in.
f8c2f9fd
EA
752** aliaslevel -- the alias nesting depth.
753** e -- the current envelope.
6eefe4f6
EA
754**
755** Returns:
e0136832 756** open error status
6eefe4f6
EA
757**
758** Side Effects:
759** reads the :include: file and sends to everyone
760** listed in that file.
247efdd6
EA
761**
762** Security Note:
763** If you have restricted chown (that is, you can't
764** give a file away), it is reasonable to allow programs
765** and files called from this :include: file to be to be
766** run as the owner of the :include: file. This is bogus
767** if there is any chance of someone giving away a file.
768** We assume that pre-POSIX systems can give away files.
769**
770** There is an additional restriction that if you
771** forward to a :include: file, it will not take on
772** the ownership of the :include: file. This may not
773** be necessary, but shouldn't hurt.
6eefe4f6
EA
774*/
775
a90a7c55 776static jmp_buf CtxIncludeTimeout;
ea07b2d2 777static void includetimeout();
a90a7c55 778
e0136832 779int
f8c2f9fd 780include(fname, forwarding, ctladdr, sendq, aliaslevel, e)
6eefe4f6 781 char *fname;
a90a7c55 782 bool forwarding;
1bf7c76b 783 ADDRESS *ctladdr;
d4f42161 784 ADDRESS **sendq;
f8c2f9fd 785 int aliaslevel;
a4076aed 786 ENVELOPE *e;
6eefe4f6 787{
ea07b2d2 788 FILE *fp = NULL;
a4076aed 789 char *oldto = e->e_to;
7338e3d4
EA
790 char *oldfilename = FileName;
791 int oldlinenumber = LineNumber;
a90a7c55 792 register EVENT *ev = NULL;
1c7897ef 793 int nincludes;
a614cf3b
EA
794 register ADDRESS *ca;
795 uid_t saveduid, uid;
796 gid_t savedgid, gid;
2b9924bc 797 char *uname;
a614cf3b 798 int rval = 0;
51cc57b9 799 int sfflags = SFF_REGONLY;
78a504b0 800 struct stat st;
117c4023 801 char buf[MAXLINE];
247efdd6 802#ifdef _POSIX_CHOWN_RESTRICTED
117c4023
EA
803# if _POSIX_CHOWN_RESTRICTED == -1
804# define safechown FALSE
805# else
806# define safechown TRUE
807# endif
808#else
809# ifdef _PC_CHOWN_RESTRICTED
247efdd6 810 bool safechown;
117c4023
EA
811# else
812# ifdef BSD
813# define safechown TRUE
814# else
815# define safechown FALSE
816# endif
817# endif
247efdd6 818#endif
117c4023 819 extern bool chownsafe();
a90a7c55 820
b21ec539
EA
821 if (tTd(27, 2))
822 printf("include(%s)\n", fname);
ba6514e2
EA
823 if (tTd(27, 4))
824 printf(" ruid=%d euid=%d\n", getuid(), geteuid());
5d32a96c
EA
825 if (tTd(27, 14))
826 {
827 printf("ctladdr ");
828 printaddr(ctladdr, FALSE);
829 }
b21ec539 830
a614cf3b
EA
831 if (tTd(27, 9))
832 printf("include: old uid = %d/%d\n", getuid(), geteuid());
a90a7c55 833
51cc57b9
EA
834 if (forwarding)
835 sfflags |= SFF_MUSTOWN;
836
5d32a96c
EA
837 ca = getctladdr(ctladdr);
838 if (ca == NULL)
2b9924bc 839 {
f161b3d2
EA
840 uid = DefUid;
841 gid = DefGid;
842 uname = DefUser;
2b9924bc 843 }
5d32a96c 844 else
2b9924bc 845 {
5d32a96c 846 uid = ca->q_uid;
2b9924bc
EA
847 gid = ca->q_gid;
848 uname = ca->q_user;
af698ca4 849 }
a614cf3b 850#ifdef HASSETREUID
af698ca4
EA
851 saveduid = geteuid();
852 savedgid = getegid();
853 if (saveduid == 0)
854 {
855 initgroups(uname, gid);
856 if (uid != 0)
a614cf3b 857 {
af698ca4
EA
858 if (setreuid(0, uid) < 0)
859 syserr("setreuid(0, %d) failure (real=%d, eff=%d)",
860 uid, getuid(), geteuid());
861 else
862 sfflags |= SFF_NOPATHCHECK;
a614cf3b 863 }
2b9924bc 864 }
af698ca4 865#endif
5d32a96c 866
a614cf3b
EA
867 if (tTd(27, 9))
868 printf("include: new uid = %d/%d\n", getuid(), geteuid());
869
870 /*
871 ** If home directory is remote mounted but server is down,
872 ** this can hang or give errors; use a timeout to avoid this
873 */
874
a90a7c55
EA
875 if (setjmp(CtxIncludeTimeout) != 0)
876 {
c069e0df 877 ctladdr->q_flags |= QQUEUEUP;
a90a7c55 878 errno = 0;
92f2b65e
EA
879
880 /* return pseudo-error code */
a614cf3b
EA
881 rval = EOPENTIMEOUT;
882 goto resetuid;
a90a7c55 883 }
039f3bb5
EA
884 if (TimeOuts.to_fileopen > 0)
885 ev = setevent(TimeOuts.to_fileopen, includetimeout, 0);
886 else
887 ev = NULL;
a90a7c55 888
5d32a96c 889 /* the input file must be marked safe */
d52f8819 890 rval = safefile(fname, uid, gid, uname, sfflags, S_IREAD, NULL);
09beeadc 891 if (rval != 0)
a90a7c55 892 {
a614cf3b 893 /* don't use this :include: file */
b21ec539 894 if (tTd(27, 4))
118e6693 895 printf("include: not safe (uid=%d): %s\n",
09beeadc 896 uid, errstring(rval));
a90a7c55 897 }
78a504b0 898 else
962c3fb2 899 {
78a504b0
EA
900 fp = fopen(fname, "r");
901 if (fp == NULL)
5d41b806 902 {
09beeadc 903 rval = errno;
78a504b0
EA
904 if (tTd(27, 4))
905 printf("include: open: %s\n", errstring(rval));
a2cdf9f6 906 }
962c3fb2 907 }
039f3bb5
EA
908 if (ev != NULL)
909 clrevent(ev);
a90a7c55 910
a2cdf9f6
EA
911resetuid:
912
913#ifdef HASSETREUID
914 if (saveduid == 0)
915 {
916 if (uid != 0)
8822417b
EA
917 {
918 if (setreuid(-1, 0) < 0)
919 syserr("setreuid(-1, 0) failure (real=%d, eff=%d)",
920 getuid(), geteuid());
921 if (setreuid(RealUid, 0) < 0)
a2cdf9f6
EA
922 syserr("setreuid(%d, 0) failure (real=%d, eff=%d)",
923 RealUid, getuid(), geteuid());
8822417b 924 }
a2cdf9f6
EA
925 setgid(savedgid);
926 }
927#endif
928
929 if (tTd(27, 9))
930 printf("include: reset uid = %d/%d\n", getuid(), geteuid());
931
34bc9a9c
EA
932 if (rval == EOPENTIMEOUT)
933 usrerr("451 open timeout on %s", fname);
934
a2cdf9f6
EA
935 if (fp == NULL)
936 return rval;
937
78a504b0
EA
938 if (fstat(fileno(fp), &st) < 0)
939 {
940 rval = errno;
941 syserr("Cannot fstat %s!", fname);
942 return rval;
943 }
944
117c4023
EA
945#ifndef safechown
946 safechown = chownsafe(fileno(fp));
947#endif
247efdd6 948 if (ca == NULL && safechown)
78a504b0
EA
949 {
950 ctladdr->q_uid = st.st_uid;
951 ctladdr->q_gid = st.st_gid;
952 ctladdr->q_flags |= QGOODUID;
953 }
954 if (ca != NULL && ca->q_uid == st.st_uid)
955 {
956 /* optimization -- avoid getpwuid if we already have info */
957 ctladdr->q_flags |= ca->q_flags & QBOGUSSHELL;
958 ctladdr->q_ruser = ca->q_ruser;
959 }
960 else
961 {
962 register struct passwd *pw;
963
964 pw = getpwuid(st.st_uid);
247efdd6 965 if (pw == NULL)
78a504b0 966 ctladdr->q_flags |= QBOGUSSHELL;
0c35b842 967 else
247efdd6 968 {
0c35b842
EA
969 char *sh;
970
971 ctladdr->q_ruser = newstr(pw->pw_name);
247efdd6 972 if (safechown)
0c35b842 973 sh = pw->pw_shell;
247efdd6 974 else
0c35b842
EA
975 sh = "/SENDMAIL/ANY/SHELL/";
976 if (!usershellok(sh))
977 {
978 if (safechown)
979 ctladdr->q_flags |= QBOGUSSHELL;
980 else
981 ctladdr->q_flags |= QUNSAFEADDR;
982 }
78a504b0
EA
983 }
984 }
985
8f48def8
EA
986 if (bitset(EF_VRFYONLY, e->e_flags))
987 {
988 /* don't do any more now */
5f6654cf 989 ctladdr->q_flags |= QVERIFIED;
a7dc53bd 990 e->e_nrcpts++;
bc854e30 991 xfclose(fp, "include", fname);
a2cdf9f6 992 return rval;
8f48def8
EA
993 }
994
78a504b0
EA
995 /*
996 ** Check to see if some bad guy can write this file
997 **
998 ** This should really do something clever with group
999 ** permissions; currently we just view world writable
1000 ** as unsafe. Also, we don't check for writable
1001 ** directories in the path. We've got to leave
1002 ** something for the local sysad to do.
1003 */
1004
1005 if (bitset(S_IWOTH, st.st_mode))
1006 ctladdr->q_flags |= QUNSAFEADDR;
1007
6eefe4f6 1008 /* read the file -- each line is a comma-separated list. */
7338e3d4
EA
1009 FileName = fname;
1010 LineNumber = 0;
1c7897ef
EA
1011 ctladdr->q_flags &= ~QSELFREF;
1012 nincludes = 0;
6eefe4f6
EA
1013 while (fgets(buf, sizeof buf, fp) != NULL)
1014 {
f3d8f6d6 1015 register char *p = strchr(buf, '\n');
6eefe4f6 1016
dd0758e5 1017 LineNumber++;
6eefe4f6
EA
1018 if (p != NULL)
1019 *p = '\0';
b21ec539 1020 if (buf[0] == '#' || buf[0] == '\0')
af04f6e4 1021 continue;
51d9cc47 1022 e->e_to = NULL;
b6edea3d 1023 message("%s to %s",
a90a7c55 1024 forwarding ? "forwarding" : "sending", buf);
aa102c71 1025#ifdef LOG
68f7099c 1026 if (forwarding && LogLevel > 9)
aa102c71 1027 syslog(LOG_INFO, "%s: forward %s => %s",
1db90aeb
EA
1028 e->e_id == NULL ? "NOQUEUE" : e->e_id,
1029 oldto, buf);
aa102c71
EA
1030#endif
1031
f8c2f9fd 1032 nincludes += sendtolist(buf, ctladdr, sendq, aliaslevel + 1, e);
6eefe4f6 1033 }
ba6514e2
EA
1034
1035 if (ferror(fp) && tTd(27, 3))
1036 printf("include: read error: %s\n", errstring(errno));
1c7897ef 1037 if (nincludes > 0 && !bitset(QSELFREF, ctladdr->q_flags))
f7eca811
EA
1038 {
1039 if (tTd(27, 5))
1040 {
1041 printf("include: QDONTSEND ");
1042 printaddr(ctladdr, FALSE);
1043 }
1044 ctladdr->q_flags |= QDONTSEND;
1045 }
6eefe4f6 1046
bc854e30 1047 (void) xfclose(fp, "include", fname);
7338e3d4
EA
1048 FileName = oldfilename;
1049 LineNumber = oldlinenumber;
d1147db7 1050 e->e_to = oldto;
a614cf3b 1051 return rval;
6eefe4f6 1052}
a90a7c55 1053
ea07b2d2 1054static void
a90a7c55
EA
1055includetimeout()
1056{
1057 longjmp(CtxIncludeTimeout, 1);
1058}
d6b27179
EA
1059\f/*
1060** SENDTOARGV -- send to an argument vector.
1061**
1062** Parameters:
1063** argv -- argument vector to send to.
118e6693 1064** e -- the current envelope.
d6b27179
EA
1065**
1066** Returns:
1067** none.
1068**
1069** Side Effects:
1070** puts all addresses on the argument vector onto the
1071** send queue.
1072*/
1073
a4076aed 1074sendtoargv(argv, e)
d6b27179 1075 register char **argv;
a4076aed 1076 register ENVELOPE *e;
d6b27179
EA
1077{
1078 register char *p;
d6b27179
EA
1079
1080 while ((p = *argv++) != NULL)
1081 {
abae7b2d 1082 sendto(p, 0, (ADDRESS *) NULL, 0);
d6b27179
EA
1083 }
1084}
1bf7c76b
EA
1085\f/*
1086** GETCTLADDR -- get controlling address from an address header.
1087**
1088** If none, get one corresponding to the effective userid.
1089**
1090** Parameters:
1091** a -- the address to find the controller of.
1092**
1093** Returns:
1094** the controlling address.
1095**
1096** Side Effects:
1097** none.
1098*/
1099
1100ADDRESS *
1101getctladdr(a)
1102 register ADDRESS *a;
1103{
2c1457f0 1104 while (a != NULL && !bitset(QGOODUID, a->q_flags))
1bf7c76b 1105 a = a->q_alias;
1bf7c76b
EA
1106 return (a);
1107}