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 ** INITMACROS -- initialize the macro system
88 **
89 ** This just involves defining some macros that are actually
90 ** used internally as metasymbols to be themselves.
91 **
92 ** Parameters:
93 ** none.
94 **
95 ** Returns:
96 ** none.
97 **
98 ** Side Effects:
99 ** initializes several macros to be themselves.
100 */
101
102 struct metamac MetaMacros[] =
103 {
104 /* LHS pattern matching characters */
105 { '*', MATCHZANY }, { '+', MATCHANY }, { '-', MATCHONE },
106 { '=', MATCHCLASS }, { '~', MATCHNCLASS },
107
108 /* these are RHS metasymbols */
109 { '#', CANONNET }, { '@', CANONHOST }, { ':', CANONUSER },
110 { '>', CALLSUBR },
111
112 /* the conditional operations */
113 { '?', CONDIF }, { '|', CONDELSE }, { '.', CONDFI },
114
115 /* the hostname lookup characters */
116 { '[', HOSTBEGIN }, { ']', HOSTEND },
117 { '(', LOOKUPBEGIN }, { ')', LOOKUPEND },
118
119 /* miscellaneous control characters */
120 { '&', MACRODEXPAND },
121
122 { '\0', '\0' }
123 };
124
125 #define MACBINDING(name, mid) \
126 stab(name, ST_MACRO, ST_ENTER)->s_macro = mid; \
127 MacroName[mid] = name;
128
129 void
initmacros(e)130 initmacros(e)
131 ENVELOPE *e;
132 {
133 struct metamac *m;
134 int c;
135 char buf[5];
136
137 for (m = MetaMacros; m->metaname != '\0'; m++)
138 {
139 buf[0] = m->metaval;
140 buf[1] = '\0';
141 macdefine(&e->e_macro, A_TEMP, m->metaname, buf);
142 }
143 buf[0] = MATCHREPL;
144 buf[2] = '\0';
145 for (c = '0'; c <= '9'; c++)
146 {
147 buf[1] = c;
148 macdefine(&e->e_macro, A_TEMP, c, buf);
149 }
150
151 /* set defaults for some macros sendmail will use later */
152 macdefine(&e->e_macro, A_PERM, 'n', "MAILER-DAEMON");
153
154 /* set up external names for some internal macros */
155 MACBINDING("opMode", MID_OPMODE);
156 /*XXX should probably add equivalents for all short macros here XXX*/
157 }
158
159 /*
160 ** EXPAND/DOEXPAND -- macro expand a string using $x escapes.
161 ** (including conditionals, e.g., $?x Y $| N $.)
162 **
163 ** Parameters:
164 ** s -- the string to expand. [i]
165 ** buf -- the place to put the expansion. [i]
166 ** bufsize -- the size of the buffer.
167 ** explevel -- the depth of expansion (doexpand only)
168 ** e -- envelope in which to work.
169 **
170 ** Returns:
171 ** none.
172 */
173
174 static void doexpand __P(( char *, char *, size_t, int, ENVELOPE *));
175
176 static void
doexpand(s,buf,bufsize,explevel,e)177 doexpand(s, buf, bufsize, explevel, e)
178 char *s;
179 char *buf;
180 size_t bufsize;
181 int explevel;
182 ENVELOPE *e;
183 {
184 char *xp;
185 char *q;
186 bool skipping; /* set if conditionally skipping output */
187 bool recurse; /* set if recursion required */
188 size_t i;
189 int skiplev; /* skipping nesting level */
190 int iflev; /* if nesting level */
191 bool quotenext; /* quote the following character */
192 char xbuf[MACBUFSIZE];
193
194 if (tTd(35, 24))
195 {
196 sm_dprintf("expand(");
197 xputs(sm_debug_file(), s);
198 sm_dprintf(")\n");
199 }
200
201 recurse = false;
202 skipping = false;
203 skiplev = 0;
204 iflev = 0;
205 quotenext = false;
206 if (s == NULL)
207 s = "";
208 for (xp = xbuf; *s != '\0'; s++)
209 {
210 int c;
211
212 /*
213 ** Check for non-ordinary (special?) character.
214 ** 'q' will be the interpolated quantity.
215 */
216
217 q = NULL;
218 c = *s & 0377;
219
220 if (quotenext)
221 {
222 quotenext = false;
223 goto simpleinterpolate;
224 }
225
226 switch (c)
227 {
228 case CONDIF: /* see if var set */
229 iflev++;
230 c = *++s & 0377;
231 if (skipping)
232 skiplev++;
233 else
234 {
235 char *mv;
236
237 mv = macvalue(c, e);
238 skipping = (mv == NULL || *mv == '\0');
239 }
240 continue;
241
242 case CONDELSE: /* change state of skipping */
243 if (iflev == 0)
244 break; /* XXX: error */
245 if (skiplev == 0)
246 skipping = !skipping;
247 continue;
248
249 case CONDFI: /* stop skipping */
250 if (iflev == 0)
251 break; /* XXX: error */
252 iflev--;
253 if (skiplev == 0)
254 skipping = false;
255 if (skipping)
256 skiplev--;
257 continue;
258
259 case MACROEXPAND: /* macro interpolation */
260 c = bitidx(*++s);
261 if (c != '\0')
262 q = macvalue(c, e);
263 else
264 {
265 s--;
266 q = NULL;
267 }
268 if (q == NULL)
269 continue;
270 break;
271
272 case METAQUOTE:
273 /* next octet completely quoted */
274 quotenext = true;
275 break;
276 }
277
278 /*
279 ** Interpolate q or output one character
280 */
281
282 simpleinterpolate:
283 if (skipping || xp >= &xbuf[sizeof(xbuf) - 1])
284 continue;
285 if (q == NULL)
286 *xp++ = c;
287 else
288 {
289 /* copy to end of q or max space remaining in buf */
290 bool hiderecurse = false;
291
292 while ((c = *q++) != '\0' &&
293 xp < &xbuf[sizeof(xbuf) - 1])
294 {
295 /* check for any sendmail metacharacters */
296 if (!hiderecurse && (c & 0340) == 0200)
297 recurse = true;
298 *xp++ = c;
299
300 /* give quoted characters a free ride */
301 hiderecurse = (c & 0377) == METAQUOTE;
302 }
303 }
304 }
305 *xp = '\0';
306
307 if (tTd(35, 28))
308 {
309 sm_dprintf("expand(%d) ==> ", explevel);
310 xputs(sm_debug_file(), xbuf);
311 sm_dprintf("\n");
312 }
313
314 /* recurse as appropriate */
315 if (recurse)
316 {
317 if (explevel < MaxMacroRecursion)
318 {
319 doexpand(xbuf, buf, bufsize, explevel + 1, e);
320 return;
321 }
322 syserr("expand: recursion too deep (%d max)",
323 MaxMacroRecursion);
324 }
325
326 /* copy results out */
327 if (explevel == 0)
328 (void) sm_strlcpy(buf, xbuf, bufsize);
329 else
330 {
331 /* leave in internal form */
332 i = xp - xbuf;
333 if (i >= bufsize)
334 i = bufsize - 1;
335 memmove(buf, xbuf, i);
336 buf[i] = '\0';
337 }
338
339 if (tTd(35, 24))
340 {
341 sm_dprintf("expand ==> ");
342 xputs(sm_debug_file(), buf);
343 sm_dprintf("\n");
344 }
345 }
346
347 void
expand(s,buf,bufsize,e)348 expand(s, buf, bufsize, e)
349 char *s;
350 char *buf;
351 size_t bufsize;
352 ENVELOPE *e;
353 {
354 doexpand(s, buf, bufsize, 0, e);
355 }
356
357 /*
358 ** MACTABCLEAR -- clear entire macro table
359 **
360 ** Parameters:
361 ** mac -- Macro table.
362 **
363 ** Returns:
364 ** none.
365 **
366 ** Side Effects:
367 ** clears entire mac structure including rpool pointer!
368 */
369
370 void
mactabclear(mac)371 mactabclear(mac)
372 MACROS_T *mac;
373 {
374 int i;
375
376 if (mac->mac_rpool == NULL)
377 {
378 for (i = 0; i < MAXMACROID; i++)
379 SM_FREE(mac->mac_table[i]);
380 }
381 memset((char *) mac, '\0', sizeof(*mac));
382 }
383
384 /*
385 ** MACDEFINE -- bind a macro name to a value
386 **
387 ** Set a macro to a value, with fancy storage management.
388 ** macdefine will make a copy of the value, if required,
389 ** and will ensure that the storage for the previous value
390 ** is not leaked.
391 **
392 ** Parameters:
393 ** mac -- Macro table.
394 ** vclass -- storage class of 'value', ignored if value==NULL.
395 ** A_HEAP means that the value was allocated by
396 ** malloc, and that macdefine owns the storage.
397 ** A_TEMP means that value points to temporary storage,
398 ** and thus macdefine needs to make a copy.
399 ** A_PERM means that value points to storage that
400 ** will remain allocated and unchanged for
401 ** at least the lifetime of mac. Use A_PERM if:
402 ** -- value == NULL,
403 ** -- value points to a string literal,
404 ** -- value was allocated from mac->mac_rpool
405 ** or (in the case of an envelope macro)
406 ** from e->e_rpool,
407 ** -- in the case of an envelope macro,
408 ** value is a string member of the envelope
409 ** such as e->e_sender.
410 ** id -- Macro id. This is a single character macro name
411 ** such as 'g', or a value returned by macid().
412 ** value -- Macro value: either NULL, or a string.
413 **
414 ** Returns:
415 ** none.
416 */
417
418 void
419 #if SM_HEAP_CHECK
macdefine_tagged(mac,vclass,id,value,file,line,grp)420 macdefine_tagged(mac, vclass, id, value, file, line, grp)
421 #else
422 macdefine(mac, vclass, id, value)
423 #endif
424 MACROS_T *mac;
425 ARGCLASS_T vclass;
426 int id;
427 char *value;
428 #if SM_HEAP_CHECK
429 char *file;
430 int line;
431 int grp;
432 #endif
433 {
434 char *newvalue;
435
436 if (id < 0 || id > MAXMACROID)
437 return;
438
439 if (tTd(35, 9))
440 {
441 sm_dprintf("%sdefine(%s as ",
442 mac->mac_table[id] == NULL ? "" : "re", macname(id));
443 xputs(sm_debug_file(), value);
444 sm_dprintf(")\n");
445 }
446 #if USE_EAI && 0
447 // if (('j' == id || 'm' == id) && !addr_is_ascii(value))
448 // return an error/warning to caller and let them handle it.
449 #endif
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 ** Returns:
511 ** none.
512 */
513
514 void
macset(mac,i,value)515 macset(mac, i, value)
516 MACROS_T *mac;
517 int i;
518 char *value;
519 {
520 if (i < 0 || i > MAXMACROID)
521 return;
522
523 if (tTd(35, 9))
524 {
525 sm_dprintf("macset(%s as ", macname(i));
526 xputs(sm_debug_file(), value);
527 sm_dprintf(")\n");
528 }
529 mac->mac_table[i] = value;
530 }
531
532 /*
533 ** MACVALUE -- return uninterpreted value of a macro.
534 **
535 ** Does fancy path searching.
536 ** The low level counterpart is macget.
537 **
538 ** Parameters:
539 ** n -- the name of the macro.
540 ** e -- envelope in which to start looking for the macro.
541 **
542 ** Returns:
543 ** The value of n.
544 **
545 ** Side Effects:
546 ** none.
547 */
548
549 char *
macvalue(n,e)550 macvalue(n, e)
551 int n;
552 ENVELOPE *e;
553 {
554 n = bitidx(n);
555 if (e != NULL && e->e_mci != NULL)
556 {
557 char *p = e->e_mci->mci_macro.mac_table[n];
558
559 if (p != NULL)
560 return p;
561 }
562 while (e != NULL)
563 {
564 char *p = e->e_macro.mac_table[n];
565
566 if (p != NULL)
567 return p;
568 if (e == e->e_parent)
569 break;
570 e = e->e_parent;
571 }
572 #if _FFR_BLANKENV_MACV
573 if (LOOKUP_MACRO_IN_BLANKENV && e != &BlankEnvelope)
574 {
575 char *p = BlankEnvelope.e_macro.mac_table[n];
576
577 if (p != NULL)
578 return p;
579 }
580 #endif
581 return GlobalMacros.mac_table[n];
582 }
583
584 /*
585 ** MACNAME -- return the name of a macro given its internal id
586 **
587 ** Parameter:
588 ** n -- the id of the macro
589 **
590 ** Returns:
591 ** The name of n.
592 **
593 ** Side Effects:
594 ** none.
595 **
596 ** WARNING:
597 ** Not thread-safe.
598 */
599
600 char *
macname(n)601 macname(n)
602 int n;
603 {
604 static char mbuf[2];
605
606 n = (int)(unsigned char)n;
607 if (n > MAXMACROID)
608 return "***OUT OF RANGE MACRO***";
609
610 /* if not ASCII printable, look up the name */
611 if (n <= 0x20 || n > 0x7f)
612 {
613 char *p = MacroName[n];
614
615 if (p != NULL)
616 return p;
617 return "***UNDEFINED MACRO***";
618 }
619
620 /* if in the ASCII graphic range, just return the id directly */
621 mbuf[0] = n;
622 mbuf[1] = '\0';
623 return mbuf;
624 }
625
626 /*
627 ** MACID_PARSE -- return id of macro identified by its name
628 **
629 ** Parameters:
630 ** p -- pointer to name string -- either a single
631 ** character or {name}.
632 ** ep -- filled in with the pointer to the byte
633 ** after the name.
634 **
635 ** Returns:
636 ** 0 -- An error was detected.
637 ** 1..MAXMACROID -- The internal id code for this macro.
638 **
639 ** Side Effects:
640 ** If this is a new macro name, a new id is allocated.
641 ** On error, syserr is called.
642 */
643
644 int
macid_parse(p,ep)645 macid_parse(p, ep)
646 char *p;
647 char **ep;
648 {
649 int mid;
650 char *bp;
651 char mbuf[MAXMACNAMELEN + 1];
652
653 if (tTd(35, 14))
654 {
655 sm_dprintf("macid(");
656 xputs(sm_debug_file(), p);
657 sm_dprintf(") => ");
658 }
659
660 if (*p == '\0' || (p[0] == '{' && p[1] == '}'))
661 {
662 syserr("Name required for macro/class");
663 if (ep != NULL)
664 *ep = p;
665 if (tTd(35, 14))
666 sm_dprintf("NULL\n");
667 return 0;
668 }
669 if (*p != '{')
670 {
671 /* the macro is its own code */
672 if (ep != NULL)
673 *ep = p + 1;
674 if (tTd(35, 14))
675 {
676 char buf[2];
677
678 buf[0] = *p;
679 buf[1] = '\0';
680 xputs(sm_debug_file(), buf);
681 sm_dprintf("\n");
682 }
683 return bitidx(*p);
684 }
685 bp = mbuf;
686 while (*++p != '\0' && *p != '}' && bp < &mbuf[sizeof(mbuf) - 1])
687 {
688 if (isascii(*p) && (isalnum(*p) || *p == '_'))
689 *bp++ = *p;
690 else
691 syserr("Invalid macro/class character %c", *p);
692 }
693 *bp = '\0';
694 mid = -1;
695 if (*p == '\0')
696 {
697 syserr("Unbalanced { on %s", mbuf); /* missing } */
698 }
699 else if (*p != '}')
700 {
701 syserr("Macro/class name ({%s}) too long (%d chars max)",
702 mbuf, (int) (sizeof(mbuf) - 1));
703 }
704 else if (mbuf[1] == '\0' && mbuf[0] >= 0x20)
705 {
706 /* ${x} == $x */
707 mid = bitidx(mbuf[0]);
708 p++;
709 }
710 else
711 {
712 STAB *s;
713
714 s = stab(mbuf, ST_MACRO, ST_ENTER);
715 if (s->s_macro != 0)
716 mid = s->s_macro;
717 else
718 {
719 if (NextMacroId > MAXMACROID)
720 {
721 syserr("Macro/class {%s}: too many long names",
722 mbuf);
723 s->s_macro = -1;
724 }
725 else
726 {
727 MacroName[NextMacroId] = s->s_name;
728 s->s_macro = mid = NextMacroId;
729 NextMacroId = NEXTMACROID(NextMacroId);
730 }
731 }
732 p++;
733 }
734 if (ep != NULL)
735 *ep = p;
736 if (mid < 0 || mid > MAXMACROID)
737 {
738 syserr("Unable to assign macro/class ID (mid = 0x%x)", mid);
739 if (tTd(35, 14))
740 sm_dprintf("NULL\n");
741 return 0;
742 }
743 if (tTd(35, 14))
744 sm_dprintf("0x%x\n", mid);
745 return mid;
746 }
747
748 /*
749 ** WORDINCLASS -- tell if a word is in a specific class
750 **
751 ** Parameters:
752 ** str -- the name of the word to look up.
753 ** cl -- the class name.
754 **
755 ** Returns:
756 ** true if str can be found in cl.
757 ** false otherwise.
758 */
759
760 bool
wordinclass(str,cl)761 wordinclass(str, cl)
762 char *str;
763 int cl;
764 {
765 STAB *s;
766 #if _FFR_DYN_CLASS
767 MAP *map;
768 int status;
769 char *p;
770 char key[MAXLINE];
771
772 p = macname(cl);
773 s = stab(p, ST_DYNMAP, ST_FIND);
774 if (NULL == s)
775 {
776 #endif
777 s = stab(str, ST_CLASS, ST_FIND);
778 return s != NULL && bitnset(bitidx(cl), s->s_class);
779 #if _FFR_DYN_CLASS
780 }
781 map = &s->s_dynclass;
782 SM_REQUIRE(NULL != map);
783 SM_REQUIRE(!SM_IS_EMPTY(str));
784 if (bitset(MF_OPENBOGUS, map->map_mflags))
785 {
786 /* need to set some error! */
787 return false;
788 }
789
790 key[0] = '\0';
791 if (!SM_IS_EMPTY(map->map_tag))
792 {
793 sm_strlcpy(key, map->map_tag, sizeof(key));
794 sm_strlcat(key, ":", sizeof(key));
795 }
796 sm_strlcat(key, str, sizeof(key));
797 status = EX_OK;
798 p = (map->map_class->map_lookup)(map, key, NULL, &status);
799 if (NULL != p)
800 return true;
801 if ((EX_OK == status && NULL == p) || EX_NOTFOUND == status)
802 return false;
803
804 sm_syslog(LOG_WARNING, CurEnv->e_id,
805 "dynamic class: A{%s}: map lookup failed: key=%s, status=%d",
806 map->map_mname, key, status);
807
808 /* Note: this error is shown to the client, so do not "leak" info */
809 usrerr("451 4.3.1 temporary error");
810
811 return false;
812 #endif
813 }
814