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