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