1 #include <pwd.h> 2 #include <time.h> 3 #include "sendmail.h" 4 #include <sys/stat.h> 5 6 SCCSID(@(#)envelope.c 3.14 03/19/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 auto time_t now; 238 static char cbuf[5]; /* holds hop count */ 239 static char dbuf[30]; /* holds ctime(tbuf) */ 240 static char pbuf[10]; /* holds pid */ 241 static char tbuf[20]; /* holds "current" time */ 242 static char ybuf[10]; /* holds tty id */ 243 register char *p; 244 register struct tm *tm; 245 extern char *ttyname(); 246 extern char *arpadate(); 247 extern struct tm *gmtime(); 248 extern char *macvalue(); 249 extern char Version[]; 250 251 /* 252 ** Give this envelope a reality. 253 ** I.e., an id, a transcript, and a creation time. 254 */ 255 256 openxscript(CurEnv); 257 CurEnv->e_ctime = curtime(); 258 259 /* 260 ** Set OutChannel to something useful if stdout isn't it. 261 ** This arranges that any extra stuff the mailer produces 262 ** gets sent back to the user on error (because it is 263 ** tucked away in the transcript). 264 */ 265 266 if (OpMode == MD_DAEMON && QueueRun) 267 OutChannel = CurEnv->e_xfp; 268 269 /* 270 ** Set up some basic system macros. 271 */ 272 273 /* process id */ 274 (void) sprintf(pbuf, "%d", getpid()); 275 define('p', pbuf, CurEnv); 276 277 /* hop count */ 278 (void) sprintf(cbuf, "%d", CurEnv->e_hopcount); 279 define('c', cbuf, CurEnv); 280 281 /* time as integer, unix time, arpa time */ 282 now = curtime(); 283 tm = gmtime(&now); 284 (void) sprintf(tbuf, "%02d%02d%02d%02d%02d", tm->tm_year, tm->tm_mon+1, 285 tm->tm_mday, tm->tm_hour, tm->tm_min); 286 define('t', tbuf, CurEnv); 287 (void) strcpy(dbuf, ctime(&now)); 288 *index(dbuf, '\n') = '\0'; 289 if (macvalue('d', CurEnv) == NULL) 290 define('d', dbuf, CurEnv); 291 p = newstr(arpadate(dbuf)); 292 if (macvalue('a', CurEnv) == NULL) 293 define('a', p, CurEnv); 294 define('b', p, CurEnv); 295 296 /* tty name */ 297 if (macvalue('y', CurEnv) == NULL) 298 { 299 p = ttyname(2); 300 if (p != NULL) 301 { 302 if (rindex(p, '/') != NULL) 303 p = rindex(p, '/') + 1; 304 (void) strcpy(ybuf, p); 305 define('y', ybuf, CurEnv); 306 } 307 } 308 } 309 /* 310 ** QUEUENAME -- build a file name in the queue directory for this envelope. 311 ** 312 ** Assigns an id code if one does not already exist. 313 ** This code is very careful to avoid trashing existing files 314 ** under any circumstances. 315 ** We first create an nf file that is only used when 316 ** assigning an id. This file is always empty, so that 317 ** we can never accidently truncate an lf file. 318 ** 319 ** Parameters: 320 ** e -- envelope to build it in/from. 321 ** type -- the file type, used as the first character 322 ** of the file name. 323 ** 324 ** Returns: 325 ** a pointer to the new file name (in a static buffer). 326 ** 327 ** Side Effects: 328 ** Will create the lf and qf files if no id code is 329 ** already assigned. This will cause the envelope 330 ** to be modified. 331 */ 332 333 char * 334 queuename(e, type) 335 register ENVELOPE *e; 336 char type; 337 { 338 static char buf[MAXNAME]; 339 static int pid = -1; 340 char c1 = 'A'; 341 char c2 = 'A'; 342 343 if (e->e_id == NULL) 344 { 345 char qf[20]; 346 char lf[20]; 347 char nf[20]; 348 349 /* find a unique id */ 350 if (pid != getpid()) 351 { 352 /* new process -- start back at "AA" */ 353 pid = getpid(); 354 c1 = 'A'; 355 c2 = 'A' - 1; 356 } 357 (void) sprintf(qf, "qfAA%05d", pid); 358 strcpy(lf, qf); 359 lf[0] = 'l'; 360 strcpy(nf, qf); 361 nf[0] = 'n'; 362 363 while (c1 < '~' || c2 < 'Z') 364 { 365 int i; 366 367 if (c2 >= 'Z') 368 { 369 c1++; 370 c2 = 'A' - 1; 371 } 372 qf[2] = lf[2] = nf[2] = c1; 373 qf[3] = lf[3] = nf[3] = ++c2; 374 # ifdef DEBUG 375 if (tTd(7, 20)) 376 printf("queuename: trying \"%s\"\n", nf); 377 # endif DEBUG 378 # ifdef QUEUE 379 if (access(lf, 0) >= 0 || access(qf, 0) >= 0) 380 continue; 381 errno = 0; 382 i = creat(nf, FileMode); 383 if (i < 0) 384 { 385 (void) unlink(nf); /* kernel bug */ 386 continue; 387 } 388 (void) close(i); 389 i = link(nf, lf); 390 (void) unlink(nf); 391 if (i < 0) 392 continue; 393 if (link(lf, qf) >= 0) 394 break; 395 (void) unlink(lf); 396 # else QUEUE 397 if (close(creat(qf, FileMode)) < 0) 398 continue; 399 # endif QUEUE 400 } 401 if (c1 >= '~' && c2 >= 'Z') 402 { 403 syserr("queuename: Cannot create \"%s\" in \"%s\"", 404 lf, QueueDir); 405 exit(EX_OSERR); 406 } 407 e->e_id = newstr(&qf[2]); 408 define('i', e->e_id, e); 409 # ifdef DEBUG 410 if (tTd(7, 1)) 411 printf("queuename: assigned id %s, env=%x\n", e->e_id, e); 412 # ifdef LOG 413 if (LogLevel > 16) 414 syslog(LOG_DEBUG, "%s: assigned id", e->e_id); 415 # endif LOG 416 # endif DEBUG 417 } 418 419 if (type == '\0') 420 return (NULL); 421 (void) sprintf(buf, "%cf%s", type, e->e_id); 422 # ifdef DEBUG 423 if (tTd(7, 2)) 424 printf("queuename: %s\n", buf); 425 # endif DEBUG 426 return (buf); 427 } 428 /* 429 ** OPENXSCRIPT -- Open transcript file 430 ** 431 ** Creates a transcript file for possible eventual mailing or 432 ** sending back. 433 ** 434 ** Parameters: 435 ** e -- the envelope to create the transcript in/for. 436 ** 437 ** Returns: 438 ** none 439 ** 440 ** Side Effects: 441 ** Creates the transcript file. 442 */ 443 444 openxscript(e) 445 register ENVELOPE *e; 446 { 447 register char *p; 448 449 # ifdef LOG 450 if (LogLevel > 19) 451 syslog(LOG_DEBUG, "%s: openx%s", e->e_id, e->e_xfp == NULL ? "" : " (no)"); 452 # endif LOG 453 if (e->e_xfp != NULL) 454 return; 455 p = queuename(e, 'x'); 456 e->e_xfp = fopen(p, "w"); 457 if (e->e_xfp == NULL) 458 syserr("Can't create %s", p); 459 else 460 (void) chmod(p, 0644); 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 closexscript(e) 476 register ENVELOPE *e; 477 { 478 if (e->e_xfp == NULL) 479 return; 480 (void) fclose(e->e_xfp); 481 e->e_xfp = NULL; 482 } 483 /* 484 ** SETSENDER -- set the person who this message is from 485 ** 486 ** Under certain circumstances allow the user to say who 487 ** s/he is (using -f or -r). These are: 488 ** 1. The user's uid is zero (root). 489 ** 2. The user's login name is in an approved list (typically 490 ** from a network server). 491 ** 3. The address the user is trying to claim has a 492 ** "!" character in it (since #2 doesn't do it for 493 ** us if we are dialing out for UUCP). 494 ** A better check to replace #3 would be if the 495 ** effective uid is "UUCP" -- this would require me 496 ** to rewrite getpwent to "grab" uucp as it went by, 497 ** make getname more nasty, do another passwd file 498 ** scan, or compile the UID of "UUCP" into the code, 499 ** all of which are reprehensible. 500 ** 501 ** Assuming all of these fail, we figure out something 502 ** ourselves. 503 ** 504 ** Parameters: 505 ** from -- the person we would like to believe this message 506 ** is from, as specified on the command line. 507 ** 508 ** Returns: 509 ** none. 510 ** 511 ** Side Effects: 512 ** sets sendmail's notion of who the from person is. 513 */ 514 515 setsender(from) 516 char *from; 517 { 518 register char **pvp; 519 register struct passwd *pw = NULL; 520 char *realname = NULL; 521 char buf[MAXNAME]; 522 extern char *macvalue(); 523 extern char **prescan(); 524 extern bool safefile(); 525 extern char *FullName; 526 527 # ifdef DEBUG 528 if (tTd(45, 1)) 529 printf("setsender(%s)\n", from); 530 # endif DEBUG 531 532 /* 533 ** Figure out the real user executing us. 534 ** Username can return errno != 0 on non-errors. 535 */ 536 537 if (QueueRun || OpMode == MD_SMTP || OpMode == MD_ARPAFTP) 538 realname = from; 539 if (realname == NULL || realname[0] == '\0') 540 { 541 extern char *username(); 542 543 realname = username(); 544 errno = 0; 545 } 546 if (realname == NULL || realname[0] == '\0') 547 { 548 extern struct passwd *getpwuid(); 549 550 pw = getpwuid(getruid()); 551 if (pw != NULL) 552 realname = pw->pw_name; 553 } 554 if (realname == NULL || realname[0] == '\0') 555 { 556 syserr("Who are you?"); 557 realname = "root"; 558 } 559 560 /* 561 ** Determine if this real person is allowed to alias themselves. 562 */ 563 564 if (from != NULL) 565 { 566 extern bool trusteduser(); 567 568 if (!trusteduser(realname) && 569 # ifdef DEBUG 570 (!tTd(1, 9) || getuid() != geteuid()) && 571 # endif DEBUG 572 index(from, '!') == NULL && getuid() != 0) 573 { 574 /* network sends -r regardless (why why why?) */ 575 /* syserr("%s, you cannot use the -f flag", realname); */ 576 from = NULL; 577 } 578 else if (strcmp(from, realname) != 0) 579 pw = NULL; 580 } 581 582 SuprErrs = TRUE; 583 if (from == NULL || parseaddr(from, &CurEnv->e_from, 1, '\0') == NULL) 584 { 585 from = newstr(realname); 586 (void) parseaddr(from, &CurEnv->e_from, 1, '\0'); 587 } 588 else 589 FromFlag = TRUE; 590 CurEnv->e_from.q_flags |= QDONTSEND; 591 SuprErrs = FALSE; 592 593 if (pw == NULL && CurEnv->e_from.q_mailer == LocalMailer) 594 { 595 extern struct passwd *getpwnam(); 596 597 pw = getpwnam(CurEnv->e_from.q_user); 598 } 599 600 /* 601 ** Process passwd file entry. 602 */ 603 604 if (pw != NULL) 605 { 606 /* extract home directory */ 607 CurEnv->e_from.q_home = newstr(pw->pw_dir); 608 609 /* extract user and group id */ 610 CurEnv->e_from.q_uid = pw->pw_uid; 611 CurEnv->e_from.q_gid = pw->pw_gid; 612 613 /* run user's .mailcf file */ 614 define('z', CurEnv->e_from.q_home, CurEnv); 615 expand("$z/.mailcf", buf, &buf[sizeof buf - 1], CurEnv); 616 if (safefile(buf, getruid(), S_IREAD)) 617 readcf(buf, FALSE); 618 619 /* if the user has given fullname already, don't redefine */ 620 if (FullName == NULL) 621 FullName = macvalue('x', CurEnv); 622 if (FullName[0] == '\0') 623 FullName = NULL; 624 625 /* extract full name from passwd file */ 626 if (FullName == NULL && pw->pw_gecos != NULL && 627 strcmp(pw->pw_name, CurEnv->e_from.q_user) == 0) 628 { 629 buildfname(pw->pw_gecos, CurEnv->e_from.q_user, buf); 630 if (buf[0] != '\0') 631 FullName = newstr(buf); 632 } 633 if (FullName != NULL) 634 define('x', FullName, CurEnv); 635 } 636 else 637 { 638 #ifndef V6 639 if (CurEnv->e_from.q_home == NULL) 640 CurEnv->e_from.q_home = getenv("HOME"); 641 #endif V6 642 CurEnv->e_from.q_uid = getuid(); 643 CurEnv->e_from.q_gid = getgid(); 644 } 645 646 if (CurEnv->e_from.q_uid != 0) 647 { 648 DefUid = CurEnv->e_from.q_uid; 649 DefGid = CurEnv->e_from.q_gid; 650 } 651 652 /* 653 ** Rewrite the from person to dispose of possible implicit 654 ** links in the net. 655 */ 656 657 pvp = prescan(from, '\0'); 658 if (pvp == NULL) 659 { 660 syserr("cannot prescan from (%s)", from); 661 finis(); 662 } 663 rewrite(pvp, 3); 664 rewrite(pvp, 1); 665 rewrite(pvp, 4); 666 cataddr(pvp, buf, sizeof buf); 667 define('f', newstr(buf), CurEnv); 668 669 /* save the domain spec if this mailer wants it */ 670 if (bitnset(M_CANONICAL, CurEnv->e_from.q_mailer->m_flags)) 671 { 672 extern char **copyplist(); 673 674 while (*pvp != NULL && strcmp(*pvp, "@") != 0) 675 pvp++; 676 if (*pvp != NULL) 677 CurEnv->e_fromdomain = copyplist(pvp, TRUE); 678 } 679 } 680 /* 681 ** TRUSTEDUSER -- tell us if this user is to be trusted. 682 ** 683 ** Parameters: 684 ** user -- the user to be checked. 685 ** 686 ** Returns: 687 ** TRUE if the user is in an approved list. 688 ** FALSE otherwise. 689 ** 690 ** Side Effects: 691 ** none. 692 */ 693 694 bool 695 trusteduser(user) 696 char *user; 697 { 698 register char **ulist; 699 extern char *TrustedUsers[]; 700 701 for (ulist = TrustedUsers; *ulist != NULL; ulist++) 702 if (strcmp(*ulist, user) == 0) 703 return (TRUE); 704 return (FALSE); 705 } 706