]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/sendmail/src/macro.c
MFV: expat 2.6.0.
[FreeBSD/FreeBSD.git] / contrib / sendmail / src / macro.c
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
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
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
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
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
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
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 *
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 *
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
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
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 }