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