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.7 2003/09/03 21:32:20 ca 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 } 735 } 736 if (tTd(32, 1)) 737 sm_dprintf("----------------------------\n"); 738 739 /* if we are just verifying (that is, sendmail -t -bv), drop out now */ 740 if (OpMode == MD_VERIFY) 741 return; 742 743 /* store hop count */ 744 if (hopcnt > e->e_hopcount) 745 { 746 e->e_hopcount = hopcnt; 747 (void) sm_snprintf(buf, sizeof buf, "%d", e->e_hopcount); 748 macdefine(&e->e_macro, A_TEMP, 'c', buf); 749 } 750 751 /* message priority */ 752 p = hvalue("precedence", e->e_header); 753 if (p != NULL) 754 e->e_class = priencode(p); 755 if (e->e_class < 0) 756 e->e_timeoutclass = TOC_NONURGENT; 757 else if (e->e_class > 0) 758 e->e_timeoutclass = TOC_URGENT; 759 if (full) 760 { 761 e->e_msgpriority = e->e_msgsize 762 - e->e_class * WkClassFact 763 + e->e_nrcpts * WkRecipFact; 764 } 765 766 /* message timeout priority */ 767 p = hvalue("priority", e->e_header); 768 if (p != NULL) 769 { 770 /* (this should be in the configuration file) */ 771 if (sm_strcasecmp(p, "urgent") == 0) 772 e->e_timeoutclass = TOC_URGENT; 773 else if (sm_strcasecmp(p, "normal") == 0) 774 e->e_timeoutclass = TOC_NORMAL; 775 else if (sm_strcasecmp(p, "non-urgent") == 0) 776 e->e_timeoutclass = TOC_NONURGENT; 777 } 778 779 #if _FFR_QUEUERETURN_DSN 780 /* If no timeoutclass picked and it's a DSN, use that timeoutclass */ 781 if (e->e_timeoutclass == TOC_NORMAL && bitset(EF_RESPONSE, e->e_flags)) 782 e->e_timeoutclass = TOC_DSN; 783 #endif /* _FFR_QUEUERETURN_DSN */ 784 785 /* date message originated */ 786 p = hvalue("posted-date", e->e_header); 787 if (p == NULL) 788 p = hvalue("date", e->e_header); 789 if (p != NULL) 790 macdefine(&e->e_macro, A_PERM, 'a', p); 791 792 /* check to see if this is a MIME message */ 793 if ((e->e_bodytype != NULL && 794 sm_strcasecmp(e->e_bodytype, "8BITMIME") == 0) || 795 hvalue("MIME-Version", e->e_header) != NULL) 796 { 797 e->e_flags |= EF_IS_MIME; 798 if (HasEightBits) 799 e->e_bodytype = "8BITMIME"; 800 } 801 else if ((p = hvalue("Content-Type", e->e_header)) != NULL) 802 { 803 /* this may be an RFC 1049 message */ 804 p = strpbrk(p, ";/"); 805 if (p == NULL || *p == ';') 806 { 807 /* yep, it is */ 808 e->e_flags |= EF_DONT_MIME; 809 } 810 } 811 812 /* 813 ** From person in antiquated ARPANET mode 814 ** required by UK Grey Book e-mail gateways (sigh) 815 */ 816 817 if (OpMode == MD_ARPAFTP) 818 { 819 register struct hdrinfo *hi; 820 821 for (hi = HdrInfo; hi->hi_field != NULL; hi++) 822 { 823 if (bitset(H_FROM, hi->hi_flags) && 824 (!bitset(H_RESENT, hi->hi_flags) || 825 bitset(EF_RESENT, e->e_flags)) && 826 (p = hvalue(hi->hi_field, e->e_header)) != NULL) 827 break; 828 } 829 if (hi->hi_field != NULL) 830 { 831 if (tTd(32, 2)) 832 sm_dprintf("eatheader: setsender(*%s == %s)\n", 833 hi->hi_field, p); 834 setsender(p, e, NULL, '\0', true); 835 } 836 } 837 838 /* 839 ** Log collection information. 840 */ 841 842 if (log && bitset(EF_LOGSENDER, e->e_flags) && LogLevel > 4) 843 { 844 logsender(e, e->e_msgid); 845 e->e_flags &= ~EF_LOGSENDER; 846 } 847 } 848 /* 849 ** LOGSENDER -- log sender information 850 ** 851 ** Parameters: 852 ** e -- the envelope to log 853 ** msgid -- the message id 854 ** 855 ** Returns: 856 ** none 857 */ 858 859 void 860 logsender(e, msgid) 861 register ENVELOPE *e; 862 char *msgid; 863 { 864 char *name; 865 register char *sbp; 866 register char *p; 867 int l; 868 char hbuf[MAXNAME + 1]; 869 char sbuf[MAXLINE + 1]; 870 char mbuf[MAXNAME + 1]; 871 872 /* don't allow newlines in the message-id */ 873 /* XXX do we still need this? sm_syslog() replaces control chars */ 874 if (msgid != NULL) 875 { 876 l = strlen(msgid); 877 if (l > sizeof mbuf - 1) 878 l = sizeof mbuf - 1; 879 memmove(mbuf, msgid, l); 880 mbuf[l] = '\0'; 881 p = mbuf; 882 while ((p = strchr(p, '\n')) != NULL) 883 *p++ = ' '; 884 } 885 886 if (bitset(EF_RESPONSE, e->e_flags)) 887 name = "[RESPONSE]"; 888 else if ((name = macvalue('_', e)) != NULL) 889 /* EMPTY */ 890 ; 891 else if (RealHostName == NULL) 892 name = "localhost"; 893 else if (RealHostName[0] == '[') 894 name = RealHostName; 895 else 896 { 897 name = hbuf; 898 (void) sm_snprintf(hbuf, sizeof hbuf, "%.80s", RealHostName); 899 if (RealHostAddr.sa.sa_family != 0) 900 { 901 p = &hbuf[strlen(hbuf)]; 902 (void) sm_snprintf(p, SPACELEFT(hbuf, p), 903 " (%.100s)", 904 anynet_ntoa(&RealHostAddr)); 905 } 906 } 907 908 /* some versions of syslog only take 5 printf args */ 909 #if (SYSLOG_BUFSIZE) >= 256 910 sbp = sbuf; 911 (void) sm_snprintf(sbp, SPACELEFT(sbuf, sbp), 912 "from=%.200s, size=%ld, class=%d, nrcpts=%d", 913 e->e_from.q_paddr == NULL ? "<NONE>" : e->e_from.q_paddr, 914 e->e_msgsize, e->e_class, e->e_nrcpts); 915 sbp += strlen(sbp); 916 if (msgid != NULL) 917 { 918 (void) sm_snprintf(sbp, SPACELEFT(sbuf, sbp), 919 ", msgid=%.100s", mbuf); 920 sbp += strlen(sbp); 921 } 922 if (e->e_bodytype != NULL) 923 { 924 (void) sm_snprintf(sbp, SPACELEFT(sbuf, sbp), 925 ", bodytype=%.20s", e->e_bodytype); 926 sbp += strlen(sbp); 927 } 928 p = macvalue('r', e); 929 if (p != NULL) 930 { 931 (void) sm_snprintf(sbp, SPACELEFT(sbuf, sbp), 932 ", proto=%.20s", p); 933 sbp += strlen(sbp); 934 } 935 p = macvalue(macid("{daemon_name}"), e); 936 if (p != NULL) 937 { 938 (void) sm_snprintf(sbp, SPACELEFT(sbuf, sbp), 939 ", daemon=%.20s", p); 940 sbp += strlen(sbp); 941 } 942 sm_syslog(LOG_INFO, e->e_id, "%.850s, relay=%s", sbuf, name); 943 944 #else /* (SYSLOG_BUFSIZE) >= 256 */ 945 946 sm_syslog(LOG_INFO, e->e_id, 947 "from=%s", 948 e->e_from.q_paddr == NULL ? "<NONE>" 949 : shortenstring(e->e_from.q_paddr, 950 83)); 951 sm_syslog(LOG_INFO, e->e_id, 952 "size=%ld, class=%ld, nrcpts=%d", 953 e->e_msgsize, e->e_class, e->e_nrcpts); 954 if (msgid != NULL) 955 sm_syslog(LOG_INFO, e->e_id, 956 "msgid=%s", 957 shortenstring(mbuf, 83)); 958 sbp = sbuf; 959 *sbp = '\0'; 960 if (e->e_bodytype != NULL) 961 { 962 (void) sm_snprintf(sbp, SPACELEFT(sbuf, sbp), 963 "bodytype=%.20s, ", e->e_bodytype); 964 sbp += strlen(sbp); 965 } 966 p = macvalue('r', e); 967 if (p != NULL) 968 { 969 (void) sm_snprintf(sbp, SPACELEFT(sbuf, sbp), 970 "proto=%.20s, ", p); 971 sbp += strlen(sbp); 972 } 973 sm_syslog(LOG_INFO, e->e_id, 974 "%.400srelay=%s", sbuf, name); 975 #endif /* (SYSLOG_BUFSIZE) >= 256 */ 976 } 977 /* 978 ** PRIENCODE -- encode external priority names into internal values. 979 ** 980 ** Parameters: 981 ** p -- priority in ascii. 982 ** 983 ** Returns: 984 ** priority as a numeric level. 985 ** 986 ** Side Effects: 987 ** none. 988 */ 989 990 static int 991 priencode(p) 992 char *p; 993 { 994 register int i; 995 996 for (i = 0; i < NumPriorities; i++) 997 { 998 if (sm_strcasecmp(p, Priorities[i].pri_name) == 0) 999 return Priorities[i].pri_val; 1000 } 1001 1002 /* unknown priority */ 1003 return 0; 1004 } 1005 /* 1006 ** CRACKADDR -- parse an address and turn it into a macro 1007 ** 1008 ** This doesn't actually parse the address -- it just extracts 1009 ** it and replaces it with "$g". The parse is totally ad hoc 1010 ** and isn't even guaranteed to leave something syntactically 1011 ** identical to what it started with. However, it does leave 1012 ** something semantically identical if possible, else at least 1013 ** syntactically correct. 1014 ** 1015 ** For example, it changes "Real Name <real@example.com> (Comment)" 1016 ** to "Real Name <$g> (Comment)". 1017 ** 1018 ** This algorithm has been cleaned up to handle a wider range 1019 ** of cases -- notably quoted and backslash escaped strings. 1020 ** This modification makes it substantially better at preserving 1021 ** the original syntax. 1022 ** 1023 ** Parameters: 1024 ** addr -- the address to be cracked. 1025 ** e -- the current envelope. 1026 ** 1027 ** Returns: 1028 ** a pointer to the new version. 1029 ** 1030 ** Side Effects: 1031 ** none. 1032 ** 1033 ** Warning: 1034 ** The return value is saved in local storage and should 1035 ** be copied if it is to be reused. 1036 */ 1037 1038 #define SM_HAVE_ROOM ((bp < buflim) && (buflim <= bufend)) 1039 1040 /* 1041 ** Append a character to bp if we have room. 1042 ** If not, punt and return $g. 1043 */ 1044 1045 #define SM_APPEND_CHAR(c) \ 1046 do \ 1047 { \ 1048 if (SM_HAVE_ROOM) \ 1049 *bp++ = (c); \ 1050 else \ 1051 goto returng; \ 1052 } while (0) 1053 1054 #if MAXNAME < 10 1055 ERROR MAXNAME must be at least 10 1056 #endif /* MAXNAME < 10 */ 1057 1058 char * 1059 crackaddr(addr, e) 1060 register char *addr; 1061 ENVELOPE *e; 1062 { 1063 register char *p; 1064 register char c; 1065 int cmtlev; /* comment level in input string */ 1066 int realcmtlev; /* comment level in output string */ 1067 int anglelev; /* angle level in input string */ 1068 int copylev; /* 0 == in address, >0 copying */ 1069 int bracklev; /* bracket level for IPv6 addr check */ 1070 bool addangle; /* put closing angle in output */ 1071 bool qmode; /* quoting in original string? */ 1072 bool realqmode; /* quoting in output string? */ 1073 bool putgmac = false; /* already wrote $g */ 1074 bool quoteit = false; /* need to quote next character */ 1075 bool gotangle = false; /* found first '<' */ 1076 bool gotcolon = false; /* found a ':' */ 1077 register char *bp; 1078 char *buflim; 1079 char *bufhead; 1080 char *addrhead; 1081 char *bufend; 1082 static char buf[MAXNAME + 1]; 1083 1084 if (tTd(33, 1)) 1085 sm_dprintf("crackaddr(%s)\n", addr); 1086 1087 /* strip leading spaces */ 1088 while (*addr != '\0' && isascii(*addr) && isspace(*addr)) 1089 addr++; 1090 1091 /* 1092 ** Start by assuming we have no angle brackets. This will be 1093 ** adjusted later if we find them. 1094 */ 1095 1096 buflim = bufend = &buf[sizeof(buf) - 1]; 1097 bp = bufhead = buf; 1098 p = addrhead = addr; 1099 copylev = anglelev = cmtlev = realcmtlev = 0; 1100 bracklev = 0; 1101 qmode = realqmode = addangle = false; 1102 1103 while ((c = *p++) != '\0') 1104 { 1105 /* 1106 ** Try to keep legal syntax using spare buffer space 1107 ** (maintained by buflim). 1108 */ 1109 1110 if (copylev > 0) 1111 SM_APPEND_CHAR(c); 1112 1113 /* check for backslash escapes */ 1114 if (c == '\\') 1115 { 1116 /* arrange to quote the address */ 1117 if (cmtlev <= 0 && !qmode) 1118 quoteit = true; 1119 1120 if ((c = *p++) == '\0') 1121 { 1122 /* too far */ 1123 p--; 1124 goto putg; 1125 } 1126 if (copylev > 0) 1127 SM_APPEND_CHAR(c); 1128 goto putg; 1129 } 1130 1131 /* check for quoted strings */ 1132 if (c == '"' && cmtlev <= 0) 1133 { 1134 qmode = !qmode; 1135 if (copylev > 0 && SM_HAVE_ROOM) 1136 { 1137 if (realqmode) 1138 buflim--; 1139 else 1140 buflim++; 1141 realqmode = !realqmode; 1142 } 1143 continue; 1144 } 1145 if (qmode) 1146 goto putg; 1147 1148 /* check for comments */ 1149 if (c == '(') 1150 { 1151 cmtlev++; 1152 1153 /* allow space for closing paren */ 1154 if (SM_HAVE_ROOM) 1155 { 1156 buflim--; 1157 realcmtlev++; 1158 if (copylev++ <= 0) 1159 { 1160 if (bp != bufhead) 1161 SM_APPEND_CHAR(' '); 1162 SM_APPEND_CHAR(c); 1163 } 1164 } 1165 } 1166 if (cmtlev > 0) 1167 { 1168 if (c == ')') 1169 { 1170 cmtlev--; 1171 copylev--; 1172 if (SM_HAVE_ROOM) 1173 { 1174 realcmtlev--; 1175 buflim++; 1176 } 1177 } 1178 continue; 1179 } 1180 else if (c == ')') 1181 { 1182 /* syntax error: unmatched ) */ 1183 if (copylev > 0 && SM_HAVE_ROOM && bp > bufhead) 1184 bp--; 1185 } 1186 1187 /* count nesting on [ ... ] (for IPv6 domain literals) */ 1188 if (c == '[') 1189 bracklev++; 1190 else if (c == ']') 1191 bracklev--; 1192 1193 /* check for group: list; syntax */ 1194 if (c == ':' && anglelev <= 0 && bracklev <= 0 && 1195 !gotcolon && !ColonOkInAddr) 1196 { 1197 register char *q; 1198 1199 /* 1200 ** Check for DECnet phase IV ``::'' (host::user) 1201 ** or DECnet phase V ``:.'' syntaxes. The latter 1202 ** covers ``user@DEC:.tay.myhost'' and 1203 ** ``DEC:.tay.myhost::user'' syntaxes (bletch). 1204 */ 1205 1206 if (*p == ':' || *p == '.') 1207 { 1208 if (cmtlev <= 0 && !qmode) 1209 quoteit = true; 1210 if (copylev > 0) 1211 { 1212 SM_APPEND_CHAR(c); 1213 SM_APPEND_CHAR(*p); 1214 } 1215 p++; 1216 goto putg; 1217 } 1218 1219 gotcolon = true; 1220 1221 bp = bufhead; 1222 if (quoteit) 1223 { 1224 SM_APPEND_CHAR('"'); 1225 1226 /* back up over the ':' and any spaces */ 1227 --p; 1228 while (p > addr && 1229 isascii(*--p) && isspace(*p)) 1230 continue; 1231 p++; 1232 } 1233 for (q = addrhead; q < p; ) 1234 { 1235 c = *q++; 1236 if (quoteit && c == '"') 1237 { 1238 SM_APPEND_CHAR('\\'); 1239 SM_APPEND_CHAR(c); 1240 } 1241 else 1242 SM_APPEND_CHAR(c); 1243 } 1244 if (quoteit) 1245 { 1246 if (bp == &bufhead[1]) 1247 bp--; 1248 else 1249 SM_APPEND_CHAR('"'); 1250 while ((c = *p++) != ':') 1251 SM_APPEND_CHAR(c); 1252 SM_APPEND_CHAR(c); 1253 } 1254 1255 /* any trailing white space is part of group: */ 1256 while (isascii(*p) && isspace(*p)) 1257 { 1258 SM_APPEND_CHAR(*p); 1259 p++; 1260 } 1261 copylev = 0; 1262 putgmac = quoteit = false; 1263 bufhead = bp; 1264 addrhead = p; 1265 continue; 1266 } 1267 1268 if (c == ';' && copylev <= 0 && !ColonOkInAddr) 1269 SM_APPEND_CHAR(c); 1270 1271 /* check for characters that may have to be quoted */ 1272 if (strchr(MustQuoteChars, c) != NULL) 1273 { 1274 /* 1275 ** If these occur as the phrase part of a <> 1276 ** construct, but are not inside of () or already 1277 ** quoted, they will have to be quoted. Note that 1278 ** now (but don't actually do the quoting). 1279 */ 1280 1281 if (cmtlev <= 0 && !qmode) 1282 quoteit = true; 1283 } 1284 1285 /* check for angle brackets */ 1286 if (c == '<') 1287 { 1288 register char *q; 1289 1290 /* assume first of two angles is bogus */ 1291 if (gotangle) 1292 quoteit = true; 1293 gotangle = true; 1294 1295 /* oops -- have to change our mind */ 1296 anglelev = 1; 1297 if (SM_HAVE_ROOM) 1298 { 1299 if (!addangle) 1300 buflim--; 1301 addangle = true; 1302 } 1303 1304 bp = bufhead; 1305 if (quoteit) 1306 { 1307 SM_APPEND_CHAR('"'); 1308 1309 /* back up over the '<' and any spaces */ 1310 --p; 1311 while (p > addr && 1312 isascii(*--p) && isspace(*p)) 1313 continue; 1314 p++; 1315 } 1316 for (q = addrhead; q < p; ) 1317 { 1318 c = *q++; 1319 if (quoteit && c == '"') 1320 { 1321 SM_APPEND_CHAR('\\'); 1322 SM_APPEND_CHAR(c); 1323 } 1324 else 1325 SM_APPEND_CHAR(c); 1326 } 1327 if (quoteit) 1328 { 1329 if (bp == &buf[1]) 1330 bp--; 1331 else 1332 SM_APPEND_CHAR('"'); 1333 while ((c = *p++) != '<') 1334 SM_APPEND_CHAR(c); 1335 SM_APPEND_CHAR(c); 1336 } 1337 copylev = 0; 1338 putgmac = quoteit = false; 1339 continue; 1340 } 1341 1342 if (c == '>') 1343 { 1344 if (anglelev > 0) 1345 { 1346 anglelev--; 1347 if (SM_HAVE_ROOM) 1348 { 1349 if (addangle) 1350 buflim++; 1351 addangle = false; 1352 } 1353 } 1354 else if (SM_HAVE_ROOM) 1355 { 1356 /* syntax error: unmatched > */ 1357 if (copylev > 0 && bp > bufhead) 1358 bp--; 1359 quoteit = true; 1360 continue; 1361 } 1362 if (copylev++ <= 0) 1363 SM_APPEND_CHAR(c); 1364 continue; 1365 } 1366 1367 /* must be a real address character */ 1368 putg: 1369 if (copylev <= 0 && !putgmac) 1370 { 1371 if (bp > buf && bp[-1] == ')') 1372 SM_APPEND_CHAR(' '); 1373 SM_APPEND_CHAR(MACROEXPAND); 1374 SM_APPEND_CHAR('g'); 1375 putgmac = true; 1376 } 1377 } 1378 1379 /* repair any syntactic damage */ 1380 if (realqmode && bp < bufend) 1381 *bp++ = '"'; 1382 while (realcmtlev-- > 0 && bp < bufend) 1383 *bp++ = ')'; 1384 if (addangle && bp < bufend) 1385 *bp++ = '>'; 1386 *bp = '\0'; 1387 if (bp < bufend) 1388 goto success; 1389 1390 returng: 1391 /* String too long, punt */ 1392 buf[0] = '<'; 1393 buf[1] = MACROEXPAND; 1394 buf[2]= 'g'; 1395 buf[3] = '>'; 1396 buf[4]= '\0'; 1397 sm_syslog(LOG_ALERT, e->e_id, 1398 "Dropped invalid comments from header address"); 1399 1400 success: 1401 if (tTd(33, 1)) 1402 { 1403 sm_dprintf("crackaddr=>`"); 1404 xputs(buf); 1405 sm_dprintf("'\n"); 1406 } 1407 return buf; 1408 } 1409 /* 1410 ** PUTHEADER -- put the header part of a message from the in-core copy 1411 ** 1412 ** Parameters: 1413 ** mci -- the connection information. 1414 ** hdr -- the header to put. 1415 ** e -- envelope to use. 1416 ** flags -- MIME conversion flags. 1417 ** 1418 ** Returns: 1419 ** none. 1420 ** 1421 ** Side Effects: 1422 ** none. 1423 */ 1424 1425 void 1426 putheader(mci, hdr, e, flags) 1427 register MCI *mci; 1428 HDR *hdr; 1429 register ENVELOPE *e; 1430 int flags; 1431 { 1432 register HDR *h; 1433 char buf[SM_MAX(MAXLINE,BUFSIZ)]; 1434 char obuf[MAXLINE]; 1435 1436 if (tTd(34, 1)) 1437 sm_dprintf("--- putheader, mailer = %s ---\n", 1438 mci->mci_mailer->m_name); 1439 1440 /* 1441 ** If we're in MIME mode, we're not really in the header of the 1442 ** message, just the header of one of the parts of the body of 1443 ** the message. Therefore MCIF_INHEADER should not be turned on. 1444 */ 1445 1446 if (!bitset(MCIF_INMIME, mci->mci_flags)) 1447 mci->mci_flags |= MCIF_INHEADER; 1448 1449 for (h = hdr; h != NULL; h = h->h_link) 1450 { 1451 register char *p = h->h_value; 1452 char *q; 1453 1454 if (tTd(34, 11)) 1455 { 1456 sm_dprintf(" %s: ", h->h_field); 1457 xputs(p); 1458 } 1459 1460 /* Skip empty headers */ 1461 if (h->h_value == NULL) 1462 continue; 1463 1464 /* heuristic shortening of MIME fields to avoid MUA overflows */ 1465 if (MaxMimeFieldLength > 0 && 1466 wordinclass(h->h_field, 1467 macid("{checkMIMEFieldHeaders}"))) 1468 { 1469 size_t len; 1470 1471 len = fix_mime_header(h, e); 1472 if (len > 0) 1473 { 1474 sm_syslog(LOG_ALERT, e->e_id, 1475 "Truncated MIME %s header due to field size (length = %ld) (possible attack)", 1476 h->h_field, (unsigned long) len); 1477 if (tTd(34, 11)) 1478 sm_dprintf(" truncated MIME %s header due to field size (length = %ld) (possible attack)\n", 1479 h->h_field, 1480 (unsigned long) len); 1481 } 1482 } 1483 1484 if (MaxMimeHeaderLength > 0 && 1485 wordinclass(h->h_field, 1486 macid("{checkMIMETextHeaders}"))) 1487 { 1488 size_t len; 1489 1490 len = strlen(h->h_value); 1491 if (len > (size_t) MaxMimeHeaderLength) 1492 { 1493 h->h_value[MaxMimeHeaderLength - 1] = '\0'; 1494 sm_syslog(LOG_ALERT, e->e_id, 1495 "Truncated long MIME %s header (length = %ld) (possible attack)", 1496 h->h_field, (unsigned long) len); 1497 if (tTd(34, 11)) 1498 sm_dprintf(" truncated long MIME %s header (length = %ld) (possible attack)\n", 1499 h->h_field, 1500 (unsigned long) len); 1501 } 1502 } 1503 1504 if (MaxMimeHeaderLength > 0 && 1505 wordinclass(h->h_field, 1506 macid("{checkMIMEHeaders}"))) 1507 { 1508 size_t len; 1509 1510 len = strlen(h->h_value); 1511 if (shorten_rfc822_string(h->h_value, 1512 MaxMimeHeaderLength)) 1513 { 1514 if (len < MaxMimeHeaderLength) 1515 { 1516 /* we only rebalanced a bogus header */ 1517 sm_syslog(LOG_ALERT, e->e_id, 1518 "Fixed MIME %s header (possible attack)", 1519 h->h_field); 1520 if (tTd(34, 11)) 1521 sm_dprintf(" fixed MIME %s header (possible attack)\n", 1522 h->h_field); 1523 } 1524 else 1525 { 1526 /* we actually shortened header */ 1527 sm_syslog(LOG_ALERT, e->e_id, 1528 "Truncated long MIME %s header (length = %ld) (possible attack)", 1529 h->h_field, 1530 (unsigned long) len); 1531 if (tTd(34, 11)) 1532 sm_dprintf(" truncated long MIME %s header (length = %ld) (possible attack)\n", 1533 h->h_field, 1534 (unsigned long) len); 1535 } 1536 } 1537 } 1538 1539 /* 1540 ** Suppress Content-Transfer-Encoding: if we are MIMEing 1541 ** and we are potentially converting from 8 bit to 7 bit 1542 ** MIME. If converting, add a new CTE header in 1543 ** mime8to7(). 1544 */ 1545 1546 if (bitset(H_CTE, h->h_flags) && 1547 bitset(MCIF_CVT8TO7|MCIF_CVT7TO8|MCIF_INMIME, 1548 mci->mci_flags) && 1549 !bitset(M87F_NO8TO7, flags)) 1550 { 1551 if (tTd(34, 11)) 1552 sm_dprintf(" (skipped (content-transfer-encoding))\n"); 1553 continue; 1554 } 1555 1556 if (bitset(MCIF_INMIME, mci->mci_flags)) 1557 { 1558 if (tTd(34, 11)) 1559 sm_dprintf("\n"); 1560 put_vanilla_header(h, p, mci); 1561 continue; 1562 } 1563 1564 if (bitset(H_CHECK|H_ACHECK, h->h_flags) && 1565 !bitintersect(h->h_mflags, mci->mci_mailer->m_flags) && 1566 (h->h_macro == '\0' || 1567 (q = macvalue(bitidx(h->h_macro), e)) == NULL || 1568 *q == '\0')) 1569 { 1570 if (tTd(34, 11)) 1571 sm_dprintf(" (skipped)\n"); 1572 continue; 1573 } 1574 1575 /* handle Resent-... headers specially */ 1576 if (bitset(H_RESENT, h->h_flags) && !bitset(EF_RESENT, e->e_flags)) 1577 { 1578 if (tTd(34, 11)) 1579 sm_dprintf(" (skipped (resent))\n"); 1580 continue; 1581 } 1582 1583 /* suppress return receipts if requested */ 1584 if (bitset(H_RECEIPTTO, h->h_flags) && 1585 (RrtImpliesDsn || bitset(EF_NORECEIPT, e->e_flags))) 1586 { 1587 if (tTd(34, 11)) 1588 sm_dprintf(" (skipped (receipt))\n"); 1589 continue; 1590 } 1591 1592 /* macro expand value if generated internally */ 1593 if (bitset(H_DEFAULT, h->h_flags) || 1594 bitset(H_BINDLATE, h->h_flags)) 1595 { 1596 expand(p, buf, sizeof buf, e); 1597 p = buf; 1598 if (*p == '\0') 1599 { 1600 if (tTd(34, 11)) 1601 sm_dprintf(" (skipped -- null value)\n"); 1602 continue; 1603 } 1604 } 1605 1606 if (bitset(H_BCC, h->h_flags)) 1607 { 1608 /* Bcc: field -- either truncate or delete */ 1609 if (bitset(EF_DELETE_BCC, e->e_flags)) 1610 { 1611 if (tTd(34, 11)) 1612 sm_dprintf(" (skipped -- bcc)\n"); 1613 } 1614 else 1615 { 1616 /* no other recipient headers: truncate value */ 1617 (void) sm_strlcpyn(obuf, sizeof obuf, 2, 1618 h->h_field, ":"); 1619 putline(obuf, mci); 1620 } 1621 continue; 1622 } 1623 1624 if (tTd(34, 11)) 1625 sm_dprintf("\n"); 1626 1627 if (bitset(H_FROM|H_RCPT, h->h_flags)) 1628 { 1629 /* address field */ 1630 bool oldstyle = bitset(EF_OLDSTYLE, e->e_flags); 1631 1632 if (bitset(H_FROM, h->h_flags)) 1633 oldstyle = false; 1634 commaize(h, p, oldstyle, mci, e); 1635 } 1636 else 1637 { 1638 put_vanilla_header(h, p, mci); 1639 } 1640 } 1641 1642 /* 1643 ** If we are converting this to a MIME message, add the 1644 ** MIME headers (but not in MIME mode!). 1645 */ 1646 1647 #if MIME8TO7 1648 if (bitset(MM_MIME8BIT, MimeMode) && 1649 bitset(EF_HAS8BIT, e->e_flags) && 1650 !bitset(EF_DONT_MIME, e->e_flags) && 1651 !bitnset(M_8BITS, mci->mci_mailer->m_flags) && 1652 !bitset(MCIF_CVT8TO7|MCIF_CVT7TO8|MCIF_INMIME, mci->mci_flags) && 1653 hvalue("MIME-Version", e->e_header) == NULL) 1654 { 1655 putline("MIME-Version: 1.0", mci); 1656 if (hvalue("Content-Type", e->e_header) == NULL) 1657 { 1658 (void) sm_snprintf(obuf, sizeof obuf, 1659 "Content-Type: text/plain; charset=%s", 1660 defcharset(e)); 1661 putline(obuf, mci); 1662 } 1663 if (hvalue("Content-Transfer-Encoding", e->e_header) == NULL) 1664 putline("Content-Transfer-Encoding: 8bit", mci); 1665 } 1666 #endif /* MIME8TO7 */ 1667 } 1668 /* 1669 ** PUT_VANILLA_HEADER -- output a fairly ordinary header 1670 ** 1671 ** Parameters: 1672 ** h -- the structure describing this header 1673 ** v -- the value of this header 1674 ** mci -- the connection info for output 1675 ** 1676 ** Returns: 1677 ** none. 1678 */ 1679 1680 static void 1681 put_vanilla_header(h, v, mci) 1682 HDR *h; 1683 char *v; 1684 MCI *mci; 1685 { 1686 register char *nlp; 1687 register char *obp; 1688 int putflags; 1689 char obuf[MAXLINE]; 1690 1691 putflags = PXLF_HEADER; 1692 if (bitnset(M_7BITHDRS, mci->mci_mailer->m_flags)) 1693 putflags |= PXLF_STRIP8BIT; 1694 (void) sm_snprintf(obuf, sizeof obuf, "%.200s: ", h->h_field); 1695 obp = obuf + strlen(obuf); 1696 while ((nlp = strchr(v, '\n')) != NULL) 1697 { 1698 int l; 1699 1700 l = nlp - v; 1701 1702 /* 1703 ** XXX This is broken for SPACELEFT()==0 1704 ** However, SPACELEFT() is always > 0 unless MAXLINE==1. 1705 */ 1706 1707 if (SPACELEFT(obuf, obp) - 1 < (size_t) l) 1708 l = SPACELEFT(obuf, obp) - 1; 1709 1710 (void) sm_snprintf(obp, SPACELEFT(obuf, obp), "%.*s", l, v); 1711 putxline(obuf, strlen(obuf), mci, putflags); 1712 v += l + 1; 1713 obp = obuf; 1714 if (*v != ' ' && *v != '\t') 1715 *obp++ = ' '; 1716 } 1717 1718 /* XXX This is broken for SPACELEFT()==0 */ 1719 (void) sm_snprintf(obp, SPACELEFT(obuf, obp), "%.*s", 1720 (int) (SPACELEFT(obuf, obp) - 1), v); 1721 putxline(obuf, strlen(obuf), mci, putflags); 1722 } 1723 /* 1724 ** COMMAIZE -- output a header field, making a comma-translated list. 1725 ** 1726 ** Parameters: 1727 ** h -- the header field to output. 1728 ** p -- the value to put in it. 1729 ** oldstyle -- true if this is an old style header. 1730 ** mci -- the connection information. 1731 ** e -- the envelope containing the message. 1732 ** 1733 ** Returns: 1734 ** none. 1735 ** 1736 ** Side Effects: 1737 ** outputs "p" to file "fp". 1738 */ 1739 1740 void 1741 commaize(h, p, oldstyle, mci, e) 1742 register HDR *h; 1743 register char *p; 1744 bool oldstyle; 1745 register MCI *mci; 1746 register ENVELOPE *e; 1747 { 1748 register char *obp; 1749 int opos; 1750 int omax; 1751 bool firstone = true; 1752 int putflags = PXLF_HEADER; 1753 char **res; 1754 char obuf[MAXLINE + 3]; 1755 1756 /* 1757 ** Output the address list translated by the 1758 ** mailer and with commas. 1759 */ 1760 1761 if (tTd(14, 2)) 1762 sm_dprintf("commaize(%s: %s)\n", h->h_field, p); 1763 1764 if (bitnset(M_7BITHDRS, mci->mci_mailer->m_flags)) 1765 putflags |= PXLF_STRIP8BIT; 1766 1767 obp = obuf; 1768 (void) sm_snprintf(obp, SPACELEFT(obuf, obp), "%.200s: ", 1769 h->h_field); 1770 1771 /* opos = strlen(obp); */ 1772 opos = strlen(h->h_field) + 2; 1773 if (opos > 202) 1774 opos = 202; 1775 obp += opos; 1776 omax = mci->mci_mailer->m_linelimit - 2; 1777 if (omax < 0 || omax > 78) 1778 omax = 78; 1779 1780 /* 1781 ** Run through the list of values. 1782 */ 1783 1784 while (*p != '\0') 1785 { 1786 register char *name; 1787 register int c; 1788 char savechar; 1789 int flags; 1790 auto int status; 1791 1792 /* 1793 ** Find the end of the name. New style names 1794 ** end with a comma, old style names end with 1795 ** a space character. However, spaces do not 1796 ** necessarily delimit an old-style name -- at 1797 ** signs mean keep going. 1798 */ 1799 1800 /* find end of name */ 1801 while ((isascii(*p) && isspace(*p)) || *p == ',') 1802 p++; 1803 name = p; 1804 res = NULL; 1805 for (;;) 1806 { 1807 auto char *oldp; 1808 char pvpbuf[PSBUFSIZE]; 1809 1810 res = prescan(p, oldstyle ? ' ' : ',', pvpbuf, 1811 sizeof pvpbuf, &oldp, NULL); 1812 p = oldp; 1813 #if _FFR_IGNORE_BOGUS_ADDR 1814 /* ignore addresses that can't be parsed */ 1815 if (res == NULL) 1816 { 1817 name = p; 1818 continue; 1819 } 1820 #endif /* _FFR_IGNORE_BOGUS_ADDR */ 1821 1822 /* look to see if we have an at sign */ 1823 while (*p != '\0' && isascii(*p) && isspace(*p)) 1824 p++; 1825 1826 if (*p != '@') 1827 { 1828 p = oldp; 1829 break; 1830 } 1831 ++p; 1832 while (*p != '\0' && isascii(*p) && isspace(*p)) 1833 p++; 1834 } 1835 /* at the end of one complete name */ 1836 1837 /* strip off trailing white space */ 1838 while (p >= name && 1839 ((isascii(*p) && isspace(*p)) || *p == ',' || *p == '\0')) 1840 p--; 1841 if (++p == name) 1842 continue; 1843 1844 /* 1845 ** if prescan() failed go a bit backwards; this is a hack, 1846 ** there should be some better error recovery. 1847 */ 1848 1849 if (res == NULL && p > name && 1850 !((isascii(*p) && isspace(*p)) || *p == ',' || *p == '\0')) 1851 --p; 1852 savechar = *p; 1853 *p = '\0'; 1854 1855 /* translate the name to be relative */ 1856 flags = RF_HEADERADDR|RF_ADDDOMAIN; 1857 if (bitset(H_FROM, h->h_flags)) 1858 flags |= RF_SENDERADDR; 1859 #if USERDB 1860 else if (e->e_from.q_mailer != NULL && 1861 bitnset(M_UDBRECIPIENT, e->e_from.q_mailer->m_flags)) 1862 { 1863 char *q; 1864 1865 q = udbsender(name, e->e_rpool); 1866 if (q != NULL) 1867 name = q; 1868 } 1869 #endif /* USERDB */ 1870 status = EX_OK; 1871 name = remotename(name, mci->mci_mailer, flags, &status, e); 1872 if (*name == '\0') 1873 { 1874 *p = savechar; 1875 continue; 1876 } 1877 name = denlstring(name, false, true); 1878 1879 /* 1880 ** record data progress so DNS timeouts 1881 ** don't cause DATA timeouts 1882 */ 1883 1884 DataProgress = true; 1885 1886 /* output the name with nice formatting */ 1887 opos += strlen(name); 1888 if (!firstone) 1889 opos += 2; 1890 if (opos > omax && !firstone) 1891 { 1892 (void) sm_strlcpy(obp, ",\n", SPACELEFT(obuf, obp)); 1893 putxline(obuf, strlen(obuf), mci, putflags); 1894 obp = obuf; 1895 (void) sm_strlcpy(obp, " ", sizeof obuf); 1896 opos = strlen(obp); 1897 obp += opos; 1898 opos += strlen(name); 1899 } 1900 else if (!firstone) 1901 { 1902 (void) sm_strlcpy(obp, ", ", SPACELEFT(obuf, obp)); 1903 obp += 2; 1904 } 1905 1906 while ((c = *name++) != '\0' && obp < &obuf[MAXLINE]) 1907 *obp++ = c; 1908 firstone = false; 1909 *p = savechar; 1910 } 1911 if (obp < &obuf[sizeof obuf]) 1912 *obp = '\0'; 1913 else 1914 obuf[sizeof obuf - 1] = '\0'; 1915 putxline(obuf, strlen(obuf), mci, putflags); 1916 } 1917 /* 1918 ** COPYHEADER -- copy header list 1919 ** 1920 ** This routine is the equivalent of newstr for header lists 1921 ** 1922 ** Parameters: 1923 ** header -- list of header structures to copy. 1924 ** rpool -- resource pool, or NULL 1925 ** 1926 ** Returns: 1927 ** a copy of 'header'. 1928 ** 1929 ** Side Effects: 1930 ** none. 1931 */ 1932 1933 HDR * 1934 copyheader(header, rpool) 1935 register HDR *header; 1936 SM_RPOOL_T *rpool; 1937 { 1938 register HDR *newhdr; 1939 HDR *ret; 1940 register HDR **tail = &ret; 1941 1942 while (header != NULL) 1943 { 1944 newhdr = (HDR *) sm_rpool_malloc_x(rpool, sizeof *newhdr); 1945 STRUCTCOPY(*header, *newhdr); 1946 *tail = newhdr; 1947 tail = &newhdr->h_link; 1948 header = header->h_link; 1949 } 1950 *tail = NULL; 1951 1952 return ret; 1953 } 1954 /* 1955 ** FIX_MIME_HEADER -- possibly truncate/rebalance parameters in a MIME header 1956 ** 1957 ** Run through all of the parameters of a MIME header and 1958 ** possibly truncate and rebalance the parameter according 1959 ** to MaxMimeFieldLength. 1960 ** 1961 ** Parameters: 1962 ** h -- the header to truncate/rebalance 1963 ** e -- the current envelope 1964 ** 1965 ** Returns: 1966 ** length of last offending field, 0 if all ok. 1967 ** 1968 ** Side Effects: 1969 ** string modified in place 1970 */ 1971 1972 static size_t 1973 fix_mime_header(h, e) 1974 HDR *h; 1975 ENVELOPE *e; 1976 { 1977 char *begin = h->h_value; 1978 char *end; 1979 size_t len = 0; 1980 size_t retlen = 0; 1981 1982 if (begin == NULL || *begin == '\0') 1983 return 0; 1984 1985 /* Split on each ';' */ 1986 /* find_character() never returns NULL */ 1987 while ((end = find_character(begin, ';')) != NULL) 1988 { 1989 char save = *end; 1990 char *bp; 1991 1992 *end = '\0'; 1993 1994 len = strlen(begin); 1995 1996 /* Shorten individual parameter */ 1997 if (shorten_rfc822_string(begin, MaxMimeFieldLength)) 1998 { 1999 if (len < MaxMimeFieldLength) 2000 { 2001 /* we only rebalanced a bogus field */ 2002 sm_syslog(LOG_ALERT, e->e_id, 2003 "Fixed MIME %s header field (possible attack)", 2004 h->h_field); 2005 if (tTd(34, 11)) 2006 sm_dprintf(" fixed MIME %s header field (possible attack)\n", 2007 h->h_field); 2008 } 2009 else 2010 { 2011 /* we actually shortened the header */ 2012 retlen = len; 2013 } 2014 } 2015 2016 /* Collapse the possibly shortened string with rest */ 2017 bp = begin + strlen(begin); 2018 if (bp != end) 2019 { 2020 char *ep = end; 2021 2022 *end = save; 2023 end = bp; 2024 2025 /* copy character by character due to overlap */ 2026 while (*ep != '\0') 2027 *bp++ = *ep++; 2028 *bp = '\0'; 2029 } 2030 else 2031 *end = save; 2032 if (*end == '\0') 2033 break; 2034 2035 /* Move past ';' */ 2036 begin = end + 1; 2037 } 2038 return retlen; 2039 } 2040