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