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