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