1 /* 2 * Copyright (c) 1998-2001, 2003, 2006, 2007 Proofpoint, 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 #include <sendmail.h> 15 16 SM_RCSID("@(#)$Id: macro.c,v 8.108 2013-11-22 20:51:55 ca Exp $") 17 18 #include <sm/sendmail.h> 19 #if MAXMACROID != (BITMAPBITS - 1) 20 ERROR Read the comment in conf.h 21 #endif /* MAXMACROID != (BITMAPBITS - 1) */ 22 23 static char *MacroName[MAXMACROID + 1]; /* macro id to name table */ 24 25 /* 26 ** Codes for long named macros. 27 ** See also macname(): 28 * if not ASCII printable, look up the name * 29 if (n <= 0x20 || n > 0x7f) 30 ** First use 1 to NEXTMACROID_L, then use NEXTMACROID_H to MAXMACROID. 31 */ 32 33 #define NEXTMACROID_L 037 34 #define NEXTMACROID_H 0240 35 36 #if _FFR_MORE_MACROS 37 /* table for next id in non-printable ASCII range: disallow some value */ 38 static int NextMIdTable[] = 39 { 40 /* 0 nul */ 1, 41 /* 1 soh */ 2, 42 /* 2 stx */ 3, 43 /* 3 etx */ 4, 44 /* 4 eot */ 5, 45 /* 5 enq */ 6, 46 /* 6 ack */ 7, 47 /* 7 bel */ 8, 48 /* 8 bs */ 14, 49 /* 9 ht */ -1, 50 /* 10 nl */ -1, 51 /* 11 vt */ -1, 52 /* 12 np */ -1, 53 /* 13 cr */ -1, 54 /* 14 so */ 15, 55 /* 15 si */ 16, 56 /* 16 dle */ 17, 57 /* 17 dc1 */ 18, 58 /* 18 dc2 */ 19, 59 /* 19 dc3 */ 20, 60 /* 20 dc4 */ 21, 61 /* 21 nak */ 22, 62 /* 22 syn */ 23, 63 /* 23 etb */ 24, 64 /* 24 can */ 25, 65 /* 25 em */ 26, 66 /* 26 sub */ 27, 67 /* 27 esc */ 28, 68 /* 28 fs */ 29, 69 /* 29 gs */ 30, 70 /* 30 rs */ 31, 71 /* 31 us */ 32, 72 /* 32 sp */ -1, 73 }; 74 75 #define NEXTMACROID(mid) ( \ 76 (mid < NEXTMACROID_L) ? (NextMIdTable[mid]) : \ 77 ((mid < NEXTMACROID_H) ? NEXTMACROID_H : (mid + 1))) 78 79 int NextMacroId = 1; /* codes for long named macros */ 80 /* see sendmail.h: Special characters in rewriting rules. */ 81 #else /* _FFR_MORE_MACROS */ 82 int NextMacroId = 0240; /* codes for long named macros */ 83 #define NEXTMACROID(mid) ((mid) + 1) 84 #endif /* _FFR_MORE_MACROS */ 85 86 87 /* 88 ** INITMACROS -- initialize the macro system 89 ** 90 ** This just involves defining some macros that are actually 91 ** used internally as metasymbols to be themselves. 92 ** 93 ** Parameters: 94 ** none. 95 ** 96 ** Returns: 97 ** none. 98 ** 99 ** Side Effects: 100 ** initializes several macros to be themselves. 101 */ 102 103 struct metamac MetaMacros[] = 104 { 105 /* LHS pattern matching characters */ 106 { '*', MATCHZANY }, { '+', MATCHANY }, { '-', MATCHONE }, 107 { '=', MATCHCLASS }, { '~', MATCHNCLASS }, 108 109 /* these are RHS metasymbols */ 110 { '#', CANONNET }, { '@', CANONHOST }, { ':', CANONUSER }, 111 { '>', CALLSUBR }, 112 113 /* the conditional operations */ 114 { '?', CONDIF }, { '|', CONDELSE }, { '.', CONDFI }, 115 116 /* the hostname lookup characters */ 117 { '[', HOSTBEGIN }, { ']', HOSTEND }, 118 { '(', LOOKUPBEGIN }, { ')', LOOKUPEND }, 119 120 /* miscellaneous control characters */ 121 { '&', MACRODEXPAND }, 122 123 { '\0', '\0' } 124 }; 125 126 #define MACBINDING(name, mid) \ 127 stab(name, ST_MACRO, ST_ENTER)->s_macro = mid; \ 128 MacroName[mid] = name; 129 130 void 131 initmacros(e) 132 ENVELOPE *e; 133 { 134 struct metamac *m; 135 int c; 136 char buf[5]; 137 138 for (m = MetaMacros; m->metaname != '\0'; m++) 139 { 140 buf[0] = m->metaval; 141 buf[1] = '\0'; 142 macdefine(&e->e_macro, A_TEMP, m->metaname, buf); 143 } 144 buf[0] = MATCHREPL; 145 buf[2] = '\0'; 146 for (c = '0'; c <= '9'; c++) 147 { 148 buf[1] = c; 149 macdefine(&e->e_macro, A_TEMP, c, buf); 150 } 151 152 /* set defaults for some macros sendmail will use later */ 153 macdefine(&e->e_macro, A_PERM, 'n', "MAILER-DAEMON"); 154 155 /* set up external names for some internal macros */ 156 MACBINDING("opMode", MID_OPMODE); 157 /*XXX should probably add equivalents for all short macros here XXX*/ 158 } 159 160 /* 161 ** EXPAND/DOEXPAND -- macro expand a string using $x escapes. 162 ** 163 ** After expansion, the expansion will be in external form (that is, 164 ** there will be no sendmail metacharacters and METAQUOTEs will have 165 ** been stripped out). 166 ** 167 ** Parameters: 168 ** s -- the string to expand. 169 ** buf -- the place to put the expansion. 170 ** bufsize -- the size of the buffer. 171 ** explevel -- the depth of expansion (doexpand only) 172 ** e -- envelope in which to work. 173 ** 174 ** Returns: 175 ** none. 176 ** 177 ** Side Effects: 178 ** none. 179 */ 180 181 static void doexpand __P(( char *, char *, size_t, int, ENVELOPE *)); 182 183 static void 184 doexpand(s, buf, bufsize, explevel, e) 185 char *s; 186 char *buf; 187 size_t bufsize; 188 int explevel; 189 ENVELOPE *e; 190 { 191 char *xp; 192 char *q; 193 bool skipping; /* set if conditionally skipping output */ 194 bool recurse; /* set if recursion required */ 195 size_t i; 196 int skiplev; /* skipping nesting level */ 197 int iflev; /* if nesting level */ 198 bool quotenext; /* quote the following character */ 199 char xbuf[MACBUFSIZE]; 200 201 if (tTd(35, 24)) 202 { 203 sm_dprintf("expand("); 204 xputs(sm_debug_file(), s); 205 sm_dprintf(")\n"); 206 } 207 208 recurse = false; 209 skipping = false; 210 skiplev = 0; 211 iflev = 0; 212 quotenext = false; 213 if (s == NULL) 214 s = ""; 215 for (xp = xbuf; *s != '\0'; s++) 216 { 217 int c; 218 219 /* 220 ** Check for non-ordinary (special?) character. 221 ** 'q' will be the interpolated quantity. 222 */ 223 224 q = NULL; 225 c = *s & 0377; 226 227 if (quotenext) 228 { 229 quotenext = false; 230 goto simpleinterpolate; 231 } 232 233 switch (c) 234 { 235 case CONDIF: /* see if var set */ 236 iflev++; 237 c = *++s & 0377; 238 if (skipping) 239 skiplev++; 240 else 241 { 242 char *mv; 243 244 mv = macvalue(c, e); 245 skipping = (mv == NULL || *mv == '\0'); 246 } 247 continue; 248 249 case CONDELSE: /* change state of skipping */ 250 if (iflev == 0) 251 break; /* XXX: error */ 252 if (skiplev == 0) 253 skipping = !skipping; 254 continue; 255 256 case CONDFI: /* stop skipping */ 257 if (iflev == 0) 258 break; /* XXX: error */ 259 iflev--; 260 if (skiplev == 0) 261 skipping = false; 262 if (skipping) 263 skiplev--; 264 continue; 265 266 case MACROEXPAND: /* macro interpolation */ 267 c = bitidx(*++s); 268 if (c != '\0') 269 q = macvalue(c, e); 270 else 271 { 272 s--; 273 q = NULL; 274 } 275 if (q == NULL) 276 continue; 277 break; 278 279 case METAQUOTE: 280 /* next octet completely quoted */ 281 quotenext = true; 282 break; 283 } 284 285 /* 286 ** Interpolate q or output one character 287 */ 288 289 simpleinterpolate: 290 if (skipping || xp >= &xbuf[sizeof(xbuf) - 1]) 291 continue; 292 if (q == NULL) 293 *xp++ = c; 294 else 295 { 296 /* copy to end of q or max space remaining in buf */ 297 bool hiderecurse = false; 298 299 while ((c = *q++) != '\0' && 300 xp < &xbuf[sizeof(xbuf) - 1]) 301 { 302 /* check for any sendmail metacharacters */ 303 if (!hiderecurse && (c & 0340) == 0200) 304 recurse = true; 305 *xp++ = c; 306 307 /* give quoted characters a free ride */ 308 hiderecurse = (c & 0377) == METAQUOTE; 309 } 310 } 311 } 312 *xp = '\0'; 313 314 if (tTd(35, 28)) 315 { 316 sm_dprintf("expand(%d) ==> ", explevel); 317 xputs(sm_debug_file(), xbuf); 318 sm_dprintf("\n"); 319 } 320 321 /* recurse as appropriate */ 322 if (recurse) 323 { 324 if (explevel < MaxMacroRecursion) 325 { 326 doexpand(xbuf, buf, bufsize, explevel + 1, e); 327 return; 328 } 329 syserr("expand: recursion too deep (%d max)", 330 MaxMacroRecursion); 331 } 332 333 /* copy results out */ 334 if (explevel == 0) 335 (void) sm_strlcpy(buf, xbuf, bufsize); 336 else 337 { 338 /* leave in internal form */ 339 i = xp - xbuf; 340 if (i >= bufsize) 341 i = bufsize - 1; 342 memmove(buf, xbuf, i); 343 buf[i] = '\0'; 344 } 345 346 if (tTd(35, 24)) 347 { 348 sm_dprintf("expand ==> "); 349 xputs(sm_debug_file(), buf); 350 sm_dprintf("\n"); 351 } 352 } 353 354 void 355 expand(s, buf, bufsize, e) 356 char *s; 357 char *buf; 358 size_t bufsize; 359 ENVELOPE *e; 360 { 361 doexpand(s, buf, bufsize, 0, e); 362 } 363 364 /* 365 ** MACDEFINE -- bind a macro name to a value 366 ** 367 ** Set a macro to a value, with fancy storage management. 368 ** macdefine will make a copy of the value, if required, 369 ** and will ensure that the storage for the previous value 370 ** is not leaked. 371 ** 372 ** Parameters: 373 ** mac -- Macro table. 374 ** vclass -- storage class of 'value', ignored if value==NULL. 375 ** A_HEAP means that the value was allocated by 376 ** malloc, and that macdefine owns the storage. 377 ** A_TEMP means that value points to temporary storage, 378 ** and thus macdefine needs to make a copy. 379 ** A_PERM means that value points to storage that 380 ** will remain allocated and unchanged for 381 ** at least the lifetime of mac. Use A_PERM if: 382 ** -- value == NULL, 383 ** -- value points to a string literal, 384 ** -- value was allocated from mac->mac_rpool 385 ** or (in the case of an envelope macro) 386 ** from e->e_rpool, 387 ** -- in the case of an envelope macro, 388 ** value is a string member of the envelope 389 ** such as e->e_sender. 390 ** id -- Macro id. This is a single character macro name 391 ** such as 'g', or a value returned by macid(). 392 ** value -- Macro value: either NULL, or a string. 393 */ 394 395 void 396 #if SM_HEAP_CHECK 397 macdefine_tagged(mac, vclass, id, value, file, line, grp) 398 #else /* SM_HEAP_CHECK */ 399 macdefine(mac, vclass, id, value) 400 #endif /* SM_HEAP_CHECK */ 401 MACROS_T *mac; 402 ARGCLASS_T vclass; 403 int id; 404 char *value; 405 #if SM_HEAP_CHECK 406 char *file; 407 int line; 408 int grp; 409 #endif /* SM_HEAP_CHECK */ 410 { 411 char *newvalue; 412 413 if (id < 0 || id > MAXMACROID) 414 return; 415 416 if (tTd(35, 9)) 417 { 418 sm_dprintf("%sdefine(%s as ", 419 mac->mac_table[id] == NULL ? "" : "re", macname(id)); 420 xputs(sm_debug_file(), value); 421 sm_dprintf(")\n"); 422 } 423 424 if (mac->mac_rpool == NULL) 425 { 426 char *freeit = NULL; 427 428 if (mac->mac_table[id] != NULL && 429 bitnset(id, mac->mac_allocated)) 430 freeit = mac->mac_table[id]; 431 432 if (value == NULL || vclass == A_HEAP) 433 { 434 sm_heap_checkptr_tagged(value, file, line); 435 newvalue = value; 436 clrbitn(id, mac->mac_allocated); 437 } 438 else 439 { 440 #if SM_HEAP_CHECK 441 newvalue = sm_strdup_tagged_x(value, file, line, 0); 442 #else /* SM_HEAP_CHECK */ 443 newvalue = sm_strdup_x(value); 444 #endif /* SM_HEAP_CHECK */ 445 setbitn(id, mac->mac_allocated); 446 } 447 mac->mac_table[id] = newvalue; 448 if (freeit != NULL) 449 sm_free(freeit); 450 } 451 else 452 { 453 if (value == NULL || vclass == A_PERM) 454 newvalue = value; 455 else 456 newvalue = sm_rpool_strdup_x(mac->mac_rpool, value); 457 mac->mac_table[id] = newvalue; 458 if (vclass == A_HEAP) 459 sm_free(value); 460 } 461 462 #if _FFR_RESET_MACRO_GLOBALS 463 switch (id) 464 { 465 case 'j': 466 PSTRSET(MyHostName, value); 467 break; 468 } 469 #endif /* _FFR_RESET_MACRO_GLOBALS */ 470 } 471 472 /* 473 ** MACSET -- set a named macro to a value (low level) 474 ** 475 ** No fancy storage management; the caller takes full responsibility. 476 ** Often used with macget; see also macdefine. 477 ** 478 ** Parameters: 479 ** mac -- Macro table. 480 ** i -- Macro name, specified as an integer offset. 481 ** value -- Macro value: either NULL, or a string. 482 */ 483 484 void 485 macset(mac, i, value) 486 MACROS_T *mac; 487 int i; 488 char *value; 489 { 490 if (i < 0 || i > MAXMACROID) 491 return; 492 493 if (tTd(35, 9)) 494 { 495 sm_dprintf("macset(%s as ", macname(i)); 496 xputs(sm_debug_file(), value); 497 sm_dprintf(")\n"); 498 } 499 mac->mac_table[i] = value; 500 } 501 502 /* 503 ** MACVALUE -- return uninterpreted value of a macro. 504 ** 505 ** Does fancy path searching. 506 ** The low level counterpart is macget. 507 ** 508 ** Parameters: 509 ** n -- the name of the macro. 510 ** e -- envelope in which to start looking for the macro. 511 ** 512 ** Returns: 513 ** The value of n. 514 ** 515 ** Side Effects: 516 ** none. 517 */ 518 519 char * 520 macvalue(n, e) 521 int n; 522 ENVELOPE *e; 523 { 524 n = bitidx(n); 525 if (e != NULL && e->e_mci != NULL) 526 { 527 char *p = e->e_mci->mci_macro.mac_table[n]; 528 529 if (p != NULL) 530 return p; 531 } 532 while (e != NULL) 533 { 534 char *p = e->e_macro.mac_table[n]; 535 536 if (p != NULL) 537 return p; 538 if (e == e->e_parent) 539 break; 540 e = e->e_parent; 541 } 542 return GlobalMacros.mac_table[n]; 543 } 544 545 /* 546 ** MACNAME -- return the name of a macro given its internal id 547 ** 548 ** Parameter: 549 ** n -- the id of the macro 550 ** 551 ** Returns: 552 ** The name of n. 553 ** 554 ** Side Effects: 555 ** none. 556 ** 557 ** WARNING: 558 ** Not thread-safe. 559 */ 560 561 char * 562 macname(n) 563 int n; 564 { 565 static char mbuf[2]; 566 567 n = (int)(unsigned char)n; 568 if (n > MAXMACROID) 569 return "***OUT OF RANGE MACRO***"; 570 571 /* if not ASCII printable, look up the name */ 572 if (n <= 0x20 || n > 0x7f) 573 { 574 char *p = MacroName[n]; 575 576 if (p != NULL) 577 return p; 578 return "***UNDEFINED MACRO***"; 579 } 580 581 /* if in the ASCII graphic range, just return the id directly */ 582 mbuf[0] = n; 583 mbuf[1] = '\0'; 584 return mbuf; 585 } 586 587 /* 588 ** MACID_PARSE -- return id of macro identified by its name 589 ** 590 ** Parameters: 591 ** p -- pointer to name string -- either a single 592 ** character or {name}. 593 ** ep -- filled in with the pointer to the byte 594 ** after the name. 595 ** 596 ** Returns: 597 ** 0 -- An error was detected. 598 ** 1..MAXMACROID -- The internal id code for this macro. 599 ** 600 ** Side Effects: 601 ** If this is a new macro name, a new id is allocated. 602 ** On error, syserr is called. 603 */ 604 605 int 606 macid_parse(p, ep) 607 char *p; 608 char **ep; 609 { 610 int mid; 611 char *bp; 612 char mbuf[MAXMACNAMELEN + 1]; 613 614 if (tTd(35, 14)) 615 { 616 sm_dprintf("macid("); 617 xputs(sm_debug_file(), p); 618 sm_dprintf(") => "); 619 } 620 621 if (*p == '\0' || (p[0] == '{' && p[1] == '}')) 622 { 623 syserr("Name required for macro/class"); 624 if (ep != NULL) 625 *ep = p; 626 if (tTd(35, 14)) 627 sm_dprintf("NULL\n"); 628 return 0; 629 } 630 if (*p != '{') 631 { 632 /* the macro is its own code */ 633 if (ep != NULL) 634 *ep = p + 1; 635 if (tTd(35, 14)) 636 { 637 char buf[2]; 638 639 buf[0] = *p; 640 buf[1] = '\0'; 641 xputs(sm_debug_file(), buf); 642 sm_dprintf("\n"); 643 } 644 return bitidx(*p); 645 } 646 bp = mbuf; 647 while (*++p != '\0' && *p != '}' && bp < &mbuf[sizeof(mbuf) - 1]) 648 { 649 if (isascii(*p) && (isalnum(*p) || *p == '_')) 650 *bp++ = *p; 651 else 652 syserr("Invalid macro/class character %c", *p); 653 } 654 *bp = '\0'; 655 mid = -1; 656 if (*p == '\0') 657 { 658 syserr("Unbalanced { on %s", mbuf); /* missing } */ 659 } 660 else if (*p != '}') 661 { 662 syserr("Macro/class name ({%s}) too long (%d chars max)", 663 mbuf, (int) (sizeof(mbuf) - 1)); 664 } 665 else if (mbuf[1] == '\0' && mbuf[0] >= 0x20) 666 { 667 /* ${x} == $x */ 668 mid = bitidx(mbuf[0]); 669 p++; 670 } 671 else 672 { 673 STAB *s; 674 675 s = stab(mbuf, ST_MACRO, ST_ENTER); 676 if (s->s_macro != 0) 677 mid = s->s_macro; 678 else 679 { 680 if (NextMacroId > MAXMACROID) 681 { 682 syserr("Macro/class {%s}: too many long names", 683 mbuf); 684 s->s_macro = -1; 685 } 686 else 687 { 688 MacroName[NextMacroId] = s->s_name; 689 s->s_macro = mid = NextMacroId; 690 NextMacroId = NEXTMACROID(NextMacroId); 691 } 692 } 693 p++; 694 } 695 if (ep != NULL) 696 *ep = p; 697 if (mid < 0 || mid > MAXMACROID) 698 { 699 syserr("Unable to assign macro/class ID (mid = 0x%x)", mid); 700 if (tTd(35, 14)) 701 sm_dprintf("NULL\n"); 702 return 0; 703 } 704 if (tTd(35, 14)) 705 sm_dprintf("0x%x\n", mid); 706 return mid; 707 } 708 709 /* 710 ** WORDINCLASS -- tell if a word is in a specific class 711 ** 712 ** Parameters: 713 ** str -- the name of the word to look up. 714 ** cl -- the class name. 715 ** 716 ** Returns: 717 ** true if str can be found in cl. 718 ** false otherwise. 719 */ 720 721 bool 722 wordinclass(str, cl) 723 char *str; 724 int cl; 725 { 726 STAB *s; 727 728 s = stab(str, ST_CLASS, ST_FIND); 729 return s != NULL && bitnset(bitidx(cl), s->s_class); 730 } 731