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.41 (Berkeley) 05/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 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, getruid(), 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 = getruid(); 515 egid = getrgid(); 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 char buf[MAXLINE]; 574 static int includetimeout(); 575 576 if (tTd(27, 2)) 577 printf("include(%s)\n", fname); 578 579 /* 580 ** If home directory is remote mounted but server is down, 581 ** this can hang or give errors; use a timeout to avoid this 582 */ 583 584 if (setjmp(CtxIncludeTimeout) != 0) 585 { 586 ctladdr->q_flags |= QQUEUEUP|QDONTSEND; 587 errno = 0; 588 usrerr("451 open timeout on %s", fname); 589 return ETIMEDOUT; 590 } 591 ev = setevent((time_t) 60, includetimeout, 0); 592 593 /* if forwarding, the input file must be marked safe */ 594 if (forwarding && (ret = safefile(fname, ctladdr->q_uid, S_IREAD)) != 0) 595 { 596 /* don't use this .forward file */ 597 clrevent(ev); 598 if (tTd(27, 4)) 599 printf("include: not safe (uid=%d): %s\n", 600 ctladdr->q_uid, errstring(ret)); 601 return ret; 602 } 603 604 fp = fopen(fname, "r"); 605 if (fp == NULL) 606 { 607 int ret = errno; 608 609 clrevent(ev); 610 return ret; 611 } 612 613 if (getctladdr(ctladdr) == NULL) 614 { 615 struct stat st; 616 617 if (fstat(fileno(fp), &st) < 0) 618 { 619 int ret = errno; 620 621 clrevent(ev); 622 syserr("Cannot fstat %s!", fname); 623 return ret; 624 } 625 ctladdr->q_uid = st.st_uid; 626 ctladdr->q_gid = st.st_gid; 627 ctladdr->q_flags |= QGOODUID; 628 } 629 630 clrevent(ev); 631 632 if (bitset(EF_VRFYONLY, e->e_flags)) 633 { 634 /* don't do any more now */ 635 ctladdr->q_flags |= QVERIFIED; 636 e->e_nrcpts++; 637 xfclose(fp, "include", fname); 638 return 0; 639 } 640 641 /* read the file -- each line is a comma-separated list. */ 642 FileName = fname; 643 LineNumber = 0; 644 ctladdr->q_flags &= ~QSELFREF; 645 nincludes = 0; 646 while (fgets(buf, sizeof buf, fp) != NULL) 647 { 648 register char *p = strchr(buf, '\n'); 649 650 LineNumber++; 651 if (p != NULL) 652 *p = '\0'; 653 if (buf[0] == '#' || buf[0] == '\0') 654 continue; 655 e->e_to = NULL; 656 message("%s to %s", 657 forwarding ? "forwarding" : "sending", buf); 658 #ifdef LOG 659 if (forwarding && LogLevel > 9) 660 syslog(LOG_INFO, "%s: forward %s => %s", 661 e->e_id, oldto, buf); 662 #endif 663 664 AliasLevel++; 665 nincludes += sendtolist(buf, ctladdr, sendq, e); 666 AliasLevel--; 667 } 668 if (nincludes > 0 && !bitset(QSELFREF, ctladdr->q_flags)) 669 { 670 if (tTd(27, 5)) 671 { 672 printf("include: QDONTSEND "); 673 printaddr(ctladdr, FALSE); 674 } 675 ctladdr->q_flags |= QDONTSEND; 676 } 677 678 (void) xfclose(fp, "include", fname); 679 FileName = oldfilename; 680 LineNumber = oldlinenumber; 681 return 0; 682 } 683 684 static 685 includetimeout() 686 { 687 longjmp(CtxIncludeTimeout, 1); 688 } 689 /* 690 ** SENDTOARGV -- send to an argument vector. 691 ** 692 ** Parameters: 693 ** argv -- argument vector to send to. 694 ** e -- the current envelope. 695 ** 696 ** Returns: 697 ** none. 698 ** 699 ** Side Effects: 700 ** puts all addresses on the argument vector onto the 701 ** send queue. 702 */ 703 704 sendtoargv(argv, e) 705 register char **argv; 706 register ENVELOPE *e; 707 { 708 register char *p; 709 710 while ((p = *argv++) != NULL) 711 { 712 (void) sendtolist(p, (ADDRESS *) NULL, &e->e_sendqueue, e); 713 } 714 } 715 /* 716 ** GETCTLADDR -- get controlling address from an address header. 717 ** 718 ** If none, get one corresponding to the effective userid. 719 ** 720 ** Parameters: 721 ** a -- the address to find the controller of. 722 ** 723 ** Returns: 724 ** the controlling address. 725 ** 726 ** Side Effects: 727 ** none. 728 */ 729 730 ADDRESS * 731 getctladdr(a) 732 register ADDRESS *a; 733 { 734 while (a != NULL && !bitset(QGOODUID, a->q_flags)) 735 a = a->q_alias; 736 return (a); 737 } 738