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