convert assertion to run-time check.
[freeradius.git] / src / main / xlat.c
1 /*
2  *   This program is free software; you can redistribute it and/or modify
3  *   it under the terms of the GNU General Public License as published by
4  *   the Free Software Foundation; either version 2 of the License, or
5  *   (at your option) any later version.
6  *
7  *   This program is distributed in the hope that it will be useful,
8  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
9  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  *   GNU General Public License for more details.
11  *
12  *   You should have received a copy of the GNU General Public License
13  *   along with this program; if not, write to the Free Software
14  *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15  */
16
17 /**
18  * $Id$
19  *
20  * @file xlat.c
21  * @brief String expansion ("translation"). Implements %Attribute -> value
22  *
23  * @copyright 2000,2006  The FreeRADIUS server project
24  * @copyright 2000  Alan DeKok <aland@ox.org>
25  */
26
27 RCSID("$Id$")
28
29 #include <freeradius-devel/radiusd.h>
30 #include <freeradius-devel/parser.h>
31 #include <freeradius-devel/rad_assert.h>
32 #include <freeradius-devel/base64.h>
33
34 #include <ctype.h>
35
36 typedef struct xlat_t {
37         char                    name[MAX_STRING_LEN];   //!< Name of the xlat expansion.
38         int                     length;                 //!< Length of name.
39         void                    *instance;              //!< Module instance passed to xlat and escape functions.
40         xlat_func_t             func;                   //!< xlat function.
41         xlat_escape_t   escape;                 //!< Escape function to apply to dynamic input to func.
42         bool                    internal;               //!< If true, cannot be redefined.
43 } xlat_t;
44
45 typedef enum {
46         XLAT_LITERAL,           //!< Literal string
47         XLAT_PERCENT,           //!< Literal string with %v
48         XLAT_MODULE,            //!< xlat module
49         XLAT_VIRTUAL,           //!< virtual attribute
50         XLAT_ATTRIBUTE,         //!< xlat attribute
51 #ifdef HAVE_REGEX
52         XLAT_REGEX,             //!< regex reference
53 #endif
54         XLAT_ALTERNATE          //!< xlat conditional syntax :-
55 } xlat_state_t;
56
57 struct xlat_exp {
58         char const *fmt;        //!< The format string.
59         size_t len;             //!< Length of the format string.
60
61         xlat_state_t type;      //!< type of this expansion.
62         xlat_exp_t *next;       //!< Next in the list.
63
64         xlat_exp_t *child;      //!< Nested expansion.
65         xlat_exp_t *alternate;  //!< Alternative expansion if this one expanded to a zero length string.
66
67         vp_tmpl_t attr; //!< An attribute template.
68         xlat_t const *xlat;     //!< The xlat expansion to expand format with.
69 };
70
71 typedef struct xlat_out {
72         char const *out;        //!< Output data.
73         size_t len;             //!< Length of the output string.
74 } xlat_out_t;
75
76 static rbtree_t *xlat_root = NULL;
77
78 #ifdef WITH_UNLANG
79 static char const * const xlat_foreach_names[] = {"Foreach-Variable-0",
80                                                   "Foreach-Variable-1",
81                                                   "Foreach-Variable-2",
82                                                   "Foreach-Variable-3",
83                                                   "Foreach-Variable-4",
84                                                   "Foreach-Variable-5",
85                                                   "Foreach-Variable-6",
86                                                   "Foreach-Variable-7",
87                                                   "Foreach-Variable-8",
88                                                   "Foreach-Variable-9",
89                                                   NULL};
90 #endif
91
92
93 static int xlat_inst[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };      /* up to 10 for foreach */
94
95 /** Print length of its RHS.
96  *
97  */
98 static ssize_t xlat_strlen(UNUSED void *instance, UNUSED REQUEST *request,
99                            char const *fmt, char *out, size_t outlen)
100 {
101         snprintf(out, outlen, "%u", (unsigned int) strlen(fmt));
102         return strlen(out);
103 }
104
105 /** Print the size of the attribute in bytes.
106  *
107  */
108 static ssize_t xlat_length(UNUSED void *instance, REQUEST *request,
109                            char const *fmt, char *out, size_t outlen)
110 {
111         VALUE_PAIR *vp;
112         while (isspace((int) *fmt)) fmt++;
113
114         if ((radius_get_vp(&vp, request, fmt) < 0) || !vp) {
115                 *out = '\0';
116                 return 0;
117         }
118
119         snprintf(out, outlen, "%zu", vp->vp_length);
120         return strlen(out);
121 }
122
123 /** Print data as integer, not as VALUE.
124  *
125  */
126 static ssize_t xlat_integer(UNUSED void *instance, REQUEST *request,
127                             char const *fmt, char *out, size_t outlen)
128 {
129         VALUE_PAIR      *vp;
130
131         uint64_t        int64 = 0;      /* Needs to be initialised to zero */
132         uint32_t        int32 = 0;      /* Needs to be initialised to zero */
133
134         while (isspace((int) *fmt)) fmt++;
135
136         if ((radius_get_vp(&vp, request, fmt) < 0) || !vp) {
137                 *out = '\0';
138                 return 0;
139         }
140
141         switch (vp->da->type) {
142         case PW_TYPE_OCTETS:
143         case PW_TYPE_STRING:
144                 if (vp->vp_length > 8) {
145                         break;
146                 }
147
148                 if (vp->vp_length > 4) {
149                         memcpy(&int64, vp->vp_octets, vp->vp_length);
150                         return snprintf(out, outlen, "%" PRIu64, htonll(int64));
151                 }
152
153                 memcpy(&int32, vp->vp_octets, vp->vp_length);
154                 return snprintf(out, outlen, "%i", htonl(int32));
155
156         case PW_TYPE_INTEGER64:
157                 return snprintf(out, outlen, "%" PRIu64, vp->vp_integer64);
158
159         /*
160          *      IP addresses are treated specially, as parsing functions assume the value
161          *      is bigendian and will convert it for us.
162          */
163         case PW_TYPE_IPV4_ADDR:
164                 return snprintf(out, outlen, "%u", htonl(vp->vp_ipaddr));
165
166         case PW_TYPE_IPV4_PREFIX:
167                 return snprintf(out, outlen, "%u", htonl((*(uint32_t *)(vp->vp_ipv4prefix + 2))));
168
169         case PW_TYPE_INTEGER:
170                 return snprintf(out, outlen, "%u", vp->vp_integer);
171
172         case PW_TYPE_DATE:
173                 return snprintf(out, outlen, "%u", vp->vp_date);
174
175         case PW_TYPE_BYTE:
176                 return snprintf(out, outlen, "%u", (unsigned int) vp->vp_byte);
177
178         case PW_TYPE_SHORT:
179                 return snprintf(out, outlen, "%u", (unsigned int) vp->vp_short);
180
181         /*
182          *      Ethernet is weird... It's network related, so we assume to it should be
183          *      bigendian.
184          */
185         case PW_TYPE_ETHERNET:
186                 memcpy(&int64, vp->vp_ether, vp->vp_length);
187                 return snprintf(out, outlen, "%" PRIu64, htonll(int64));
188
189         case PW_TYPE_SIGNED:
190                 return snprintf(out, outlen, "%i", vp->vp_signed);
191
192         case PW_TYPE_IPV6_ADDR:
193                 return fr_prints_uint128(out, outlen, ntohlll(*(uint128_t const *) &vp->vp_ipv6addr));
194
195         case PW_TYPE_IPV6_PREFIX:
196                 return fr_prints_uint128(out, outlen, ntohlll(*(uint128_t const *) &vp->vp_ipv6prefix[2]));
197
198         default:
199                 break;
200         }
201
202         REDEBUG("Type '%s' of length %zu cannot be converted to integer",
203                 fr_int2str(dict_attr_types, vp->da->type, "???"), vp->vp_length);
204         *out = '\0';
205
206         return -1;
207 }
208
209 /** Print data as hex, not as VALUE.
210  *
211  */
212 static ssize_t xlat_hex(UNUSED void *instance, REQUEST *request,
213                         char const *fmt, char *out, size_t outlen)
214 {
215         size_t i;
216         VALUE_PAIR *vp;
217         uint8_t const *p;
218         ssize_t ret;
219         size_t  len;
220         value_data_t dst;
221         uint8_t const *buff = NULL;
222
223         while (isspace((int) *fmt)) fmt++;
224
225         if ((radius_get_vp(&vp, request, fmt) < 0) || !vp) {
226         error:
227                 *out = '\0';
228                 return -1;
229         }
230
231         /*
232          *      The easy case.
233          */
234         if (vp->da->type == PW_TYPE_OCTETS) {
235                 p = vp->vp_octets;
236                 len = vp->vp_length;
237         /*
238          *      Cast the value_data_t of the VP to an octets string and
239          *      print that as hex.
240          */
241         } else {
242                 ret = value_data_cast(request, &dst, PW_TYPE_OCTETS, NULL, vp->da->type,
243                                       NULL, &vp->data, vp->vp_length);
244                 if (ret < 0) {
245                         REDEBUG("%s", fr_strerror());
246                         goto error;
247                 }
248                 len = (size_t) ret;
249                 p = buff = dst.octets;
250         }
251
252         rad_assert(p);
253
254         /*
255          *      Don't truncate the data.
256          */
257         if (outlen < (len * 2)) {
258                 rad_const_free(buff);
259                 goto error;
260         }
261
262         for (i = 0; i < len; i++) {
263                 snprintf(out + 2*i, 3, "%02x", p[i]);
264         }
265         rad_const_free(buff);
266
267         return len * 2;
268 }
269
270 /** Return the tag of an attribute reference
271  *
272  */
273 static ssize_t xlat_tag(UNUSED void *instance, REQUEST *request,
274                         char const *fmt, char *out, size_t outlen)
275 {
276         VALUE_PAIR *vp;
277
278         while (isspace((int) *fmt)) fmt++;
279
280         if ((radius_get_vp(&vp, request, fmt) < 0) || !vp) {
281                 *out = '\0';
282                 return 0;
283         }
284
285         if (!vp->da->flags.has_tag || !TAG_VALID(vp->tag)) {
286                 *out = '\0';
287                 return 0;
288         }
289
290         return snprintf(out, outlen, "%u", vp->tag);
291 }
292
293 /** Return the vendor of an attribute reference
294  *
295  */
296 static ssize_t xlat_vendor(UNUSED void *instance, REQUEST *request,
297                            char const *fmt, char *out, size_t outlen)
298 {
299         VALUE_PAIR *vp;
300         DICT_VENDOR *vendor;
301
302         while (isspace((int) *fmt)) fmt++;
303
304         if ((radius_get_vp(&vp, request, fmt) < 0) || !vp) {
305                 *out = '\0';
306                 return 0;
307         }
308
309         vendor = dict_vendorbyvalue(vp->da->vendor);
310         if (!vendor) {
311                 *out = '\0';
312                 return 0;
313         }
314         strlcpy(out, vendor->name, outlen);
315
316         return vendor->length;
317 }
318
319 /** Return the vendor number of an attribute reference
320  *
321  */
322 static ssize_t xlat_vendor_num(UNUSED void *instance, REQUEST *request,
323                                char const *fmt, char *out, size_t outlen)
324 {
325         VALUE_PAIR *vp;
326
327         while (isspace((int) *fmt)) fmt++;
328
329         if ((radius_get_vp(&vp, request, fmt) < 0) || !vp) {
330                 *out = '\0';
331                 return 0;
332         }
333
334         return snprintf(out, outlen, "%u", vp->da->vendor);
335 }
336
337 /** Return the attribute name of an attribute reference
338  *
339  */
340 static ssize_t xlat_attr(UNUSED void *instance, REQUEST *request,
341                          char const *fmt, char *out, size_t outlen)
342 {
343         VALUE_PAIR *vp;
344
345         while (isspace((int) *fmt)) fmt++;
346
347         if ((radius_get_vp(&vp, request, fmt) < 0) || !vp) {
348                 *out = '\0';
349                 return 0;
350         }
351         strlcpy(out, vp->da->name, outlen);
352
353         return strlen(vp->da->name);
354 }
355
356 /** Return the attribute number of an attribute reference
357  *
358  */
359 static ssize_t xlat_attr_num(UNUSED void *instance, REQUEST *request,
360                              char const *fmt, char *out, size_t outlen)
361 {
362         VALUE_PAIR *vp;
363
364         while (isspace((int) *fmt)) fmt++;
365
366         if ((radius_get_vp(&vp, request, fmt) < 0) || !vp) {
367                 *out = '\0';
368                 return 0;
369         }
370
371         return snprintf(out, outlen, "%u", vp->da->attr);
372 }
373
374 /** Print out attribute info
375  *
376  * Prints out all instances of a current attribute, or all attributes in a list.
377  *
378  * At higher debugging levels, also prints out alternative decodings of the same
379  * value. This is helpful to determine types for unknown attributes of long
380  * passed vendors, or just crazy/broken NAS.
381  *
382  * This expands to a zero length string.
383  */
384 static ssize_t xlat_debug_attr(UNUSED void *instance, REQUEST *request, char const *fmt,
385                                char *out, UNUSED size_t outlen)
386 {
387         VALUE_PAIR *vp;
388         vp_cursor_t cursor;
389
390         vp_tmpl_t vpt;
391
392         if (!RDEBUG_ENABLED2) {
393                 *out = '\0';
394                 return -1;
395         }
396
397         while (isspace((int) *fmt)) fmt++;
398
399         if (tmpl_from_attr_str(&vpt, fmt, REQUEST_CURRENT, PAIR_LIST_REQUEST, false, false) <= 0) {
400                 RDEBUG("%s", fr_strerror());
401                 return -1;
402         }
403
404         RIDEBUG("Attributes matching \"%s\"", fmt);
405
406         RINDENT();
407         for (vp = tmpl_cursor_init(NULL, &cursor, request, &vpt);
408              vp;
409              vp = tmpl_cursor_next(&cursor, &vpt)) {
410                 FR_NAME_NUMBER const *type;
411                 char *value;
412
413                 value = vp_aprints_value(vp, vp, '\'');
414                 if (vp->da->flags.has_tag) {
415                         RIDEBUG2("&%s:%s:%i %s %s",
416                                 fr_int2str(pair_lists, vpt.tmpl_list, "<INVALID>"),
417                                 vp->da->name,
418                                 vp->tag,
419                                 fr_int2str(fr_tokens, vp->op, "<INVALID>"),
420                                 value);
421                 } else {
422                         RIDEBUG2("&%s:%s %s %s",
423                                 fr_int2str(pair_lists, vpt.tmpl_list, "<INVALID>"),
424                                 vp->da->name,
425                                 fr_int2str(fr_tokens, vp->op, "<INVALID>"),
426                                 value);
427                 }
428                 talloc_free(value);
429
430                 if (!RDEBUG_ENABLED3) continue;
431
432                 if (vp->da->vendor) {
433                         DICT_VENDOR *dv;
434
435                         dv = dict_vendorbyvalue(vp->da->vendor);
436                         RIDEBUG2("Vendor : %i (%s)", vp->da->vendor, dv ? dv->name : "unknown");
437                 }
438                 RIDEBUG2("Type   : %s", fr_int2str(dict_attr_types, vp->da->type, "<INVALID>"));
439                 RIDEBUG2("Length : %zu", vp->vp_length);
440
441                 if (!RDEBUG_ENABLED4) continue;
442
443                 type = dict_attr_types;
444                 while (type->name) {
445                         int pad;
446
447                         value_data_t *dst = NULL;
448
449                         ssize_t ret;
450
451                         if ((PW_TYPE) type->number == vp->da->type) {
452                                 goto next_type;
453                         }
454
455                         switch (type->number) {
456                         case PW_TYPE_INVALID:           /* Not real type */
457                         case PW_TYPE_MAX:               /* Not real type */
458                         case PW_TYPE_EXTENDED:          /* Not safe/appropriate */
459                         case PW_TYPE_LONG_EXTENDED:     /* Not safe/appropriate */
460                         case PW_TYPE_TLV:               /* Not safe/appropriate */
461                         case PW_TYPE_EVS:               /* Not safe/appropriate */
462                         case PW_TYPE_VSA:               /* @fixme We need special behaviour for these */
463                         case PW_TYPE_COMBO_IP_ADDR:     /* Covered by IPv4 address IPv6 address */
464                         case PW_TYPE_COMBO_IP_PREFIX:   /* Covered by IPv4 address IPv6 address */
465                         case PW_TYPE_TIMEVAL:           /* Not a VALUE_PAIR type */
466                                 goto next_type;
467
468                         default:
469                                 break;
470                         }
471
472                         dst = talloc_zero(vp, value_data_t);
473                         ret = value_data_cast(dst, dst, type->number, NULL, vp->da->type, vp->da,
474                                               &vp->data, vp->vp_length);
475                         if (ret < 0) goto next_type;    /* We expect some to fail */
476
477                         value = value_data_aprints(dst, type->number, NULL, dst, (size_t)ret, '\'');
478                         if (!value) goto next_type;
479
480                         if ((pad = (11 - strlen(type->name))) < 0) {
481                                 pad = 0;
482                         }
483
484                         RINDENT();
485                         RDEBUG2("as %s%*s: %s", type->name, pad, " ", value);
486                         REXDENT();
487
488                 next_type:
489                         talloc_free(dst);
490                         type++;
491                 }
492         }
493
494         *out = '\0';
495         return 0;
496 }
497
498 /** Processes fmt as a map string and applies it to the current request
499  *
500  * e.g. "%{map:&User-Name := 'foo'}"
501  *
502  * Allows sets of modifications to be cached and then applied.
503  * Useful for processing generic attributes from LDAP.
504  */
505 static ssize_t xlat_map(UNUSED void *instance, REQUEST *request,
506                         char const *fmt, char *out, size_t outlen)
507 {
508         vp_map_t *map = NULL;
509         int ret;
510
511         if (map_afrom_attr_str(request, &map, fmt,
512                                REQUEST_CURRENT, PAIR_LIST_REQUEST,
513                                REQUEST_CURRENT, PAIR_LIST_REQUEST) < 0) {
514                 REDEBUG("Failed parsing \"%s\" as map: %s", fmt, fr_strerror());
515                 return -1;
516         }
517
518         RINDENT();
519         ret = map_to_request(request, map, map_to_vp, NULL);
520         REXDENT();
521         talloc_free(map);
522         if (ret < 0) return strlcpy(out, "0", outlen);
523
524         return strlcpy(out, "1", outlen);
525 }
526
527 /** Prints the current module processing the request
528  *
529  */
530 static ssize_t xlat_module(UNUSED void *instance, REQUEST *request,
531                            UNUSED char const *fmt, char *out, size_t outlen)
532 {
533         strlcpy(out, request->module, outlen);
534
535         return strlen(out);
536 }
537
538 #if defined(HAVE_REGEX) && defined(HAVE_PCRE)
539 static ssize_t xlat_regex(UNUSED void *instance, REQUEST *request,
540                           char const *fmt, char *out, size_t outlen)
541 {
542         char *p;
543         size_t len;
544
545         if (regex_request_to_sub_named(request, &p, request, fmt) < 0) {
546                 *out = '\0';
547                 return 0;
548         }
549
550         len = talloc_array_length(p);
551         if (len > outlen) {
552                 RDEBUG("Insufficient buffer space to write subcapture value, needed %zu bytes, have %zu bytes",
553                        len, outlen);
554                 return -1;
555         }
556         strlcpy(out, p, outlen);
557
558         return len - 1; /* - \0 */
559 }
560 #endif
561
562 #ifdef WITH_UNLANG
563 /** Implements the Foreach-Variable-X
564  *
565  * @see modcall()
566  */
567 static ssize_t xlat_foreach(void *instance, REQUEST *request,
568                             UNUSED char const *fmt, char *out, size_t outlen)
569 {
570         VALUE_PAIR      **pvp;
571         size_t          len;
572
573         /*
574          *      See modcall, "FOREACH" for how this works.
575          */
576         pvp = (VALUE_PAIR **) request_data_reference(request, (void *)radius_get_vp, *(int*) instance);
577         if (!pvp || !*pvp) {
578                 *out = '\0';
579                 return 0;
580         }
581
582         len = vp_prints_value(out, outlen, *pvp, 0);
583         if (is_truncated(len, outlen)) {
584                 RDEBUG("Insufficient buffer space to write foreach value");
585                 return -1;
586         }
587
588         return len;
589 }
590 #endif
591
592 /** Print data as string, if possible.
593  *
594  * If attribute "Foo" is defined as "octets" it will normally
595  * be printed as 0x0a0a0a. The xlat "%{string:Foo}" will instead
596  * expand to "\n\n\n"
597  */
598 static ssize_t xlat_string(UNUSED void *instance, REQUEST *request,
599                            char const *fmt, char *out, size_t outlen)
600 {
601         size_t len;
602         ssize_t ret;
603         VALUE_PAIR *vp;
604         uint8_t const *p;
605
606         while (isspace((int) *fmt)) fmt++;
607
608         if (outlen < 3) {
609         nothing:
610                 *out = '\0';
611                 return 0;
612         }
613
614         if ((radius_get_vp(&vp, request, fmt) < 0) || !vp) goto nothing;
615
616         ret = rad_vp2data(&p, vp);
617         if (ret < 0) {
618                 return ret;
619         }
620
621         switch (vp->da->type) {
622         case PW_TYPE_OCTETS:
623                 len = fr_prints(out, outlen, (char const *) p, vp->vp_length, '"');
624                 break;
625
626                 /*
627                  *      Note that "%{string:...}" is NOT binary safe!
628                  *      It is explicitly used to get rid of embedded zeros.
629                  */
630         case PW_TYPE_STRING:
631                 len = strlcpy(out, vp->vp_strvalue, outlen);
632                 break;
633
634         default:
635                 len = fr_prints(out, outlen, (char const *) p, ret, '\0');
636                 break;
637         }
638
639         return len;
640 }
641
642 /** xlat expand string attribute value
643  *
644  */
645 static ssize_t xlat_xlat(UNUSED void *instance, REQUEST *request,
646                         char const *fmt, char *out, size_t outlen)
647 {
648         VALUE_PAIR *vp;
649
650         while (isspace((int) *fmt)) fmt++;
651
652         if (outlen < 3) {
653         nothing:
654                 *out = '\0';
655                 return 0;
656         }
657
658         if ((radius_get_vp(&vp, request, fmt) < 0) || !vp) goto nothing;
659
660         if (vp->da->type != PW_TYPE_STRING) goto nothing;
661
662         return radius_xlat(out, outlen, request, vp->vp_strvalue, NULL, NULL);
663 }
664
665 /** Dynamically change the debugging level for the current request
666  *
667  * Example %{debug:3}
668  */
669 static ssize_t xlat_debug(UNUSED void *instance, REQUEST *request,
670                           char const *fmt, char *out, size_t outlen)
671 {
672         int level = 0;
673
674         /*
675          *  Expand to previous (or current) level
676          */
677         snprintf(out, outlen, "%d", request->log.lvl);
678
679         /*
680          *  Assume we just want to get the current value and NOT set it to 0
681          */
682         if (!*fmt)
683                 goto done;
684
685         level = atoi(fmt);
686         if (level == 0) {
687                 request->log.lvl = RAD_REQUEST_LVL_NONE;
688                 request->log.func = NULL;
689         } else {
690                 if (level > 4) level = 4;
691
692                 request->log.lvl = level;
693                 request->log.func = vradlog_request;
694         }
695
696         done:
697         return strlen(out);
698 }
699
700 /*
701  *      Compare two xlat_t structs, based ONLY on the module name.
702  */
703 static int xlat_cmp(void const *one, void const *two)
704 {
705         xlat_t const *a = one;
706         xlat_t const *b = two;
707
708         if (a->length != b->length) {
709                 return a->length - b->length;
710         }
711
712         return memcmp(a->name, b->name, a->length);
713 }
714
715
716 /*
717  *      find the appropriate registered xlat function.
718  */
719 static xlat_t *xlat_find(char const *name)
720 {
721         xlat_t my_xlat;
722
723         strlcpy(my_xlat.name, name, sizeof(my_xlat.name));
724         my_xlat.length = strlen(my_xlat.name);
725
726         return rbtree_finddata(xlat_root, &my_xlat);
727 }
728
729
730 /** Register an xlat function.
731  *
732  * @param[in] name xlat name.
733  * @param[in] func xlat function to be called.
734  * @param[in] escape function to sanitize any sub expansions passed to the xlat function.
735  * @param[in] instance of module that's registering the xlat function.
736  * @return 0 on success, -1 on failure
737  */
738 int xlat_register(char const *name, xlat_func_t func, xlat_escape_t escape, void *instance)
739 {
740         xlat_t  *c;
741         xlat_t  my_xlat;
742         rbnode_t *node;
743
744         if (!name || !*name) {
745                 DEBUG("xlat_register: Invalid xlat name");
746                 return -1;
747         }
748
749         /*
750          *      First time around, build up the tree...
751          *
752          *      FIXME: This code should be hoisted out of this function,
753          *      and into a global "initialization".  But it isn't critical...
754          */
755         if (!xlat_root) {
756 #ifdef WITH_UNLANG
757                 int i;
758 #endif
759
760                 xlat_root = rbtree_create(NULL, xlat_cmp, NULL, RBTREE_FLAG_REPLACE);
761                 if (!xlat_root) {
762                         DEBUG("xlat_register: Failed to create tree");
763                         return -1;
764                 }
765
766 #ifdef WITH_UNLANG
767                 for (i = 0; xlat_foreach_names[i] != NULL; i++) {
768                         xlat_register(xlat_foreach_names[i],
769                                       xlat_foreach, NULL, &xlat_inst[i]);
770                         c = xlat_find(xlat_foreach_names[i]);
771                         rad_assert(c != NULL);
772                         c->internal = true;
773                 }
774 #endif
775
776 #define XLAT_REGISTER(_x) xlat_register(STRINGIFY(_x), xlat_ ## _x, NULL, NULL); \
777                 c = xlat_find(STRINGIFY(_x)); \
778                 rad_assert(c != NULL); \
779                 c->internal = true
780
781                 XLAT_REGISTER(integer);
782                 XLAT_REGISTER(strlen);
783                 XLAT_REGISTER(length);
784                 XLAT_REGISTER(hex);
785                 XLAT_REGISTER(tag);
786                 XLAT_REGISTER(vendor);
787                 XLAT_REGISTER(vendor_num);
788                 XLAT_REGISTER(attr);
789                 XLAT_REGISTER(attr_num);
790                 XLAT_REGISTER(string);
791                 XLAT_REGISTER(xlat);
792                 XLAT_REGISTER(map);
793                 XLAT_REGISTER(module);
794                 XLAT_REGISTER(debug_attr);
795 #if defined(HAVE_REGEX) && defined(HAVE_PCRE)
796                 XLAT_REGISTER(regex);
797 #endif
798
799                 xlat_register("debug", xlat_debug, NULL, &xlat_inst[0]);
800                 c = xlat_find("debug");
801                 rad_assert(c != NULL);
802                 c->internal = true;
803         }
804
805         /*
806          *      If it already exists, replace the instance.
807          */
808         strlcpy(my_xlat.name, name, sizeof(my_xlat.name));
809         my_xlat.length = strlen(my_xlat.name);
810         c = rbtree_finddata(xlat_root, &my_xlat);
811         if (c) {
812                 if (c->internal) {
813                         DEBUG("xlat_register: Cannot re-define internal xlat");
814                         return -1;
815                 }
816
817                 c->func = func;
818                 c->escape = escape;
819                 c->instance = instance;
820                 return 0;
821         }
822
823         /*
824          *      Doesn't exist.  Create it.
825          */
826         c = talloc_zero(xlat_root, xlat_t);
827
828         c->func = func;
829         c->escape = escape;
830         strlcpy(c->name, name, sizeof(c->name));
831         c->length = strlen(c->name);
832         c->instance = instance;
833
834         node = rbtree_insert_node(xlat_root, c);
835         if (!node) {
836                 talloc_free(c);
837                 return -1;
838         }
839
840         /*
841          *      Ensure that the data is deleted when the node is
842          *      deleted.
843          *
844          *      @todo: Maybe this should be the other way around...
845          *      when a thing IN the tree is deleted, it's automatically
846          *      removed from the tree.  But for now, this works.
847          */
848         (void) talloc_steal(node, c);
849         return 0;
850 }
851
852 /** Unregister an xlat function
853  *
854  * We can only have one function to call per name, so the passing of "func"
855  * here is extraneous.
856  *
857  * @param[in] name xlat to unregister.
858  * @param[in] func unused.
859  * @param[in] instance data.
860  */
861 void xlat_unregister(char const *name, UNUSED xlat_func_t func, void *instance)
862 {
863         xlat_t  *c;
864         xlat_t          my_xlat;
865
866         if (!name || !xlat_root) return;
867
868         strlcpy(my_xlat.name, name, sizeof(my_xlat.name));
869         my_xlat.length = strlen(my_xlat.name);
870
871         c = rbtree_finddata(xlat_root, &my_xlat);
872         if (!c) return;
873
874         if (c->instance != instance) return;
875
876         rbtree_deletebydata(xlat_root, c);
877 }
878
879 static int xlat_unregister_callback(void *instance, void *data)
880 {
881         xlat_t *c = (xlat_t *) data;
882
883         if (c->instance != instance) return 0; /* keep walking */
884
885         return 2;               /* delete it */
886 }
887
888 void xlat_unregister_module(void *instance)
889 {
890         rbtree_walk(xlat_root, RBTREE_DELETE_ORDER, xlat_unregister_callback, instance);
891 }
892
893 /*
894  *      Internal redundant handler for xlats
895  */
896 typedef enum xlat_redundant_type_t {
897         XLAT_INVALID = 0,
898         XLAT_REDUNDANT,
899         XLAT_LOAD_BALANCE,
900         XLAT_REDUNDANT_LOAD_BALANCE,
901 } xlat_redundant_type_t;
902
903 typedef struct xlat_redundant_t {
904         xlat_redundant_type_t type;
905         uint32_t        count;
906         CONF_SECTION *cs;
907 } xlat_redundant_t;
908
909
910 static ssize_t xlat_redundant(void *instance, REQUEST *request,
911                               char const *fmt, char *out, size_t outlen)
912 {
913         xlat_redundant_t *xr = instance;
914         CONF_ITEM *ci;
915         char const *name;
916         xlat_t *xlat;
917
918         rad_assert(xr->type == XLAT_REDUNDANT);
919
920         /*
921          *      Pick the first xlat which succeeds
922          */
923         for (ci = cf_item_find_next(xr->cs, NULL);
924              ci != NULL;
925              ci = cf_item_find_next(xr->cs, ci)) {
926                 ssize_t rcode;
927
928                 if (!cf_item_is_pair(ci)) continue;
929
930                 name = cf_pair_attr(cf_item_to_pair(ci));
931                 rad_assert(name != NULL);
932
933                 xlat = xlat_find(name);
934                 if (!xlat) continue;
935
936                 rcode = xlat->func(xlat->instance, request, fmt, out, outlen);
937                 if (rcode <= 0) continue;
938                 return rcode;
939         }
940
941         /*
942          *      Everything failed.  Oh well.
943          */
944         *out  = 0;
945         return 0;
946 }
947
948
949 static ssize_t xlat_load_balance(void *instance, REQUEST *request,
950                               char const *fmt, char *out, size_t outlen)
951 {
952         uint32_t count = 0;
953         xlat_redundant_t *xr = instance;
954         CONF_ITEM *ci;
955         CONF_ITEM *found = NULL;
956         char const *name;
957         xlat_t *xlat;
958
959         /*
960          *      Choose a child at random.
961          */
962         for (ci = cf_item_find_next(xr->cs, NULL);
963              ci != NULL;
964              ci = cf_item_find_next(xr->cs, ci)) {
965                 if (!cf_item_is_pair(ci)) continue;
966                 count++;
967
968                 /*
969                  *      Replace the previously found one with a random
970                  *      new one.
971                  */
972                 if ((count * (fr_rand() & 0xffff)) < (uint32_t) 0x10000) {
973                         found = ci;
974                 }
975         }
976
977         /*
978          *      Plain load balancing: do one child, and only one child.
979          */
980         if (xr->type == XLAT_LOAD_BALANCE) {
981                 name = cf_pair_attr(cf_item_to_pair(found));
982                 rad_assert(name != NULL);
983
984                 xlat = xlat_find(name);
985                 if (!xlat) return -1;
986
987                 return xlat->func(xlat->instance, request, fmt, out, outlen);
988         }
989
990         rad_assert(xr->type == XLAT_REDUNDANT_LOAD_BALANCE);
991
992         /*
993          *      Try the random one we found.  If it fails, keep going
994          *      through the rest of the children.
995          */
996         ci = found;
997         do {
998                 name = cf_pair_attr(cf_item_to_pair(ci));
999                 rad_assert(name != NULL);
1000
1001                 xlat = xlat_find(name);
1002                 if (xlat) {
1003                         ssize_t rcode;
1004
1005                         rcode = xlat->func(xlat->instance, request, fmt, out, outlen);
1006                         if (rcode > 0) return rcode;
1007                 }
1008
1009                 /*
1010                  *      Go to the next one, wrapping around at the end.
1011                  */
1012                 ci = cf_item_find_next(xr->cs, ci);
1013                 if (!ci) ci = cf_item_find_next(xr->cs, NULL);
1014         } while (ci != found);
1015
1016         return -1;
1017 }
1018
1019
1020 bool xlat_register_redundant(CONF_SECTION *cs)
1021 {
1022         char const *name1, *name2;
1023         xlat_redundant_t *xr;
1024
1025         name1 = cf_section_name1(cs);
1026         name2 = cf_section_name2(cs);
1027
1028         if (!name2) return false;
1029
1030         if (xlat_find(name2)) {
1031                 cf_log_err_cs(cs, "An expansion is already registered for this name");
1032                 return false;
1033         }
1034
1035         xr = talloc_zero(cs, xlat_redundant_t);
1036         if (!xr) return false;
1037
1038         if (strcmp(name1, "redundant") == 0) {
1039                 xr->type = XLAT_REDUNDANT;
1040
1041         } else if (strcmp(name1, "redundant-load-balance") == 0) {
1042                 xr->type = XLAT_REDUNDANT_LOAD_BALANCE;
1043
1044         } else if (strcmp(name1, "load-balance") == 0) {
1045                 xr->type = XLAT_LOAD_BALANCE;
1046
1047         } else {
1048                 return false;
1049         }
1050
1051         xr->cs = cs;
1052
1053         /*
1054          *      Get the number of children for load balancing.
1055          */
1056         if (xr->type == XLAT_REDUNDANT) {
1057                 if (xlat_register(name2, xlat_redundant, NULL, xr) < 0) {
1058                         talloc_free(xr);
1059                         return false;
1060                 }
1061
1062         } else {
1063                 CONF_ITEM *ci;
1064
1065                 for (ci = cf_item_find_next(cs, NULL);
1066                      ci != NULL;
1067                      ci = cf_item_find_next(cs, ci)) {
1068                         if (!cf_item_is_pair(ci)) continue;
1069
1070                         if (!xlat_find(cf_pair_attr(cf_item_to_pair(ci)))) {
1071                                 talloc_free(xr);
1072                                 return false;
1073                         }
1074
1075                         xr->count++;
1076                 }
1077
1078                 if (xlat_register(name2, xlat_load_balance, NULL, xr) < 0) {
1079                         talloc_free(xr);
1080                         return false;
1081                 }
1082         }
1083
1084         return true;
1085 }
1086
1087
1088 /** Crappy temporary function to add attribute ref support to xlats
1089  *
1090  * This needs to die, and hopefully will die, when xlat functions accept
1091  * xlat node structures.
1092  *
1093  * Provides either a pointer to a buffer which contains the value of the reference VALUE_PAIR
1094  * in an architecture independent format. Or a pointer to the start of the fmt string.
1095  *
1096  * The pointer is only guaranteed to be valid between calls to xlat_fmt_to_ref,
1097  * and so long as the source VALUE_PAIR is not freed.
1098  *
1099  * @param out where to write a pointer to the buffer to the data the xlat function needs to work on.
1100  * @param request current request.
1101  * @param fmt string.
1102  * @returns the length of the data or -1 on error.
1103  */
1104 ssize_t xlat_fmt_to_ref(uint8_t const **out, REQUEST *request, char const *fmt)
1105 {
1106         VALUE_PAIR *vp;
1107
1108         while (isspace((int) *fmt)) fmt++;
1109
1110         if (fmt[0] == '&') {
1111                 if ((radius_get_vp(&vp, request, fmt) < 0) || !vp) {
1112                         *out = NULL;
1113                         return -1;
1114                 }
1115
1116                 return rad_vp2data(out, vp);
1117         }
1118
1119         *out = (uint8_t const *)fmt;
1120         return strlen(fmt);
1121 }
1122
1123 /** De-register all xlat functions, used mainly for debugging.
1124  *
1125  */
1126 void xlat_free(void)
1127 {
1128         rbtree_free(xlat_root);
1129 }
1130
1131 #ifdef DEBUG_XLAT
1132 #  define XLAT_DEBUG DEBUG3
1133 #else
1134 #  define XLAT_DEBUG(...)
1135 #endif
1136
1137 static ssize_t xlat_tokenize_expansion(TALLOC_CTX *ctx, char *fmt, xlat_exp_t **head,
1138                                        char const **error);
1139 static ssize_t xlat_tokenize_literal(TALLOC_CTX *ctx, char *fmt, xlat_exp_t **head,
1140                                      bool brace, char const **error);
1141 static size_t xlat_process(char **out, REQUEST *request, xlat_exp_t const * const head,
1142                            xlat_escape_t escape, void *escape_ctx);
1143
1144 static ssize_t xlat_tokenize_alternation(TALLOC_CTX *ctx, char *fmt, xlat_exp_t **head,
1145                                          char const **error)
1146 {
1147         ssize_t slen;
1148         char *p;
1149         xlat_exp_t *node;
1150
1151         rad_assert(fmt[0] == '%');
1152         rad_assert(fmt[1] == '{');
1153         rad_assert(fmt[2] == '%');
1154         rad_assert(fmt[3] == '{');
1155
1156         XLAT_DEBUG("ALTERNATE <-- %s", fmt);
1157
1158         node = talloc_zero(ctx, xlat_exp_t);
1159         node->type = XLAT_ALTERNATE;
1160
1161         p = fmt + 2;
1162         slen = xlat_tokenize_expansion(node, p, &node->child, error);
1163         if (slen <= 0) {
1164                 talloc_free(node);
1165                 return slen - (p - fmt);
1166         }
1167         p += slen;
1168
1169         if (p[0] != ':') {
1170                 talloc_free(node);
1171                 *error = "Expected ':' after first expansion";
1172                 return -(p - fmt);
1173         }
1174         p++;
1175
1176         if (p[0] != '-') {
1177                 talloc_free(node);
1178                 *error = "Expected '-' after ':'";
1179                 return -(p - fmt);
1180         }
1181         p++;
1182
1183         /*
1184          *      Allow the RHS to be empty as a special case.
1185          */
1186         if (*p == '}') {
1187                 /*
1188                  *      Hack up an empty string.
1189                  */
1190                 node->alternate = talloc_zero(node, xlat_exp_t);
1191                 node->alternate->type = XLAT_LITERAL;
1192                 node->alternate->fmt = talloc_typed_strdup(node->alternate, "");
1193                 *(p++) = '\0';
1194
1195         } else {
1196                 slen = xlat_tokenize_literal(node, p,  &node->alternate, true, error);
1197                 if (slen <= 0) {
1198                         talloc_free(node);
1199                         return slen - (p - fmt);
1200                 }
1201
1202                 if (!node->alternate) {
1203                         talloc_free(node);
1204                         *error = "Empty expansion is invalid";
1205                         return -(p - fmt);
1206                 }
1207                 p += slen;
1208         }
1209
1210         *head = node;
1211         return p - fmt;
1212 }
1213
1214 static ssize_t xlat_tokenize_expansion(TALLOC_CTX *ctx, char *fmt, xlat_exp_t **head,
1215                                        char const **error)
1216 {
1217         ssize_t slen;
1218         char *p, *q;
1219         xlat_exp_t *node;
1220         long num;
1221
1222         rad_assert(fmt[0] == '%');
1223         rad_assert(fmt[1] == '{');
1224
1225         /*
1226          *      %{%{...}:-bar}
1227          */
1228         if ((fmt[2] == '%') && (fmt[3] == '{')) return xlat_tokenize_alternation(ctx, fmt, head, error);
1229
1230         XLAT_DEBUG("EXPANSION <-- %s", fmt);
1231         node = talloc_zero(ctx, xlat_exp_t);
1232         node->fmt = fmt + 2;
1233         node->len = 0;
1234
1235 #ifdef HAVE_REGEX
1236         /*
1237          *      Handle regex's specially.
1238          */
1239         p = fmt + 2;
1240         num = strtol(p, &q, 10);
1241         if (p != q && (*q == '}')) {
1242                 XLAT_DEBUG("REGEX <-- %s", fmt);
1243                 *q = '\0';
1244
1245                 if ((num > REQUEST_MAX_REGEX) || (num < 0)) {
1246                         talloc_free(node);
1247                         *error = "Invalid regex reference.  Must be in range 0-" STRINGIFY(REQUEST_MAX_REGEX);
1248                         return -2;
1249                 }
1250                 node->attr.tmpl_num = num;
1251
1252                 node->type = XLAT_REGEX;
1253                 *head = node;
1254
1255                 return (q - fmt) + 1;
1256         }
1257 #endif /* HAVE_REGEX */
1258
1259         /*
1260          *      %{Attr-Name}
1261          *      %{Attr-Name[#]}
1262          *      %{Tunnel-Password:1}
1263          *      %{Tunnel-Password:1[#]}
1264          *      %{request:Attr-Name}
1265          *      %{request:Tunnel-Password:1}
1266          *      %{request:Tunnel-Password:1[#]}
1267          *      %{mod:foo}
1268          */
1269
1270         /*
1271          *      This is for efficiency, so we don't search for an xlat,
1272          *      when what's being referenced is obviously an attribute.
1273          */
1274         p = fmt + 2;
1275         for (q = p; *q != '\0'; q++) {
1276                 if (*q == ':') break;
1277
1278                 if (isspace((int) *q)) break;
1279
1280                 if (*q == '[') continue;
1281
1282                 if (*q == '}') break;
1283         }
1284
1285         /*
1286          *      Check for empty expressions %{}
1287          */
1288         if ((*q == '}') && (q == p)) {
1289                 talloc_free(node);
1290                 *error = "Empty expression is invalid";
1291                 return -(p - fmt);
1292         }
1293
1294         /*
1295          *      Might be a module name reference.
1296          *
1297          *      If it's not, it's an attribute or parse error.
1298          */
1299         if (*q == ':') {
1300                 *q = '\0';
1301                 node->xlat = xlat_find(node->fmt);
1302                 if (node->xlat) {
1303                         /*
1304                          *      %{mod:foo}
1305                          */
1306                         node->type = XLAT_MODULE;
1307
1308                         p = q + 1;
1309                         XLAT_DEBUG("MOD <-- %s ... %s", node->fmt, p);
1310
1311                         slen = xlat_tokenize_literal(node, p, &node->child, true, error);
1312                         if (slen < 0) {
1313                                 talloc_free(node);
1314                                 return slen - (p - fmt);
1315                         }
1316                         p += slen;
1317
1318                         *head = node;
1319                         rad_assert(node->next == NULL);
1320
1321                         return p - fmt;
1322                 }
1323                 *q = ':';       /* Avoids a strdup */
1324         }
1325
1326         /*
1327          *      The first token ends with:
1328          *      - '[' - Which is an attribute index, so it must be an attribute.
1329          *      - '}' - The end of the expansion, which means it was a bareword.
1330          */
1331         slen = tmpl_from_attr_substr(&node->attr, p, REQUEST_CURRENT, PAIR_LIST_REQUEST, true, true);
1332         if (slen <= 0) {
1333                 /*
1334                  *      If the parse error occurred before the ':'
1335                  *      then the error is changed to 'Unknown module',
1336                  *      as it was more likely to be a bad module name,
1337                  *      than a request qualifier.
1338                  */
1339                 if ((*q == ':') && ((p + (slen * -1)) < q)) {
1340                         *error = "Unknown module";
1341                 } else {
1342                         *error = fr_strerror();
1343                 }
1344
1345                 talloc_free(node);
1346                 return slen - (p - fmt);
1347         }
1348
1349         /*
1350          *      Might be a virtual XLAT attribute
1351          */
1352         if (node->attr.type == TMPL_TYPE_ATTR_UNDEFINED) {
1353                 node->xlat = xlat_find(node->attr.tmpl_unknown_name);
1354                 if (node->xlat && node->xlat->instance && !node->xlat->internal) {
1355                         talloc_free(node);
1356                         *error = "Missing content in expansion";
1357                         return -(p - fmt) - slen;
1358                 }
1359
1360                 if (node->xlat) {
1361                         node->type = XLAT_VIRTUAL;
1362                         node->fmt = node->attr.tmpl_unknown_name;
1363
1364                         XLAT_DEBUG("VIRTUAL <-- %s", node->fmt);
1365                         *head = node;
1366                         rad_assert(node->next == NULL);
1367                         q++;
1368                         return q - fmt;
1369                 }
1370
1371                 talloc_free(node);
1372                 *error = "Unknown attribute";
1373                 return -(p - fmt);
1374         }
1375
1376         node->type = XLAT_ATTRIBUTE;
1377         p += slen;
1378
1379         if (*p != '}') {
1380                 talloc_free(node);
1381                 *error = "No matching closing brace";
1382                 return -1;      /* second character of format string */
1383         }
1384         *p++ = '\0';
1385         *head = node;
1386         rad_assert(node->next == NULL);
1387
1388         return p - fmt;
1389 }
1390
1391
1392 static ssize_t xlat_tokenize_literal(TALLOC_CTX *ctx, char *fmt, xlat_exp_t **head,
1393                                      bool brace, char const **error)
1394 {
1395         char *p;
1396         xlat_exp_t *node;
1397
1398         if (!*fmt) return 0;
1399
1400         XLAT_DEBUG("LITERAL <-- %s", fmt);
1401
1402         node = talloc_zero(ctx, xlat_exp_t);
1403         node->fmt = fmt;
1404         node->len = 0;
1405         node->type = XLAT_LITERAL;
1406
1407         p = fmt;
1408
1409         while (*p) {
1410                 if (*p == '\\') {
1411                         if (!p[1]) {
1412                                 talloc_free(node);
1413                                 *error = "Invalid escape at end of string";
1414                                 return -(p - fmt);
1415                         }
1416
1417                         p += 2;
1418                         node->len += 2;
1419                         continue;
1420                 }
1421
1422                 /*
1423                  *      Process the expansion.
1424                  */
1425                 if ((p[0] == '%') && (p[1] == '{')) {
1426                         ssize_t slen;
1427
1428                         XLAT_DEBUG("EXPANSION-2 <-- %s", node->fmt);
1429
1430                         slen = xlat_tokenize_expansion(node, p, &node->next, error);
1431                         if (slen <= 0) {
1432                                 talloc_free(node);
1433                                 return slen - (p - fmt);
1434                         }
1435                         *p = '\0'; /* end the literal */
1436                         p += slen;
1437
1438                         rad_assert(node->next != NULL);
1439
1440                         /*
1441                          *      Short-circuit the recursive call.
1442                          *      This saves another function call and
1443                          *      memory allocation.
1444                          */
1445                         if (!*p) break;
1446
1447                         /*
1448                          *      "foo %{User-Name} bar"
1449                          *      LITERAL         "foo "
1450                          *      EXPANSION       User-Name
1451                          *      LITERAL         " bar"
1452                          */
1453                         slen = xlat_tokenize_literal(node->next, p, &(node->next->next), brace, error);
1454                         rad_assert(slen != 0);
1455                         if (slen < 0) {
1456                                 talloc_free(node);
1457                                 return slen - (p - fmt);
1458                         }
1459
1460                         brace = false; /* it was found above, or else the above code errored out */
1461                         p += slen;
1462                         break;  /* stop processing the string */
1463                 }
1464
1465                 /*
1466                  *      Check for valid single-character expansions.
1467                  */
1468                 if (p[0] == '%') {
1469                         ssize_t slen;
1470                         xlat_exp_t *next;
1471
1472                         if (!p[1] || !strchr("%}dlmntDGHISTYv", p[1])) {
1473                                 talloc_free(node);
1474                                 *error = "Invalid variable expansion";
1475                                 p++;
1476                                 return - (p - fmt);
1477                         }
1478
1479                         next = talloc_zero(node, xlat_exp_t);
1480                         next->len = 1;
1481
1482                         switch (p[1]) {
1483                         case '%':
1484                         case '}':
1485                                 next->fmt = talloc_strndup(next, p + 1, 1);
1486
1487                                 XLAT_DEBUG("LITERAL-ESCAPED <-- %s", next->fmt);
1488                                 next->type = XLAT_LITERAL;
1489                                 break;
1490
1491                         default:
1492                                 next->fmt = p + 1;
1493
1494                                 XLAT_DEBUG("PERCENT <-- %c", *next->fmt);
1495                                 next->type = XLAT_PERCENT;
1496                                 break;
1497                         }
1498
1499                         node->next = next;
1500                         *p = '\0';
1501                         p += 2;
1502
1503                         if (!*p) break;
1504
1505                         /*
1506                          *      And recurse.
1507                          */
1508                         slen = xlat_tokenize_literal(node->next, p, &(node->next->next), brace, error);
1509                         rad_assert(slen != 0);
1510                         if (slen < 0) {
1511                                 talloc_free(node);
1512                                 return slen - (p - fmt);
1513                         }
1514
1515                         brace = false; /* it was found above, or else the above code errored out */
1516                         p += slen;
1517                         break;  /* stop processing the string */
1518                 }
1519
1520                 /*
1521                  *      If required, eat the brace.
1522                  */
1523                 if (brace && (*p == '}')) {
1524                         brace = false;
1525                         *p = '\0';
1526                         p++;
1527                         break;
1528                 }
1529
1530                 p++;
1531                 node->len++;
1532         }
1533
1534         /*
1535          *      We were told to look for a brace, but we ran off of
1536          *      the end of the string before we found one.
1537          */
1538         if (brace) {
1539                 *error = "Missing closing brace at end of string";
1540                 return -(p - fmt);
1541         }
1542
1543         /*
1544          *      Squash zero-width literals
1545          */
1546         if (node->len > 0) {
1547                 *head = node;
1548
1549         } else {
1550                 (void) talloc_steal(ctx, node->next);
1551                 *head = node->next;
1552                 talloc_free(node);
1553         }
1554
1555         return p - fmt;
1556 }
1557
1558
1559 static char const xlat_tabs[] = "                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               ";
1560
1561 static void xlat_tokenize_debug(xlat_exp_t const *node, int lvl)
1562 {
1563         rad_assert(node != NULL);
1564
1565         if (lvl >= (int) sizeof(xlat_tabs)) lvl = sizeof(xlat_tabs);
1566
1567         while (node) {
1568                 switch (node->type) {
1569                 case XLAT_LITERAL:
1570                         DEBUG("%.*sliteral --> %s", lvl, xlat_tabs, node->fmt);
1571                         break;
1572
1573                 case XLAT_PERCENT:
1574                         DEBUG("%.*spercent --> %c", lvl, xlat_tabs, node->fmt[0]);
1575                         break;
1576
1577                 case XLAT_ATTRIBUTE:
1578                         rad_assert(node->attr.tmpl_da != NULL);
1579                         DEBUG("%.*sattribute --> %s", lvl, xlat_tabs, node->attr.tmpl_da->name);
1580                         rad_assert(node->child == NULL);
1581                         if ((node->attr.tmpl_tag != TAG_ANY) || (node->attr.tmpl_num != NUM_ANY)) {
1582                                 DEBUG("%.*s{", lvl, xlat_tabs);
1583
1584                                 DEBUG("%.*sref  %d", lvl + 1, xlat_tabs, node->attr.tmpl_request);
1585                                 DEBUG("%.*slist %d", lvl + 1, xlat_tabs, node->attr.tmpl_list);
1586
1587                                 if (node->attr.tmpl_tag != TAG_ANY) {
1588                                         DEBUG("%.*stag %d", lvl + 1, xlat_tabs, node->attr.tmpl_tag);
1589                                 }
1590                                 if (node->attr.tmpl_num != NUM_ANY) {
1591                                         if (node->attr.tmpl_num == NUM_COUNT) {
1592                                                 DEBUG("%.*s[#]", lvl + 1, xlat_tabs);
1593                                         } else if (node->attr.tmpl_num == NUM_ALL) {
1594                                                 DEBUG("%.*s[*]", lvl + 1, xlat_tabs);
1595                                         } else {
1596                                                 DEBUG("%.*s[%d]", lvl + 1, xlat_tabs, node->attr.tmpl_num);
1597                                         }
1598                                 }
1599
1600                                 DEBUG("%.*s}", lvl, xlat_tabs);
1601                         }
1602                         break;
1603
1604                 case XLAT_VIRTUAL:
1605                         rad_assert(node->fmt != NULL);
1606                         DEBUG("%.*svirtual --> %s", lvl, xlat_tabs, node->fmt);
1607                         break;
1608
1609                 case XLAT_MODULE:
1610                         rad_assert(node->xlat != NULL);
1611                         DEBUG("%.*sxlat --> %s", lvl, xlat_tabs, node->xlat->name);
1612                         if (node->child) {
1613                                 DEBUG("%.*s{", lvl, xlat_tabs);
1614                                 xlat_tokenize_debug(node->child, lvl + 1);
1615                                 DEBUG("%.*s}", lvl, xlat_tabs);
1616                         }
1617                         break;
1618
1619 #ifdef HAVE_REGEX
1620                 case XLAT_REGEX:
1621                         DEBUG("%.*sregex-var --> %d", lvl, xlat_tabs, node->attr.tmpl_num);
1622                         break;
1623 #endif
1624
1625                 case XLAT_ALTERNATE:
1626                         DEBUG("%.*sXLAT-IF {", lvl, xlat_tabs);
1627                         xlat_tokenize_debug(node->child, lvl + 1);
1628                         DEBUG("%.*s}", lvl, xlat_tabs);
1629                         DEBUG("%.*sXLAT-ELSE {", lvl, xlat_tabs);
1630                         xlat_tokenize_debug(node->alternate, lvl + 1);
1631                         DEBUG("%.*s}", lvl, xlat_tabs);
1632                         break;
1633                 }
1634                 node = node->next;
1635         }
1636 }
1637
1638 size_t xlat_sprint(char *buffer, size_t bufsize, xlat_exp_t const *node)
1639 {
1640         size_t len;
1641         char *p, *end;
1642
1643         if (!node) {
1644                 *buffer = '\0';
1645                 return 0;
1646         }
1647
1648         p = buffer;
1649         end = buffer + bufsize;
1650
1651         while (node) {
1652                 switch (node->type) {
1653                 case XLAT_LITERAL:
1654                         strlcpy(p, node->fmt, end - p);
1655                         p += strlen(p);
1656                         break;
1657
1658                 case XLAT_PERCENT:
1659                         p[0] = '%';
1660                         p[1] = node->fmt[0];
1661                         p += 2;
1662                         break;
1663
1664                 case XLAT_ATTRIBUTE:
1665                         *(p++) = '%';
1666                         *(p++) = '{';
1667
1668                         if (node->attr.tmpl_request != REQUEST_CURRENT) {
1669                                 strlcpy(p, fr_int2str(request_refs, node->attr.tmpl_request, "??"), end - p);
1670                                 p += strlen(p);
1671                                 *(p++) = '.';
1672                         }
1673
1674                         if ((node->attr.tmpl_request != REQUEST_CURRENT) ||
1675                             (node->attr.tmpl_list != PAIR_LIST_REQUEST)) {
1676                                 strlcpy(p, fr_int2str(pair_lists, node->attr.tmpl_list, "??"), end - p);
1677                                 p += strlen(p);
1678                                 *(p++) = ':';
1679                         }
1680
1681                         strlcpy(p, node->attr.tmpl_da->name, end - p);
1682                         p += strlen(p);
1683
1684                         if (node->attr.tmpl_tag != TAG_ANY) {
1685                                 *(p++) = ':';
1686                                 snprintf(p, end - p, "%u", node->attr.tmpl_tag);
1687                                 p += strlen(p);
1688                         }
1689
1690                         if (node->attr.tmpl_num != NUM_ANY) {
1691                                 *(p++) = '[';
1692                                 switch (node->attr.tmpl_num) {
1693                                 case NUM_COUNT:
1694                                         *(p++) = '#';
1695                                         break;
1696
1697                                 case NUM_ALL:
1698                                         *(p++) = '*';
1699                                         break;
1700
1701                                 default:
1702                                         snprintf(p, end - p, "%i", node->attr.tmpl_num);
1703                                         p += strlen(p);
1704                                 }
1705                                 *(p++) = ']';
1706                         }
1707                         *(p++) = '}';
1708                         break;
1709 #ifdef HAVE_REGEX
1710                 case XLAT_REGEX:
1711                         snprintf(p, end - p, "%%{%i}", node->attr.tmpl_num);
1712                         p += strlen(p);
1713                         break;
1714 #endif
1715                 case XLAT_VIRTUAL:
1716                         *(p++) = '%';
1717                         *(p++) = '{';
1718                         strlcpy(p, node->fmt, end - p);
1719                         p += strlen(p);
1720                         *(p++) = '}';
1721                         break;
1722
1723                 case XLAT_MODULE:
1724                         *(p++) = '%';
1725                         *(p++) = '{';
1726                         strlcpy(p, node->xlat->name, end - p);
1727                         p += strlen(p);
1728                         *(p++) = ':';
1729                         rad_assert(node->child != NULL);
1730                         len = xlat_sprint(p, end - p, node->child);
1731                         p += len;
1732                         *(p++) = '}';
1733                         break;
1734
1735                 case XLAT_ALTERNATE:
1736                         *(p++) = '%';
1737                         *(p++) = '{';
1738
1739                         len = xlat_sprint(p, end - p, node->child);
1740                         p += len;
1741
1742                         *(p++) = ':';
1743                         *(p++) = '-';
1744
1745                         len = xlat_sprint(p, end - p, node->alternate);
1746                         p += len;
1747
1748                         *(p++) = '}';
1749                         break;
1750                 }
1751
1752
1753                 if (p == end) break;
1754
1755                 node = node->next;
1756         }
1757
1758         *p = '\0';
1759
1760         return p - buffer;
1761 }
1762
1763 ssize_t xlat_tokenize(TALLOC_CTX *ctx, char *fmt, xlat_exp_t **head,
1764                       char const **error)
1765 {
1766         return xlat_tokenize_literal(ctx, fmt, head, false, error);
1767 }
1768
1769
1770 /** Tokenize an xlat expansion
1771  *
1772  * @param[in] request the input request.  Memory will be attached here.
1773  * @param[in] fmt the format string to expand
1774  * @param[out] head the head of the xlat list / tree structure.
1775  */
1776 static ssize_t xlat_tokenize_request(REQUEST *request, char const *fmt, xlat_exp_t **head)
1777 {
1778         ssize_t slen;
1779         char *tokens;
1780         char const *error = NULL;
1781
1782         *head = NULL;
1783
1784         /*
1785          *      Copy the original format string to a buffer so that
1786          *      the later functions can mangle it in-place, which is
1787          *      much faster.
1788          */
1789         tokens = talloc_typed_strdup(request, fmt);
1790         if (!tokens) {
1791                 error = "Out of memory";
1792                 return -1;
1793         }
1794
1795         slen = xlat_tokenize_literal(request, tokens, head, false, &error);
1796
1797         /*
1798          *      Zero length expansion, return a zero length node.
1799          */
1800         if (slen == 0) {
1801                 *head = talloc_zero(request, xlat_exp_t);
1802         }
1803
1804         /*
1805          *      Output something like:
1806          *
1807          *      "format string"
1808          *      "       ^ error was here"
1809          */
1810         if (slen < 0) {
1811                 talloc_free(tokens);
1812
1813                 if (!error) error = "Unknown error";
1814
1815                 REMARKER(fmt, -slen, error);
1816                 return slen;
1817         }
1818
1819         if (*head && (rad_debug_lvl > 2)) {
1820                 DEBUG("%s", fmt);
1821                 DEBUG("Parsed xlat tree:");
1822                 xlat_tokenize_debug(*head, 0);
1823         }
1824
1825         /*
1826          *      All of the nodes point to offsets in the "tokens"
1827          *      string.  Let's ensure that free'ing head will free
1828          *      "tokens", too.
1829          */
1830         (void) talloc_steal(*head, tokens);
1831
1832         return slen;
1833 }
1834
1835
1836 static char *xlat_getvp(TALLOC_CTX *ctx, REQUEST *request, vp_tmpl_t const *vpt,
1837                         bool escape, bool return_null)
1838 {
1839         VALUE_PAIR *vp = NULL, *virtual = NULL;
1840         RADIUS_PACKET *packet = NULL;
1841         DICT_VALUE *dv;
1842         char *ret = NULL;
1843
1844         vp_cursor_t cursor;
1845         char quote = escape ? '"' : '\0';
1846
1847         rad_assert((vpt->type == TMPL_TYPE_ATTR) || (vpt->type == TMPL_TYPE_LIST));
1848
1849         /*
1850          *      We only support count and concatenate operations on lists.
1851          */
1852         if (vpt->type == TMPL_TYPE_LIST) {
1853                 vp = tmpl_cursor_init(NULL, &cursor, request, vpt);
1854                 goto do_print;
1855         }
1856
1857         /*
1858          *      See if we're dealing with an attribute in the request
1859          *
1860          *      This allows users to manipulate virtual attributes as if
1861          *      they were real ones.
1862          */
1863         vp = tmpl_cursor_init(NULL, &cursor, request, vpt);
1864         if (vp) goto do_print;
1865
1866         /*
1867          *      We didn't find the VP in a list.
1868          *      If it's not a virtual one, and we're not meant to
1869          *      be counting it, return.
1870          */
1871         if (!vpt->tmpl_da->flags.virtual) {
1872                 if (vpt->tmpl_num == NUM_COUNT) goto do_print;
1873                 return NULL;
1874         }
1875
1876         /*
1877          *      Switch out the request to the one specified by the template
1878          */
1879         if (radius_request(&request, vpt->tmpl_request) < 0) return NULL;
1880
1881         /*
1882          *      Some non-packet expansions
1883          */
1884         switch (vpt->tmpl_da->attr) {
1885         default:
1886                 break;          /* ignore them */
1887
1888         case PW_CLIENT_SHORTNAME:
1889                 if (vpt->tmpl_num == NUM_COUNT) goto count_virtual;
1890                 if (request->client && request->client->shortname) {
1891                         return talloc_typed_strdup(ctx, request->client->shortname);
1892                 }
1893                 return talloc_typed_strdup(ctx, "<UNKNOWN-CLIENT>");
1894
1895         case PW_REQUEST_PROCESSING_STAGE:
1896                 if (vpt->tmpl_num == NUM_COUNT) goto count_virtual;
1897                 if (request->component) {
1898                         return talloc_typed_strdup(ctx, request->component);
1899                 }
1900                 return talloc_typed_strdup(ctx, "server_core");
1901
1902         case PW_VIRTUAL_SERVER:
1903                 if (vpt->tmpl_num == NUM_COUNT) goto count_virtual;
1904                 if (!request->server) return NULL;
1905                 return talloc_typed_strdup(ctx, request->server);
1906
1907         case PW_MODULE_RETURN_CODE:
1908                 if (vpt->tmpl_num == NUM_COUNT) goto count_virtual;
1909                 if (!request->rcode) return NULL;
1910                 return talloc_typed_strdup(ctx, fr_int2str(modreturn_table, request->rcode, ""));
1911         }
1912
1913         /*
1914          *      All of the attributes must now refer to a packet.
1915          *      If there's no packet, we can't print any attribute
1916          *      referencing it.
1917          */
1918         packet = radius_packet(request, vpt->tmpl_list);
1919         if (!packet) {
1920                 if (return_null) return NULL;
1921                 return vp_aprints_type(ctx, vpt->tmpl_da->type);
1922         }
1923
1924         vp = NULL;
1925         switch (vpt->tmpl_da->attr) {
1926         default:
1927                 break;
1928
1929         case PW_PACKET_TYPE:
1930                 dv = dict_valbyattr(PW_PACKET_TYPE, 0, packet->code);
1931                 if (dv) return talloc_typed_strdup(ctx, dv->name);
1932                 return talloc_typed_asprintf(ctx, "%d", packet->code);
1933
1934         case PW_RESPONSE_PACKET_TYPE:
1935         {
1936                 int code = 0;
1937
1938 #ifdef WITH_PROXY
1939                 if (request->proxy_reply && (!request->reply || !request->reply->code)) {
1940                         code = request->proxy_reply->code;
1941                 } else
1942 #endif
1943                         if (request->reply) {
1944                                 code = request->reply->code;
1945                         }
1946
1947                 return talloc_typed_strdup(ctx, fr_packet_codes[code]);
1948         }
1949
1950         /*
1951          *      Virtual attributes which require a temporary VALUE_PAIR
1952          *      to be allocated. We can't use stack allocated memory
1953          *      because of the talloc checks sprinkled throughout the
1954          *      various VP functions.
1955          */
1956         case PW_PACKET_AUTHENTICATION_VECTOR:
1957                 virtual = fr_pair_afrom_da(ctx, vpt->tmpl_da);
1958                 fr_pair_value_memcpy(virtual, packet->vector, sizeof(packet->vector));
1959                 vp = virtual;
1960                 break;
1961
1962         case PW_CLIENT_IP_ADDRESS:
1963         case PW_PACKET_SRC_IP_ADDRESS:
1964                 if (packet->src_ipaddr.af == AF_INET) {
1965                         virtual = fr_pair_afrom_da(ctx, vpt->tmpl_da);
1966                         virtual->vp_ipaddr = packet->src_ipaddr.ipaddr.ip4addr.s_addr;
1967                         vp = virtual;
1968                 }
1969                 break;
1970
1971         case PW_PACKET_DST_IP_ADDRESS:
1972                 if (packet->dst_ipaddr.af == AF_INET) {
1973                         virtual = fr_pair_afrom_da(ctx, vpt->tmpl_da);
1974                         virtual->vp_ipaddr = packet->dst_ipaddr.ipaddr.ip4addr.s_addr;
1975                         vp = virtual;
1976                 }
1977                 break;
1978
1979         case PW_PACKET_SRC_IPV6_ADDRESS:
1980                 if (packet->src_ipaddr.af == AF_INET6) {
1981                         virtual = fr_pair_afrom_da(ctx, vpt->tmpl_da);
1982                         memcpy(&virtual->vp_ipv6addr,
1983                                &packet->src_ipaddr.ipaddr.ip6addr,
1984                                sizeof(packet->src_ipaddr.ipaddr.ip6addr));
1985                         vp = virtual;
1986                 }
1987                 break;
1988
1989         case PW_PACKET_DST_IPV6_ADDRESS:
1990                 if (packet->dst_ipaddr.af == AF_INET6) {
1991                         virtual = fr_pair_afrom_da(ctx, vpt->tmpl_da);
1992                         memcpy(&virtual->vp_ipv6addr,
1993                                &packet->dst_ipaddr.ipaddr.ip6addr,
1994                                sizeof(packet->dst_ipaddr.ipaddr.ip6addr));
1995                         vp = virtual;
1996                 }
1997                 break;
1998
1999         case PW_PACKET_SRC_PORT:
2000                 virtual = fr_pair_afrom_da(ctx, vpt->tmpl_da);
2001                 virtual->vp_integer = packet->src_port;
2002                 vp = virtual;
2003                 break;
2004
2005         case PW_PACKET_DST_PORT:
2006                 virtual = fr_pair_afrom_da(ctx, vpt->tmpl_da);
2007                 virtual->vp_integer = packet->dst_port;
2008                 vp = virtual;
2009                 break;
2010         }
2011
2012         /*
2013          *      Fake various operations for virtual attributes.
2014          */
2015         if (virtual) {
2016                 if (vpt->tmpl_num != NUM_ANY) switch (vpt->tmpl_num) {
2017                 /*
2018                  *      [n] is NULL (we only have [0])
2019                  */
2020                 default:
2021                         goto finish;
2022                 /*
2023                  *      [*] means only one.
2024                  */
2025                 case NUM_ALL:
2026                         break;
2027
2028                 /*
2029                  *      [#] means 1 (as there's only one)
2030                  */
2031                 case NUM_COUNT:
2032                 count_virtual:
2033                         ret = talloc_strdup(ctx, "1");
2034                         goto finish;
2035
2036                 /*
2037                  *      [0] is fine (get the first instance)
2038                  */
2039                 case 0:
2040                         break;
2041                 }
2042                 goto print;
2043         }
2044
2045 do_print:
2046         switch (vpt->tmpl_num) {
2047         /*
2048          *      Return a count of the VPs.
2049          */
2050         case NUM_COUNT:
2051         {
2052                 int count = 0;
2053
2054                 for (vp = tmpl_cursor_init(NULL, &cursor, request, vpt);
2055                      vp;
2056                      vp = tmpl_cursor_next(&cursor, vpt)) count++;
2057
2058                 return talloc_typed_asprintf(ctx, "%d", count);
2059         }
2060
2061
2062         /*
2063          *      Concatenate all values together,
2064          *      separated by commas.
2065          */
2066         case NUM_ALL:
2067         {
2068                 char *p, *q;
2069
2070                 if (!fr_cursor_current(&cursor)) return NULL;
2071                 p = vp_aprints_value(ctx, vp, quote);
2072                 if (!p) return NULL;
2073
2074                 while ((vp = tmpl_cursor_next(&cursor, vpt)) != NULL) {
2075                         q = vp_aprints_value(ctx, vp, quote);
2076                         if (!q) return NULL;
2077                         p = talloc_strdup_append(p, ",");
2078                         p = talloc_strdup_append(p, q);
2079                 }
2080
2081                 return p;
2082         }
2083
2084         default:
2085                 /*
2086                  *      The cursor was set to the correct
2087                  *      position above by tmpl_cursor_init.
2088                  */
2089                 vp = fr_cursor_current(&cursor);
2090                 break;
2091         }
2092
2093         if (!vp) {
2094                 if (return_null) return NULL;
2095                 return vp_aprints_type(ctx, vpt->tmpl_da->type);
2096         }
2097
2098 print:
2099         ret = vp_aprints_value(ctx, vp, quote);
2100
2101 finish:
2102         talloc_free(virtual);
2103         return ret;
2104 }
2105
2106 #ifdef DEBUG_XLAT
2107 static const char xlat_spaces[] = "                                                                                                                                                                                                                                                                ";
2108 #endif
2109
2110 static char *xlat_aprint(TALLOC_CTX *ctx, REQUEST *request, xlat_exp_t const * const node,
2111                          xlat_escape_t escape, void *escape_ctx, int lvl)
2112 {
2113         ssize_t rcode;
2114         char *str = NULL, *child;
2115         char const *p;
2116
2117         XLAT_DEBUG("%.*sxlat aprint %d %s", lvl, xlat_spaces, node->type, node->fmt);
2118
2119         switch (node->type) {
2120                 /*
2121                  *      Don't escape this.
2122                  */
2123         case XLAT_LITERAL:
2124                 XLAT_DEBUG("%.*sxlat_aprint LITERAL", lvl, xlat_spaces);
2125                 return talloc_typed_strdup(ctx, node->fmt);
2126
2127                 /*
2128                  *      Do a one-character expansion.
2129                  */
2130         case XLAT_PERCENT:
2131         {
2132                 char *nl;
2133                 size_t freespace = 256;
2134                 struct tm ts;
2135                 time_t when;
2136                 int usec;
2137
2138                 XLAT_DEBUG("%.*sxlat_aprint PERCENT", lvl, xlat_spaces);
2139
2140                 str = talloc_array(ctx, char, freespace); /* @todo do better allocation */
2141                 p = node->fmt;
2142
2143                 when = request->timestamp;
2144                 usec = 0;
2145                 if (request->packet) {
2146                         when = request->packet->timestamp.tv_sec;
2147                         usec = request->packet->timestamp.tv_usec;
2148                 }
2149
2150                 switch (*p) {
2151                 case '%':
2152                         str[0] = '%';
2153                         str[1] = '\0';
2154                         break;
2155
2156                 case 'd': /* request day */
2157                         if (!localtime_r(&when, &ts)) goto error;
2158                         strftime(str, freespace, "%d", &ts);
2159                         break;
2160
2161                 case 'l': /* request timestamp */
2162                         snprintf(str, freespace, "%lu",
2163                                  (unsigned long) when);
2164                         break;
2165
2166                 case 'm': /* request month */
2167                         if (!localtime_r(&when, &ts)) goto error;
2168                         strftime(str, freespace, "%m", &ts);
2169                         break;
2170
2171                 case 'n': /* Request Number*/
2172                         snprintf(str, freespace, "%u", request->number);
2173                         break;
2174
2175                 case 't': /* request timestamp */
2176                         CTIME_R(&when, str, freespace);
2177                         nl = strchr(str, '\n');
2178                         if (nl) *nl = '\0';
2179                         break;
2180
2181                 case 'D': /* request date */
2182                         if (!localtime_r(&when, &ts)) goto error;
2183                         strftime(str, freespace, "%Y%m%d", &ts);
2184                         break;
2185
2186                 case 'G': /* request minute */
2187                         if (!localtime_r(&when, &ts)) goto error;
2188                         strftime(str, freespace, "%M", &ts);
2189                         break;
2190
2191                 case 'H': /* request hour */
2192                         if (!localtime_r(&when, &ts)) goto error;
2193                         strftime(str, freespace, "%H", &ts);
2194                         break;
2195
2196                 case 'I': /* Request ID */
2197                         if (request->packet) {
2198                                 snprintf(str, freespace, "%i", request->packet->id);
2199                         }
2200                         break;
2201
2202                 case 'S': /* request timestamp in SQL format*/
2203                         if (!localtime_r(&when, &ts)) goto error;
2204                         strftime(str, freespace, "%Y-%m-%d %H:%M:%S", &ts);
2205                         break;
2206
2207                 case 'T': /* request timestamp */
2208                         if (!localtime_r(&when, &ts)) goto error;
2209                         nl = str + strftime(str, freespace, "%Y-%m-%d-%H.%M.%S", &ts);
2210                         rad_assert(((str + freespace) - nl) >= 8);
2211                         snprintf(nl, (str + freespace) - nl, ".%06d",  usec);
2212                         break;
2213
2214                 case 'Y': /* request year */
2215                         if (!localtime_r(&when, &ts)) {
2216                                 error:
2217                                 REDEBUG("Failed converting packet timestamp to localtime: %s", fr_syserror(errno));
2218                                 talloc_free(str);
2219                                 return NULL;
2220                         }
2221                         strftime(str, freespace, "%Y", &ts);
2222                         break;
2223
2224                 case 'v': /* Version of code */
2225                         RWDEBUG("%%v is deprecated and will be removed.  Use ${version.freeradius-server}");
2226                         snprintf(str, freespace, "%s", radiusd_version_short);
2227                         break;
2228
2229                 default:
2230                         rad_assert(0 == 1);
2231                         break;
2232                 }
2233         }
2234                 break;
2235
2236         case XLAT_ATTRIBUTE:
2237                 XLAT_DEBUG("%.*sxlat_aprint ATTRIBUTE", lvl, xlat_spaces);
2238
2239                 /*
2240                  *      Some attributes are virtual <sigh>
2241                  */
2242                 str = xlat_getvp(ctx, request, &node->attr, escape ? false : true, true);
2243                 if (str) {
2244                         XLAT_DEBUG("%.*sEXPAND attr %s", lvl, xlat_spaces, node->attr.tmpl_da->name);
2245                         XLAT_DEBUG("%.*s       ---> %s", lvl ,xlat_spaces, str);
2246                 }
2247                 break;
2248
2249         case XLAT_VIRTUAL:
2250                 XLAT_DEBUG("xlat_aprint VIRTUAL");
2251                 str = talloc_array(ctx, char, 2048); /* FIXME: have the module call talloc_typed_asprintf */
2252                 rcode = node->xlat->func(node->xlat->instance, request, NULL, str, 2048);
2253                 if (rcode < 0) {
2254                         talloc_free(str);
2255                         return NULL;
2256                 }
2257                 RDEBUG2("EXPAND %s", node->xlat->name);
2258                 RDEBUG2("   --> %s", str);
2259                 break;
2260
2261         case XLAT_MODULE:
2262                 XLAT_DEBUG("xlat_aprint MODULE");
2263
2264                 if (node->child) {
2265                         if (xlat_process(&child, request, node->child, node->xlat->escape, node->xlat->instance) == 0) {
2266                                 return NULL;
2267                         }
2268
2269                         XLAT_DEBUG("%.*sEXPAND mod %s %s", lvl, xlat_spaces, node->fmt, node->child->fmt);
2270                 } else {
2271                         XLAT_DEBUG("%.*sEXPAND mod %s", lvl, xlat_spaces, node->fmt);
2272                         child = talloc_typed_strdup(ctx, "");
2273                 }
2274
2275                 XLAT_DEBUG("%.*s      ---> %s", lvl, xlat_spaces, child);
2276
2277                 /*
2278                  *      Smash \n --> CR.
2279                  *
2280                  *      The OUTPUT of xlat is a "raw" string.  The INPUT is a printable string.
2281                  *
2282                  *      This is really the reverse of fr_prints().
2283                  */
2284                 if (cf_new_escape && *child) {
2285                         ssize_t slen;
2286                         PW_TYPE type;
2287                         value_data_t data;
2288
2289                         type = PW_TYPE_STRING;
2290                         slen = value_data_from_str(request, &data, &type, NULL, child, talloc_array_length(child) - 1, '"');
2291                         if (slen <= 0) {
2292                                 talloc_free(child);
2293                                 return NULL;
2294                         }
2295
2296                         talloc_free(child);
2297                         child = data.ptr;
2298
2299                 } else {
2300                         char *q;
2301
2302                         p = q = child;
2303                         while (*p) {
2304                                 if (*p == '\\') switch (p[1]) {
2305                                         default:
2306                                                 *(q++) = p[1];
2307                                                 p += 2;
2308                                                 continue;
2309
2310                                         case 'n':
2311                                                 *(q++) = '\n';
2312                                                 p += 2;
2313                                                 continue;
2314
2315                                         case 't':
2316                                                 *(q++) = '\t';
2317                                                 p += 2;
2318                                                 continue;
2319                                         }
2320
2321                                 *(q++) = *(p++);
2322                         }
2323                         *q = '\0';
2324                 }
2325
2326                 str = talloc_array(ctx, char, 2048); /* FIXME: have the module call talloc_typed_asprintf */
2327                 *str = '\0';    /* Be sure the string is NULL terminated, we now only free on error */
2328
2329                 rcode = node->xlat->func(node->xlat->instance, request, child, str, 2048);
2330                 talloc_free(child);
2331                 if (rcode < 0) {
2332                         talloc_free(str);
2333                         return NULL;
2334                 }
2335                 break;
2336
2337 #ifdef HAVE_REGEX
2338         case XLAT_REGEX:
2339                 XLAT_DEBUG("%.*sxlat_aprint REGEX", lvl, xlat_spaces);
2340                 if (regex_request_to_sub(ctx, &str, request, node->attr.tmpl_num) < 0) return NULL;
2341
2342                 break;
2343 #endif
2344
2345         case XLAT_ALTERNATE:
2346                 XLAT_DEBUG("%.*sxlat_aprint ALTERNATE", lvl, xlat_spaces);
2347                 rad_assert(node->child != NULL);
2348                 rad_assert(node->alternate != NULL);
2349
2350                 /*
2351                  *      If there are no "next" nodes, call ourselves
2352                  *      recursively, which is fast.
2353                  *
2354                  *      If there are "next" nodes, call xlat_process()
2355                  *      which does a ton more work.
2356                  */
2357                 if (!node->next) {
2358                         str = xlat_aprint(ctx, request, node->child, escape, escape_ctx, lvl);
2359                         if (str) {
2360                                 XLAT_DEBUG("%.*sALTERNATE got first string: %s", lvl, xlat_spaces, str);
2361                         } else {
2362                                 str = xlat_aprint(ctx, request, node->alternate, escape, escape_ctx, lvl);
2363                                 XLAT_DEBUG("%.*sALTERNATE got alternate string %s", lvl, xlat_spaces, str);
2364                         }
2365                 } else {
2366
2367                         if (xlat_process(&str, request, node->child, escape, escape_ctx) > 0) {
2368                                 XLAT_DEBUG("%.*sALTERNATE got first string: %s", lvl, xlat_spaces, str);
2369                         } else {
2370                                 (void) xlat_process(&str, request, node->alternate, escape, escape_ctx);
2371                                 XLAT_DEBUG("%.*sALTERNATE got alternate string %s", lvl, xlat_spaces, str);
2372                         }
2373                 }
2374                 break;
2375         }
2376
2377         /*
2378          *      If there's no data, return that, instead of an empty string.
2379          */
2380         if (str && !str[0]) {
2381                 talloc_free(str);
2382                 return NULL;
2383         }
2384
2385         /*
2386          *      Escape the non-literals we found above.
2387          */
2388         if (str && escape) {
2389                 size_t len;
2390                 char *escaped;
2391
2392                 len = talloc_array_length(str) * 3;
2393
2394                 escaped = talloc_array(ctx, char, len);
2395                 escape(request, escaped, len, str, escape_ctx);
2396                 talloc_free(str);
2397                 str = escaped;
2398         }
2399
2400         return str;
2401 }
2402
2403
2404 static size_t xlat_process(char **out, REQUEST *request, xlat_exp_t const * const head,
2405                            xlat_escape_t escape, void *escape_ctx)
2406 {
2407         int i, list;
2408         size_t total;
2409         char **array, *answer;
2410         xlat_exp_t const *node;
2411
2412         *out = NULL;
2413
2414         /*
2415          *      There are no nodes to process, so the result is a zero
2416          *      length string.
2417          */
2418         if (!head) {
2419                 *out = talloc_zero_array(request, char, 1);
2420                 return 0;
2421         }
2422
2423         /*
2424          *      Hack for speed.  If it's one expansion, just allocate
2425          *      that and return, instead of allocating an intermediary
2426          *      array.
2427          */
2428         if (!head->next) {
2429                 /*
2430                  *      Pass the MAIN escape function.  Recursive
2431                  *      calls will call node-specific escape
2432                  *      functions.
2433                  */
2434                 answer = xlat_aprint(request, request, head, escape, escape_ctx, 0);
2435                 if (!answer) {
2436                         *out = talloc_zero_array(request, char, 1);
2437                         return 0;
2438                 }
2439                 *out = answer;
2440                 return strlen(answer);
2441         }
2442
2443         list = 0;               /* FIXME: calculate this once */
2444         for (node = head; node != NULL; node = node->next) {
2445                 list++;
2446         }
2447
2448         array = talloc_array(request, char *, list);
2449         if (!array) return -1;
2450
2451         for (node = head, i = 0; node != NULL; node = node->next, i++) {
2452                 array[i] = xlat_aprint(array, request, node, escape, escape_ctx, 0); /* may be NULL */
2453         }
2454
2455         total = 0;
2456         for (i = 0; i < list; i++) {
2457                 if (array[i]) total += strlen(array[i]); /* FIXME: calculate strlen once */
2458         }
2459
2460         if (!total) {
2461                 talloc_free(array);
2462                 *out = talloc_zero_array(request, char, 1);
2463                 return 0;
2464         }
2465
2466         answer = talloc_array(request, char, total + 1);
2467
2468         total = 0;
2469         for (i = 0; i < list; i++) {
2470                 size_t len;
2471
2472                 if (array[i]) {
2473                         len = strlen(array[i]);
2474                         memcpy(answer + total, array[i], len);
2475                         total += len;
2476                 }
2477         }
2478         answer[total] = '\0';
2479         talloc_free(array);     /* and child entries */
2480
2481         *out = answer;
2482         return total;
2483 }
2484
2485
2486 /** Replace %whatever in a string.
2487  *
2488  * See 'doc/configuration/variables.rst' for more information.
2489  *
2490  * @param[out] out Where to write pointer to output buffer.
2491  * @param[in] outlen Size of out.
2492  * @param[in] request current request.
2493  * @param[in] node the xlat structure to expand
2494  * @param[in] escape function to escape final value e.g. SQL quoting.
2495  * @param[in] escape_ctx pointer to pass to escape function.
2496  * @return length of string written @bug should really have -1 for failure
2497  */
2498 static ssize_t xlat_expand_struct(char **out, size_t outlen, REQUEST *request, xlat_exp_t const *node,
2499                                   xlat_escape_t escape, void *escape_ctx)
2500 {
2501         char *buff;
2502         ssize_t len;
2503
2504         rad_assert(node != NULL);
2505
2506         len = xlat_process(&buff, request, node, escape, escape_ctx);
2507         if ((len < 0) || !buff) {
2508                 rad_assert(buff == NULL);
2509                 if (*out) *out[0] = '\0';
2510                 return len;
2511         }
2512
2513         len = strlen(buff);
2514
2515         /*
2516          *      If out doesn't point to an existing buffer
2517          *      copy the pointer to our buffer over.
2518          */
2519         if (!*out) {
2520                 *out = buff;
2521                 return len;
2522         }
2523
2524         /*
2525          *      Otherwise copy the malloced buffer to the fixed one.
2526          */
2527         strlcpy(*out, buff, outlen);
2528         talloc_free(buff);
2529         return len;
2530 }
2531
2532 static ssize_t xlat_expand(char **out, size_t outlen, REQUEST *request, char const *fmt,
2533                            xlat_escape_t escape, void *escape_ctx) CC_HINT(nonnull (1, 3, 4));
2534
2535 /** Replace %whatever in a string.
2536  *
2537  * See 'doc/configuration/variables.rst' for more information.
2538  *
2539  * @param[out] out Where to write pointer to output buffer.
2540  * @param[in] outlen Size of out.
2541  * @param[in] request current request.
2542  * @param[in] fmt string to expand.
2543  * @param[in] escape function to escape final value e.g. SQL quoting.
2544  * @param[in] escape_ctx pointer to pass to escape function.
2545  * @return length of string written @bug should really have -1 for failure
2546  */
2547 static ssize_t xlat_expand(char **out, size_t outlen, REQUEST *request, char const *fmt,
2548                            xlat_escape_t escape, void *escape_ctx)
2549 {
2550         ssize_t len;
2551         xlat_exp_t *node;
2552
2553         /*
2554          *      Give better errors than the old code.
2555          */
2556         len = xlat_tokenize_request(request, fmt, &node);
2557         if (len == 0) {
2558                 if (*out) {
2559                         *out[0] = '\0';
2560                 } else {
2561                         *out = talloc_zero_array(request, char, 1);
2562                 }
2563                 return 0;
2564         }
2565
2566         if (len < 0) {
2567                 if (*out) *out[0] = '\0';
2568                 return -1;
2569         }
2570
2571         len = xlat_expand_struct(out, outlen, request, node, escape, escape_ctx);
2572         talloc_free(node);
2573
2574         RDEBUG2("EXPAND %s", fmt);
2575         RDEBUG2("   --> %s", *out);
2576
2577         return len;
2578 }
2579
2580 /** Try to convert an xlat to a tmpl for efficiency
2581  *
2582  * @param ctx to allocate new vp_tmpl_t in.
2583  * @param node to convert.
2584  * @return NULL if unable to convert (not necessarily error), or a new vp_tmpl_t.
2585  */
2586 vp_tmpl_t *xlat_to_tmpl_attr(TALLOC_CTX *ctx, xlat_exp_t *node)
2587 {
2588         vp_tmpl_t *vpt;
2589
2590         if (node->next || (node->type != XLAT_ATTRIBUTE) || (node->attr.type != TMPL_TYPE_ATTR)) return NULL;
2591
2592         /*
2593          *   Concat means something completely different as an attribute reference
2594          *   Count isn't implemented.
2595          */
2596         if ((node->attr.tmpl_num == NUM_COUNT) || (node->attr.tmpl_num == NUM_ALL)) return NULL;
2597
2598         vpt = tmpl_alloc(ctx, TMPL_TYPE_ATTR, node->fmt, -1);
2599         if (!vpt) return NULL;
2600         memcpy(&vpt->data, &node->attr.data, sizeof(vpt->data));
2601
2602         VERIFY_TMPL(vpt);
2603
2604         return vpt;
2605 }
2606
2607 /** Try to convert attr tmpl to an xlat for &attr[*] and artificially constructing expansions
2608  *
2609  * @param ctx to allocate new xlat_expt_t in.
2610  * @param vpt to convert.
2611  * @return NULL if unable to convert (not necessarily error), or a new vp_tmpl_t.
2612  */
2613 xlat_exp_t *xlat_from_tmpl_attr(TALLOC_CTX *ctx, vp_tmpl_t *vpt)
2614 {
2615         xlat_exp_t *node;
2616
2617         if (vpt->type != TMPL_TYPE_ATTR) return NULL;
2618
2619         node = talloc_zero(ctx, xlat_exp_t);
2620         node->type = XLAT_ATTRIBUTE;
2621         node->fmt = talloc_bstrndup(node, vpt->name, vpt->len);
2622         tmpl_init(&node->attr, TMPL_TYPE_ATTR, node->fmt, talloc_array_length(node->fmt) - 1);
2623         memcpy(&node->attr.data, &vpt->data, sizeof(vpt->data));
2624
2625         return node;
2626 }
2627
2628 ssize_t radius_xlat(char *out, size_t outlen, REQUEST *request, char const *fmt, xlat_escape_t escape, void *ctx)
2629 {
2630         return xlat_expand(&out, outlen, request, fmt, escape, ctx);
2631 }
2632
2633 ssize_t radius_xlat_struct(char *out, size_t outlen, REQUEST *request, xlat_exp_t const *xlat, xlat_escape_t escape, void *ctx)
2634 {
2635         return xlat_expand_struct(&out, outlen, request, xlat, escape, ctx);
2636 }
2637
2638 ssize_t radius_axlat(char **out, REQUEST *request, char const *fmt, xlat_escape_t escape, void *ctx)
2639 {
2640         *out = NULL;
2641         return xlat_expand(out, 0, request, fmt, escape, ctx);
2642 }
2643
2644 ssize_t radius_axlat_struct(char **out, REQUEST *request, xlat_exp_t const *xlat, xlat_escape_t escape, void *ctx)
2645 {
2646         *out = NULL;
2647         return xlat_expand_struct(out, 0, request, xlat, escape, ctx);
2648 }