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 16SM_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 23static 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 */ 38static 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 79int NextMacroId = 1; /* codes for long named macros */ 80/* see sendmail.h: Special characters in rewriting rules. */ 81#else /* _FFR_MORE_MACROS */ 82int 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 103struct 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 130void 131initmacros(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 181static void doexpand __P(( char *, char *, size_t, int, ENVELOPE *)); 182 183static void 184doexpand(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 354void 355expand(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 395void 396#if SM_HEAP_CHECK 397macdefine_tagged(mac, vclass, id, value, file, line, grp) 398#else /* SM_HEAP_CHECK */ 399macdefine(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 484void 485macset(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 519char * 520macvalue(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 561char * 562macname(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 605int 606macid_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 721bool 722wordinclass(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