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
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
initmacros(e)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
doexpand(s,buf,bufsize,explevel,e)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
expand(s,buf,bufsize,e)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 ** MACTABCLEAR -- clear entire macro table
366 **
367 ** Parameters:
368 ** mac -- Macro table.
369 **
370 ** Returns:
371 ** none.
372 **
373 ** Side Effects:
374 ** clears entire mac structure including rpool pointer!
375 */
376
377 void
mactabclear(mac)378 mactabclear(mac)
379 MACROS_T *mac;
380 {
381 int i;
382
383 if (mac->mac_rpool == NULL)
384 {
385 for (i = 0; i < MAXMACROID; i++)
386 SM_FREE(mac->mac_table[i]);
387 }
388 memset((char *) mac, '\0', sizeof(*mac));
389 }
390
391 /*
392 ** MACDEFINE -- bind a macro name to a value
393 **
394 ** Set a macro to a value, with fancy storage management.
395 ** macdefine will make a copy of the value, if required,
396 ** and will ensure that the storage for the previous value
397 ** is not leaked.
398 **
399 ** Parameters:
400 ** mac -- Macro table.
401 ** vclass -- storage class of 'value', ignored if value==NULL.
402 ** A_HEAP means that the value was allocated by
403 ** malloc, and that macdefine owns the storage.
404 ** A_TEMP means that value points to temporary storage,
405 ** and thus macdefine needs to make a copy.
406 ** A_PERM means that value points to storage that
407 ** will remain allocated and unchanged for
408 ** at least the lifetime of mac. Use A_PERM if:
409 ** -- value == NULL,
410 ** -- value points to a string literal,
411 ** -- value was allocated from mac->mac_rpool
412 ** or (in the case of an envelope macro)
413 ** from e->e_rpool,
414 ** -- in the case of an envelope macro,
415 ** value is a string member of the envelope
416 ** such as e->e_sender.
417 ** id -- Macro id. This is a single character macro name
418 ** such as 'g', or a value returned by macid().
419 ** value -- Macro value: either NULL, or a string.
420 */
421
422 void
423 #if SM_HEAP_CHECK
macdefine_tagged(mac,vclass,id,value,file,line,grp)424 macdefine_tagged(mac, vclass, id, value, file, line, grp)
425 #else /* SM_HEAP_CHECK */
426 macdefine(mac, vclass, id, value)
427 #endif /* SM_HEAP_CHECK */
428 MACROS_T *mac;
429 ARGCLASS_T vclass;
430 int id;
431 char *value;
432 #if SM_HEAP_CHECK
433 char *file;
434 int line;
435 int grp;
436 #endif /* SM_HEAP_CHECK */
437 {
438 char *newvalue;
439
440 if (id < 0 || id > MAXMACROID)
441 return;
442
443 if (tTd(35, 9))
444 {
445 sm_dprintf("%sdefine(%s as ",
446 mac->mac_table[id] == NULL ? "" : "re", macname(id));
447 xputs(sm_debug_file(), value);
448 sm_dprintf(")\n");
449 }
450
451 if (mac->mac_rpool == NULL)
452 {
453 char *freeit = NULL;
454
455 if (mac->mac_table[id] != NULL &&
456 bitnset(id, mac->mac_allocated))
457 freeit = mac->mac_table[id];
458
459 if (value == NULL || vclass == A_HEAP)
460 {
461 sm_heap_checkptr_tagged(value, file, line);
462 newvalue = value;
463 clrbitn(id, mac->mac_allocated);
464 }
465 else
466 {
467 #if SM_HEAP_CHECK
468 newvalue = sm_strdup_tagged_x(value, file, line, 0);
469 #else
470 newvalue = sm_strdup_x(value);
471 #endif
472 setbitn(id, mac->mac_allocated);
473 }
474 mac->mac_table[id] = newvalue;
475 if (freeit != NULL)
476 sm_free(freeit);
477 }
478 else
479 {
480 if (value == NULL || vclass == A_PERM)
481 newvalue = value;
482 else
483 newvalue = sm_rpool_strdup_x(mac->mac_rpool, value);
484 mac->mac_table[id] = newvalue;
485 if (vclass == A_HEAP)
486 sm_free(value);
487 }
488
489 #if _FFR_RESET_MACRO_GLOBALS
490 switch (id)
491 {
492 case 'j':
493 PSTRSET(MyHostName, value);
494 break;
495 }
496 #endif /* _FFR_RESET_MACRO_GLOBALS */
497 }
498
499 /*
500 ** MACSET -- set a named macro to a value (low level)
501 **
502 ** No fancy storage management; the caller takes full responsibility.
503 ** Often used with macget; see also macdefine.
504 **
505 ** Parameters:
506 ** mac -- Macro table.
507 ** i -- Macro name, specified as an integer offset.
508 ** value -- Macro value: either NULL, or a string.
509 */
510
511 void
macset(mac,i,value)512 macset(mac, i, value)
513 MACROS_T *mac;
514 int i;
515 char *value;
516 {
517 if (i < 0 || i > MAXMACROID)
518 return;
519
520 if (tTd(35, 9))
521 {
522 sm_dprintf("macset(%s as ", macname(i));
523 xputs(sm_debug_file(), value);
524 sm_dprintf(")\n");
525 }
526 mac->mac_table[i] = value;
527 }
528
529 /*
530 ** MACVALUE -- return uninterpreted value of a macro.
531 **
532 ** Does fancy path searching.
533 ** The low level counterpart is macget.
534 **
535 ** Parameters:
536 ** n -- the name of the macro.
537 ** e -- envelope in which to start looking for the macro.
538 **
539 ** Returns:
540 ** The value of n.
541 **
542 ** Side Effects:
543 ** none.
544 */
545
546 char *
macvalue(n,e)547 macvalue(n, e)
548 int n;
549 ENVELOPE *e;
550 {
551 n = bitidx(n);
552 if (e != NULL && e->e_mci != NULL)
553 {
554 char *p = e->e_mci->mci_macro.mac_table[n];
555
556 if (p != NULL)
557 return p;
558 }
559 while (e != NULL)
560 {
561 char *p = e->e_macro.mac_table[n];
562
563 if (p != NULL)
564 return p;
565 if (e == e->e_parent)
566 break;
567 e = e->e_parent;
568 }
569 #if _FFR_BLANKENV_MACV
570 if (LOOKUP_MACRO_IN_BLANKENV && e != &BlankEnvelope)
571 {
572 char *p = BlankEnvelope.e_macro.mac_table[n];
573
574 if (p != NULL)
575 return p;
576 }
577 #endif
578 return GlobalMacros.mac_table[n];
579 }
580
581 /*
582 ** MACNAME -- return the name of a macro given its internal id
583 **
584 ** Parameter:
585 ** n -- the id of the macro
586 **
587 ** Returns:
588 ** The name of n.
589 **
590 ** Side Effects:
591 ** none.
592 **
593 ** WARNING:
594 ** Not thread-safe.
595 */
596
597 char *
macname(n)598 macname(n)
599 int n;
600 {
601 static char mbuf[2];
602
603 n = (int)(unsigned char)n;
604 if (n > MAXMACROID)
605 return "***OUT OF RANGE MACRO***";
606
607 /* if not ASCII printable, look up the name */
608 if (n <= 0x20 || n > 0x7f)
609 {
610 char *p = MacroName[n];
611
612 if (p != NULL)
613 return p;
614 return "***UNDEFINED MACRO***";
615 }
616
617 /* if in the ASCII graphic range, just return the id directly */
618 mbuf[0] = n;
619 mbuf[1] = '\0';
620 return mbuf;
621 }
622
623 /*
624 ** MACID_PARSE -- return id of macro identified by its name
625 **
626 ** Parameters:
627 ** p -- pointer to name string -- either a single
628 ** character or {name}.
629 ** ep -- filled in with the pointer to the byte
630 ** after the name.
631 **
632 ** Returns:
633 ** 0 -- An error was detected.
634 ** 1..MAXMACROID -- The internal id code for this macro.
635 **
636 ** Side Effects:
637 ** If this is a new macro name, a new id is allocated.
638 ** On error, syserr is called.
639 */
640
641 int
macid_parse(p,ep)642 macid_parse(p, ep)
643 char *p;
644 char **ep;
645 {
646 int mid;
647 char *bp;
648 char mbuf[MAXMACNAMELEN + 1];
649
650 if (tTd(35, 14))
651 {
652 sm_dprintf("macid(");
653 xputs(sm_debug_file(), p);
654 sm_dprintf(") => ");
655 }
656
657 if (*p == '\0' || (p[0] == '{' && p[1] == '}'))
658 {
659 syserr("Name required for macro/class");
660 if (ep != NULL)
661 *ep = p;
662 if (tTd(35, 14))
663 sm_dprintf("NULL\n");
664 return 0;
665 }
666 if (*p != '{')
667 {
668 /* the macro is its own code */
669 if (ep != NULL)
670 *ep = p + 1;
671 if (tTd(35, 14))
672 {
673 char buf[2];
674
675 buf[0] = *p;
676 buf[1] = '\0';
677 xputs(sm_debug_file(), buf);
678 sm_dprintf("\n");
679 }
680 return bitidx(*p);
681 }
682 bp = mbuf;
683 while (*++p != '\0' && *p != '}' && bp < &mbuf[sizeof(mbuf) - 1])
684 {
685 if (isascii(*p) && (isalnum(*p) || *p == '_'))
686 *bp++ = *p;
687 else
688 syserr("Invalid macro/class character %c", *p);
689 }
690 *bp = '\0';
691 mid = -1;
692 if (*p == '\0')
693 {
694 syserr("Unbalanced { on %s", mbuf); /* missing } */
695 }
696 else if (*p != '}')
697 {
698 syserr("Macro/class name ({%s}) too long (%d chars max)",
699 mbuf, (int) (sizeof(mbuf) - 1));
700 }
701 else if (mbuf[1] == '\0' && mbuf[0] >= 0x20)
702 {
703 /* ${x} == $x */
704 mid = bitidx(mbuf[0]);
705 p++;
706 }
707 else
708 {
709 STAB *s;
710
711 s = stab(mbuf, ST_MACRO, ST_ENTER);
712 if (s->s_macro != 0)
713 mid = s->s_macro;
714 else
715 {
716 if (NextMacroId > MAXMACROID)
717 {
718 syserr("Macro/class {%s}: too many long names",
719 mbuf);
720 s->s_macro = -1;
721 }
722 else
723 {
724 MacroName[NextMacroId] = s->s_name;
725 s->s_macro = mid = NextMacroId;
726 NextMacroId = NEXTMACROID(NextMacroId);
727 }
728 }
729 p++;
730 }
731 if (ep != NULL)
732 *ep = p;
733 if (mid < 0 || mid > MAXMACROID)
734 {
735 syserr("Unable to assign macro/class ID (mid = 0x%x)", mid);
736 if (tTd(35, 14))
737 sm_dprintf("NULL\n");
738 return 0;
739 }
740 if (tTd(35, 14))
741 sm_dprintf("0x%x\n", mid);
742 return mid;
743 }
744
745 /*
746 ** WORDINCLASS -- tell if a word is in a specific class
747 **
748 ** Parameters:
749 ** str -- the name of the word to look up.
750 ** cl -- the class name.
751 **
752 ** Returns:
753 ** true if str can be found in cl.
754 ** false otherwise.
755 */
756
757 bool
wordinclass(str,cl)758 wordinclass(str, cl)
759 char *str;
760 int cl;
761 {
762 STAB *s;
763
764 s = stab(str, ST_CLASS, ST_FIND);
765 return s != NULL && bitnset(bitidx(cl), s->s_class);
766 }
767