1 #include <pwd.h> 2 #include <sys/time.h> 3 #include "sendmail.h" 4 #include <sys/stat.h> 5 6 SCCSID(@(#)envelope.c 4.7 08/11/84); 7 8 /* 9 ** NEWENVELOPE -- allocate a new envelope 10 ** 11 ** Supports inheritance. 12 ** 13 ** Parameters: 14 ** e -- the new envelope to fill in. 15 ** 16 ** Returns: 17 ** e. 18 ** 19 ** Side Effects: 20 ** none. 21 */ 22 23 ENVELOPE * 24 newenvelope(e) 25 register ENVELOPE *e; 26 { 27 register HDR *bh; 28 register HDR **nhp; 29 register ENVELOPE *parent; 30 extern putheader(), putbody(); 31 extern ENVELOPE BlankEnvelope; 32 33 parent = CurEnv; 34 if (e == CurEnv) 35 parent = e->e_parent; 36 bzero((char *) e, sizeof *e); 37 bcopy((char *) &CurEnv->e_from, (char *) &e->e_from, sizeof e->e_from); 38 e->e_parent = parent; 39 e->e_ctime = curtime(); 40 e->e_puthdr = putheader; 41 e->e_putbody = putbody; 42 bh = BlankEnvelope.e_header; 43 nhp = &e->e_header; 44 while (bh != NULL) 45 { 46 *nhp = (HDR *) xalloc(sizeof *bh); 47 bcopy((char *) bh, (char *) *nhp, sizeof *bh); 48 bh = bh->h_link; 49 nhp = &(*nhp)->h_link; 50 } 51 if (CurEnv->e_xfp != NULL) 52 (void) fflush(CurEnv->e_xfp); 53 54 return (e); 55 } 56 /* 57 ** DROPENVELOPE -- deallocate an envelope. 58 ** 59 ** Parameters: 60 ** e -- the envelope to deallocate. 61 ** 62 ** Returns: 63 ** none. 64 ** 65 ** Side Effects: 66 ** housekeeping necessary to dispose of an envelope. 67 ** Unlocks this queue file. 68 */ 69 70 dropenvelope(e) 71 register ENVELOPE *e; 72 { 73 bool queueit = FALSE; 74 register ADDRESS *q; 75 76 #ifdef DEBUG 77 if (tTd(50, 1)) 78 { 79 printf("dropenvelope %x id=", e); 80 xputs(e->e_id); 81 printf(" flags=%o\n", e->e_flags); 82 } 83 #endif DEBUG 84 #ifdef LOG 85 if (LogLevel > 10) 86 syslog(LOG_DEBUG, "dropenvelope, id=%s, flags=%o, pid=%d", 87 e->e_id == NULL ? "(none)" : e->e_id, 88 e->e_flags, getpid()); 89 #endif LOG 90 91 /* we must have an id to remove disk files */ 92 if (e->e_id == NULL) 93 return; 94 95 /* 96 ** Extract state information from dregs of send list. 97 */ 98 99 for (q = e->e_sendqueue; q != NULL; q = q->q_next) 100 { 101 if (bitset(QQUEUEUP, q->q_flags)) 102 queueit = TRUE; 103 } 104 105 /* 106 ** Send back return receipts as requested. 107 */ 108 109 if (e->e_receiptto != NULL && bitset(EF_SENDRECEIPT, e->e_flags)) 110 { 111 auto ADDRESS *rlist = NULL; 112 113 sendtolist(CurEnv->e_receiptto, (ADDRESS *) NULL, &rlist); 114 (void) returntosender("Return receipt", rlist, FALSE); 115 } 116 117 /* 118 ** Arrange to send error messages if there are fatal errors. 119 */ 120 121 if (bitset(EF_FATALERRS|EF_TIMEOUT, e->e_flags) && ErrorMode != EM_QUIET) 122 savemail(e); 123 124 /* 125 ** Instantiate or deinstantiate the queue. 126 */ 127 128 if ((!queueit && !bitset(EF_KEEPQUEUE, e->e_flags)) || 129 bitset(EF_CLRQUEUE, e->e_flags)) 130 { 131 if (e->e_dfp != NULL) 132 (void) fclose(e->e_dfp); 133 if (e->e_df != NULL) 134 xunlink(e->e_df); 135 xunlink(queuename(e, 'q')); 136 } 137 else if (queueit || !bitset(EF_INQUEUE, e->e_flags)) 138 { 139 #ifdef QUEUE 140 queueup(e, FALSE, FALSE); 141 #else QUEUE 142 syserr("dropenvelope: queueup"); 143 #endif QUEUE 144 } 145 146 /* now unlock the job */ 147 closexscript(e); 148 unlockqueue(e); 149 150 /* make sure that this envelope is marked unused */ 151 e->e_id = e->e_df = NULL; 152 e->e_dfp = NULL; 153 } 154 /* 155 ** CLEARENVELOPE -- clear an envelope without unlocking 156 ** 157 ** This is normally used by a child process to get a clean 158 ** envelope without disturbing the parent. 159 ** 160 ** Parameters: 161 ** e -- the envelope to clear. 162 ** 163 ** Returns: 164 ** none. 165 ** 166 ** Side Effects: 167 ** Closes files associated with the envelope. 168 ** Marks the envelope as unallocated. 169 */ 170 171 clearenvelope(e) 172 register ENVELOPE *e; 173 { 174 /* clear out any file information */ 175 if (e->e_xfp != NULL) 176 (void) fclose(e->e_xfp); 177 if (e->e_dfp != NULL) 178 (void) fclose(e->e_dfp); 179 e->e_xfp = e->e_dfp = NULL; 180 181 /* now expunge names of objects */ 182 e->e_df = e->e_id = NULL; 183 184 /* and the flags which are now meaningless */ 185 e->e_flags = 0; 186 } 187 /* 188 ** UNLOCKQUEUE -- unlock the queue entry for a specified envelope 189 ** 190 ** Parameters: 191 ** e -- the envelope to unlock. 192 ** 193 ** Returns: 194 ** none 195 ** 196 ** Side Effects: 197 ** unlocks the queue for `e'. 198 */ 199 200 unlockqueue(e) 201 ENVELOPE *e; 202 { 203 /* remove the transcript */ 204 #ifdef DEBUG 205 # ifdef LOG 206 if (LogLevel > 19) 207 syslog(LOG_DEBUG, "%s: unlock", e->e_id); 208 # endif LOG 209 if (!tTd(51, 4)) 210 #endif DEBUG 211 xunlink(queuename(e, 'x')); 212 213 # ifdef QUEUE 214 /* last but not least, remove the lock */ 215 xunlink(queuename(e, 'l')); 216 # endif QUEUE 217 } 218 /* 219 ** INITSYS -- initialize instantiation of system 220 ** 221 ** In Daemon mode, this is done in the child. 222 ** 223 ** Parameters: 224 ** none. 225 ** 226 ** Returns: 227 ** none. 228 ** 229 ** Side Effects: 230 ** Initializes the system macros, some global variables, 231 ** etc. In particular, the current time in various 232 ** forms is set. 233 */ 234 235 initsys() 236 { 237 static char cbuf[5]; /* holds hop count */ 238 static char pbuf[10]; /* holds pid */ 239 static char ybuf[10]; /* holds tty id */ 240 register char *p; 241 extern char *ttyname(); 242 extern char *macvalue(); 243 extern char Version[]; 244 245 /* 246 ** Give this envelope a reality. 247 ** I.e., an id, a transcript, and a creation time. 248 */ 249 250 openxscript(CurEnv); 251 CurEnv->e_ctime = curtime(); 252 253 /* 254 ** Set OutChannel to something useful if stdout isn't it. 255 ** This arranges that any extra stuff the mailer produces 256 ** gets sent back to the user on error (because it is 257 ** tucked away in the transcript). 258 */ 259 260 if (OpMode == MD_DAEMON && QueueRun) 261 OutChannel = CurEnv->e_xfp; 262 263 /* 264 ** Set up some basic system macros. 265 */ 266 267 /* process id */ 268 (void) sprintf(pbuf, "%d", getpid()); 269 define('p', pbuf, CurEnv); 270 271 /* hop count */ 272 (void) sprintf(cbuf, "%d", CurEnv->e_hopcount); 273 define('c', cbuf, CurEnv); 274 275 /* time as integer, unix time, arpa time */ 276 settime(); 277 278 /* tty name */ 279 if (macvalue('y', CurEnv) == NULL) 280 { 281 p = ttyname(2); 282 if (p != NULL) 283 { 284 if (rindex(p, '/') != NULL) 285 p = rindex(p, '/') + 1; 286 (void) strcpy(ybuf, p); 287 define('y', ybuf, CurEnv); 288 } 289 } 290 } 291 /* 292 ** SETTIME -- set the current time. 293 ** 294 ** Parameters: 295 ** none. 296 ** 297 ** Returns: 298 ** none. 299 ** 300 ** Side Effects: 301 ** Sets the various time macros -- $a, $b, $d, $t. 302 */ 303 304 settime() 305 { 306 register char *p; 307 auto time_t now; 308 static char tbuf[20]; /* holds "current" time */ 309 static char dbuf[30]; /* holds ctime(tbuf) */ 310 register struct tm *tm; 311 extern char *arpadate(); 312 extern struct tm *gmtime(); 313 extern char *macvalue(); 314 315 now = curtime(); 316 tm = gmtime(&now); 317 (void) sprintf(tbuf, "%02d%02d%02d%02d%02d", tm->tm_year, tm->tm_mon+1, 318 tm->tm_mday, tm->tm_hour, tm->tm_min); 319 define('t', tbuf, CurEnv); 320 (void) strcpy(dbuf, ctime(&now)); 321 *index(dbuf, '\n') = '\0'; 322 if (macvalue('d', CurEnv) == NULL) 323 define('d', dbuf, CurEnv); 324 p = newstr(arpadate(dbuf)); 325 if (macvalue('a', CurEnv) == NULL) 326 define('a', p, CurEnv); 327 define('b', p, CurEnv); 328 } 329 /* 330 ** QUEUENAME -- build a file name in the queue directory for this envelope. 331 ** 332 ** Assigns an id code if one does not already exist. 333 ** This code is very careful to avoid trashing existing files 334 ** under any circumstances. 335 ** We first create an nf file that is only used when 336 ** assigning an id. This file is always empty, so that 337 ** we can never accidently truncate an lf file. 338 ** 339 ** Parameters: 340 ** e -- envelope to build it in/from. 341 ** type -- the file type, used as the first character 342 ** of the file name. 343 ** 344 ** Returns: 345 ** a pointer to the new file name (in a static buffer). 346 ** 347 ** Side Effects: 348 ** Will create the lf and qf files if no id code is 349 ** already assigned. This will cause the envelope 350 ** to be modified. 351 */ 352 353 char * 354 queuename(e, type) 355 register ENVELOPE *e; 356 char type; 357 { 358 static char buf[MAXNAME]; 359 static int pid = -1; 360 char c1 = 'A'; 361 char c2 = 'A'; 362 363 if (e->e_id == NULL) 364 { 365 char qf[20]; 366 char lf[20]; 367 char nf[20]; 368 369 /* find a unique id */ 370 if (pid != getpid()) 371 { 372 /* new process -- start back at "AA" */ 373 pid = getpid(); 374 c1 = 'A'; 375 c2 = 'A' - 1; 376 } 377 (void) sprintf(qf, "qfAA%05d", pid); 378 strcpy(lf, qf); 379 lf[0] = 'l'; 380 strcpy(nf, qf); 381 nf[0] = 'n'; 382 383 while (c1 < '~' || c2 < 'Z') 384 { 385 int i; 386 387 if (c2 >= 'Z') 388 { 389 c1++; 390 c2 = 'A' - 1; 391 } 392 qf[2] = lf[2] = nf[2] = c1; 393 qf[3] = lf[3] = nf[3] = ++c2; 394 # ifdef DEBUG 395 if (tTd(7, 20)) 396 printf("queuename: trying \"%s\"\n", nf); 397 # endif DEBUG 398 # ifdef QUEUE 399 if (access(lf, 0) >= 0 || access(qf, 0) >= 0) 400 continue; 401 errno = 0; 402 i = creat(nf, FileMode); 403 if (i < 0) 404 { 405 (void) unlink(nf); /* kernel bug */ 406 continue; 407 } 408 (void) close(i); 409 i = link(nf, lf); 410 (void) unlink(nf); 411 if (i < 0) 412 continue; 413 if (link(lf, qf) >= 0) 414 break; 415 (void) unlink(lf); 416 # else QUEUE 417 if (close(creat(qf, FileMode)) < 0) 418 continue; 419 # endif QUEUE 420 } 421 if (c1 >= '~' && c2 >= 'Z') 422 { 423 syserr("queuename: Cannot create \"%s\" in \"%s\"", 424 lf, QueueDir); 425 exit(EX_OSERR); 426 } 427 e->e_id = newstr(&qf[2]); 428 define('i', e->e_id, e); 429 # ifdef DEBUG 430 if (tTd(7, 1)) 431 printf("queuename: assigned id %s, env=%x\n", e->e_id, e); 432 # ifdef LOG 433 if (LogLevel > 16) 434 syslog(LOG_DEBUG, "%s: assigned id", e->e_id); 435 # endif LOG 436 # endif DEBUG 437 } 438 439 if (type == '\0') 440 return (NULL); 441 (void) sprintf(buf, "%cf%s", type, e->e_id); 442 # ifdef DEBUG 443 if (tTd(7, 2)) 444 printf("queuename: %s\n", buf); 445 # endif DEBUG 446 return (buf); 447 } 448 /* 449 ** OPENXSCRIPT -- Open transcript file 450 ** 451 ** Creates a transcript file for possible eventual mailing or 452 ** sending back. 453 ** 454 ** Parameters: 455 ** e -- the envelope to create the transcript in/for. 456 ** 457 ** Returns: 458 ** none 459 ** 460 ** Side Effects: 461 ** Creates the transcript file. 462 */ 463 464 openxscript(e) 465 register ENVELOPE *e; 466 { 467 register char *p; 468 469 # ifdef LOG 470 if (LogLevel > 19) 471 syslog(LOG_DEBUG, "%s: openx%s", e->e_id, e->e_xfp == NULL ? "" : " (no)"); 472 # endif LOG 473 if (e->e_xfp != NULL) 474 return; 475 p = queuename(e, 'x'); 476 e->e_xfp = fopen(p, "w"); 477 if (e->e_xfp == NULL) 478 syserr("Can't create %s", p); 479 else 480 (void) chmod(p, 0644); 481 } 482 /* 483 ** CLOSEXSCRIPT -- close the transcript file. 484 ** 485 ** Parameters: 486 ** e -- the envelope containing the transcript to close. 487 ** 488 ** Returns: 489 ** none. 490 ** 491 ** Side Effects: 492 ** none. 493 */ 494 495 closexscript(e) 496 register ENVELOPE *e; 497 { 498 if (e->e_xfp == NULL) 499 return; 500 (void) fclose(e->e_xfp); 501 e->e_xfp = NULL; 502 } 503 /* 504 ** SETSENDER -- set the person who this message is from 505 ** 506 ** Under certain circumstances allow the user to say who 507 ** s/he is (using -f or -r). These are: 508 ** 1. The user's uid is zero (root). 509 ** 2. The user's login name is in an approved list (typically 510 ** from a network server). 511 ** 3. The address the user is trying to claim has a 512 ** "!" character in it (since #2 doesn't do it for 513 ** us if we are dialing out for UUCP). 514 ** A better check to replace #3 would be if the 515 ** effective uid is "UUCP" -- this would require me 516 ** to rewrite getpwent to "grab" uucp as it went by, 517 ** make getname more nasty, do another passwd file 518 ** scan, or compile the UID of "UUCP" into the code, 519 ** all of which are reprehensible. 520 ** 521 ** Assuming all of these fail, we figure out something 522 ** ourselves. 523 ** 524 ** Parameters: 525 ** from -- the person we would like to believe this message 526 ** is from, as specified on the command line. 527 ** 528 ** Returns: 529 ** none. 530 ** 531 ** Side Effects: 532 ** sets sendmail's notion of who the from person is. 533 */ 534 535 setsender(from) 536 char *from; 537 { 538 register char **pvp; 539 register struct passwd *pw = NULL; 540 char *realname = NULL; 541 char buf[MAXNAME]; 542 char pvpbuf[PSBUFSIZE]; 543 extern char *macvalue(); 544 extern char **prescan(); 545 extern bool safefile(); 546 extern char *FullName; 547 548 # ifdef DEBUG 549 if (tTd(45, 1)) 550 printf("setsender(%s)\n", from == NULL ? "" : from); 551 # endif DEBUG 552 553 /* 554 ** Figure out the real user executing us. 555 ** Username can return errno != 0 on non-errors. 556 */ 557 558 if (QueueRun || OpMode == MD_SMTP || OpMode == MD_ARPAFTP) 559 realname = from; 560 if (realname == NULL || realname[0] == '\0') 561 { 562 extern char *username(); 563 564 realname = username(); 565 errno = 0; 566 } 567 if (realname == NULL || realname[0] == '\0') 568 { 569 extern struct passwd *getpwuid(); 570 571 pw = getpwuid(getruid()); 572 if (pw != NULL) 573 realname = pw->pw_name; 574 } 575 if (realname == NULL || realname[0] == '\0') 576 { 577 syserr("Who are you?"); 578 realname = "root"; 579 } 580 581 /* 582 ** Determine if this real person is allowed to alias themselves. 583 */ 584 585 if (from != NULL) 586 { 587 extern bool trusteduser(); 588 589 if (!trusteduser(realname) && 590 # ifdef DEBUG 591 (!tTd(1, 9) || getuid() != geteuid()) && 592 # endif DEBUG 593 index(from, '!') == NULL && getuid() != 0) 594 { 595 /* network sends -r regardless (why why why?) */ 596 /* syserr("%s, you cannot use the -f flag", realname); */ 597 from = NULL; 598 } 599 else if (strcmp(from, realname) != 0) 600 pw = NULL; 601 } 602 603 SuprErrs = TRUE; 604 if (from == NULL || parseaddr(from, &CurEnv->e_from, 1, '\0') == NULL) 605 { 606 from = newstr(realname); 607 (void) parseaddr(from, &CurEnv->e_from, 1, '\0'); 608 } 609 else 610 FromFlag = TRUE; 611 CurEnv->e_from.q_flags |= QDONTSEND; 612 loweraddr(&CurEnv->e_from); 613 SuprErrs = FALSE; 614 615 if (pw == NULL && CurEnv->e_from.q_mailer == LocalMailer) 616 { 617 extern struct passwd *getpwnam(); 618 619 pw = getpwnam(CurEnv->e_from.q_user); 620 } 621 622 /* 623 ** Process passwd file entry. 624 */ 625 626 if (pw != NULL) 627 { 628 /* extract home directory */ 629 CurEnv->e_from.q_home = newstr(pw->pw_dir); 630 define('z', CurEnv->e_from.q_home, CurEnv); 631 632 /* extract user and group id */ 633 CurEnv->e_from.q_uid = pw->pw_uid; 634 CurEnv->e_from.q_gid = pw->pw_gid; 635 636 /* if the user has given fullname already, don't redefine */ 637 if (FullName == NULL) 638 FullName = macvalue('x', CurEnv); 639 if (FullName != NULL && FullName[0] == '\0') 640 FullName = NULL; 641 642 /* extract full name from passwd file */ 643 if (FullName == NULL && pw->pw_gecos != NULL && 644 strcmp(pw->pw_name, CurEnv->e_from.q_user) == 0) 645 { 646 buildfname(pw->pw_gecos, CurEnv->e_from.q_user, buf); 647 if (buf[0] != '\0') 648 FullName = newstr(buf); 649 } 650 if (FullName != NULL) 651 define('x', FullName, CurEnv); 652 } 653 else 654 { 655 #ifndef V6 656 if (CurEnv->e_from.q_home == NULL) 657 CurEnv->e_from.q_home = getenv("HOME"); 658 #endif V6 659 CurEnv->e_from.q_uid = getuid(); 660 CurEnv->e_from.q_gid = getgid(); 661 } 662 663 if (CurEnv->e_from.q_uid != 0) 664 { 665 DefUid = CurEnv->e_from.q_uid; 666 DefGid = CurEnv->e_from.q_gid; 667 } 668 669 /* 670 ** Rewrite the from person to dispose of possible implicit 671 ** links in the net. 672 */ 673 674 pvp = prescan(from, '\0', pvpbuf); 675 if (pvp == NULL) 676 { 677 syserr("cannot prescan from (%s)", from); 678 finis(); 679 } 680 rewrite(pvp, 3); 681 rewrite(pvp, 1); 682 rewrite(pvp, 4); 683 cataddr(pvp, buf, sizeof buf); 684 define('f', newstr(buf), CurEnv); 685 686 /* save the domain spec if this mailer wants it */ 687 if (bitnset(M_CANONICAL, CurEnv->e_from.q_mailer->m_flags)) 688 { 689 extern char **copyplist(); 690 691 while (*pvp != NULL && strcmp(*pvp, "@") != 0) 692 pvp++; 693 if (*pvp != NULL) 694 CurEnv->e_fromdomain = copyplist(pvp, TRUE); 695 } 696 } 697 /* 698 ** TRUSTEDUSER -- tell us if this user is to be trusted. 699 ** 700 ** Parameters: 701 ** user -- the user to be checked. 702 ** 703 ** Returns: 704 ** TRUE if the user is in an approved list. 705 ** FALSE otherwise. 706 ** 707 ** Side Effects: 708 ** none. 709 */ 710 711 bool 712 trusteduser(user) 713 char *user; 714 { 715 register char **ulist; 716 extern char *TrustedUsers[]; 717 718 for (ulist = TrustedUsers; *ulist != NULL; ulist++) 719 if (strcmp(*ulist, user) == 0) 720 return (TRUE); 721 return (FALSE); 722 } 723