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