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