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.35 (Berkeley) 04/09/93"; 11 #endif /* not lint */ 12 13 # include "sendmail.h" 14 # include <sys/stat.h> 15 # include <pwd.h> 16 17 /* 18 ** SENDTOLIST -- Designate a send list. 19 ** 20 ** The parameter is a comma-separated list of people to send to. 21 ** This routine arranges to send to all of them. 22 ** 23 ** Parameters: 24 ** list -- the send list. 25 ** ctladdr -- the address template for the person to 26 ** send to -- effective uid/gid are important. 27 ** This is typically the alias that caused this 28 ** expansion. 29 ** sendq -- a pointer to the head of a queue to put 30 ** these people into. 31 ** e -- the envelope in which to add these recipients. 32 ** 33 ** Returns: 34 ** The number of addresses actually on the list. 35 ** 36 ** Side Effects: 37 ** none. 38 */ 39 40 # define MAXRCRSN 10 41 42 sendtolist(list, ctladdr, sendq, e) 43 char *list; 44 ADDRESS *ctladdr; 45 ADDRESS **sendq; 46 register ENVELOPE *e; 47 { 48 register char *p; 49 register ADDRESS *al; /* list of addresses to send to */ 50 bool firstone; /* set on first address sent */ 51 char delimiter; /* the address delimiter */ 52 int naddrs; 53 54 if (tTd(25, 1)) 55 { 56 printf("sendto: %s\n ctladdr=", list); 57 printaddr(ctladdr, FALSE); 58 } 59 60 /* heuristic to determine old versus new style addresses */ 61 if (ctladdr == NULL && 62 (strchr(list, ',') != NULL || strchr(list, ';') != NULL || 63 strchr(list, '<') != NULL || strchr(list, '(') != NULL)) 64 e->e_flags &= ~EF_OLDSTYLE; 65 delimiter = ' '; 66 if (!bitset(EF_OLDSTYLE, e->e_flags) || ctladdr != NULL) 67 delimiter = ','; 68 69 firstone = TRUE; 70 al = NULL; 71 naddrs = 0; 72 73 for (p = list; *p != '\0'; ) 74 { 75 auto char *delimptr; 76 register ADDRESS *a; 77 78 /* parse the address */ 79 while ((isascii(*p) && isspace(*p)) || *p == ',') 80 p++; 81 a = parseaddr(p, (ADDRESS *) NULL, 1, delimiter, &delimptr, e); 82 p = delimptr; 83 if (a == NULL) 84 continue; 85 a->q_next = al; 86 a->q_alias = ctladdr; 87 88 /* see if this should be marked as a primary address */ 89 if (ctladdr == NULL || 90 (firstone && *p == '\0' && bitset(QPRIMARY, ctladdr->q_flags))) 91 a->q_flags |= QPRIMARY; 92 93 if (ctladdr != NULL && sameaddr(ctladdr, a)) 94 ctladdr->q_flags |= QSELFREF; 95 al = a; 96 firstone = FALSE; 97 } 98 99 /* arrange to send to everyone on the local send list */ 100 while (al != NULL) 101 { 102 register ADDRESS *a = al; 103 extern ADDRESS *recipient(); 104 105 al = a->q_next; 106 a = recipient(a, sendq, e); 107 108 /* arrange to inherit full name */ 109 if (a->q_fullname == NULL && ctladdr != NULL) 110 a->q_fullname = ctladdr->q_fullname; 111 naddrs++; 112 } 113 114 e->e_to = NULL; 115 return (naddrs); 116 } 117 /* 118 ** RECIPIENT -- Designate a message recipient 119 ** 120 ** Saves the named person for future mailing. 121 ** 122 ** Parameters: 123 ** a -- the (preparsed) address header for the recipient. 124 ** sendq -- a pointer to the head of a queue to put the 125 ** recipient in. Duplicate supression is done 126 ** in this queue. 127 ** e -- the current envelope. 128 ** 129 ** Returns: 130 ** The actual address in the queue. This will be "a" if 131 ** the address is not a duplicate, else the original address. 132 ** 133 ** Side Effects: 134 ** none. 135 */ 136 137 extern ADDRESS *getctladdr(); 138 139 ADDRESS * 140 recipient(a, sendq, e) 141 register ADDRESS *a; 142 register ADDRESS **sendq; 143 register ENVELOPE *e; 144 { 145 register ADDRESS *q; 146 ADDRESS **pq; 147 register struct mailer *m; 148 register char *p; 149 bool quoted = FALSE; /* set if the addr has a quote bit */ 150 int findusercount = 0; 151 char buf[MAXNAME]; /* unquoted image of the user name */ 152 extern int safefile(); 153 154 e->e_to = a->q_paddr; 155 m = a->q_mailer; 156 errno = 0; 157 if (tTd(26, 1)) 158 { 159 printf("\nrecipient: "); 160 printaddr(a, FALSE); 161 } 162 163 /* break aliasing loops */ 164 if (AliasLevel > MAXRCRSN) 165 { 166 usrerr("554 aliasing/forwarding loop broken"); 167 return (a); 168 } 169 170 /* 171 ** Finish setting up address structure. 172 */ 173 174 /* set the queue timeout */ 175 a->q_timeout = TimeOuts.to_q_return; 176 177 /* get unquoted user for file, program or user.name check */ 178 (void) strcpy(buf, a->q_user); 179 for (p = buf; *p != '\0' && !quoted; p++) 180 { 181 if (*p == '\\') 182 quoted = TRUE; 183 } 184 stripquotes(buf); 185 186 /* check for direct mailing to restricted mailers */ 187 if (a->q_alias == NULL && m == ProgMailer && 188 !bitset(EF_QUEUERUN, e->e_flags)) 189 { 190 a->q_flags |= QBADADDR; 191 usrerr("550 Cannot mail directly to programs", m->m_name); 192 } 193 194 /* 195 ** Look up this person in the recipient list. 196 ** If they are there already, return, otherwise continue. 197 ** If the list is empty, just add it. Notice the cute 198 ** hack to make from addresses suppress things correctly: 199 ** the QDONTSEND bit will be set in the send list. 200 ** [Please note: the emphasis is on "hack."] 201 */ 202 203 for (pq = sendq; (q = *pq) != NULL; pq = &q->q_next) 204 { 205 if (sameaddr(q, a)) 206 { 207 if (tTd(26, 1)) 208 { 209 printf("%s in sendq: ", a->q_paddr); 210 printaddr(q, FALSE); 211 } 212 if (!bitset(QPRIMARY, q->q_flags)) 213 { 214 if (!bitset(QDONTSEND, a->q_flags)) 215 message("duplicate suppressed"); 216 q->q_flags |= a->q_flags; 217 } 218 return (q); 219 } 220 } 221 222 /* add address on list */ 223 *pq = a; 224 a->q_next = NULL; 225 226 /* 227 ** Alias the name and handle special mailer types. 228 */ 229 230 trylocaluser: 231 if (tTd(29, 7)) 232 printf("at trylocaluser %s\n", a->q_user); 233 234 if (bitset(QDONTSEND|QBADADDR|QVERIFIED, a->q_flags)) 235 return (a); 236 237 if (m == InclMailer) 238 { 239 a->q_flags |= QDONTSEND; 240 if (a->q_alias == NULL && !bitset(EF_QUEUERUN, e->e_flags)) 241 { 242 a->q_flags |= QBADADDR; 243 usrerr("550 Cannot mail directly to :include:s"); 244 } 245 else 246 { 247 int err; 248 249 message("including file %s", a->q_user); 250 err = include(a->q_user, FALSE, a, sendq, e); 251 if (transienterror(err)) 252 a->q_flags |= QQUEUEUP|QDONTSEND; 253 } 254 } 255 else if (m == FileMailer) 256 { 257 struct stat stb; 258 extern bool writable(); 259 260 p = strrchr(buf, '/'); 261 /* check if writable or creatable */ 262 if (a->q_alias == NULL && !bitset(EF_QUEUERUN, e->e_flags)) 263 { 264 a->q_flags |= QBADADDR; 265 usrerr("550 Cannot mail directly to files"); 266 } 267 else if ((stat(buf, &stb) >= 0) ? (!writable(&stb)) : 268 (*p = '\0', safefile(buf, getruid(), S_IWRITE|S_IEXEC) != 0)) 269 { 270 a->q_flags |= QBADADDR; 271 giveresponse(EX_CANTCREAT, m, NULL, e); 272 } 273 } 274 275 if (m != LocalMailer) 276 { 277 if (!bitset(QDONTSEND, a->q_flags)) 278 e->e_nrcpts++; 279 return (a); 280 } 281 282 /* try aliasing */ 283 alias(a, sendq, e); 284 285 # ifdef USERDB 286 /* if not aliased, look it up in the user database */ 287 if (!bitset(QDONTSEND|QNOTREMOTE|QVERIFIED, a->q_flags)) 288 { 289 extern int udbexpand(); 290 291 if (udbexpand(a, sendq, e) == EX_TEMPFAIL) 292 { 293 a->q_flags |= QQUEUEUP|QDONTSEND; 294 if (e->e_message == NULL) 295 e->e_message = newstr("Deferred: user database error"); 296 # ifdef LOG 297 if (LogLevel > 8) 298 syslog(LOG_INFO, "%s: deferred: udbexpand", 299 e->e_id); 300 # endif 301 message("queued (user database error)"); 302 e->e_nrcpts++; 303 return (a); 304 } 305 } 306 # endif 307 308 /* if it was an alias or a UDB expansion, just return now */ 309 if (bitset(QDONTSEND|QQUEUEUP|QVERIFIED, a->q_flags)) 310 return (a); 311 312 /* 313 ** If we have a level two config file, then pass the name through 314 ** Ruleset 5 before sending it off. Ruleset 5 has the right 315 ** to send rewrite it to another mailer. This gives us a hook 316 ** after local aliasing has been done. 317 */ 318 319 if (tTd(29, 5)) 320 { 321 printf("recipient: testing local? cl=%d, rr5=%x\n\t", 322 ConfigLevel, RewriteRules[5]); 323 printaddr(a, FALSE); 324 } 325 if (!bitset(QNOTREMOTE, a->q_flags) && ConfigLevel >= 2 && 326 RewriteRules[5] != NULL) 327 { 328 maplocaluser(a, sendq, e); 329 } 330 331 /* 332 ** If it didn't get rewritten to another mailer, go ahead 333 ** and deliver it. 334 */ 335 336 if (!bitset(QDONTSEND|QQUEUEUP, a->q_flags)) 337 { 338 auto bool fuzzy; 339 register struct passwd *pw; 340 extern struct passwd *finduser(); 341 342 /* warning -- finduser may trash buf */ 343 pw = finduser(buf, &fuzzy); 344 if (pw == NULL) 345 { 346 a->q_flags |= QBADADDR; 347 giveresponse(EX_NOUSER, m, NULL, e); 348 } 349 else 350 { 351 char nbuf[MAXNAME]; 352 353 if (fuzzy) 354 { 355 /* name was a fuzzy match */ 356 a->q_user = newstr(pw->pw_name); 357 if (findusercount++ > 3) 358 { 359 a->q_flags |= QBADADDR; 360 usrerr("554 aliasing/forwarding loop for %s broken", 361 pw->pw_name); 362 return (a); 363 } 364 365 /* see if it aliases */ 366 (void) strcpy(buf, pw->pw_name); 367 goto trylocaluser; 368 } 369 a->q_home = newstr(pw->pw_dir); 370 a->q_uid = pw->pw_uid; 371 a->q_gid = pw->pw_gid; 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