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