1 #include <pwd.h> 2 #include <time.h> 3 #include "sendmail.h" 4 #include <sys/stat.h> 5 6 SCCSID(@(#)envelope.c 3.15 04/17/83); 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 clear((char *) e, sizeof *e); 37 bmove((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 bmove((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 extern char *macvalue(); 543 extern char **prescan(); 544 extern bool safefile(); 545 extern char *FullName; 546 547 # ifdef DEBUG 548 if (tTd(45, 1)) 549 printf("setsender(%s)\n", from); 550 # endif DEBUG 551 552 /* 553 ** Figure out the real user executing us. 554 ** Username can return errno != 0 on non-errors. 555 */ 556 557 if (QueueRun || OpMode == MD_SMTP || OpMode == MD_ARPAFTP) 558 realname = from; 559 if (realname == NULL || realname[0] == '\0') 560 { 561 extern char *username(); 562 563 realname = username(); 564 errno = 0; 565 } 566 if (realname == NULL || realname[0] == '\0') 567 { 568 extern struct passwd *getpwuid(); 569 570 pw = getpwuid(getruid()); 571 if (pw != NULL) 572 realname = pw->pw_name; 573 } 574 if (realname == NULL || realname[0] == '\0') 575 { 576 syserr("Who are you?"); 577 realname = "root"; 578 } 579 580 /* 581 ** Determine if this real person is allowed to alias themselves. 582 */ 583 584 if (from != NULL) 585 { 586 extern bool trusteduser(); 587 588 if (!trusteduser(realname) && 589 # ifdef DEBUG 590 (!tTd(1, 9) || getuid() != geteuid()) && 591 # endif DEBUG 592 index(from, '!') == NULL && getuid() != 0) 593 { 594 /* network sends -r regardless (why why why?) */ 595 /* syserr("%s, you cannot use the -f flag", realname); */ 596 from = NULL; 597 } 598 else if (strcmp(from, realname) != 0) 599 pw = NULL; 600 } 601 602 SuprErrs = TRUE; 603 if (from == NULL || parseaddr(from, &CurEnv->e_from, 1, '\0') == NULL) 604 { 605 from = newstr(realname); 606 (void) parseaddr(from, &CurEnv->e_from, 1, '\0'); 607 } 608 else 609 FromFlag = TRUE; 610 CurEnv->e_from.q_flags |= QDONTSEND; 611 SuprErrs = FALSE; 612 613 if (pw == NULL && CurEnv->e_from.q_mailer == LocalMailer) 614 { 615 extern struct passwd *getpwnam(); 616 617 pw = getpwnam(CurEnv->e_from.q_user); 618 } 619 620 /* 621 ** Process passwd file entry. 622 */ 623 624 if (pw != NULL) 625 { 626 /* extract home directory */ 627 CurEnv->e_from.q_home = newstr(pw->pw_dir); 628 629 /* extract user and group id */ 630 CurEnv->e_from.q_uid = pw->pw_uid; 631 CurEnv->e_from.q_gid = pw->pw_gid; 632 633 /* run user's .mailcf file */ 634 define('z', CurEnv->e_from.q_home, CurEnv); 635 expand("$z/.mailcf", buf, &buf[sizeof buf - 1], CurEnv); 636 if (safefile(buf, getruid(), S_IREAD)) 637 readcf(buf, FALSE); 638 639 /* if the user has given fullname already, don't redefine */ 640 if (FullName == NULL) 641 FullName = macvalue('x', CurEnv); 642 if (FullName != NULL && FullName[0] == '\0') 643 FullName = NULL; 644 645 /* extract full name from passwd file */ 646 if (FullName == NULL && pw->pw_gecos != NULL && 647 strcmp(pw->pw_name, CurEnv->e_from.q_user) == 0) 648 { 649 buildfname(pw->pw_gecos, CurEnv->e_from.q_user, buf); 650 if (buf[0] != '\0') 651 FullName = newstr(buf); 652 } 653 if (FullName != NULL) 654 define('x', FullName, CurEnv); 655 } 656 else 657 { 658 #ifndef V6 659 if (CurEnv->e_from.q_home == NULL) 660 CurEnv->e_from.q_home = getenv("HOME"); 661 #endif V6 662 CurEnv->e_from.q_uid = getuid(); 663 CurEnv->e_from.q_gid = getgid(); 664 } 665 666 if (CurEnv->e_from.q_uid != 0) 667 { 668 DefUid = CurEnv->e_from.q_uid; 669 DefGid = CurEnv->e_from.q_gid; 670 } 671 672 /* 673 ** Rewrite the from person to dispose of possible implicit 674 ** links in the net. 675 */ 676 677 pvp = prescan(from, '\0'); 678 if (pvp == NULL) 679 { 680 syserr("cannot prescan from (%s)", from); 681 finis(); 682 } 683 rewrite(pvp, 3); 684 rewrite(pvp, 1); 685 rewrite(pvp, 4); 686 cataddr(pvp, buf, sizeof buf); 687 define('f', newstr(buf), CurEnv); 688 689 /* save the domain spec if this mailer wants it */ 690 if (bitnset(M_CANONICAL, CurEnv->e_from.q_mailer->m_flags)) 691 { 692 extern char **copyplist(); 693 694 while (*pvp != NULL && strcmp(*pvp, "@") != 0) 695 pvp++; 696 if (*pvp != NULL) 697 CurEnv->e_fromdomain = copyplist(pvp, TRUE); 698 } 699 } 700 /* 701 ** TRUSTEDUSER -- tell us if this user is to be trusted. 702 ** 703 ** Parameters: 704 ** user -- the user to be checked. 705 ** 706 ** Returns: 707 ** TRUE if the user is in an approved list. 708 ** FALSE otherwise. 709 ** 710 ** Side Effects: 711 ** none. 712 */ 713 714 bool 715 trusteduser(user) 716 char *user; 717 { 718 register char **ulist; 719 extern char *TrustedUsers[]; 720 721 for (ulist = TrustedUsers; *ulist != NULL; ulist++) 722 if (strcmp(*ulist, user) == 0) 723 return (TRUE); 724 return (FALSE); 725 } 726