1 /* 2 * Copyright (c) 1983 Eric P. Allman 3 * Copyright (c) 1988, 1993 4 * The Regents of the University of California. All rights reserved. 5 * 6 * %sccs.include.redist.c% 7 */ 8 9 #ifndef lint 10 static char sccsid[] = "@(#)envelope.c 8.20 (Berkeley) 12/02/93"; 11 #endif /* not lint */ 12 13 #include "sendmail.h" 14 #include <sys/time.h> 15 #include <pwd.h> 16 17 /* 18 ** NEWENVELOPE -- allocate a new envelope 19 ** 20 ** Supports inheritance. 21 ** 22 ** Parameters: 23 ** e -- the new envelope to fill in. 24 ** parent -- the envelope to be the parent of e. 25 ** 26 ** Returns: 27 ** e. 28 ** 29 ** Side Effects: 30 ** none. 31 */ 32 33 ENVELOPE * 34 newenvelope(e, parent) 35 register ENVELOPE *e; 36 register ENVELOPE *parent; 37 { 38 extern putheader(), putbody(); 39 extern ENVELOPE BlankEnvelope; 40 41 if (e == parent && e->e_parent != NULL) 42 parent = e->e_parent; 43 clearenvelope(e, TRUE); 44 if (e == CurEnv) 45 bcopy((char *) &NullAddress, (char *) &e->e_from, sizeof e->e_from); 46 else 47 bcopy((char *) &CurEnv->e_from, (char *) &e->e_from, sizeof e->e_from); 48 e->e_parent = parent; 49 e->e_ctime = curtime(); 50 if (parent != NULL) 51 e->e_msgpriority = parent->e_msgsize; 52 e->e_puthdr = putheader; 53 e->e_putbody = putbody; 54 if (CurEnv->e_xfp != NULL) 55 (void) fflush(CurEnv->e_xfp); 56 57 return (e); 58 } 59 /* 60 ** DROPENVELOPE -- deallocate an envelope. 61 ** 62 ** Parameters: 63 ** e -- the envelope to deallocate. 64 ** 65 ** Returns: 66 ** none. 67 ** 68 ** Side Effects: 69 ** housekeeping necessary to dispose of an envelope. 70 ** Unlocks this queue file. 71 */ 72 73 void 74 dropenvelope(e) 75 register ENVELOPE *e; 76 { 77 bool queueit = FALSE; 78 bool saveit = bitset(EF_FATALERRS, e->e_flags); 79 register ADDRESS *q; 80 char *id = e->e_id; 81 char buf[MAXLINE]; 82 83 if (tTd(50, 1)) 84 { 85 printf("dropenvelope %x: id=", e); 86 xputs(e->e_id); 87 printf(", flags=%o\n", e->e_flags); 88 if (tTd(50, 10)) 89 { 90 printf("sendq="); 91 printaddr(e->e_sendqueue, TRUE); 92 } 93 } 94 95 #ifdef XDEBUG 96 checkfd012("dropenvelope 1"); 97 #endif 98 99 /* we must have an id to remove disk files */ 100 if (id == NULL) 101 return; 102 103 #ifdef LOG 104 if (LogLevel > 84) 105 syslog(LOG_DEBUG, "dropenvelope, id=%s, flags=%o, pid=%d", 106 id, e->e_flags, getpid()); 107 #endif /* LOG */ 108 109 /* post statistics */ 110 poststats(StatFile); 111 112 /* 113 ** Extract state information from dregs of send list. 114 */ 115 116 e->e_flags &= ~EF_QUEUERUN; 117 for (q = e->e_sendqueue; q != NULL; q = q->q_next) 118 { 119 if (bitset(QQUEUEUP, q->q_flags)) 120 queueit = TRUE; 121 if (!bitset(QDONTSEND, q->q_flags) && 122 bitset(QBADADDR, q->q_flags)) 123 { 124 if (q->q_owner == NULL && 125 strcmp(e->e_from.q_paddr, "<>") != 0) 126 (void) sendtolist(e->e_from.q_paddr, NULL, 127 &e->e_errorqueue, e); 128 } 129 } 130 131 /* 132 ** See if the message timed out. 133 */ 134 135 if (!queueit) 136 /* nothing to do */ ; 137 else if (curtime() > e->e_ctime + TimeOuts.to_q_return) 138 { 139 (void) sprintf(buf, "Cannot send message for %s", 140 pintvl(TimeOuts.to_q_return, FALSE)); 141 if (e->e_message != NULL) 142 free(e->e_message); 143 e->e_message = newstr(buf); 144 message(buf); 145 e->e_flags |= EF_CLRQUEUE; 146 saveit = TRUE; 147 fprintf(e->e_xfp, "Message could not be delivered for %s\n", 148 pintvl(TimeOuts.to_q_return, FALSE)); 149 fprintf(e->e_xfp, "Message will be deleted from queue\n"); 150 for (q = e->e_sendqueue; q != NULL; q = q->q_next) 151 { 152 if (bitset(QQUEUEUP, q->q_flags)) 153 q->q_flags |= QBADADDR; 154 } 155 } 156 else if (TimeOuts.to_q_warning > 0 && 157 curtime() > e->e_ctime + TimeOuts.to_q_warning) 158 { 159 if (!bitset(EF_WARNING|EF_RESPONSE, e->e_flags) && 160 e->e_class >= 0 && 161 strcmp(e->e_from.q_paddr, "<>") != 0) 162 { 163 (void) sprintf(buf, 164 "warning: cannot send message for %s", 165 pintvl(TimeOuts.to_q_warning, FALSE)); 166 if (e->e_message != NULL) 167 free(e->e_message); 168 e->e_message = newstr(buf); 169 message(buf); 170 e->e_flags |= EF_WARNING; 171 saveit = TRUE; 172 } 173 fprintf(e->e_xfp, 174 "Warning: message still undelivered after %s\n", 175 pintvl(TimeOuts.to_q_warning, FALSE)); 176 fprintf(e->e_xfp, "Will keep trying until message is %s old\n", 177 pintvl(TimeOuts.to_q_return, FALSE)); 178 for (q = e->e_sendqueue; q != NULL; q = q->q_next) 179 { 180 if (bitset(QQUEUEUP, q->q_flags)) 181 q->q_flags |= QREPORT; 182 } 183 } 184 185 /* 186 ** Send back return receipts as requested. 187 */ 188 189 if (e->e_receiptto != NULL && bitset(EF_SENDRECEIPT, e->e_flags)) 190 { 191 auto ADDRESS *rlist = NULL; 192 193 (void) sendtolist(e->e_receiptto, NULLADDR, &rlist, e); 194 (void) returntosender("Return receipt", rlist, FALSE, e); 195 } 196 197 /* 198 ** Arrange to send error messages if there are fatal errors. 199 */ 200 201 if (saveit && e->e_errormode != EM_QUIET) 202 savemail(e); 203 204 #ifdef XDEBUG 205 checkfd012("dropenvelope 2"); 206 #endif 207 208 /* 209 ** Arrange to send warning messages to postmaster as requested. 210 */ 211 212 if (bitset(EF_PM_NOTIFY, e->e_flags) && PostMasterCopy != NULL && 213 !bitset(EF_RESPONSE, e->e_flags) && e->e_class >= 0) 214 { 215 auto ADDRESS *rlist = NULL; 216 217 (void) sendtolist(PostMasterCopy, NULLADDR, &rlist, e); 218 (void) returntosender(e->e_message, rlist, FALSE, e); 219 } 220 221 /* 222 ** Instantiate or deinstantiate the queue. 223 */ 224 225 if ((!queueit && !bitset(EF_KEEPQUEUE, e->e_flags)) || 226 bitset(EF_CLRQUEUE, e->e_flags)) 227 { 228 if (tTd(50, 1)) 229 printf("\n===== Dropping [dq]f%s =====\n\n", e->e_id); 230 if (e->e_df != NULL) 231 xunlink(e->e_df); 232 xunlink(queuename(e, 'q')); 233 234 #ifdef LOG 235 if (LogLevel > 10) 236 syslog(LOG_INFO, "%s: done", id); 237 #endif 238 } 239 else if (queueit || !bitset(EF_INQUEUE, e->e_flags)) 240 { 241 #ifdef QUEUE 242 queueup(e, bitset(EF_KEEPQUEUE, e->e_flags), FALSE); 243 #else /* QUEUE */ 244 syserr("554 dropenvelope: queueup"); 245 #endif /* QUEUE */ 246 } 247 248 #ifdef XDEBUG 249 checkfd012("dropenvelope 3"); 250 #endif 251 252 /* now unlock the job */ 253 closexscript(e); 254 unlockqueue(e); 255 256 /* make sure that this envelope is marked unused */ 257 if (e->e_dfp != NULL) 258 (void) xfclose(e->e_dfp, "dropenvelope", e->e_df); 259 e->e_dfp = NULL; 260 e->e_id = e->e_df = NULL; 261 #ifdef XDEBUG 262 checkfd012("dropenvelope 4"); 263 #endif 264 } 265 /* 266 ** CLEARENVELOPE -- clear an envelope without unlocking 267 ** 268 ** This is normally used by a child process to get a clean 269 ** envelope without disturbing the parent. 270 ** 271 ** Parameters: 272 ** e -- the envelope to clear. 273 ** fullclear - if set, the current envelope is total 274 ** garbage and should be ignored; otherwise, 275 ** release any resources it may indicate. 276 ** 277 ** Returns: 278 ** none. 279 ** 280 ** Side Effects: 281 ** Closes files associated with the envelope. 282 ** Marks the envelope as unallocated. 283 */ 284 285 void 286 clearenvelope(e, fullclear) 287 register ENVELOPE *e; 288 bool fullclear; 289 { 290 register HDR *bh; 291 register HDR **nhp; 292 extern ENVELOPE BlankEnvelope; 293 294 if (!fullclear) 295 { 296 /* clear out any file information */ 297 if (e->e_xfp != NULL) 298 (void) xfclose(e->e_xfp, "clearenvelope xfp", e->e_id); 299 if (e->e_dfp != NULL) 300 (void) xfclose(e->e_dfp, "clearenvelope dfp", e->e_df); 301 e->e_xfp = e->e_dfp = NULL; 302 } 303 304 /* now clear out the data */ 305 STRUCTCOPY(BlankEnvelope, *e); 306 if (Verbose) 307 e->e_sendmode = SM_DELIVER; 308 bh = BlankEnvelope.e_header; 309 nhp = &e->e_header; 310 while (bh != NULL) 311 { 312 *nhp = (HDR *) xalloc(sizeof *bh); 313 bcopy((char *) bh, (char *) *nhp, sizeof *bh); 314 bh = bh->h_link; 315 nhp = &(*nhp)->h_link; 316 } 317 } 318 /* 319 ** INITSYS -- initialize instantiation of system 320 ** 321 ** In Daemon mode, this is done in the child. 322 ** 323 ** Parameters: 324 ** none. 325 ** 326 ** Returns: 327 ** none. 328 ** 329 ** Side Effects: 330 ** Initializes the system macros, some global variables, 331 ** etc. In particular, the current time in various 332 ** forms is set. 333 */ 334 335 void 336 initsys(e) 337 register ENVELOPE *e; 338 { 339 char cbuf[5]; /* holds hop count */ 340 char pbuf[10]; /* holds pid */ 341 #ifdef TTYNAME 342 static char ybuf[60]; /* holds tty id */ 343 register char *p; 344 #endif /* TTYNAME */ 345 extern char *ttyname(); 346 extern void settime(); 347 extern char Version[]; 348 349 /* 350 ** Give this envelope a reality. 351 ** I.e., an id, a transcript, and a creation time. 352 */ 353 354 openxscript(e); 355 e->e_ctime = curtime(); 356 357 /* 358 ** Set OutChannel to something useful if stdout isn't it. 359 ** This arranges that any extra stuff the mailer produces 360 ** gets sent back to the user on error (because it is 361 ** tucked away in the transcript). 362 */ 363 364 if (OpMode == MD_DAEMON && bitset(EF_QUEUERUN, e->e_flags) && 365 e->e_xfp != NULL) 366 OutChannel = e->e_xfp; 367 368 /* 369 ** Set up some basic system macros. 370 */ 371 372 /* process id */ 373 (void) sprintf(pbuf, "%d", getpid()); 374 define('p', newstr(pbuf), e); 375 376 /* hop count */ 377 (void) sprintf(cbuf, "%d", e->e_hopcount); 378 define('c', newstr(cbuf), e); 379 380 /* time as integer, unix time, arpa time */ 381 settime(e); 382 383 #ifdef TTYNAME 384 /* tty name */ 385 if (macvalue('y', e) == NULL) 386 { 387 p = ttyname(2); 388 if (p != NULL) 389 { 390 if (strrchr(p, '/') != NULL) 391 p = strrchr(p, '/') + 1; 392 (void) strcpy(ybuf, p); 393 define('y', ybuf, e); 394 } 395 } 396 #endif /* TTYNAME */ 397 } 398 /* 399 ** SETTIME -- set the current time. 400 ** 401 ** Parameters: 402 ** none. 403 ** 404 ** Returns: 405 ** none. 406 ** 407 ** Side Effects: 408 ** Sets the various time macros -- $a, $b, $d, $t. 409 */ 410 411 void 412 settime(e) 413 register ENVELOPE *e; 414 { 415 register char *p; 416 auto time_t now; 417 char tbuf[20]; /* holds "current" time */ 418 char dbuf[30]; /* holds ctime(tbuf) */ 419 register struct tm *tm; 420 extern char *arpadate(); 421 extern struct tm *gmtime(); 422 423 now = curtime(); 424 tm = gmtime(&now); 425 (void) sprintf(tbuf, "%04d%02d%02d%02d%02d", tm->tm_year + 1900, 426 tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min); 427 define('t', newstr(tbuf), e); 428 (void) strcpy(dbuf, ctime(&now)); 429 p = strchr(dbuf, '\n'); 430 if (p != NULL) 431 *p = '\0'; 432 define('d', newstr(dbuf), e); 433 p = arpadate(dbuf); 434 p = newstr(p); 435 if (macvalue('a', e) == NULL) 436 define('a', p, e); 437 define('b', p, e); 438 } 439 /* 440 ** OPENXSCRIPT -- Open transcript file 441 ** 442 ** Creates a transcript file for possible eventual mailing or 443 ** sending back. 444 ** 445 ** Parameters: 446 ** e -- the envelope to create the transcript in/for. 447 ** 448 ** Returns: 449 ** none 450 ** 451 ** Side Effects: 452 ** Creates the transcript file. 453 */ 454 455 #ifndef O_APPEND 456 #define O_APPEND 0 457 #endif 458 459 void 460 openxscript(e) 461 register ENVELOPE *e; 462 { 463 register char *p; 464 int fd; 465 466 if (e->e_xfp != NULL) 467 return; 468 p = queuename(e, 'x'); 469 fd = open(p, O_WRONLY|O_CREAT|O_APPEND, 0644); 470 if (fd < 0) 471 { 472 syserr("Can't create transcript file %s", p); 473 fd = open("/dev/null", O_WRONLY, 0644); 474 if (fd < 0) 475 syserr("!Can't open /dev/null"); 476 } 477 e->e_xfp = fdopen(fd, "w"); 478 if (e->e_xfp == NULL) 479 { 480 syserr("!Can't create transcript stream %s", p); 481 } 482 if (tTd(46, 9)) 483 { 484 printf("openxscript(%s):\n ", p); 485 dumpfd(fileno(e->e_xfp), TRUE, FALSE); 486 } 487 } 488 /* 489 ** CLOSEXSCRIPT -- close the transcript file. 490 ** 491 ** Parameters: 492 ** e -- the envelope containing the transcript to close. 493 ** 494 ** Returns: 495 ** none. 496 ** 497 ** Side Effects: 498 ** none. 499 */ 500 501 void 502 closexscript(e) 503 register ENVELOPE *e; 504 { 505 if (e->e_xfp == NULL) 506 return; 507 (void) xfclose(e->e_xfp, "closexscript", e->e_id); 508 e->e_xfp = NULL; 509 } 510 /* 511 ** SETSENDER -- set the person who this message is from 512 ** 513 ** Under certain circumstances allow the user to say who 514 ** s/he is (using -f or -r). These are: 515 ** 1. The user's uid is zero (root). 516 ** 2. The user's login name is in an approved list (typically 517 ** from a network server). 518 ** 3. The address the user is trying to claim has a 519 ** "!" character in it (since #2 doesn't do it for 520 ** us if we are dialing out for UUCP). 521 ** A better check to replace #3 would be if the 522 ** effective uid is "UUCP" -- this would require me 523 ** to rewrite getpwent to "grab" uucp as it went by, 524 ** make getname more nasty, do another passwd file 525 ** scan, or compile the UID of "UUCP" into the code, 526 ** all of which are reprehensible. 527 ** 528 ** Assuming all of these fail, we figure out something 529 ** ourselves. 530 ** 531 ** Parameters: 532 ** from -- the person we would like to believe this message 533 ** is from, as specified on the command line. 534 ** e -- the envelope in which we would like the sender set. 535 ** delimptr -- if non-NULL, set to the location of the 536 ** trailing delimiter. 537 ** internal -- set if this address is coming from an internal 538 ** source such as an owner alias. 539 ** 540 ** Returns: 541 ** none. 542 ** 543 ** Side Effects: 544 ** sets sendmail's notion of who the from person is. 545 */ 546 547 void 548 setsender(from, e, delimptr, internal) 549 char *from; 550 register ENVELOPE *e; 551 char **delimptr; 552 bool internal; 553 { 554 register char **pvp; 555 char *realname = NULL; 556 register struct passwd *pw; 557 char delimchar; 558 char *bp; 559 char buf[MAXNAME + 2]; 560 char pvpbuf[PSBUFSIZE]; 561 extern struct passwd *getpwnam(); 562 extern char *FullName; 563 564 if (tTd(45, 1)) 565 printf("setsender(%s)\n", from == NULL ? "" : from); 566 567 /* 568 ** Figure out the real user executing us. 569 ** Username can return errno != 0 on non-errors. 570 */ 571 572 if (bitset(EF_QUEUERUN, e->e_flags) || OpMode == MD_SMTP) 573 realname = from; 574 if (realname == NULL || realname[0] == '\0') 575 realname = username(); 576 577 if (ConfigLevel < 2) 578 SuprErrs = TRUE; 579 580 delimchar = internal ? '\0' : ' '; 581 e->e_from.q_flags = QBADADDR; 582 if (from == NULL || 583 parseaddr(from, &e->e_from, RF_COPYALL|RF_SENDERADDR, 584 delimchar, delimptr, e) == NULL || 585 bitset(QBADADDR, e->e_from.q_flags) || 586 e->e_from.q_mailer == ProgMailer || 587 e->e_from.q_mailer == FileMailer || 588 e->e_from.q_mailer == InclMailer) 589 { 590 /* log garbage addresses for traceback */ 591 # ifdef LOG 592 if (from != NULL && LogLevel > 2) 593 { 594 char *p; 595 char ebuf[MAXNAME * 2 + 2]; 596 597 p = macvalue('_', e); 598 if (p == NULL) 599 { 600 char *host = RealHostName; 601 if (host == NULL) 602 host = MyHostName; 603 (void) sprintf(ebuf, "%s@%s", realname, host); 604 p = ebuf; 605 } 606 syslog(LOG_NOTICE, 607 "setsender: %s: invalid or unparseable, received from %s", 608 shortenstring(from, 83), p); 609 } 610 # endif /* LOG */ 611 if (from != NULL) 612 { 613 if (!bitset(QBADADDR, e->e_from.q_flags)) 614 { 615 /* it was a bogus mailer in the from addr */ 616 usrerr("553 Invalid sender address"); 617 } 618 SuprErrs = TRUE; 619 } 620 if (from == realname || 621 parseaddr(from = newstr(realname), &e->e_from, 622 RF_COPYALL|RF_SENDERADDR, ' ', NULL, e) == NULL) 623 { 624 char nbuf[100]; 625 626 SuprErrs = TRUE; 627 expand("\201n", nbuf, &nbuf[sizeof nbuf], e); 628 if (parseaddr(from = newstr(nbuf), &e->e_from, 629 RF_COPYALL, ' ', NULL, e) == NULL && 630 parseaddr(from = "postmaster", &e->e_from, 631 RF_COPYALL, ' ', NULL, e) == NULL) 632 syserr("553 setsender: can't even parse postmaster!"); 633 } 634 } 635 else 636 FromFlag = TRUE; 637 e->e_from.q_flags |= QDONTSEND; 638 if (tTd(45, 5)) 639 { 640 printf("setsender: QDONTSEND "); 641 printaddr(&e->e_from, FALSE); 642 } 643 SuprErrs = FALSE; 644 645 pvp = NULL; 646 if (e->e_from.q_mailer == LocalMailer) 647 { 648 # ifdef USERDB 649 register char *p; 650 extern char *udbsender(); 651 # endif 652 653 if (!internal) 654 { 655 /* if the user has given fullname already, don't redefine */ 656 if (FullName == NULL) 657 FullName = macvalue('x', e); 658 if (FullName != NULL && FullName[0] == '\0') 659 FullName = NULL; 660 661 # ifdef USERDB 662 p = udbsender(e->e_from.q_user); 663 664 if (p != NULL) 665 { 666 /* 667 ** We have an alternate address for the sender 668 */ 669 670 pvp = prescan(p, '\0', pvpbuf, NULL); 671 } 672 # endif /* USERDB */ 673 } 674 675 if ((pw = getpwnam(e->e_from.q_user)) != NULL) 676 { 677 /* 678 ** Process passwd file entry. 679 */ 680 681 682 /* extract home directory */ 683 e->e_from.q_home = newstr(pw->pw_dir); 684 define('z', e->e_from.q_home, e); 685 686 /* extract user and group id */ 687 e->e_from.q_uid = pw->pw_uid; 688 e->e_from.q_gid = pw->pw_gid; 689 690 /* extract full name from passwd file */ 691 if (FullName == NULL && pw->pw_gecos != NULL && 692 strcmp(pw->pw_name, e->e_from.q_user) == 0 && 693 !internal) 694 { 695 buildfname(pw->pw_gecos, e->e_from.q_user, buf); 696 if (buf[0] != '\0') 697 FullName = newstr(buf); 698 } 699 } 700 if (FullName != NULL && !internal) 701 define('x', FullName, e); 702 } 703 else if (!internal) 704 { 705 if (e->e_from.q_home == NULL) 706 e->e_from.q_home = getenv("HOME"); 707 e->e_from.q_uid = RealUid; 708 e->e_from.q_gid = RealGid; 709 } 710 711 /* 712 ** Rewrite the from person to dispose of possible implicit 713 ** links in the net. 714 */ 715 716 if (pvp == NULL) 717 pvp = prescan(from, delimchar, pvpbuf, NULL); 718 if (pvp == NULL) 719 { 720 /* don't need to give error -- prescan did that already */ 721 # ifdef LOG 722 if (LogLevel > 2) 723 syslog(LOG_NOTICE, "cannot prescan from (%s)", from); 724 # endif 725 finis(); 726 } 727 (void) rewrite(pvp, 3, e); 728 (void) rewrite(pvp, 1, e); 729 (void) rewrite(pvp, 4, e); 730 bp = buf + 1; 731 cataddr(pvp, NULL, bp, sizeof buf - 2, '\0'); 732 if (*bp == '@') 733 { 734 /* heuristic: route-addr: add angle brackets */ 735 strcat(bp, ">"); 736 *--bp = '<'; 737 } 738 e->e_sender = newstr(bp); 739 define('f', e->e_sender, e); 740 741 /* save the domain spec if this mailer wants it */ 742 if (!internal && e->e_from.q_mailer != NULL && 743 bitnset(M_CANONICAL, e->e_from.q_mailer->m_flags)) 744 { 745 extern char **copyplist(); 746 747 while (*pvp != NULL && strcmp(*pvp, "@") != 0) 748 pvp++; 749 if (*pvp != NULL) 750 e->e_fromdomain = copyplist(pvp, TRUE); 751 } 752 } 753