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