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