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