1 /* 2 * Copyright (c) 1998-2004 Sendmail, Inc. and its suppliers. 3 * All rights reserved. 4 * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. 5 * Copyright (c) 1988, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * By using this file, you agree to the terms and conditions set 9 * forth in the LICENSE file which can be found at the top level of 10 * the sendmail distribution. 11 * 12 * $FreeBSD$ 13 */ 14 15 #include <sendmail.h> 16 17 SM_RCSID("@(#)$Id: headers.c,v 8.286 2004/07/08 17:57:32 ca Exp $") 18 19 static HDR *allocheader __P((char *, char *, int, SM_RPOOL_T *)); 20 static size_t fix_mime_header __P((HDR *, ENVELOPE *)); 21 static int priencode __P((char *)); 22 static void put_vanilla_header __P((HDR *, char *, MCI *)); 23 24 /* 25 ** SETUPHEADERS -- initialize headers in symbol table 26 ** 27 ** Parameters: 28 ** none 29 ** 30 ** Returns: 31 ** none 32 */ 33 34 void 35 setupheaders() 36 { 37 struct hdrinfo *hi; 38 STAB *s; 39 40 for (hi = HdrInfo; hi->hi_field != NULL; hi++) 41 { 42 s = stab(hi->hi_field, ST_HEADER, ST_ENTER); 43 s->s_header.hi_flags = hi->hi_flags; 44 s->s_header.hi_ruleset = NULL; 45 } 46 } 47 /* 48 ** CHOMPHEADER -- process and save a header line. 49 ** 50 ** Called by collect, readcf, and readqf to deal with header lines. 51 ** 52 ** Parameters: 53 ** line -- header as a text line. 54 ** pflag -- flags for chompheader() (from sendmail.h) 55 ** hdrp -- a pointer to the place to save the header. 56 ** e -- the envelope including this header. 57 ** 58 ** Returns: 59 ** flags for this header. 60 ** 61 ** Side Effects: 62 ** The header is saved on the header list. 63 ** Contents of 'line' are destroyed. 64 */ 65 66 static struct hdrinfo NormalHeader = { NULL, 0, NULL }; 67 68 unsigned long 69 chompheader(line, pflag, hdrp, e) 70 char *line; 71 int pflag; 72 HDR **hdrp; 73 register ENVELOPE *e; 74 { 75 unsigned char mid = '\0'; 76 register char *p; 77 register HDR *h; 78 HDR **hp; 79 char *fname; 80 char *fvalue; 81 bool cond = false; 82 bool dropfrom; 83 bool headeronly; 84 STAB *s; 85 struct hdrinfo *hi; 86 bool nullheader = false; 87 BITMAP256 mopts; 88 89 if (tTd(31, 6)) 90 { 91 sm_dprintf("chompheader: "); 92 xputs(sm_debug_file(), line); 93 sm_dprintf("\n"); 94 } 95 96 headeronly = hdrp != NULL; 97 if (!headeronly) 98 hdrp = &e->e_header; 99 100 /* strip off options */ 101 clrbitmap(mopts); 102 p = line; 103 if (!bitset(pflag, CHHDR_USER) && *p == '?') 104 { 105 int c; 106 register char *q; 107 108 q = strchr(++p, '?'); 109 if (q == NULL) 110 goto hse; 111 112 *q = '\0'; 113 c = *p & 0377; 114 115 /* possibly macro conditional */ 116 if (c == MACROEXPAND) 117 { 118 /* catch ?$? */ 119 if (*++p == '\0') 120 { 121 *q = '?'; 122 goto hse; 123 } 124 125 mid = (unsigned char) *p++; 126 127 /* catch ?$abc? */ 128 if (*p != '\0') 129 { 130 *q = '?'; 131 goto hse; 132 } 133 } 134 else if (*p == '$') 135 { 136 /* catch ?$? */ 137 if (*++p == '\0') 138 { 139 *q = '?'; 140 goto hse; 141 } 142 143 mid = (unsigned char) macid(p); 144 if (bitset(0200, mid)) 145 { 146 p += strlen(macname(mid)) + 2; 147 SM_ASSERT(p <= q); 148 } 149 else 150 p++; 151 152 /* catch ?$abc? */ 153 if (*p != '\0') 154 { 155 *q = '?'; 156 goto hse; 157 } 158 } 159 else 160 { 161 while (*p != '\0') 162 { 163 if (!isascii(*p)) 164 { 165 *q = '?'; 166 goto hse; 167 } 168 169 setbitn(bitidx(*p), mopts); 170 cond = true; 171 p++; 172 } 173 } 174 p = q + 1; 175 } 176 177 /* find canonical name */ 178 fname = p; 179 while (isascii(*p) && isgraph(*p) && *p != ':') 180 p++; 181 fvalue = p; 182 while (isascii(*p) && isspace(*p)) 183 p++; 184 if (*p++ != ':' || fname == fvalue) 185 { 186 hse: 187 syserr("553 5.3.0 header syntax error, line \"%s\"", line); 188 return 0; 189 } 190 *fvalue = '\0'; 191 192 /* strip field value on front */ 193 if (*p == ' ') 194 p++; 195 fvalue = p; 196 197 /* if the field is null, go ahead and use the default */ 198 while (isascii(*p) && isspace(*p)) 199 p++; 200 if (*p == '\0') 201 nullheader = true; 202 203 /* security scan: long field names are end-of-header */ 204 if (strlen(fname) > 100) 205 return H_EOH; 206 207 /* check to see if it represents a ruleset call */ 208 if (bitset(pflag, CHHDR_DEF)) 209 { 210 char hbuf[50]; 211 212 (void) expand(fvalue, hbuf, sizeof hbuf, e); 213 for (p = hbuf; isascii(*p) && isspace(*p); ) 214 p++; 215 if ((*p++ & 0377) == CALLSUBR) 216 { 217 auto char *endp; 218 bool strc; 219 220 strc = *p == '+'; /* strip comments? */ 221 if (strc) 222 ++p; 223 if (strtorwset(p, &endp, ST_ENTER) > 0) 224 { 225 *endp = '\0'; 226 s = stab(fname, ST_HEADER, ST_ENTER); 227 if (LogLevel > 9 && 228 s->s_header.hi_ruleset != NULL) 229 sm_syslog(LOG_WARNING, NOQID, 230 "Warning: redefined ruleset for header=%s, old=%s, new=%s", 231 fname, 232 s->s_header.hi_ruleset, p); 233 s->s_header.hi_ruleset = newstr(p); 234 if (!strc) 235 s->s_header.hi_flags |= H_STRIPCOMM; 236 } 237 return 0; 238 } 239 } 240 241 /* see if it is a known type */ 242 s = stab(fname, ST_HEADER, ST_FIND); 243 if (s != NULL) 244 hi = &s->s_header; 245 else 246 hi = &NormalHeader; 247 248 if (tTd(31, 9)) 249 { 250 if (s == NULL) 251 sm_dprintf("no header flags match\n"); 252 else 253 sm_dprintf("header match, flags=%lx, ruleset=%s\n", 254 hi->hi_flags, 255 hi->hi_ruleset == NULL ? "<NULL>" 256 : hi->hi_ruleset); 257 } 258 259 /* see if this is a resent message */ 260 if (!bitset(pflag, CHHDR_DEF) && !headeronly && 261 bitset(H_RESENT, hi->hi_flags)) 262 e->e_flags |= EF_RESENT; 263 264 /* if this is an Errors-To: header keep track of it now */ 265 if (UseErrorsTo && !bitset(pflag, CHHDR_DEF) && !headeronly && 266 bitset(H_ERRORSTO, hi->hi_flags)) 267 (void) sendtolist(fvalue, NULLADDR, &e->e_errorqueue, 0, e); 268 269 /* if this means "end of header" quit now */ 270 if (!headeronly && bitset(H_EOH, hi->hi_flags)) 271 return hi->hi_flags; 272 273 /* 274 ** Horrible hack to work around problem with Lotus Notes SMTP 275 ** mail gateway, which generates From: headers with newlines in 276 ** them and the <address> on the second line. Although this is 277 ** legal RFC 822, many MUAs don't handle this properly and thus 278 ** never find the actual address. 279 */ 280 281 if (bitset(H_FROM, hi->hi_flags) && SingleLineFromHeader) 282 { 283 while ((p = strchr(fvalue, '\n')) != NULL) 284 *p = ' '; 285 } 286 287 /* 288 ** If there is a check ruleset, verify it against the header. 289 */ 290 291 if (bitset(pflag, CHHDR_CHECK)) 292 { 293 int rscheckflags; 294 char *rs; 295 296 rscheckflags = RSF_COUNT; 297 if (!bitset(hi->hi_flags, H_FROM|H_RCPT)) 298 rscheckflags |= RSF_UNSTRUCTURED; 299 300 /* no ruleset? look for default */ 301 rs = hi->hi_ruleset; 302 if (rs == NULL) 303 { 304 s = stab("*", ST_HEADER, ST_FIND); 305 if (s != NULL) 306 { 307 rs = (&s->s_header)->hi_ruleset; 308 if (bitset((&s->s_header)->hi_flags, 309 H_STRIPCOMM)) 310 rscheckflags |= RSF_RMCOMM; 311 } 312 } 313 else if (bitset(hi->hi_flags, H_STRIPCOMM)) 314 rscheckflags |= RSF_RMCOMM; 315 if (rs != NULL) 316 { 317 int l, k; 318 char qval[MAXNAME]; 319 320 l = 0; 321 qval[l++] = '"'; 322 323 /* - 3 to avoid problems with " at the end */ 324 /* should be sizeof(qval), not MAXNAME */ 325 for (k = 0; fvalue[k] != '\0' && l < MAXNAME - 3; k++) 326 { 327 switch (fvalue[k]) 328 { 329 /* XXX other control chars? */ 330 case '\011': /* ht */ 331 case '\012': /* nl */ 332 case '\013': /* vt */ 333 case '\014': /* np */ 334 case '\015': /* cr */ 335 qval[l++] = ' '; 336 break; 337 case '"': 338 qval[l++] = '\\'; 339 /* FALLTHROUGH */ 340 default: 341 qval[l++] = fvalue[k]; 342 break; 343 } 344 } 345 qval[l++] = '"'; 346 qval[l] = '\0'; 347 k += strlen(fvalue + k); 348 if (k >= MAXNAME) 349 { 350 if (LogLevel > 9) 351 sm_syslog(LOG_WARNING, e->e_id, 352 "Warning: truncated header '%s' before check with '%s' len=%d max=%d", 353 fname, rs, k, MAXNAME - 1); 354 } 355 macdefine(&e->e_macro, A_TEMP, 356 macid("{currHeader}"), qval); 357 macdefine(&e->e_macro, A_TEMP, 358 macid("{hdr_name}"), fname); 359 360 (void) sm_snprintf(qval, sizeof qval, "%d", k); 361 macdefine(&e->e_macro, A_TEMP, macid("{hdrlen}"), qval); 362 #if _FFR_HDR_TYPE 363 if (bitset(H_FROM, hi->hi_flags)) 364 macdefine(&e->e_macro, A_PERM, 365 macid("{addr_type}"), "h s"); 366 else if (bitset(H_RCPT, hi->hi_flags)) 367 macdefine(&e->e_macro, A_PERM, 368 macid("{addr_type}"), "h r"); 369 else 370 #endif /* _FFR_HDR_TYPE */ 371 macdefine(&e->e_macro, A_PERM, 372 macid("{addr_type}"), "h"); 373 (void) rscheck(rs, fvalue, NULL, e, rscheckflags, 3, 374 NULL, e->e_id); 375 } 376 } 377 378 /* 379 ** Drop explicit From: if same as what we would generate. 380 ** This is to make MH (which doesn't always give a full name) 381 ** insert the full name information in all circumstances. 382 */ 383 384 dropfrom = false; 385 p = "resent-from"; 386 if (!bitset(EF_RESENT, e->e_flags)) 387 p += 7; 388 if (!bitset(pflag, CHHDR_DEF) && !headeronly && 389 !bitset(EF_QUEUERUN, e->e_flags) && sm_strcasecmp(fname, p) == 0) 390 { 391 if (tTd(31, 2)) 392 { 393 sm_dprintf("comparing header from (%s) against default (%s or %s)\n", 394 fvalue, e->e_from.q_paddr, e->e_from.q_user); 395 } 396 if (e->e_from.q_paddr != NULL && 397 e->e_from.q_mailer != NULL && 398 bitnset(M_LOCALMAILER, e->e_from.q_mailer->m_flags) && 399 (strcmp(fvalue, e->e_from.q_paddr) == 0 || 400 strcmp(fvalue, e->e_from.q_user) == 0)) 401 dropfrom = true; 402 } 403 404 /* delete default value for this header */ 405 for (hp = hdrp; (h = *hp) != NULL; hp = &h->h_link) 406 { 407 if (sm_strcasecmp(fname, h->h_field) == 0 && 408 !bitset(H_USER, h->h_flags) && 409 !bitset(H_FORCE, h->h_flags)) 410 { 411 if (nullheader) 412 { 413 /* user-supplied value was null */ 414 return 0; 415 } 416 if (dropfrom) 417 { 418 /* make this look like the user entered it */ 419 h->h_flags |= H_USER; 420 return hi->hi_flags; 421 } 422 h->h_value = NULL; 423 if (!cond) 424 { 425 /* copy conditions from default case */ 426 memmove((char *) mopts, (char *) h->h_mflags, 427 sizeof mopts); 428 } 429 h->h_macro = mid; 430 } 431 } 432 433 /* create a new node */ 434 h = (HDR *) sm_rpool_malloc_x(e->e_rpool, sizeof *h); 435 h->h_field = sm_rpool_strdup_x(e->e_rpool, fname); 436 h->h_value = sm_rpool_strdup_x(e->e_rpool, fvalue); 437 h->h_link = NULL; 438 memmove((char *) h->h_mflags, (char *) mopts, sizeof mopts); 439 h->h_macro = mid; 440 *hp = h; 441 h->h_flags = hi->hi_flags; 442 if (bitset(pflag, CHHDR_USER) || bitset(pflag, CHHDR_QUEUE)) 443 h->h_flags |= H_USER; 444 445 /* strip EOH flag if parsing MIME headers */ 446 if (headeronly) 447 h->h_flags &= ~H_EOH; 448 if (bitset(pflag, CHHDR_DEF)) 449 h->h_flags |= H_DEFAULT; 450 if (cond || mid != '\0') 451 h->h_flags |= H_CHECK; 452 453 /* hack to see if this is a new format message */ 454 if (!bitset(pflag, CHHDR_DEF) && !headeronly && 455 bitset(H_RCPT|H_FROM, h->h_flags) && 456 (strchr(fvalue, ',') != NULL || strchr(fvalue, '(') != NULL || 457 strchr(fvalue, '<') != NULL || strchr(fvalue, ';') != NULL)) 458 { 459 e->e_flags &= ~EF_OLDSTYLE; 460 } 461 462 return h->h_flags; 463 } 464 /* 465 ** ALLOCHEADER -- allocate a header entry 466 ** 467 ** Parameters: 468 ** field -- the name of the header field. 469 ** value -- the value of the field. 470 ** flags -- flags to add to h_flags. 471 ** rp -- resource pool for allocations 472 ** 473 ** Returns: 474 ** Pointer to a newly allocated and populated HDR. 475 */ 476 477 static HDR * 478 allocheader(field, value, flags, rp) 479 char *field; 480 char *value; 481 int flags; 482 SM_RPOOL_T *rp; 483 { 484 HDR *h; 485 STAB *s; 486 487 /* find info struct */ 488 s = stab(field, ST_HEADER, ST_FIND); 489 490 /* allocate space for new header */ 491 h = (HDR *) sm_rpool_malloc_x(rp, sizeof *h); 492 h->h_field = field; 493 h->h_value = sm_rpool_strdup_x(rp, value); 494 h->h_flags = flags; 495 if (s != NULL) 496 h->h_flags |= s->s_header.hi_flags; 497 clrbitmap(h->h_mflags); 498 h->h_macro = '\0'; 499 500 return h; 501 } 502 /* 503 ** ADDHEADER -- add a header entry to the end of the queue. 504 ** 505 ** This bypasses the special checking of chompheader. 506 ** 507 ** Parameters: 508 ** field -- the name of the header field. 509 ** value -- the value of the field. 510 ** flags -- flags to add to h_flags. 511 ** e -- envelope. 512 ** 513 ** Returns: 514 ** none. 515 ** 516 ** Side Effects: 517 ** adds the field on the list of headers for this envelope. 518 */ 519 520 void 521 addheader(field, value, flags, e) 522 char *field; 523 char *value; 524 int flags; 525 ENVELOPE *e; 526 { 527 register HDR *h; 528 HDR **hp; 529 HDR **hdrlist = &e->e_header; 530 531 /* find current place in list -- keep back pointer? */ 532 for (hp = hdrlist; (h = *hp) != NULL; hp = &h->h_link) 533 { 534 if (sm_strcasecmp(field, h->h_field) == 0) 535 break; 536 } 537 538 /* allocate space for new header */ 539 h = allocheader(field, value, flags, e->e_rpool); 540 h->h_link = *hp; 541 *hp = h; 542 } 543 /* 544 ** INSHEADER -- insert a header entry at the specified index 545 ** 546 ** This bypasses the special checking of chompheader. 547 ** 548 ** Parameters: 549 ** idx -- index into the header list at which to insert 550 ** field -- the name of the header field. 551 ** value -- the value of the field. 552 ** flags -- flags to add to h_flags. 553 ** e -- envelope. 554 ** 555 ** Returns: 556 ** none. 557 ** 558 ** Side Effects: 559 ** inserts the field on the list of headers for this envelope. 560 */ 561 562 void 563 insheader(idx, field, value, flags, e) 564 int idx; 565 char *field; 566 char *value; 567 int flags; 568 ENVELOPE *e; 569 { 570 HDR *h, *srch, *last = NULL; 571 572 /* allocate space for new header */ 573 h = allocheader(field, value, flags, e->e_rpool); 574 575 /* find insertion position */ 576 for (srch = e->e_header; srch != NULL && idx > 0; 577 srch = srch->h_link, idx--) 578 last = srch; 579 580 if (e->e_header == NULL) 581 { 582 e->e_header = h; 583 h->h_link = NULL; 584 } 585 else if (srch == NULL) 586 { 587 SM_ASSERT(last != NULL); 588 last->h_link = h; 589 h->h_link = NULL; 590 } 591 else 592 { 593 h->h_link = srch->h_link; 594 srch->h_link = h; 595 } 596 } 597 /* 598 ** HVALUE -- return value of a header. 599 ** 600 ** Only "real" fields (i.e., ones that have not been supplied 601 ** as a default) are used. 602 ** 603 ** Parameters: 604 ** field -- the field name. 605 ** header -- the header list. 606 ** 607 ** Returns: 608 ** pointer to the value part. 609 ** NULL if not found. 610 ** 611 ** Side Effects: 612 ** none. 613 */ 614 615 char * 616 hvalue(field, header) 617 char *field; 618 HDR *header; 619 { 620 register HDR *h; 621 622 for (h = header; h != NULL; h = h->h_link) 623 { 624 if (!bitset(H_DEFAULT, h->h_flags) && 625 sm_strcasecmp(h->h_field, field) == 0) 626 return h->h_value; 627 } 628 return NULL; 629 } 630 /* 631 ** ISHEADER -- predicate telling if argument is a header. 632 ** 633 ** A line is a header if it has a single word followed by 634 ** optional white space followed by a colon. 635 ** 636 ** Header fields beginning with two dashes, although technically 637 ** permitted by RFC822, are automatically rejected in order 638 ** to make MIME work out. Without this we could have a technically 639 ** legal header such as ``--"foo:bar"'' that would also be a legal 640 ** MIME separator. 641 ** 642 ** Parameters: 643 ** h -- string to check for possible headerness. 644 ** 645 ** Returns: 646 ** true if h is a header. 647 ** false otherwise. 648 ** 649 ** Side Effects: 650 ** none. 651 */ 652 653 bool 654 isheader(h) 655 char *h; 656 { 657 register char *s = h; 658 659 if (s[0] == '-' && s[1] == '-') 660 return false; 661 662 while (*s > ' ' && *s != ':' && *s != '\0') 663 s++; 664 665 if (h == s) 666 return false; 667 668 /* following technically violates RFC822 */ 669 while (isascii(*s) && isspace(*s)) 670 s++; 671 672 return (*s == ':'); 673 } 674 /* 675 ** EATHEADER -- run through the stored header and extract info. 676 ** 677 ** Parameters: 678 ** e -- the envelope to process. 679 ** full -- if set, do full processing (e.g., compute 680 ** message priority). This should not be set 681 ** when reading a queue file because some info 682 ** needed to compute the priority is wrong. 683 ** log -- call logsender()? 684 ** 685 ** Returns: 686 ** none. 687 ** 688 ** Side Effects: 689 ** Sets a bunch of global variables from information 690 ** in the collected header. 691 */ 692 693 void 694 eatheader(e, full, log) 695 register ENVELOPE *e; 696 bool full; 697 bool log; 698 { 699 register HDR *h; 700 register char *p; 701 int hopcnt = 0; 702 char buf[MAXLINE]; 703 704 /* 705 ** Set up macros for possible expansion in headers. 706 */ 707 708 macdefine(&e->e_macro, A_PERM, 'f', e->e_sender); 709 macdefine(&e->e_macro, A_PERM, 'g', e->e_sender); 710 if (e->e_origrcpt != NULL && *e->e_origrcpt != '\0') 711 macdefine(&e->e_macro, A_PERM, 'u', e->e_origrcpt); 712 else 713 macdefine(&e->e_macro, A_PERM, 'u', NULL); 714 715 /* full name of from person */ 716 p = hvalue("full-name", e->e_header); 717 if (p != NULL) 718 { 719 if (!rfc822_string(p)) 720 { 721 /* 722 ** Quote a full name with special characters 723 ** as a comment so crackaddr() doesn't destroy 724 ** the name portion of the address. 725 */ 726 727 p = addquotes(p, e->e_rpool); 728 } 729 macdefine(&e->e_macro, A_PERM, 'x', p); 730 } 731 732 if (tTd(32, 1)) 733 sm_dprintf("----- collected header -----\n"); 734 e->e_msgid = NULL; 735 for (h = e->e_header; h != NULL; h = h->h_link) 736 { 737 if (tTd(32, 1)) 738 sm_dprintf("%s: ", h->h_field); 739 if (h->h_value == NULL) 740 { 741 if (tTd(32, 1)) 742 sm_dprintf("<NULL>\n"); 743 continue; 744 } 745 746 /* do early binding */ 747 if (bitset(H_DEFAULT, h->h_flags) && 748 !bitset(H_BINDLATE, h->h_flags)) 749 { 750 if (tTd(32, 1)) 751 { 752 sm_dprintf("("); 753 xputs(sm_debug_file(), h->h_value); 754 sm_dprintf(") "); 755 } 756 expand(h->h_value, buf, sizeof buf, e); 757 if (buf[0] != '\0') 758 { 759 if (bitset(H_FROM, h->h_flags)) 760 expand(crackaddr(buf, e), 761 buf, sizeof buf, e); 762 h->h_value = sm_rpool_strdup_x(e->e_rpool, buf); 763 h->h_flags &= ~H_DEFAULT; 764 } 765 } 766 if (tTd(32, 1)) 767 { 768 xputs(sm_debug_file(), h->h_value); 769 sm_dprintf("\n"); 770 } 771 772 /* count the number of times it has been processed */ 773 if (bitset(H_TRACE, h->h_flags)) 774 hopcnt++; 775 776 /* send to this person if we so desire */ 777 if (GrabTo && bitset(H_RCPT, h->h_flags) && 778 !bitset(H_DEFAULT, h->h_flags) && 779 (!bitset(EF_RESENT, e->e_flags) || 780 bitset(H_RESENT, h->h_flags))) 781 { 782 #if 0 783 int saveflags = e->e_flags; 784 #endif /* 0 */ 785 786 (void) sendtolist(denlstring(h->h_value, true, false), 787 NULLADDR, &e->e_sendqueue, 0, e); 788 789 #if 0 790 /* 791 ** Change functionality so a fatal error on an 792 ** address doesn't affect the entire envelope. 793 */ 794 795 /* delete fatal errors generated by this address */ 796 if (!bitset(EF_FATALERRS, saveflags)) 797 e->e_flags &= ~EF_FATALERRS; 798 #endif /* 0 */ 799 } 800 801 /* save the message-id for logging */ 802 p = "resent-message-id"; 803 if (!bitset(EF_RESENT, e->e_flags)) 804 p += 7; 805 if (sm_strcasecmp(h->h_field, p) == 0) 806 { 807 e->e_msgid = h->h_value; 808 while (isascii(*e->e_msgid) && isspace(*e->e_msgid)) 809 e->e_msgid++; 810 macdefine(&e->e_macro, A_PERM, macid("{msg_id}"), 811 e->e_msgid); 812 } 813 } 814 if (tTd(32, 1)) 815 sm_dprintf("----------------------------\n"); 816 817 /* if we are just verifying (that is, sendmail -t -bv), drop out now */ 818 if (OpMode == MD_VERIFY) 819 return; 820 821 /* store hop count */ 822 if (hopcnt > e->e_hopcount) 823 { 824 e->e_hopcount = hopcnt; 825 (void) sm_snprintf(buf, sizeof buf, "%d", e->e_hopcount); 826 macdefine(&e->e_macro, A_TEMP, 'c', buf); 827 } 828 829 /* message priority */ 830 p = hvalue("precedence", e->e_header); 831 if (p != NULL) 832 e->e_class = priencode(p); 833 if (e->e_class < 0) 834 e->e_timeoutclass = TOC_NONURGENT; 835 else if (e->e_class > 0) 836 e->e_timeoutclass = TOC_URGENT; 837 if (full) 838 { 839 e->e_msgpriority = e->e_msgsize 840 - e->e_class * WkClassFact 841 + e->e_nrcpts * WkRecipFact; 842 } 843 844 /* check for DSN to properly set e_timeoutclass */ 845 p = hvalue("content-type", e->e_header); 846 if (p != NULL) 847 { 848 bool oldsupr; 849 char **pvp; 850 char pvpbuf[MAXLINE]; 851 extern unsigned char MimeTokenTab[256]; 852 853 /* tokenize header */ 854 oldsupr = SuprErrs; 855 SuprErrs = true; 856 pvp = prescan(p, '\0', pvpbuf, sizeof pvpbuf, NULL, 857 MimeTokenTab, false); 858 SuprErrs = oldsupr; 859 860 /* Check if multipart/report */ 861 if (pvp != NULL && pvp[0] != NULL && 862 pvp[1] != NULL && pvp[2] != NULL && 863 sm_strcasecmp(*pvp++, "multipart") == 0 && 864 strcmp(*pvp++, "/") == 0 && 865 sm_strcasecmp(*pvp++, "report") == 0) 866 { 867 /* Look for report-type=delivery-status */ 868 while (*pvp != NULL) 869 { 870 /* skip to semicolon separator */ 871 while (*pvp != NULL && strcmp(*pvp, ";") != 0) 872 pvp++; 873 874 /* skip semicolon */ 875 if (*pvp++ == NULL || *pvp == NULL) 876 break; 877 878 /* look for report-type */ 879 if (sm_strcasecmp(*pvp++, "report-type") != 0) 880 continue; 881 882 /* skip equal */ 883 if (*pvp == NULL || strcmp(*pvp, "=") != 0) 884 continue; 885 886 /* check value */ 887 if (*++pvp != NULL && 888 sm_strcasecmp(*pvp, 889 "delivery-status") == 0) 890 e->e_timeoutclass = TOC_DSN; 891 892 /* found report-type, no need to continue */ 893 break; 894 } 895 } 896 } 897 898 /* message timeout priority */ 899 p = hvalue("priority", e->e_header); 900 if (p != NULL) 901 { 902 /* (this should be in the configuration file) */ 903 if (sm_strcasecmp(p, "urgent") == 0) 904 e->e_timeoutclass = TOC_URGENT; 905 else if (sm_strcasecmp(p, "normal") == 0) 906 e->e_timeoutclass = TOC_NORMAL; 907 else if (sm_strcasecmp(p, "non-urgent") == 0) 908 e->e_timeoutclass = TOC_NONURGENT; 909 else if (bitset(EF_RESPONSE, e->e_flags)) 910 e->e_timeoutclass = TOC_DSN; 911 } 912 else if (bitset(EF_RESPONSE, e->e_flags)) 913 e->e_timeoutclass = TOC_DSN; 914 915 /* date message originated */ 916 p = hvalue("posted-date", e->e_header); 917 if (p == NULL) 918 p = hvalue("date", e->e_header); 919 if (p != NULL) 920 macdefine(&e->e_macro, A_PERM, 'a', p); 921 922 /* check to see if this is a MIME message */ 923 if ((e->e_bodytype != NULL && 924 sm_strcasecmp(e->e_bodytype, "8BITMIME") == 0) || 925 hvalue("MIME-Version", e->e_header) != NULL) 926 { 927 e->e_flags |= EF_IS_MIME; 928 if (HasEightBits) 929 e->e_bodytype = "8BITMIME"; 930 } 931 else if ((p = hvalue("Content-Type", e->e_header)) != NULL) 932 { 933 /* this may be an RFC 1049 message */ 934 p = strpbrk(p, ";/"); 935 if (p == NULL || *p == ';') 936 { 937 /* yep, it is */ 938 e->e_flags |= EF_DONT_MIME; 939 } 940 } 941 942 /* 943 ** From person in antiquated ARPANET mode 944 ** required by UK Grey Book e-mail gateways (sigh) 945 */ 946 947 if (OpMode == MD_ARPAFTP) 948 { 949 register struct hdrinfo *hi; 950 951 for (hi = HdrInfo; hi->hi_field != NULL; hi++) 952 { 953 if (bitset(H_FROM, hi->hi_flags) && 954 (!bitset(H_RESENT, hi->hi_flags) || 955 bitset(EF_RESENT, e->e_flags)) && 956 (p = hvalue(hi->hi_field, e->e_header)) != NULL) 957 break; 958 } 959 if (hi->hi_field != NULL) 960 { 961 if (tTd(32, 2)) 962 sm_dprintf("eatheader: setsender(*%s == %s)\n", 963 hi->hi_field, p); 964 setsender(p, e, NULL, '\0', true); 965 } 966 } 967 968 /* 969 ** Log collection information. 970 */ 971 972 if (log && bitset(EF_LOGSENDER, e->e_flags) && LogLevel > 4) 973 { 974 logsender(e, e->e_msgid); 975 e->e_flags &= ~EF_LOGSENDER; 976 } 977 } 978 /* 979 ** LOGSENDER -- log sender information 980 ** 981 ** Parameters: 982 ** e -- the envelope to log 983 ** msgid -- the message id 984 ** 985 ** Returns: 986 ** none 987 */ 988 989 void 990 logsender(e, msgid) 991 register ENVELOPE *e; 992 char *msgid; 993 { 994 char *name; 995 register char *sbp; 996 register char *p; 997 int l; 998 char hbuf[MAXNAME + 1]; 999 char sbuf[MAXLINE + 1]; 1000 char mbuf[MAXNAME + 1]; 1001 1002 /* don't allow newlines in the message-id */ 1003 /* XXX do we still need this? sm_syslog() replaces control chars */ 1004 if (msgid != NULL) 1005 { 1006 l = strlen(msgid); 1007 if (l > sizeof mbuf - 1) 1008 l = sizeof mbuf - 1; 1009 memmove(mbuf, msgid, l); 1010 mbuf[l] = '\0'; 1011 p = mbuf; 1012 while ((p = strchr(p, '\n')) != NULL) 1013 *p++ = ' '; 1014 } 1015 1016 if (bitset(EF_RESPONSE, e->e_flags)) 1017 name = "[RESPONSE]"; 1018 else if ((name = macvalue('_', e)) != NULL) 1019 /* EMPTY */ 1020 ; 1021 else if (RealHostName == NULL) 1022 name = "localhost"; 1023 else if (RealHostName[0] == '[') 1024 name = RealHostName; 1025 else 1026 { 1027 name = hbuf; 1028 (void) sm_snprintf(hbuf, sizeof hbuf, "%.80s", RealHostName); 1029 if (RealHostAddr.sa.sa_family != 0) 1030 { 1031 p = &hbuf[strlen(hbuf)]; 1032 (void) sm_snprintf(p, SPACELEFT(hbuf, p), 1033 " (%.100s)", 1034 anynet_ntoa(&RealHostAddr)); 1035 } 1036 } 1037 1038 /* some versions of syslog only take 5 printf args */ 1039 #if (SYSLOG_BUFSIZE) >= 256 1040 sbp = sbuf; 1041 (void) sm_snprintf(sbp, SPACELEFT(sbuf, sbp), 1042 "from=%.200s, size=%ld, class=%d, nrcpts=%d", 1043 e->e_from.q_paddr == NULL ? "<NONE>" : e->e_from.q_paddr, 1044 e->e_msgsize, e->e_class, e->e_nrcpts); 1045 sbp += strlen(sbp); 1046 if (msgid != NULL) 1047 { 1048 (void) sm_snprintf(sbp, SPACELEFT(sbuf, sbp), 1049 ", msgid=%.100s", mbuf); 1050 sbp += strlen(sbp); 1051 } 1052 if (e->e_bodytype != NULL) 1053 { 1054 (void) sm_snprintf(sbp, SPACELEFT(sbuf, sbp), 1055 ", bodytype=%.20s", e->e_bodytype); 1056 sbp += strlen(sbp); 1057 } 1058 p = macvalue('r', e); 1059 if (p != NULL) 1060 { 1061 (void) sm_snprintf(sbp, SPACELEFT(sbuf, sbp), 1062 ", proto=%.20s", p); 1063 sbp += strlen(sbp); 1064 } 1065 p = macvalue(macid("{daemon_name}"), e); 1066 if (p != NULL) 1067 { 1068 (void) sm_snprintf(sbp, SPACELEFT(sbuf, sbp), 1069 ", daemon=%.20s", p); 1070 sbp += strlen(sbp); 1071 } 1072 sm_syslog(LOG_INFO, e->e_id, "%.850s, relay=%s", sbuf, name); 1073 1074 #else /* (SYSLOG_BUFSIZE) >= 256 */ 1075 1076 sm_syslog(LOG_INFO, e->e_id, 1077 "from=%s", 1078 e->e_from.q_paddr == NULL ? "<NONE>" 1079 : shortenstring(e->e_from.q_paddr, 1080 83)); 1081 sm_syslog(LOG_INFO, e->e_id, 1082 "size=%ld, class=%ld, nrcpts=%d", 1083 e->e_msgsize, e->e_class, e->e_nrcpts); 1084 if (msgid != NULL) 1085 sm_syslog(LOG_INFO, e->e_id, 1086 "msgid=%s", 1087 shortenstring(mbuf, 83)); 1088 sbp = sbuf; 1089 *sbp = '\0'; 1090 if (e->e_bodytype != NULL) 1091 { 1092 (void) sm_snprintf(sbp, SPACELEFT(sbuf, sbp), 1093 "bodytype=%.20s, ", e->e_bodytype); 1094 sbp += strlen(sbp); 1095 } 1096 p = macvalue('r', e); 1097 if (p != NULL) 1098 { 1099 (void) sm_snprintf(sbp, SPACELEFT(sbuf, sbp), 1100 "proto=%.20s, ", p); 1101 sbp += strlen(sbp); 1102 } 1103 sm_syslog(LOG_INFO, e->e_id, 1104 "%.400srelay=%s", sbuf, name); 1105 #endif /* (SYSLOG_BUFSIZE) >= 256 */ 1106 } 1107 /* 1108 ** PRIENCODE -- encode external priority names into internal values. 1109 ** 1110 ** Parameters: 1111 ** p -- priority in ascii. 1112 ** 1113 ** Returns: 1114 ** priority as a numeric level. 1115 ** 1116 ** Side Effects: 1117 ** none. 1118 */ 1119 1120 static int 1121 priencode(p) 1122 char *p; 1123 { 1124 register int i; 1125 1126 for (i = 0; i < NumPriorities; i++) 1127 { 1128 if (sm_strcasecmp(p, Priorities[i].pri_name) == 0) 1129 return Priorities[i].pri_val; 1130 } 1131 1132 /* unknown priority */ 1133 return 0; 1134 } 1135 /* 1136 ** CRACKADDR -- parse an address and turn it into a macro 1137 ** 1138 ** This doesn't actually parse the address -- it just extracts 1139 ** it and replaces it with "$g". The parse is totally ad hoc 1140 ** and isn't even guaranteed to leave something syntactically 1141 ** identical to what it started with. However, it does leave 1142 ** something semantically identical if possible, else at least 1143 ** syntactically correct. 1144 ** 1145 ** For example, it changes "Real Name <real@example.com> (Comment)" 1146 ** to "Real Name <$g> (Comment)". 1147 ** 1148 ** This algorithm has been cleaned up to handle a wider range 1149 ** of cases -- notably quoted and backslash escaped strings. 1150 ** This modification makes it substantially better at preserving 1151 ** the original syntax. 1152 ** 1153 ** Parameters: 1154 ** addr -- the address to be cracked. 1155 ** e -- the current envelope. 1156 ** 1157 ** Returns: 1158 ** a pointer to the new version. 1159 ** 1160 ** Side Effects: 1161 ** none. 1162 ** 1163 ** Warning: 1164 ** The return value is saved in local storage and should 1165 ** be copied if it is to be reused. 1166 */ 1167 1168 #define SM_HAVE_ROOM ((bp < buflim) && (buflim <= bufend)) 1169 1170 /* 1171 ** Append a character to bp if we have room. 1172 ** If not, punt and return $g. 1173 */ 1174 1175 #define SM_APPEND_CHAR(c) \ 1176 do \ 1177 { \ 1178 if (SM_HAVE_ROOM) \ 1179 *bp++ = (c); \ 1180 else \ 1181 goto returng; \ 1182 } while (0) 1183 1184 #if MAXNAME < 10 1185 ERROR MAXNAME must be at least 10 1186 #endif /* MAXNAME < 10 */ 1187 1188 char * 1189 crackaddr(addr, e) 1190 register char *addr; 1191 ENVELOPE *e; 1192 { 1193 register char *p; 1194 register char c; 1195 int cmtlev; /* comment level in input string */ 1196 int realcmtlev; /* comment level in output string */ 1197 int anglelev; /* angle level in input string */ 1198 int copylev; /* 0 == in address, >0 copying */ 1199 int bracklev; /* bracket level for IPv6 addr check */ 1200 bool addangle; /* put closing angle in output */ 1201 bool qmode; /* quoting in original string? */ 1202 bool realqmode; /* quoting in output string? */ 1203 bool putgmac = false; /* already wrote $g */ 1204 bool quoteit = false; /* need to quote next character */ 1205 bool gotangle = false; /* found first '<' */ 1206 bool gotcolon = false; /* found a ':' */ 1207 register char *bp; 1208 char *buflim; 1209 char *bufhead; 1210 char *addrhead; 1211 char *bufend; 1212 static char buf[MAXNAME + 1]; 1213 1214 if (tTd(33, 1)) 1215 sm_dprintf("crackaddr(%s)\n", addr); 1216 1217 /* strip leading spaces */ 1218 while (*addr != '\0' && isascii(*addr) && isspace(*addr)) 1219 addr++; 1220 1221 /* 1222 ** Start by assuming we have no angle brackets. This will be 1223 ** adjusted later if we find them. 1224 */ 1225 1226 buflim = bufend = &buf[sizeof(buf) - 1]; 1227 bp = bufhead = buf; 1228 p = addrhead = addr; 1229 copylev = anglelev = cmtlev = realcmtlev = 0; 1230 bracklev = 0; 1231 qmode = realqmode = addangle = false; 1232 1233 while ((c = *p++) != '\0') 1234 { 1235 /* 1236 ** Try to keep legal syntax using spare buffer space 1237 ** (maintained by buflim). 1238 */ 1239 1240 if (copylev > 0) 1241 SM_APPEND_CHAR(c); 1242 1243 /* check for backslash escapes */ 1244 if (c == '\\') 1245 { 1246 /* arrange to quote the address */ 1247 if (cmtlev <= 0 && !qmode) 1248 quoteit = true; 1249 1250 if ((c = *p++) == '\0') 1251 { 1252 /* too far */ 1253 p--; 1254 goto putg; 1255 } 1256 if (copylev > 0) 1257 SM_APPEND_CHAR(c); 1258 goto putg; 1259 } 1260 1261 /* check for quoted strings */ 1262 if (c == '"' && cmtlev <= 0) 1263 { 1264 qmode = !qmode; 1265 if (copylev > 0 && SM_HAVE_ROOM) 1266 { 1267 if (realqmode) 1268 buflim--; 1269 else 1270 buflim++; 1271 realqmode = !realqmode; 1272 } 1273 continue; 1274 } 1275 if (qmode) 1276 goto putg; 1277 1278 /* check for comments */ 1279 if (c == '(') 1280 { 1281 cmtlev++; 1282 1283 /* allow space for closing paren */ 1284 if (SM_HAVE_ROOM) 1285 { 1286 buflim--; 1287 realcmtlev++; 1288 if (copylev++ <= 0) 1289 { 1290 if (bp != bufhead) 1291 SM_APPEND_CHAR(' '); 1292 SM_APPEND_CHAR(c); 1293 } 1294 } 1295 } 1296 if (cmtlev > 0) 1297 { 1298 if (c == ')') 1299 { 1300 cmtlev--; 1301 copylev--; 1302 if (SM_HAVE_ROOM) 1303 { 1304 realcmtlev--; 1305 buflim++; 1306 } 1307 } 1308 continue; 1309 } 1310 else if (c == ')') 1311 { 1312 /* syntax error: unmatched ) */ 1313 if (copylev > 0 && SM_HAVE_ROOM && bp > bufhead) 1314 bp--; 1315 } 1316 1317 /* count nesting on [ ... ] (for IPv6 domain literals) */ 1318 if (c == '[') 1319 bracklev++; 1320 else if (c == ']') 1321 bracklev--; 1322 1323 /* check for group: list; syntax */ 1324 if (c == ':' && anglelev <= 0 && bracklev <= 0 && 1325 !gotcolon && !ColonOkInAddr) 1326 { 1327 register char *q; 1328 1329 /* 1330 ** Check for DECnet phase IV ``::'' (host::user) 1331 ** or DECnet phase V ``:.'' syntaxes. The latter 1332 ** covers ``user@DEC:.tay.myhost'' and 1333 ** ``DEC:.tay.myhost::user'' syntaxes (bletch). 1334 */ 1335 1336 if (*p == ':' || *p == '.') 1337 { 1338 if (cmtlev <= 0 && !qmode) 1339 quoteit = true; 1340 if (copylev > 0) 1341 { 1342 SM_APPEND_CHAR(c); 1343 SM_APPEND_CHAR(*p); 1344 } 1345 p++; 1346 goto putg; 1347 } 1348 1349 gotcolon = true; 1350 1351 bp = bufhead; 1352 if (quoteit) 1353 { 1354 SM_APPEND_CHAR('"'); 1355 1356 /* back up over the ':' and any spaces */ 1357 --p; 1358 while (p > addr && 1359 isascii(*--p) && isspace(*p)) 1360 continue; 1361 p++; 1362 } 1363 for (q = addrhead; q < p; ) 1364 { 1365 c = *q++; 1366 if (quoteit && c == '"') 1367 SM_APPEND_CHAR('\\'); 1368 SM_APPEND_CHAR(c); 1369 } 1370 if (quoteit) 1371 { 1372 if (bp == &bufhead[1]) 1373 bp--; 1374 else 1375 SM_APPEND_CHAR('"'); 1376 while ((c = *p++) != ':') 1377 SM_APPEND_CHAR(c); 1378 SM_APPEND_CHAR(c); 1379 } 1380 1381 /* any trailing white space is part of group: */ 1382 while (isascii(*p) && isspace(*p)) 1383 { 1384 SM_APPEND_CHAR(*p); 1385 p++; 1386 } 1387 copylev = 0; 1388 putgmac = quoteit = false; 1389 bufhead = bp; 1390 addrhead = p; 1391 continue; 1392 } 1393 1394 if (c == ';' && copylev <= 0 && !ColonOkInAddr) 1395 SM_APPEND_CHAR(c); 1396 1397 /* check for characters that may have to be quoted */ 1398 if (strchr(MustQuoteChars, c) != NULL) 1399 { 1400 /* 1401 ** If these occur as the phrase part of a <> 1402 ** construct, but are not inside of () or already 1403 ** quoted, they will have to be quoted. Note that 1404 ** now (but don't actually do the quoting). 1405 */ 1406 1407 if (cmtlev <= 0 && !qmode) 1408 quoteit = true; 1409 } 1410 1411 /* check for angle brackets */ 1412 if (c == '<') 1413 { 1414 register char *q; 1415 1416 /* assume first of two angles is bogus */ 1417 if (gotangle) 1418 quoteit = true; 1419 gotangle = true; 1420 1421 /* oops -- have to change our mind */ 1422 anglelev = 1; 1423 if (SM_HAVE_ROOM) 1424 { 1425 if (!addangle) 1426 buflim--; 1427 addangle = true; 1428 } 1429 1430 bp = bufhead; 1431 if (quoteit) 1432 { 1433 SM_APPEND_CHAR('"'); 1434 1435 /* back up over the '<' and any spaces */ 1436 --p; 1437 while (p > addr && 1438 isascii(*--p) && isspace(*p)) 1439 continue; 1440 p++; 1441 } 1442 for (q = addrhead; q < p; ) 1443 { 1444 c = *q++; 1445 if (quoteit && c == '"') 1446 { 1447 SM_APPEND_CHAR('\\'); 1448 SM_APPEND_CHAR(c); 1449 } 1450 else 1451 SM_APPEND_CHAR(c); 1452 } 1453 if (quoteit) 1454 { 1455 if (bp == &buf[1]) 1456 bp--; 1457 else 1458 SM_APPEND_CHAR('"'); 1459 while ((c = *p++) != '<') 1460 SM_APPEND_CHAR(c); 1461 SM_APPEND_CHAR(c); 1462 } 1463 copylev = 0; 1464 putgmac = quoteit = false; 1465 continue; 1466 } 1467 1468 if (c == '>') 1469 { 1470 if (anglelev > 0) 1471 { 1472 anglelev--; 1473 if (SM_HAVE_ROOM) 1474 { 1475 if (addangle) 1476 buflim++; 1477 addangle = false; 1478 } 1479 } 1480 else if (SM_HAVE_ROOM) 1481 { 1482 /* syntax error: unmatched > */ 1483 if (copylev > 0 && bp > bufhead) 1484 bp--; 1485 quoteit = true; 1486 continue; 1487 } 1488 if (copylev++ <= 0) 1489 SM_APPEND_CHAR(c); 1490 continue; 1491 } 1492 1493 /* must be a real address character */ 1494 putg: 1495 if (copylev <= 0 && !putgmac) 1496 { 1497 if (bp > buf && bp[-1] == ')') 1498 SM_APPEND_CHAR(' '); 1499 SM_APPEND_CHAR(MACROEXPAND); 1500 SM_APPEND_CHAR('g'); 1501 putgmac = true; 1502 } 1503 } 1504 1505 /* repair any syntactic damage */ 1506 if (realqmode && bp < bufend) 1507 *bp++ = '"'; 1508 while (realcmtlev-- > 0 && bp < bufend) 1509 *bp++ = ')'; 1510 if (addangle && bp < bufend) 1511 *bp++ = '>'; 1512 *bp = '\0'; 1513 if (bp < bufend) 1514 goto success; 1515 1516 returng: 1517 /* String too long, punt */ 1518 buf[0] = '<'; 1519 buf[1] = MACROEXPAND; 1520 buf[2]= 'g'; 1521 buf[3] = '>'; 1522 buf[4]= '\0'; 1523 sm_syslog(LOG_ALERT, e->e_id, 1524 "Dropped invalid comments from header address"); 1525 1526 success: 1527 if (tTd(33, 1)) 1528 { 1529 sm_dprintf("crackaddr=>`"); 1530 xputs(sm_debug_file(), buf); 1531 sm_dprintf("'\n"); 1532 } 1533 return buf; 1534 } 1535 /* 1536 ** PUTHEADER -- put the header part of a message from the in-core copy 1537 ** 1538 ** Parameters: 1539 ** mci -- the connection information. 1540 ** hdr -- the header to put. 1541 ** e -- envelope to use. 1542 ** flags -- MIME conversion flags. 1543 ** 1544 ** Returns: 1545 ** none. 1546 ** 1547 ** Side Effects: 1548 ** none. 1549 */ 1550 1551 void 1552 putheader(mci, hdr, e, flags) 1553 register MCI *mci; 1554 HDR *hdr; 1555 register ENVELOPE *e; 1556 int flags; 1557 { 1558 register HDR *h; 1559 char buf[SM_MAX(MAXLINE,BUFSIZ)]; 1560 char obuf[MAXLINE]; 1561 1562 if (tTd(34, 1)) 1563 sm_dprintf("--- putheader, mailer = %s ---\n", 1564 mci->mci_mailer->m_name); 1565 1566 /* 1567 ** If we're in MIME mode, we're not really in the header of the 1568 ** message, just the header of one of the parts of the body of 1569 ** the message. Therefore MCIF_INHEADER should not be turned on. 1570 */ 1571 1572 if (!bitset(MCIF_INMIME, mci->mci_flags)) 1573 mci->mci_flags |= MCIF_INHEADER; 1574 1575 for (h = hdr; h != NULL; h = h->h_link) 1576 { 1577 register char *p = h->h_value; 1578 char *q; 1579 1580 if (tTd(34, 11)) 1581 { 1582 sm_dprintf(" %s: ", h->h_field); 1583 xputs(sm_debug_file(), p); 1584 } 1585 1586 /* Skip empty headers */ 1587 if (h->h_value == NULL) 1588 continue; 1589 1590 /* heuristic shortening of MIME fields to avoid MUA overflows */ 1591 if (MaxMimeFieldLength > 0 && 1592 wordinclass(h->h_field, 1593 macid("{checkMIMEFieldHeaders}"))) 1594 { 1595 size_t len; 1596 1597 len = fix_mime_header(h, e); 1598 if (len > 0) 1599 { 1600 sm_syslog(LOG_ALERT, e->e_id, 1601 "Truncated MIME %s header due to field size (length = %ld) (possible attack)", 1602 h->h_field, (unsigned long) len); 1603 if (tTd(34, 11)) 1604 sm_dprintf(" truncated MIME %s header due to field size (length = %ld) (possible attack)\n", 1605 h->h_field, 1606 (unsigned long) len); 1607 } 1608 } 1609 1610 if (MaxMimeHeaderLength > 0 && 1611 wordinclass(h->h_field, 1612 macid("{checkMIMETextHeaders}"))) 1613 { 1614 size_t len; 1615 1616 len = strlen(h->h_value); 1617 if (len > (size_t) MaxMimeHeaderLength) 1618 { 1619 h->h_value[MaxMimeHeaderLength - 1] = '\0'; 1620 sm_syslog(LOG_ALERT, e->e_id, 1621 "Truncated long MIME %s header (length = %ld) (possible attack)", 1622 h->h_field, (unsigned long) len); 1623 if (tTd(34, 11)) 1624 sm_dprintf(" truncated long MIME %s header (length = %ld) (possible attack)\n", 1625 h->h_field, 1626 (unsigned long) len); 1627 } 1628 } 1629 1630 if (MaxMimeHeaderLength > 0 && 1631 wordinclass(h->h_field, 1632 macid("{checkMIMEHeaders}"))) 1633 { 1634 size_t len; 1635 1636 len = strlen(h->h_value); 1637 if (shorten_rfc822_string(h->h_value, 1638 MaxMimeHeaderLength)) 1639 { 1640 if (len < MaxMimeHeaderLength) 1641 { 1642 /* we only rebalanced a bogus header */ 1643 sm_syslog(LOG_ALERT, e->e_id, 1644 "Fixed MIME %s header (possible attack)", 1645 h->h_field); 1646 if (tTd(34, 11)) 1647 sm_dprintf(" fixed MIME %s header (possible attack)\n", 1648 h->h_field); 1649 } 1650 else 1651 { 1652 /* we actually shortened header */ 1653 sm_syslog(LOG_ALERT, e->e_id, 1654 "Truncated long MIME %s header (length = %ld) (possible attack)", 1655 h->h_field, 1656 (unsigned long) len); 1657 if (tTd(34, 11)) 1658 sm_dprintf(" truncated long MIME %s header (length = %ld) (possible attack)\n", 1659 h->h_field, 1660 (unsigned long) len); 1661 } 1662 } 1663 } 1664 1665 /* 1666 ** Suppress Content-Transfer-Encoding: if we are MIMEing 1667 ** and we are potentially converting from 8 bit to 7 bit 1668 ** MIME. If converting, add a new CTE header in 1669 ** mime8to7(). 1670 */ 1671 1672 if (bitset(H_CTE, h->h_flags) && 1673 bitset(MCIF_CVT8TO7|MCIF_CVT7TO8|MCIF_INMIME, 1674 mci->mci_flags) && 1675 !bitset(M87F_NO8TO7, flags)) 1676 { 1677 if (tTd(34, 11)) 1678 sm_dprintf(" (skipped (content-transfer-encoding))\n"); 1679 continue; 1680 } 1681 1682 if (bitset(MCIF_INMIME, mci->mci_flags)) 1683 { 1684 if (tTd(34, 11)) 1685 sm_dprintf("\n"); 1686 put_vanilla_header(h, p, mci); 1687 continue; 1688 } 1689 1690 if (bitset(H_CHECK|H_ACHECK, h->h_flags) && 1691 !bitintersect(h->h_mflags, mci->mci_mailer->m_flags) && 1692 (h->h_macro == '\0' || 1693 (q = macvalue(bitidx(h->h_macro), e)) == NULL || 1694 *q == '\0')) 1695 { 1696 if (tTd(34, 11)) 1697 sm_dprintf(" (skipped)\n"); 1698 continue; 1699 } 1700 1701 /* handle Resent-... headers specially */ 1702 if (bitset(H_RESENT, h->h_flags) && !bitset(EF_RESENT, e->e_flags)) 1703 { 1704 if (tTd(34, 11)) 1705 sm_dprintf(" (skipped (resent))\n"); 1706 continue; 1707 } 1708 1709 /* suppress return receipts if requested */ 1710 if (bitset(H_RECEIPTTO, h->h_flags) && 1711 (RrtImpliesDsn || bitset(EF_NORECEIPT, e->e_flags))) 1712 { 1713 if (tTd(34, 11)) 1714 sm_dprintf(" (skipped (receipt))\n"); 1715 continue; 1716 } 1717 1718 /* macro expand value if generated internally */ 1719 if (bitset(H_DEFAULT, h->h_flags) || 1720 bitset(H_BINDLATE, h->h_flags)) 1721 { 1722 expand(p, buf, sizeof buf, e); 1723 p = buf; 1724 if (*p == '\0') 1725 { 1726 if (tTd(34, 11)) 1727 sm_dprintf(" (skipped -- null value)\n"); 1728 continue; 1729 } 1730 } 1731 1732 if (bitset(H_BCC, h->h_flags)) 1733 { 1734 /* Bcc: field -- either truncate or delete */ 1735 if (bitset(EF_DELETE_BCC, e->e_flags)) 1736 { 1737 if (tTd(34, 11)) 1738 sm_dprintf(" (skipped -- bcc)\n"); 1739 } 1740 else 1741 { 1742 /* no other recipient headers: truncate value */ 1743 (void) sm_strlcpyn(obuf, sizeof obuf, 2, 1744 h->h_field, ":"); 1745 putline(obuf, mci); 1746 } 1747 continue; 1748 } 1749 1750 if (tTd(34, 11)) 1751 sm_dprintf("\n"); 1752 1753 if (bitset(H_FROM|H_RCPT, h->h_flags)) 1754 { 1755 /* address field */ 1756 bool oldstyle = bitset(EF_OLDSTYLE, e->e_flags); 1757 1758 if (bitset(H_FROM, h->h_flags)) 1759 oldstyle = false; 1760 commaize(h, p, oldstyle, mci, e); 1761 } 1762 else 1763 { 1764 put_vanilla_header(h, p, mci); 1765 } 1766 } 1767 1768 /* 1769 ** If we are converting this to a MIME message, add the 1770 ** MIME headers (but not in MIME mode!). 1771 */ 1772 1773 #if MIME8TO7 1774 if (bitset(MM_MIME8BIT, MimeMode) && 1775 bitset(EF_HAS8BIT, e->e_flags) && 1776 !bitset(EF_DONT_MIME, e->e_flags) && 1777 !bitnset(M_8BITS, mci->mci_mailer->m_flags) && 1778 !bitset(MCIF_CVT8TO7|MCIF_CVT7TO8|MCIF_INMIME, mci->mci_flags) && 1779 hvalue("MIME-Version", e->e_header) == NULL) 1780 { 1781 putline("MIME-Version: 1.0", mci); 1782 if (hvalue("Content-Type", e->e_header) == NULL) 1783 { 1784 (void) sm_snprintf(obuf, sizeof obuf, 1785 "Content-Type: text/plain; charset=%s", 1786 defcharset(e)); 1787 putline(obuf, mci); 1788 } 1789 if (hvalue("Content-Transfer-Encoding", e->e_header) == NULL) 1790 putline("Content-Transfer-Encoding: 8bit", mci); 1791 } 1792 #endif /* MIME8TO7 */ 1793 } 1794 /* 1795 ** PUT_VANILLA_HEADER -- output a fairly ordinary header 1796 ** 1797 ** Parameters: 1798 ** h -- the structure describing this header 1799 ** v -- the value of this header 1800 ** mci -- the connection info for output 1801 ** 1802 ** Returns: 1803 ** none. 1804 */ 1805 1806 static void 1807 put_vanilla_header(h, v, mci) 1808 HDR *h; 1809 char *v; 1810 MCI *mci; 1811 { 1812 register char *nlp; 1813 register char *obp; 1814 int putflags; 1815 char obuf[MAXLINE]; 1816 1817 putflags = PXLF_HEADER; 1818 if (bitnset(M_7BITHDRS, mci->mci_mailer->m_flags)) 1819 putflags |= PXLF_STRIP8BIT; 1820 (void) sm_snprintf(obuf, sizeof obuf, "%.200s: ", h->h_field); 1821 obp = obuf + strlen(obuf); 1822 while ((nlp = strchr(v, '\n')) != NULL) 1823 { 1824 int l; 1825 1826 l = nlp - v; 1827 1828 /* 1829 ** XXX This is broken for SPACELEFT()==0 1830 ** However, SPACELEFT() is always > 0 unless MAXLINE==1. 1831 */ 1832 1833 if (SPACELEFT(obuf, obp) - 1 < (size_t) l) 1834 l = SPACELEFT(obuf, obp) - 1; 1835 1836 (void) sm_snprintf(obp, SPACELEFT(obuf, obp), "%.*s", l, v); 1837 putxline(obuf, strlen(obuf), mci, putflags); 1838 v += l + 1; 1839 obp = obuf; 1840 if (*v != ' ' && *v != '\t') 1841 *obp++ = ' '; 1842 } 1843 1844 /* XXX This is broken for SPACELEFT()==0 */ 1845 (void) sm_snprintf(obp, SPACELEFT(obuf, obp), "%.*s", 1846 (int) (SPACELEFT(obuf, obp) - 1), v); 1847 putxline(obuf, strlen(obuf), mci, putflags); 1848 } 1849 /* 1850 ** COMMAIZE -- output a header field, making a comma-translated list. 1851 ** 1852 ** Parameters: 1853 ** h -- the header field to output. 1854 ** p -- the value to put in it. 1855 ** oldstyle -- true if this is an old style header. 1856 ** mci -- the connection information. 1857 ** e -- the envelope containing the message. 1858 ** 1859 ** Returns: 1860 ** none. 1861 ** 1862 ** Side Effects: 1863 ** outputs "p" to file "fp". 1864 */ 1865 1866 void 1867 commaize(h, p, oldstyle, mci, e) 1868 register HDR *h; 1869 register char *p; 1870 bool oldstyle; 1871 register MCI *mci; 1872 register ENVELOPE *e; 1873 { 1874 register char *obp; 1875 int opos; 1876 int omax; 1877 bool firstone = true; 1878 int putflags = PXLF_HEADER; 1879 char **res; 1880 char obuf[MAXLINE + 3]; 1881 1882 /* 1883 ** Output the address list translated by the 1884 ** mailer and with commas. 1885 */ 1886 1887 if (tTd(14, 2)) 1888 sm_dprintf("commaize(%s: %s)\n", h->h_field, p); 1889 1890 if (bitnset(M_7BITHDRS, mci->mci_mailer->m_flags)) 1891 putflags |= PXLF_STRIP8BIT; 1892 1893 obp = obuf; 1894 (void) sm_snprintf(obp, SPACELEFT(obuf, obp), "%.200s: ", 1895 h->h_field); 1896 1897 /* opos = strlen(obp); */ 1898 opos = strlen(h->h_field) + 2; 1899 if (opos > 202) 1900 opos = 202; 1901 obp += opos; 1902 omax = mci->mci_mailer->m_linelimit - 2; 1903 if (omax < 0 || omax > 78) 1904 omax = 78; 1905 1906 /* 1907 ** Run through the list of values. 1908 */ 1909 1910 while (*p != '\0') 1911 { 1912 register char *name; 1913 register int c; 1914 char savechar; 1915 int flags; 1916 auto int status; 1917 1918 /* 1919 ** Find the end of the name. New style names 1920 ** end with a comma, old style names end with 1921 ** a space character. However, spaces do not 1922 ** necessarily delimit an old-style name -- at 1923 ** signs mean keep going. 1924 */ 1925 1926 /* find end of name */ 1927 while ((isascii(*p) && isspace(*p)) || *p == ',') 1928 p++; 1929 name = p; 1930 res = NULL; 1931 for (;;) 1932 { 1933 auto char *oldp; 1934 char pvpbuf[PSBUFSIZE]; 1935 1936 res = prescan(p, oldstyle ? ' ' : ',', pvpbuf, 1937 sizeof pvpbuf, &oldp, NULL, false); 1938 p = oldp; 1939 #if _FFR_IGNORE_BOGUS_ADDR 1940 /* ignore addresses that can't be parsed */ 1941 if (res == NULL) 1942 { 1943 name = p; 1944 continue; 1945 } 1946 #endif /* _FFR_IGNORE_BOGUS_ADDR */ 1947 1948 /* look to see if we have an at sign */ 1949 while (*p != '\0' && isascii(*p) && isspace(*p)) 1950 p++; 1951 1952 if (*p != '@') 1953 { 1954 p = oldp; 1955 break; 1956 } 1957 ++p; 1958 while (*p != '\0' && isascii(*p) && isspace(*p)) 1959 p++; 1960 } 1961 /* at the end of one complete name */ 1962 1963 /* strip off trailing white space */ 1964 while (p >= name && 1965 ((isascii(*p) && isspace(*p)) || *p == ',' || *p == '\0')) 1966 p--; 1967 if (++p == name) 1968 continue; 1969 1970 /* 1971 ** if prescan() failed go a bit backwards; this is a hack, 1972 ** there should be some better error recovery. 1973 */ 1974 1975 if (res == NULL && p > name && 1976 !((isascii(*p) && isspace(*p)) || *p == ',' || *p == '\0')) 1977 --p; 1978 savechar = *p; 1979 *p = '\0'; 1980 1981 /* translate the name to be relative */ 1982 flags = RF_HEADERADDR|RF_ADDDOMAIN; 1983 if (bitset(H_FROM, h->h_flags)) 1984 flags |= RF_SENDERADDR; 1985 #if USERDB 1986 else if (e->e_from.q_mailer != NULL && 1987 bitnset(M_UDBRECIPIENT, e->e_from.q_mailer->m_flags)) 1988 { 1989 char *q; 1990 1991 q = udbsender(name, e->e_rpool); 1992 if (q != NULL) 1993 name = q; 1994 } 1995 #endif /* USERDB */ 1996 status = EX_OK; 1997 name = remotename(name, mci->mci_mailer, flags, &status, e); 1998 if (*name == '\0') 1999 { 2000 *p = savechar; 2001 continue; 2002 } 2003 name = denlstring(name, false, true); 2004 2005 /* 2006 ** record data progress so DNS timeouts 2007 ** don't cause DATA timeouts 2008 */ 2009 2010 DataProgress = true; 2011 2012 /* output the name with nice formatting */ 2013 opos += strlen(name); 2014 if (!firstone) 2015 opos += 2; 2016 if (opos > omax && !firstone) 2017 { 2018 (void) sm_strlcpy(obp, ",\n", SPACELEFT(obuf, obp)); 2019 putxline(obuf, strlen(obuf), mci, putflags); 2020 obp = obuf; 2021 (void) sm_strlcpy(obp, " ", sizeof obuf); 2022 opos = strlen(obp); 2023 obp += opos; 2024 opos += strlen(name); 2025 } 2026 else if (!firstone) 2027 { 2028 (void) sm_strlcpy(obp, ", ", SPACELEFT(obuf, obp)); 2029 obp += 2; 2030 } 2031 2032 while ((c = *name++) != '\0' && obp < &obuf[MAXLINE]) 2033 *obp++ = c; 2034 firstone = false; 2035 *p = savechar; 2036 } 2037 if (obp < &obuf[sizeof obuf]) 2038 *obp = '\0'; 2039 else 2040 obuf[sizeof obuf - 1] = '\0'; 2041 putxline(obuf, strlen(obuf), mci, putflags); 2042 } 2043 /* 2044 ** COPYHEADER -- copy header list 2045 ** 2046 ** This routine is the equivalent of newstr for header lists 2047 ** 2048 ** Parameters: 2049 ** header -- list of header structures to copy. 2050 ** rpool -- resource pool, or NULL 2051 ** 2052 ** Returns: 2053 ** a copy of 'header'. 2054 ** 2055 ** Side Effects: 2056 ** none. 2057 */ 2058 2059 HDR * 2060 copyheader(header, rpool) 2061 register HDR *header; 2062 SM_RPOOL_T *rpool; 2063 { 2064 register HDR *newhdr; 2065 HDR *ret; 2066 register HDR **tail = &ret; 2067 2068 while (header != NULL) 2069 { 2070 newhdr = (HDR *) sm_rpool_malloc_x(rpool, sizeof *newhdr); 2071 STRUCTCOPY(*header, *newhdr); 2072 *tail = newhdr; 2073 tail = &newhdr->h_link; 2074 header = header->h_link; 2075 } 2076 *tail = NULL; 2077 2078 return ret; 2079 } 2080 /* 2081 ** FIX_MIME_HEADER -- possibly truncate/rebalance parameters in a MIME header 2082 ** 2083 ** Run through all of the parameters of a MIME header and 2084 ** possibly truncate and rebalance the parameter according 2085 ** to MaxMimeFieldLength. 2086 ** 2087 ** Parameters: 2088 ** h -- the header to truncate/rebalance 2089 ** e -- the current envelope 2090 ** 2091 ** Returns: 2092 ** length of last offending field, 0 if all ok. 2093 ** 2094 ** Side Effects: 2095 ** string modified in place 2096 */ 2097 2098 static size_t 2099 fix_mime_header(h, e) 2100 HDR *h; 2101 ENVELOPE *e; 2102 { 2103 char *begin = h->h_value; 2104 char *end; 2105 size_t len = 0; 2106 size_t retlen = 0; 2107 2108 if (begin == NULL || *begin == '\0') 2109 return 0; 2110 2111 /* Split on each ';' */ 2112 /* find_character() never returns NULL */ 2113 while ((end = find_character(begin, ';')) != NULL) 2114 { 2115 char save = *end; 2116 char *bp; 2117 2118 *end = '\0'; 2119 2120 len = strlen(begin); 2121 2122 /* Shorten individual parameter */ 2123 if (shorten_rfc822_string(begin, MaxMimeFieldLength)) 2124 { 2125 if (len < MaxMimeFieldLength) 2126 { 2127 /* we only rebalanced a bogus field */ 2128 sm_syslog(LOG_ALERT, e->e_id, 2129 "Fixed MIME %s header field (possible attack)", 2130 h->h_field); 2131 if (tTd(34, 11)) 2132 sm_dprintf(" fixed MIME %s header field (possible attack)\n", 2133 h->h_field); 2134 } 2135 else 2136 { 2137 /* we actually shortened the header */ 2138 retlen = len; 2139 } 2140 } 2141 2142 /* Collapse the possibly shortened string with rest */ 2143 bp = begin + strlen(begin); 2144 if (bp != end) 2145 { 2146 char *ep = end; 2147 2148 *end = save; 2149 end = bp; 2150 2151 /* copy character by character due to overlap */ 2152 while (*ep != '\0') 2153 *bp++ = *ep++; 2154 *bp = '\0'; 2155 } 2156 else 2157 *end = save; 2158 if (*end == '\0') 2159 break; 2160 2161 /* Move past ';' */ 2162 begin = end + 1; 2163 } 2164 return retlen; 2165 } 2166