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