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