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