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