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