Build warnings WITHOUT_UNLANG
[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 #include        <limits.h>
36
37 typedef struct xlat_t {
38         char                    name[MAX_STRING_LEN];   //!< Name of the xlat expansion.
39         int                     length;                 //!< Length of name.
40         void                    *instance;              //!< Module instance passed to xlat and escape functions.
41         RAD_XLAT_FUNC           func;                   //!< xlat function.
42         RADIUS_ESCAPE_STRING    escape;                 //!< Escape function to apply to dynamic input to func.
43         int                     internal;               //!< If true, cannot be redefined.
44 } xlat_t;
45
46 typedef enum {
47         XLAT_LITERAL,           //!< Literal string
48         XLAT_PERCENT,           //!< Literal string with %v
49         XLAT_MODULE,            //!< xlat module
50         XLAT_VIRTUAL,           //!< virtual attribute
51         XLAT_ATTRIBUTE,         //!< xlat attribute
52 #ifdef HAVE_REGEX_H
53         XLAT_REGEX,             //!< regex reference
54 #endif
55         XLAT_ALTERNATE          //!< xlat conditional syntax :-
56 } xlat_state_t;
57
58 struct xlat_exp {
59         char const *fmt;        //!< The format string.
60         size_t len;             //!< Length of the format string.
61
62         DICT_ATTR const *da;    //!< the name of the dictionary attribute
63         int num;                //!< attribute number
64         int tag;                //!< attribute tag
65         pair_lists_t list;      //!< list of which attribute
66         request_refs_t ref;     //!< outer / this / ...
67
68         xlat_state_t type;      //!< type of this expansion
69         xlat_exp_t *next;       //!< Next in the list.
70
71         xlat_exp_t *child;      //!< Nested expansion.
72         xlat_exp_t *alternate;  //!< Alternative expansion if this one expanded to a zero length string.
73
74         xlat_t const *xlat;     //!< The xlat expansion to expand format with.
75 };
76
77 typedef struct xlat_out {
78         char const *out;        //!< Output data.
79         size_t len;             //!< Length of the output string.
80 } xlat_out_t;
81
82 static rbtree_t *xlat_root = NULL;
83
84 #ifdef WITH_UNLANG
85 static char const * const xlat_foreach_names[] = {"Foreach-Variable-0",
86                                                   "Foreach-Variable-1",
87                                                   "Foreach-Variable-2",
88                                                   "Foreach-Variable-3",
89                                                   "Foreach-Variable-4",
90                                                   "Foreach-Variable-5",
91                                                   "Foreach-Variable-6",
92                                                   "Foreach-Variable-7",
93                                                   "Foreach-Variable-8",
94                                                   "Foreach-Variable-9",
95                                                   NULL};
96 #endif
97
98 #if REQUEST_MAX_REGEX > 8
99 #error Please fix the following line
100 #endif
101 static int xlat_inst[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 }; /* up to 8 for regex */
102
103
104 #ifdef WITH_UNLANG
105 /** Convert the value on a VALUE_PAIR to string
106  *
107  */
108 static int valuepair2str(char * out,int outlen,VALUE_PAIR * pair, int type)
109 {
110         if (pair != NULL) {
111                 vp_prints_value(out, outlen, pair, -1);
112                 return strlen(out);
113         }
114
115         switch (type) {
116         case PW_TYPE_STRING :
117                 strlcpy(out,"_",outlen);
118                 break;
119         case PW_TYPE_INTEGER64:
120         case PW_TYPE_SIGNED:
121         case PW_TYPE_INTEGER:
122                 strlcpy(out,"0",outlen);
123                 break;
124         case PW_TYPE_IPADDR :
125                 strlcpy(out,"?.?.?.?",outlen);
126                 break;
127         case PW_TYPE_IPV6ADDR :
128                 strlcpy(out,":?:",outlen);
129                 break;
130         case PW_TYPE_DATE :
131                 strlcpy(out,"0",outlen);
132                 break;
133         default :
134                 strlcpy(out,"unknown_type",outlen);
135         }
136         return strlen(out);
137 }
138 #endif
139
140 /** Print length of its RHS.
141  *
142  */
143 static ssize_t xlat_strlen(UNUSED void *instance, UNUSED REQUEST *request,
144                            char const *fmt, char *out, size_t outlen)
145 {
146         snprintf(out, outlen, "%u", (unsigned int) strlen(fmt));
147         return strlen(out);
148 }
149
150 /** Print data as integer, not as VALUE.
151  *
152  */
153 static ssize_t xlat_integer(UNUSED void *instance, REQUEST *request,
154                             char const *fmt, char *out, size_t outlen)
155 {
156         VALUE_PAIR      *vp;
157
158         uint64_t        integer;
159
160         while (isspace((int) *fmt)) fmt++;
161
162         if ((radius_get_vp(&vp, request, fmt) < 0) || !vp) {
163                 *out = '\0';
164                 return 0;
165         }
166
167         switch (vp->da->type) {
168         case PW_TYPE_OCTETS:
169         case PW_TYPE_STRING:
170                 if (vp->length > 8) {
171                         break;
172                 }
173
174                 memcpy(&integer, &(vp->vp_octets), vp->length);
175
176                 return snprintf(out, outlen, "%" PRIu64, ntohll(integer));
177
178         case PW_TYPE_INTEGER64:
179                 return snprintf(out, outlen, "%" PRIu64, vp->vp_integer64);
180
181         case PW_TYPE_IPADDR:
182         case PW_TYPE_INTEGER:
183         case PW_TYPE_SHORT:
184         case PW_TYPE_BYTE:
185         case PW_TYPE_DATE:
186                 return snprintf(out, outlen, "%u", vp->vp_integer);
187         default:
188                 break;
189         }
190
191         REDEBUG("Type \"%s\" cannot be converted to integer",
192                 fr_int2str(dict_attr_types, vp->da->type, PW_TYPE_INVALID));
193         *out = '\0';
194
195         return -1;
196 }
197
198 /** Print data as hex, not as VALUE.
199  *
200  */
201 static ssize_t xlat_hex(UNUSED void *instance, REQUEST *request,
202                         char const *fmt, char *out, size_t outlen)
203 {
204         size_t i;
205         VALUE_PAIR *vp;
206         uint8_t buffer[MAX_STRING_LEN];
207         ssize_t ret;
208         size_t  len;
209
210         while (isspace((int) *fmt)) fmt++;
211
212         if ((radius_get_vp(&vp, request, fmt) < 0) || !vp) {
213                 *out = '\0';
214                 return -1;
215         }
216
217         ret = rad_vp2data(vp, buffer, sizeof(buffer));
218         len = (size_t) ret;
219
220         /*
221          *      Don't truncate the data.
222          */
223         if ((ret < 0 ) || (outlen < (len * 2))) {
224                 *out = 0;
225                 return 0;
226         }
227
228         for (i = 0; i < len; i++) {
229                 snprintf(out + 2*i, 3, "%02x", buffer[i]);
230         }
231
232         return len * 2;
233 }
234
235 /** Print data as base64, not as VALUE
236  *
237  */
238 static ssize_t xlat_base64(UNUSED void *instance, REQUEST *request,
239                            char const *fmt, char *out, size_t outlen)
240 {
241         VALUE_PAIR *vp;
242         uint8_t buffer[MAX_STRING_LEN];
243         ssize_t ret;
244
245         while (isspace((int) *fmt)) fmt++;
246
247         if ((radius_get_vp(&vp, request, fmt) < 0) || !vp) {
248                 *out = '\0';
249                 return 0;
250         }
251
252         ret = rad_vp2data(vp, buffer, sizeof(buffer));
253         if (ret < 0) {
254                 *out = '\0';
255                 return ret;
256         }
257
258         return fr_base64_encode(buffer, (size_t) ret, out, outlen);
259 }
260
261 /** Print out attribute info
262  *
263  * Prints out all instances of a current attribute, or all attributes in a list.
264  *
265  * At higher debugging levels, also prints out alternative decodings of the same
266  * value. This is helpful to determine types for unknown attributes of long
267  * passed vendors, or just crazy/broken NAS.
268  *
269  * It's also useful for exposing issues in the packet decoding functions, as in
270  * some cases they get fed random garbage data.
271  *
272  * This expands to a zero length string.
273  */
274 static ssize_t xlat_debug_attr(UNUSED void *instance, REQUEST *request, char const *fmt,
275                                char *out, UNUSED size_t outlen)
276 {
277         VALUE_PAIR *vp, **vps;
278         REQUEST *current;
279         value_pair_tmpl_t vpt;
280         vp_cursor_t cursor;
281         char buffer[1024];
282
283         if (!RDEBUG_ENABLED2) {
284                 *out = '\0';
285                 return -1;
286         }
287
288         while (isspace((int) *fmt)) fmt++;
289
290         if (*fmt == '&') fmt++;
291
292         if (radius_parse_attr(fmt, &vpt, REQUEST_CURRENT, PAIR_LIST_REQUEST) < 0) {
293                 return -1;
294         }
295
296         current = request;
297         if (radius_request(&current, vpt.request) < 0) return -2;
298
299         vps = radius_list(current, vpt.list);
300         if (!vps) {
301                 return -2;
302         }
303
304         RIDEBUG("Attributes matching \"%s\"", fmt);
305         vp = paircursor(&cursor, vps);
306
307         if (vpt.da) {
308                 vp = pairfindnext(&cursor, vpt.da->attr, vpt.da->vendor, TAG_ANY);
309         }
310         while (vp) {
311                 DICT_ATTR *dac = NULL;
312                 DICT_VENDOR *dv;
313
314                 vp_prints_value(buffer, sizeof(buffer), vp, '\'');
315
316                 if (vp->da->flags.has_tag) {
317                         RIDEBUG2("\t%s:%s:%i %s %s",
318                                 fr_int2str(pair_lists, vpt.list, "<INVALID>"),
319                                 vp->da->name,
320                                 vp->tag,
321                                 fr_int2str(fr_tokens, vp->op, "<INVALID>"),
322                                 buffer);
323                 } else {
324                         RIDEBUG2("\t%s:%s %s %s",
325                                 fr_int2str(pair_lists, vpt.list, "<INVALID>"),
326                                 vp->da->name,
327                                 fr_int2str(fr_tokens, vp->op, "<INVALID>"),
328                                 buffer);
329                 }
330
331                 if (!RDEBUG_ENABLED3) {
332                         goto next_vp;
333                 }
334
335                 if (vp->da->vendor) {
336                         dv = dict_vendorbyvalue(vp->da->vendor);
337                         RDEBUG3("\t\tvendor        : %i (%s)", vp->da->vendor, dv ? dv->name : "unknown");
338                 }
339                 RDEBUG3("\t\ttype          : %s", fr_int2str(dict_attr_types, vp->da->type, "<INVALID>"));
340                 RDEBUG3("\t\tlength        : %zu", vp->length);
341
342                 dac = talloc_memdup(request, vp->da, sizeof(DICT_ATTR));
343                 if (!dac) {
344                         return -1;
345                 }
346                 dac->flags.vp_free = 0;
347
348         next_vp:
349
350                 talloc_free(dac);
351
352                 if (vpt.da) {
353                         vp = pairfindnext(&cursor, vpt.da->attr, vpt.da->vendor, TAG_ANY);
354                 } else {
355                         vp = pairnext(&cursor);
356                 }
357         }
358
359         *out = '\0';
360         return 0;
361 }
362
363 /** Prints the current module processing the request
364  *
365  */
366 static ssize_t xlat_module(UNUSED void *instance, REQUEST *request,
367                            UNUSED char const *fmt, char *out, size_t outlen)
368 {
369         strlcpy(out, request->module, outlen);
370
371         return strlen(out);
372 }
373
374 #ifdef WITH_UNLANG
375 /** Implements the Foreach-Variable-X
376  *
377  * @see modcall()
378  */
379 static ssize_t xlat_foreach(void *instance, REQUEST *request,
380                             UNUSED char const *fmt, char *out, size_t outlen)
381 {
382         VALUE_PAIR      **pvp;
383
384         /*
385          *      See modcall, "FOREACH" for how this works.
386          */
387         pvp = (VALUE_PAIR **) request_data_reference(request, radius_get_vp, *(int*) instance);
388         if (!pvp || !*pvp) {
389                 *out = '\0';
390                 return 0;
391         }
392
393         return valuepair2str(out, outlen, (*pvp), (*pvp)->da->type);
394 }
395 #endif
396
397 /** Print data as string, if possible.
398  *
399  * If attribute "Foo" is defined as "octets" it will normally
400  * be printed as 0x0a0a0a. The xlat "%{string:Foo}" will instead
401  * expand to "\n\n\n"
402  */
403 static ssize_t xlat_string(UNUSED void *instance, REQUEST *request,
404                            char const *fmt, char *out, size_t outlen)
405 {
406         int len;
407         VALUE_PAIR *vp;
408
409         while (isspace((int) *fmt)) fmt++;
410
411         if (outlen < 3) {
412         nothing:
413                 *out = '\0';
414                 return 0;
415         }
416
417         if ((radius_get_vp(&vp, request, fmt) < 0) || !vp) goto nothing;
418
419         if (vp->da->type != PW_TYPE_OCTETS) goto nothing;
420
421         len = fr_print_string(vp->vp_strvalue, vp->length, out, outlen);
422         out[len] = '\0';
423
424         return len;
425 }
426
427 /** xlat expand string attribute value
428  *
429  */
430 static ssize_t xlat_xlat(UNUSED void *instance, REQUEST *request,
431                         char const *fmt, char *out, size_t outlen)
432 {
433         VALUE_PAIR *vp;
434
435         while (isspace((int) *fmt)) fmt++;
436
437         if (outlen < 3) {
438         nothing:
439                 *out = '\0';
440                 return 0;
441         }
442
443         if ((radius_get_vp(&vp, request, fmt) < 0) || !vp) goto nothing;
444
445         return radius_xlat(out, outlen, request, vp->vp_strvalue, NULL, NULL);
446 }
447
448 /** Dynamically change the debugging level for the current request
449  *
450  * Example %{debug:3}
451  */
452 static ssize_t xlat_debug(UNUSED void *instance, REQUEST *request,
453                           char const *fmt, char *out, size_t outlen)
454 {
455         int level = 0;
456
457         /*
458          *  Expand to previous (or current) level
459          */
460         snprintf(out, outlen, "%d", request->options & RAD_REQUEST_OPTION_DEBUG4);
461
462         /*
463          *  Assume we just want to get the current value and NOT set it to 0
464          */
465         if (!*fmt)
466                 goto done;
467
468         level = atoi(fmt);
469         if (level == 0) {
470                 request->options = RAD_REQUEST_OPTION_NONE;
471                 request->radlog = NULL;
472         } else {
473                 if (level > 4) level = 4;
474
475                 request->options = level;
476                 request->radlog = radlog_request;
477         }
478
479         done:
480         return strlen(out);
481 }
482
483 /*
484  *      Compare two xlat_t structs, based ONLY on the module name.
485  */
486 static int xlat_cmp(void const *one, void const *two)
487 {
488         xlat_t const *a = one;
489         xlat_t const *b = two;
490
491         if (a->length != b->length) {
492                 return a->length - b->length;
493         }
494
495         return memcmp(a->name, b->name, a->length);
496 }
497
498
499 /*
500  *      find the appropriate registered xlat function.
501  */
502 static xlat_t *xlat_find(char const *name)
503 {
504         xlat_t my_xlat;
505
506         strlcpy(my_xlat.name, name, sizeof(my_xlat.name));
507         my_xlat.length = strlen(my_xlat.name);
508
509         return rbtree_finddata(xlat_root, &my_xlat);
510 }
511
512
513 /** Register an xlat function.
514  *
515  * @param[in] name xlat name.
516  * @param[in] func xlat function to be called.
517  * @param[in] escape function to sanitize any sub expansions passed to the xlat function.
518  * @param[in] instance of module that's registering the xlat function.
519  * @return 0 on success, -1 on failure
520  */
521 int xlat_register(char const *name, RAD_XLAT_FUNC func, RADIUS_ESCAPE_STRING escape, void *instance)
522 {
523         xlat_t  *c;
524         xlat_t  my_xlat;
525
526         if (!name || !*name) {
527                 DEBUG("xlat_register: Invalid xlat name");
528                 return -1;
529         }
530
531         /*
532          *      First time around, build up the tree...
533          *
534          *      FIXME: This code should be hoisted out of this function,
535          *      and into a global "initialization".  But it isn't critical...
536          */
537         if (!xlat_root) {
538 #ifdef WITH_UNLANG
539                 int i;
540 #endif
541
542                 xlat_root = rbtree_create(xlat_cmp, free, 0);
543                 if (!xlat_root) {
544                         DEBUG("xlat_register: Failed to create tree.");
545                         return -1;
546                 }
547
548 #ifdef WITH_UNLANG
549                 for (i = 0; xlat_foreach_names[i] != NULL; i++) {
550                         xlat_register(xlat_foreach_names[i],
551                                       xlat_foreach, NULL, &xlat_inst[i]);
552                         c = xlat_find(xlat_foreach_names[i]);
553                         rad_assert(c != NULL);
554                         c->internal = true;
555                 }
556 #endif
557
558 #define XLAT_REGISTER(_x) xlat_register(STRINGIFY(_x), xlat_ ## _x, NULL, NULL); \
559                 c = xlat_find(STRINGIFY(_x)); \
560                 rad_assert(c != NULL); \
561                 c->internal = true
562
563                 XLAT_REGISTER(integer);
564                 XLAT_REGISTER(strlen);
565                 XLAT_REGISTER(hex);
566                 XLAT_REGISTER(base64);
567                 XLAT_REGISTER(string);
568                 XLAT_REGISTER(xlat);
569                 XLAT_REGISTER(module);
570                 XLAT_REGISTER(debug_attr);
571
572                 xlat_register("debug", xlat_debug, NULL, &xlat_inst[0]);
573                 c = xlat_find("debug");
574                 rad_assert(c != NULL);
575                 c->internal = true;
576         }
577
578         /*
579          *      If it already exists, replace the instance.
580          */
581         strlcpy(my_xlat.name, name, sizeof(my_xlat.name));
582         my_xlat.length = strlen(my_xlat.name);
583         c = rbtree_finddata(xlat_root, &my_xlat);
584         if (c) {
585                 if (c->internal) {
586                         DEBUG("xlat_register: Cannot re-define internal xlat");
587                         return -1;
588                 }
589
590                 c->func = func;
591                 c->escape = escape;
592                 c->instance = instance;
593                 return 0;
594         }
595
596         /*
597          *      Doesn't exist.  Create it.
598          */
599         c = rad_malloc(sizeof(*c));
600         memset(c, 0, sizeof(*c));
601
602         c->func = func;
603         c->escape = escape;
604         strlcpy(c->name, name, sizeof(c->name));
605         c->length = strlen(c->name);
606         c->instance = instance;
607
608         rbtree_insert(xlat_root, c);
609
610         return 0;
611 }
612
613 /** Unregister an xlat function
614  *
615  * We can only have one function to call per name, so the passing of "func"
616  * here is extraneous.
617  *
618  * @param[in] name xlat to unregister.
619  * @param[in] func unused.
620  * @param[in] instance data.
621  */
622 void xlat_unregister(char const *name, UNUSED RAD_XLAT_FUNC func, void *instance)
623 {
624         xlat_t  *c;
625         xlat_t          my_xlat;
626
627         if (!name) return;
628
629         strlcpy(my_xlat.name, name, sizeof(my_xlat.name));
630         my_xlat.length = strlen(my_xlat.name);
631
632         c = rbtree_finddata(xlat_root, &my_xlat);
633         if (!c) return;
634
635         if (c->instance != instance) return;
636
637         rbtree_deletebydata(xlat_root, c);
638 }
639
640 /** De-register all xlat functions, used mainly for debugging.
641  *
642  */
643 void xlat_free(void)
644 {
645         rbtree_free(xlat_root);
646 }
647
648 #if 0
649 #define XLAT_DEBUG(fmt, ...) printf(fmt, ## __VA_ARGS__);printf("\n")
650 #endif
651
652 #ifndef XLAT_DEBUG
653 #if 0
654 #define XLAT_DEBUG DEBUG3
655 #else
656 #define XLAT_DEBUG(...)
657 #endif
658 #endif
659
660 static ssize_t xlat_tokenize_expansion(TALLOC_CTX *ctx, char *fmt, xlat_exp_t **head,
661                                        char const **error);
662 static ssize_t xlat_tokenize_literal(TALLOC_CTX *ctx, char *fmt, xlat_exp_t **head,
663                                      int brace, char const **error);
664 static size_t xlat_process(char **out, REQUEST *request, xlat_exp_t const * const head,
665                            RADIUS_ESCAPE_STRING escape, void *escape_ctx);
666
667 static ssize_t xlat_tokenize_alternation(TALLOC_CTX *ctx, char *fmt, xlat_exp_t **head,
668                                          char const **error)
669 {
670         ssize_t slen;
671         char *p;
672         xlat_exp_t *node;
673
674         rad_assert(fmt[0] == '%');
675         rad_assert(fmt[1] == '{');
676         rad_assert(fmt[2] == '%');
677         rad_assert(fmt[3] == '{');
678
679         XLAT_DEBUG("ALTERNATE: %s", fmt);
680
681         node = talloc_zero(ctx, xlat_exp_t);
682         node->type = XLAT_ALTERNATE;
683
684         p = fmt + 2;
685         slen = xlat_tokenize_expansion(node, p, &node->child, error);
686         if (slen <= 0) {
687                 talloc_free(node);
688                 return slen - (p - fmt);
689         }
690         p += slen;
691
692         if (p[0] != ':') {
693                 talloc_free(node);
694                 *error = "Expected ':' after first expansion";
695                 return -(p - fmt);
696         }
697         p++;
698
699         if (p[0] != '-') {
700                 talloc_free(node);
701                 *error = "Expected '-' after ':'";
702                 return -(p - fmt);
703         }
704         p++;
705
706         /*
707          *      Allow the RHS to be empty as a special case.
708          */
709         if (*p == '}') {
710                 /*
711                  *      Hack up an empty string.
712                  */
713                 node->alternate = talloc_zero(node, xlat_exp_t);
714                 node->alternate->type = XLAT_LITERAL;
715                 node->alternate->fmt = talloc_strdup(node->alternate, "");
716                 *(p++) = '\0';
717
718         } else {
719                 slen = xlat_tokenize_literal(node, p,  &node->alternate, true, error);
720                 if (slen <= 0) {
721                         talloc_free(node);
722                         return slen - (p - fmt);
723                 }
724
725                 if (!node->alternate) {
726                         talloc_free(node);
727                         *error = "Empty expansion is invalid";
728                         return -(p - fmt);
729                 }
730                 p += slen;
731         }
732
733         *head = node;
734         return p - fmt;
735 }
736
737 static ssize_t xlat_tokenize_expansion(TALLOC_CTX *ctx, char *fmt, xlat_exp_t **head,
738                                        char const **error)
739 {
740         ssize_t slen;
741         char *p, *q, *brace;
742         char const *attrname;
743         xlat_exp_t *node;
744
745         rad_assert(fmt[0] == '%');
746         rad_assert(fmt[1] == '{');
747
748         /*
749          *      %{%{...}:-bar}
750          */
751         if ((fmt[2] == '%') && (fmt[3] == '{')) {
752                 return xlat_tokenize_alternation(ctx, fmt, head, error);
753         }
754
755         XLAT_DEBUG("EXPANSION: %s", fmt);
756         node = talloc_zero(ctx, xlat_exp_t);
757         attrname = node->fmt = fmt + 2;
758         node->len = 0;
759
760 #ifdef HAVE_REGEX_H
761         /*
762          *      Handle regex's specially.
763          */
764         if (isdigit((int) fmt[2]) && (fmt[3] == '}')) {
765                 if (fmt[2] == '9') {
766                         talloc_free(node);
767                         *error = "Invalid regex reference";
768                         return -2;
769                 }
770
771                 XLAT_DEBUG("REGEX: %s", fmt);
772                 fmt[3] = '\0';
773                 node->num = fmt[2] - '0'; /* ASCII */
774
775                 node->type = XLAT_REGEX;
776                 *head = node;
777                 return 4;
778         }
779 #endif /* HAVE_REGEX_H */
780
781         /*
782          *      %{Attr-Name}
783          *      %{Attr-Name[#]}
784          *      %{Tunnel-Password:1}
785          *      %{Tunnel-Password:1[#]}
786          *      %{request:Attr-Name}
787          *      %{request:Tunnel-Password:1}
788          *      %{request:Tunnel-Password:1[#]}
789          *      %{mod:foo}
790          */
791         q = brace = NULL;
792         for (p = fmt + 2; *p != '\0'; p++) {
793                 if (*p == ':') break;
794
795                 if (isspace((int) *p)) break;
796
797                 if (*p == '[') break;
798
799                 if (*p == '}') break;
800         }
801
802         if (*p != ':') p = NULL;
803
804         /*
805          *      Might be a module name reference.
806          */
807         if (p) {
808                 *p = '\0';
809
810                 /*
811                  *      %{mod:foo}
812                  */
813                 node->xlat = xlat_find(node->fmt);
814                 if (node->xlat) {
815                         node->type = XLAT_MODULE;
816
817                         XLAT_DEBUG("MOD: %s --> %s", node->fmt, p);
818                         slen = xlat_tokenize_literal(node, p + 1, &node->child, true, error);
819                         if (slen <= 0) {
820                                 talloc_free(node);
821                                 return slen - (p - fmt);
822                         }
823                         p += slen + 1;
824
825                         *head = node;
826                         rad_assert(node->next == NULL);
827                         return p - fmt;
828                 }
829
830                 /*
831                  *      Modules can have '}' in their RHS, so we
832                  *      didn't check for that until now.
833                  *
834                  *      As of now, node->fmt MUST be a reference to an
835                  *      attribute, however complicated.  So it MUST have a closing brace.
836                  */
837                 brace = strchr(p + 1, '}');
838                 if (!brace) goto no_brace;
839                 *brace = '\0';
840
841                 /*
842                  *      %{User-Name}
843                  *      %{User-Name[1]}
844                  *      %{Tunnel-Password:1}
845                  *      %{request:Tunnel-Password:1}
846                  *
847                  *      <sigh>  The syntax is fairly poor.
848                  */
849                 XLAT_DEBUG("Looking for list in '%s'", attrname);
850
851                 /*
852                  *      Not a module.  Has to be an attribute
853                  *      reference.
854                  *
855                  *      As of v3, we've removed %{request: ..>} as
856                  *      internally registered xlats.
857                  */
858                 *p = ':';
859                 node->ref = radius_request_name(&attrname, REQUEST_CURRENT);
860                 rad_assert(node->ref != REQUEST_UNKNOWN);
861
862                 node->list = radius_list_name(&attrname, PAIR_LIST_REQUEST);
863                 if (node->list == PAIR_LIST_UNKNOWN) {
864                         talloc_free(node);
865                         *error = "Unknown module";
866                         return -2;
867                 }
868
869                 /*
870                  *      Check for a trailing tag.
871                  */
872                 p = strchr(attrname, ':');
873                 if (p) *p = '\0';
874
875         } else {
876                 brace = strchr(attrname, '}');
877                 if (!brace) {
878                 no_brace:
879                         talloc_free(node);
880                         *error = "No matching closing brace";
881                         return -1;      /* second character of format string */
882                 }
883                 *brace = '\0';
884
885                 node->ref = REQUEST_CURRENT;
886                 node->list = PAIR_LIST_REQUEST;
887         }
888
889         *brace = '\0';
890
891         XLAT_DEBUG("Looking for attribute name in %s", attrname);
892
893         /*
894          *      Allow for an array reference.  They come AFTER the
895          *      tag, if the tag exists.  Otherwise, they come after
896          *      the attribute name.
897          */
898         if (p) {
899                 q = strchr(p + 1, '[');
900         } else {
901                 q = strchr(attrname, '[');
902         }
903         if (q) *(q++) = '\0';
904
905         if (!*attrname) {
906                 talloc_free(node);
907                 *error = "Empty expression is invalid";
908                 return -(attrname - fmt);
909         }
910
911         /*
912          *      It's either an attribute name, or a Tunnel-Password:TAG
913          *      with the ':' already set to NULL.
914          */
915         node->da = dict_attrbyname(attrname);
916         if (!node->da) {
917                 /*
918                  *      Foreach.  Maybe other stuff, too.
919                  */
920                 node->xlat = xlat_find(attrname);
921                 if (node->xlat) {
922                         node->type = XLAT_VIRTUAL;
923                         node->fmt = attrname;
924
925                         XLAT_DEBUG("VIRTUAL: %s", node->fmt);
926                         *head = node;
927                         rad_assert(node->next == NULL);
928                         brace++;
929                         return brace - fmt;
930                 }
931
932                 talloc_free(node);
933                 *error = "Unknown attribute";
934                 return -(attrname - fmt);
935         }
936
937         /*
938          *      Parse the tag.
939          */
940         if (p) {
941                 unsigned long tag;
942                 char *end;
943
944                 if (!node->da->flags.has_tag) {
945                         talloc_free(node);
946                         *error = "Attribute cannot have a tag";
947                         return - (p - fmt);
948                 }
949
950                 tag = strtoul(p + 1, &end, 10);
951                 p++;
952
953                 if (tag == ULONG_MAX) {
954                         talloc_free(node);
955                         *error = "Invalid tag value";
956                         return - (p - fmt);
957                 }
958
959                 node->tag = tag;
960                 p = end;
961
962                 if (*p) {
963                         talloc_free(node);
964                         *error = "Unexpected text after tag";
965                         return - (p - fmt);
966                 }
967
968         } else {
969                 node->tag = TAG_ANY;
970                 /* leave p alone */
971         }
972
973         /*
974          *      Check for array reference
975          */
976         if (q) {
977                 unsigned long num;
978                 char *end;
979
980                 p = q;
981                 if (*p== '#') {
982                         node->num = 65536;
983                         p++;
984
985                 } else if (*p == '*') {
986                         node->num = 65537;
987                         p++;
988
989                 } else if (isdigit((int) *p)) {
990                         num = strtoul(p, &end, 10);
991                         if ((num == ULONG_MAX) || (num > 65535)) {
992                                 talloc_free(node);
993                                 *error = "Invalid number";
994                                 return - (p - fmt);
995                         }
996                         p = end;
997                         DEBUG("END %s", p);
998                         node->num = num;
999
1000                 } else {
1001                         talloc_free(node);
1002                         *error = "Invalid array reference";
1003                         return - (p - fmt);
1004                 }
1005
1006                 if (*p != ']') {
1007                         talloc_free(node);
1008                         *error = "Expected ']'";
1009                         return - (p - fmt);
1010                 }
1011
1012                 p++;
1013                 if (*p) {
1014                         talloc_free(node);
1015                         *error = "Unexpected text after array reference";
1016                         return - (p - fmt);
1017                 }
1018         }
1019
1020         rad_assert(!p || (p == brace));
1021
1022         node->type = XLAT_ATTRIBUTE;
1023         p = brace + 1;
1024
1025         *head = node;
1026         rad_assert(node->next == NULL);
1027         return p - fmt;
1028 }
1029
1030
1031 static ssize_t xlat_tokenize_literal(TALLOC_CTX *ctx, char *fmt, xlat_exp_t **head,
1032                                      int brace, char const **error)
1033 {
1034         char *p, *q;
1035         xlat_exp_t *node;
1036
1037         if (!*fmt) return 0;
1038
1039         XLAT_DEBUG("LITERAL: %s", fmt);
1040
1041         node = talloc_zero(ctx, xlat_exp_t);
1042         node->fmt = fmt;
1043         node->len = 0;
1044         node->type = XLAT_LITERAL;
1045
1046         p = fmt;
1047         q = fmt;
1048
1049         while (*p) {
1050                 /*
1051                  *      Convert \n to it's literal representation.
1052                  */
1053                 if (p[0] == '\\') switch (p[1]) {
1054                         case 't':
1055                                 *(q++) = '\t';
1056                                 p += 2;
1057                                 node->len++;
1058                                 continue;
1059
1060                         case 'n':
1061                                 *(q++) = '\n';
1062                                 p += 2;
1063                                 node->len++;
1064                                 continue;
1065
1066                         case 'x':
1067                                 p += 2;
1068                                 if (!p[0] || !p[1]) {
1069                                         talloc_free(node);
1070                                         *error = "Hex expansion requires two hex digits";
1071                                         return -(p - fmt);
1072                                 }
1073
1074                                 if (!fr_hex2bin((uint8_t *) q, p, 2)) {
1075                                         talloc_free(node);
1076                                         *error = "Invalid hex characters";
1077                                         return -(p - fmt);
1078                                 }
1079
1080                                 /*
1081                                  *      Don't let people shoot themselves in the foot.
1082                                  *      \x00 is forbidden.
1083                                  */
1084                                 if (!*q) {
1085                                         talloc_free(node);
1086                                         *error = "Cannot add zero byte to printable string";
1087                                         return -(p - fmt);
1088                                 }
1089
1090                                 p += 2;
1091                                 q++;
1092                                 node->len++;
1093                                 continue;
1094
1095                         default:
1096                                 *(q++) = *p;
1097                                 p += 2;
1098                                 node->len++;
1099                                 continue;
1100                         }
1101
1102                 /*
1103                  *      Process the expansion.
1104                  */
1105                 if ((p[0] == '%') && (p[1] == '{')) {
1106                         ssize_t slen;
1107
1108                         XLAT_DEBUG("LITERAL: %s --> %s", node->fmt, p);
1109                         slen = xlat_tokenize_expansion(node, p, &node->next, error);
1110                         if (slen <= 0) {
1111                                 talloc_free(node);
1112                                 return slen - (p - fmt);
1113                         }
1114                         *p = '\0'; /* end the literal */
1115                         p += slen;
1116
1117                         rad_assert(node->next != NULL);
1118
1119                         /*
1120                          *      Short-circuit the recursive call.
1121                          *      This saves another function call and
1122                          *      memory allocation.
1123                          */
1124                         if (!*p) break;
1125
1126                         /*
1127                          *      "foo %{User-Name} bar"
1128                          *      LITERAL         "foo "
1129                          *      EXPANSION       User-Name
1130                          *      LITERAL         " bar"
1131                          */
1132                         slen = xlat_tokenize_literal(node->next, p, &(node->next->next), brace, error);
1133                         rad_assert(slen != 0);
1134                         if (slen < 0) {
1135                                 talloc_free(node);
1136                                 return slen - (p - fmt);
1137                         }
1138
1139                         p += slen;
1140                         break;  /* stop processing the string */
1141                 }
1142
1143                 /*
1144                  *      Check for valid single-character expansions.
1145                  */
1146                 if (p[0] == '%') {
1147                         ssize_t slen;
1148                         xlat_exp_t *next;
1149
1150                         if (!p[1] || !strchr("%dlmtDGHISTY", p[1])) {
1151                                         talloc_free(node);
1152                                         *error = "Invalid variable expansion";
1153                                         p++;
1154                                         return - (p - fmt);
1155                         }
1156
1157                         XLAT_DEBUG("PERCENT: %s --> %c", node->fmt, p[1]);
1158                         next = talloc_zero(node, xlat_exp_t);
1159                         next->fmt = p + 1;
1160                         next->len = 1;
1161                         next->type = XLAT_PERCENT;
1162
1163                         node->next = next;
1164                         *p = '\0';
1165                         p += 2;
1166
1167                         if (!*p) break;
1168
1169                         /*
1170                          *      And recurse.
1171                          */
1172                         slen = xlat_tokenize_literal(node->next, p, &(node->next->next), brace, error);
1173                         rad_assert(slen != 0);
1174                         if (slen < 0) {
1175                                 talloc_free(node);
1176                                 return slen - (p - fmt);
1177                         }
1178
1179                         p += slen;
1180                         break;  /* stop processing the string */
1181                 }
1182
1183                 /*
1184                  *      If required, eat the brace.
1185                  */
1186                 if (brace && (*p == '}')) {
1187                         *q = '\0';
1188                         p++;
1189                         break;
1190                 }
1191
1192                 *(q++) = *(p++);
1193                 node->len++;
1194         }
1195
1196         /*
1197          *      Squash zero-width literals
1198          */
1199         if (node->len > 0) {
1200                 *head = node;
1201         } else {
1202                 *head = talloc_steal(ctx, node->next);
1203                 talloc_free(node);
1204         }
1205
1206         return p - fmt;
1207 }
1208
1209
1210 static char const xlat_tabs[] = "                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               ";
1211
1212 static void xlat_tokenize_debug(xlat_exp_t const *node, int lvl)
1213 {
1214         rad_assert(node != NULL);
1215
1216         if (lvl >= (int) sizeof(xlat_tabs)) lvl = sizeof(xlat_tabs);
1217
1218         while (node) {
1219                 switch (node->type) {
1220                 case XLAT_LITERAL:
1221                         DEBUG("%.*sliteral: '%s'", lvl, xlat_tabs, node->fmt);
1222                         break;
1223
1224                 case XLAT_PERCENT:
1225                         DEBUG("%.*sliteral (with %%): '%c'", lvl, xlat_tabs, node->fmt[0]);
1226                         break;
1227
1228                 case XLAT_ATTRIBUTE:
1229                         rad_assert(node->da != NULL);
1230                         DEBUG("%.*sattribute: %s", lvl, xlat_tabs, node->da->name);
1231                         rad_assert(node->child == NULL);
1232                         if ((node->tag != 0) || (node->num != 0)) {
1233                                 DEBUG("%.*s{", lvl, xlat_tabs);
1234
1235                                 DEBUG("%.*sref  %d", lvl + 1, xlat_tabs, node->ref);
1236                                 DEBUG("%.*slist %d", lvl + 1, xlat_tabs, node->list);
1237
1238                                 if (node->tag) DEBUG("%.*stag %d", lvl + 1, xlat_tabs, node->tag);
1239                                 if (node->num) {
1240                                         if (node->num == 65536) {
1241                                                 DEBUG("%.*s[#]", lvl + 1, xlat_tabs);
1242                                         } else if (node->num == 65537) {
1243                                                 DEBUG("%.*s[*]", lvl + 1, xlat_tabs);
1244                                         } else {
1245                                                 DEBUG("%.*s[%d]", lvl + 1, xlat_tabs, node->num);
1246                                         }
1247                                 }
1248
1249                                 DEBUG("%.*s}", lvl, xlat_tabs);
1250                         }
1251                         break;
1252
1253                 case XLAT_VIRTUAL:
1254                         rad_assert(node->fmt != NULL);
1255                         DEBUG("%.*svirtual: %s", lvl, xlat_tabs, node->fmt);
1256                         break;
1257
1258                 case XLAT_MODULE:
1259                         rad_assert(node->xlat != NULL);
1260                         DEBUG("%.*sxlat: %s", lvl, xlat_tabs, node->xlat->name);
1261                         if (node->child) {
1262                                 DEBUG("%.*s{", lvl, xlat_tabs);
1263                                 xlat_tokenize_debug(node->child, lvl + 1);
1264                                 DEBUG("%.*s}", lvl, xlat_tabs);
1265                         }
1266                         break;
1267
1268 #ifdef HAVE_REGEX_H
1269                 case XLAT_REGEX:
1270                         DEBUG("%.*sregex-var: %d", lvl, xlat_tabs, node->num);
1271                         break;
1272 #endif
1273
1274                 case XLAT_ALTERNATE:
1275                         DEBUG("%.*sif {", lvl, xlat_tabs);
1276                         xlat_tokenize_debug(node->child, lvl + 1);
1277                         DEBUG("%.*s}", lvl, xlat_tabs);
1278                         DEBUG("%.*selse {", lvl, xlat_tabs);
1279                         xlat_tokenize_debug(node->alternate, lvl + 1);
1280                         DEBUG("%.*s}", lvl, xlat_tabs);
1281                         break;
1282                 }
1283                 node = node->next;
1284         }
1285 }
1286
1287 size_t xlat_sprint(char *buffer, size_t bufsize, xlat_exp_t const *node)
1288 {
1289         size_t len;
1290         char *p, *end;
1291
1292         if (!node) {
1293                 *buffer = '\0';
1294                 return 0;
1295         }
1296
1297         p = buffer;
1298         end = buffer + bufsize;
1299
1300         while (node) {
1301                 switch (node->type) {
1302                 case XLAT_LITERAL:
1303                         strlcpy(p, node->fmt, end - p);
1304                         p += strlen(p);
1305                         break;
1306
1307                 case XLAT_PERCENT:
1308                         p[0] = '%';
1309                         p[1] = node->fmt[0];
1310                         p += 2;
1311                         break;
1312
1313                 case XLAT_ATTRIBUTE:
1314                         *(p++) = '%';
1315                         *(p++) = '{';
1316
1317                         if (node->ref != REQUEST_CURRENT) {
1318                                 strlcpy(p, fr_int2str(request_refs, node->ref, "??"), end - p);
1319                                 p += strlen(p);
1320                                 *(p++) = '.';
1321                         }
1322
1323                         if ((node->ref != REQUEST_CURRENT) ||
1324                             (node->list != PAIR_LIST_REQUEST)) {
1325                                 strlcpy(p, fr_int2str(pair_lists, node->list, "??"), end - p);
1326                                 p += strlen(p);
1327                                 *(p++) = ':';
1328                         }
1329
1330                         strlcpy(p, node->da->name, end - p);
1331                         p += strlen(p);
1332
1333                         if (node->tag != TAG_ANY) {
1334                                 *(p++) = ':';
1335                                 snprintf(p, end - p, "%u", node->tag);
1336                                 p += strlen(p);
1337                         }
1338
1339                         if (node->num != 0) {
1340                                 *(p++) = '[';
1341
1342                                 if (node->num == 65536) {
1343                                         *(p++) = '#';
1344
1345                                 } else if (node->num == 65537) {
1346                                         *(p++) = '*';
1347
1348                                 } else {
1349                                         snprintf(p, end - p, "%u", node->num);
1350                                         p += strlen(p);
1351                                 }
1352                                 *(p++) = ']';
1353                         }
1354                         *(p++) = '}';
1355                         break;
1356 #ifdef HAVE_REGEX_H
1357                 case XLAT_REGEX:
1358                         snprintf(p, end - p, "%%{%u}", node->num);
1359                         p += strlen(p);
1360                         break;
1361 #endif
1362                 case XLAT_VIRTUAL:
1363                         *(p++) = '%';
1364                         *(p++) = '{';
1365                         strlcpy(p, node->fmt, end - p);
1366                         p += strlen(p);
1367                         *(p++) = '}';
1368                         break;
1369
1370                 case XLAT_MODULE:
1371                         *(p++) = '%';
1372                         *(p++) = '{';
1373                         strlcpy(p, node->xlat->name, end - p);
1374                         p += strlen(p);
1375                         *(p++) = ':';
1376                         rad_assert(node->child != NULL);
1377                         len = xlat_sprint(p, end - p, node->child);
1378                         p += len;
1379                         *(p++) = '}';
1380                         break;
1381
1382                 case XLAT_ALTERNATE:
1383                         *(p++) = '%';
1384                         *(p++) = '{';
1385
1386                         len = xlat_sprint(p, end - p, node->child);
1387                         p += len;
1388
1389                         *(p++) = ':';
1390                         *(p++) = '-';
1391
1392                         len = xlat_sprint(p, end - p, node->alternate);
1393                         p += len;
1394
1395                         *(p++) = '}';
1396                         break;
1397                 }
1398
1399
1400                 if (p == end) break;
1401
1402                 node = node->next;
1403         }
1404
1405         *p = '\0';
1406
1407         return p - buffer;
1408 }
1409
1410
1411 static char const xlat_spaces[] = "                                                                                                                                                                                                                                                                ";
1412
1413
1414 ssize_t xlat_tokenize(TALLOC_CTX *ctx, char *fmt, xlat_exp_t **head,
1415                       char const **error)
1416 {
1417         return xlat_tokenize_literal(ctx, fmt, head, false, error);
1418 }
1419
1420
1421 /** Tokenize an xlat expansion
1422  *
1423  * @param[in] request the input request.  Memory will be attached here.
1424  * @param[in] fmt the format string to expand
1425  * @param[out] head the head of the xlat list / tree structure.
1426  */
1427 static ssize_t xlat_tokenize_request(REQUEST *request, char const *fmt, xlat_exp_t **head)
1428 {
1429         ssize_t slen;
1430         char *tokens;
1431         char const *error;
1432
1433         *head = NULL;
1434
1435         /*
1436          *      Copy the original format string to a buffer so that
1437          *      the later functions can mangle it in-place, which is
1438          *      much faster.
1439          */
1440         tokens = talloc_strdup(request, fmt);
1441         if (!tokens) return -1;
1442
1443         slen = xlat_tokenize_literal(request, tokens, head, false, &error);
1444         /*
1445          *      Zero length expansion, return a zero length node.
1446          */
1447         if (slen == 0) {
1448                 *head = talloc_zero(request, xlat_exp_t);
1449         }
1450
1451         /*
1452          *      Output something like:
1453          *
1454          *      "format string"
1455          *      "       ^ error was here"
1456          */
1457         if (slen < 0) {
1458                 size_t indent = -slen;
1459                 talloc_free(tokens);
1460
1461                 rad_assert(error != NULL);
1462                 if (indent < sizeof(xlat_spaces)) {
1463                         REDEBUG("%s", fmt);
1464                         REDEBUG("%.*s^ %s", (int) -slen, xlat_spaces, error);
1465                 }
1466                 return slen;
1467         }
1468
1469         if (*head && (debug_flag > 2)) {
1470                 DEBUG("%s", fmt);
1471                 DEBUG("Parsed xlat tree:");
1472                 xlat_tokenize_debug(*head, 0);
1473         }
1474
1475         /*
1476          *      All of the nodes point to offsets in the "tokens"
1477          *      string.  Let's ensure that free'ing head will free
1478          *      "tokens", too.
1479          */
1480         (void) talloc_steal(*head, tokens);
1481
1482         return slen;
1483 }
1484
1485
1486 static char *xlat_getvp(TALLOC_CTX *ctx, REQUEST *request, pair_lists_t list, DICT_ATTR const *da, int8_t tag,
1487                         int num, bool return_null)
1488 {
1489         VALUE_PAIR *vp, *vps = NULL;
1490         RADIUS_PACKET *packet = NULL;
1491         DICT_VALUE *dv;
1492         VALUE_PAIR myvp;
1493
1494         /*
1495          *      Arg.  Too much abstraction is annoying.
1496          */
1497         switch (list) {
1498         default:
1499                 if (return_null) return NULL;
1500                 return vp_aprinttype(ctx, da->type);
1501
1502         case PAIR_LIST_CONTROL:
1503                 vps = request->config_items;
1504                 break;
1505
1506         case PAIR_LIST_REQUEST:
1507                 packet = request->packet;
1508                 if (packet) vps = packet->vps;
1509                 break;
1510
1511         case PAIR_LIST_REPLY:
1512                 packet = request->reply;
1513                 if (packet) vps = packet->vps;
1514                 break;
1515
1516 #ifdef WITH_PROXY
1517         case PAIR_LIST_PROXY_REQUEST:
1518                 packet = request->proxy;
1519                 if (packet) vps = packet->vps;
1520                 break;
1521
1522         case PAIR_LIST_PROXY_REPLY:
1523                 packet = request->proxy_reply;
1524                 if (packet) vps = packet->vps;
1525                 break;
1526 #endif
1527
1528 #ifdef WITH_COA
1529         case PAIR_LIST_COA:
1530         case PAIR_LIST_DM:
1531                 if (request->coa) packet = request->coa->packet;
1532                 if (packet) vps = packet->vps;
1533                 break;
1534
1535         case PAIR_LIST_COA_REPLY:
1536         case PAIR_LIST_DM_REPLY:
1537                 if (request->coa) packet = request->coa->reply;
1538                 if (packet) vps = packet->vps;
1539                 break;
1540
1541 #endif
1542         }
1543
1544         /*
1545          *      Now that we have the list, etc. handled,
1546          *      find the VP and print it.
1547          */
1548         if ((da->vendor != 0) || (da->attr < 256) || (list == PAIR_LIST_CONTROL)) {
1549         print_vp:
1550                 vp = pairfind(vps, da->attr, da->vendor, tag);
1551                 if (!vp) {
1552                         return NULL;
1553                 }
1554                 goto do_print;
1555         }
1556
1557         /*
1558          *      Some non-packet expansions
1559          */
1560         switch (da->attr) {
1561         default:
1562                 break;          /* ignore them */
1563
1564         case PW_CLIENT_SHORTNAME:
1565                 if (request->client && request->client->shortname) {
1566                         return talloc_strdup(ctx, request->client->shortname);
1567                 }
1568                 return talloc_strdup(ctx, "<UNKNOWN-CLIENT>");
1569
1570         case PW_REQUEST_PROCESSING_STAGE:
1571                 if (request->component) {
1572                         return talloc_strdup(ctx, request->component);
1573                 }
1574                 return talloc_strdup(ctx, "server_core");
1575
1576         case PW_VIRTUAL_SERVER:
1577                 if (!request->server) return NULL;
1578                 return talloc_strdup(ctx, request->server);
1579
1580         case PW_MODULE_RETURN_CODE:
1581                 return talloc_asprintf(ctx, "%d", request->simul_max); /* hack */
1582         }
1583
1584         /*
1585          *      All of the attributes must now refer to a packet.  If
1586          *      there's no packet, we can't print any attribute
1587          *      referencing it.
1588          */
1589         if (!packet) {
1590                 if (return_null) return NULL;
1591                 return vp_aprinttype(ctx, da->type);
1592         }
1593
1594         memset(&myvp, 0, sizeof(myvp));
1595         myvp.da = da;
1596         vp = NULL;
1597
1598         switch (da->attr) {
1599         default:
1600                 goto print_vp;
1601
1602         case PW_PACKET_TYPE:
1603                 dv = dict_valbyattr(PW_PACKET_TYPE, 0, packet->code);
1604                 if (dv) return talloc_strdup(ctx, dv->name);
1605                 return talloc_asprintf(ctx, "%d", packet->code);
1606
1607         case PW_RESPONSE_PACKET_TYPE:
1608         {
1609                 int code = 0;
1610
1611 #ifdef WITH_PROXY
1612                 if (request->proxy_reply && (!request->reply || !request->reply->code)) {
1613                         code = request->proxy_reply->code;
1614                 } else
1615 #endif
1616                         if (request->reply) {
1617                                 code = request->reply->code;
1618                         }
1619
1620                 return talloc_strdup(ctx, fr_packet_codes[code]);
1621         }
1622
1623         case PW_PACKET_AUTHENTICATION_VECTOR:
1624                 myvp.length = sizeof(packet->vector);
1625                 memcpy(&myvp.vp_octets, packet->vector, sizeof(packet->vector));
1626                 vp = &myvp;
1627                 break;
1628
1629         case PW_CLIENT_IP_ADDRESS:
1630         case PW_PACKET_SRC_IP_ADDRESS:
1631                 if (packet->src_ipaddr.af == AF_INET) {
1632                         myvp.vp_ipaddr = packet->src_ipaddr.ipaddr.ip4addr.s_addr;
1633                         vp = &myvp;
1634                 }
1635                 break;
1636
1637         case PW_PACKET_DST_IP_ADDRESS:
1638                 if (packet->dst_ipaddr.af == AF_INET) {
1639                         myvp.vp_ipaddr = packet->dst_ipaddr.ipaddr.ip4addr.s_addr;
1640                         vp = &myvp;
1641                 }
1642                 break;
1643
1644         case PW_PACKET_SRC_IPV6_ADDRESS:
1645                 if (packet->src_ipaddr.af == AF_INET6) {
1646                         memcpy(&myvp.vp_ipv6addr,
1647                                &packet->src_ipaddr.ipaddr.ip6addr,
1648                                sizeof(packet->src_ipaddr.ipaddr.ip6addr));
1649                         vp = &myvp;
1650                 }
1651                 break;
1652
1653         case PW_PACKET_DST_IPV6_ADDRESS:
1654                 if (packet->dst_ipaddr.af == AF_INET6) {
1655                         memcpy(&myvp.vp_ipv6addr,
1656                                &packet->dst_ipaddr.ipaddr.ip6addr,
1657                                sizeof(packet->dst_ipaddr.ipaddr.ip6addr));
1658                         vp = &myvp;
1659                 }
1660                 break;
1661
1662         case PW_PACKET_SRC_PORT:
1663                 myvp.vp_integer = packet->src_port;
1664                 vp = &myvp;
1665                 break;
1666
1667         case PW_PACKET_DST_PORT:
1668                 myvp.vp_integer = packet->dst_port;
1669                 vp = &myvp;
1670                 break;
1671         }
1672
1673 do_print:
1674         /*
1675          *      Hack up the virtual attributes.
1676          */
1677         if (num && (vp == &myvp)) {
1678                 char *p, *q;
1679
1680                 /*
1681                  *      [*] means only one.
1682                  */
1683                 if (num == 65537) num = 0;
1684
1685                 /*
1686                  *      [n] means NULL, as there's only one.
1687                  */
1688                 if ((num > 0) && (num < 65536)) {
1689                         return NULL;
1690                 }
1691
1692                 p = vp_aprint(ctx, vp);
1693                 rad_assert(p != NULL);
1694
1695                 /*
1696                  *      Get the length of it.
1697                  */
1698                 if (num == 65536) {
1699                         q = talloc_asprintf(ctx, "%d", (int) strlen(p));
1700                         talloc_free(p);
1701                         return q;
1702                 }
1703
1704                 return p;
1705         }
1706
1707         /*
1708          *      We want the N'th VP.
1709          */
1710         if (num) {
1711                 int count = 0;
1712                 vp_cursor_t cursor;
1713
1714                 /*
1715                  *      Return a count of the VPs.
1716                  */
1717                 if (num == 65536) {
1718                         paircursor(&cursor, &vp);
1719                         while (pairfindnext(&cursor, da->attr, da->vendor, tag) != NULL) {
1720                                 count++;
1721                         }
1722
1723                         return talloc_asprintf(ctx, "%d", count);
1724                 }
1725
1726                 /*
1727                  *      Ugly, but working.
1728                  */
1729                 if (num == 65537) {
1730                         char *p, *q;
1731
1732                         vp = paircursor(&cursor, &vp);
1733                         vp = pairfindnext(&cursor, da->attr, da->vendor, tag);
1734                         if (!vp) return NULL;
1735                         p = vp_aprint(ctx, vp);
1736                         while ((vp = pairfindnext(&cursor, da->attr, da->vendor, tag)) != NULL) {
1737                                 q = vp_aprint(ctx, vp);
1738                                 p = talloc_strdup_append(p, ",");
1739                                 p = talloc_strdup_append(p, q);
1740                         }
1741
1742                         return p;
1743                 }
1744
1745                 paircursor(&cursor, &vp);
1746                 while (pairfindnext(&cursor, da->attr, da->vendor, tag) != NULL) {
1747                         if (count == num) {
1748                                 break;
1749                         }
1750                         count++;
1751                 }
1752         }
1753
1754         if (!vp) {
1755                 if (return_null) return NULL;
1756                 return vp_aprinttype(ctx, da->type);
1757         }
1758
1759         return vp_aprint(ctx, vp);
1760 }
1761
1762 static char *xlat_aprint(TALLOC_CTX *ctx, REQUEST *request, xlat_exp_t const * const node,
1763                          RADIUS_ESCAPE_STRING escape, void *escape_ctx, int lvl)
1764 {
1765         ssize_t rcode;
1766         char *str = NULL, *child;
1767         REQUEST *ref;
1768
1769         XLAT_DEBUG("%.*sxlat aprint %d", lvl, xlat_spaces, node->type);
1770
1771         switch (node->type) {
1772                 /*
1773                  *      Don't escape this.
1774                  */
1775         case XLAT_LITERAL:
1776                 XLAT_DEBUG("xlat_aprint LITERAL");
1777                 return talloc_strdup(ctx, node->fmt);
1778
1779                 /*
1780                  *      Do a one-character expansion.
1781                  */
1782         case XLAT_PERCENT:
1783         {
1784                 char const *p;
1785                 char *nl;
1786                 size_t freespace = 256;
1787                 struct tm ts;
1788                 time_t when;
1789
1790                 XLAT_DEBUG("xlat_aprint PERCENT");
1791
1792                 str = talloc_array(ctx, char, freespace); /* @todo do better allocation */
1793                 p = node->fmt;
1794
1795                 when = request->timestamp;
1796                 if (request->packet) {
1797                         when = request->packet->timestamp.tv_sec;
1798                 }
1799
1800                 switch (*p) {
1801                 case '%':
1802                         str[0] = '%';
1803                         str[1] = '\0';
1804                         break;
1805
1806                 case 'd': /* request day */
1807                         (void) localtime_r(&when, &ts);
1808                         strftime(str, freespace, "%d", &ts);
1809                         break;
1810
1811                 case 'l': /* request timestamp */
1812                         snprintf(str, freespace, "%lu",
1813                                  (unsigned long) when);
1814                         break;
1815
1816                 case 'm': /* request month */
1817                         (void) localtime_r(&when, &ts);
1818                         strftime(str, freespace, "%m", &ts);
1819                         break;
1820
1821                 case 't': /* request timestamp */
1822                         CTIME_R(&when, str, freespace);
1823                         nl = strchr(str, '\n');
1824                         if (nl) *nl = '\0';
1825                         break;
1826
1827                 case 'D': /* request date */
1828                         (void) localtime_r(&when, &ts);
1829                         strftime(str, freespace, "%Y%m%d", &ts);
1830                         break;
1831
1832                 case 'G': /* request minute */
1833                         (void) localtime_r(&when, &ts);
1834                         strftime(str, freespace, "%M", &ts);
1835                         break;
1836
1837                 case 'H': /* request hour */
1838                         (void) localtime_r(&when, &ts);
1839                         strftime(str, freespace, "%H", &ts);
1840                         break;
1841
1842                 case 'I': /* Request ID */
1843                         if (request->packet) {
1844                                 snprintf(str, freespace, "%i", request->packet->id);
1845                         }
1846                         break;
1847
1848                 case 'S': /* request timestamp in SQL format*/
1849                         (void) localtime_r(&when, &ts);
1850                         strftime(str, freespace, "%Y-%m-%d %H:%M:%S", &ts);
1851                         break;
1852
1853                 case 'T': /* request timestamp */
1854                         (void) localtime_r(&when, &ts);
1855                         strftime(str, freespace, "%Y-%m-%d-%H.%M.%S.000000", &ts);
1856                         break;
1857
1858                 case 'Y': /* request year */
1859                         (void) localtime_r(&when, &ts);
1860                         strftime(str, freespace, "%Y", &ts);
1861                         break;
1862
1863                 default:
1864                         rad_assert(0 == 1);
1865                         break;
1866                 }
1867         }
1868                 break;
1869
1870         case XLAT_ATTRIBUTE:
1871                 XLAT_DEBUG("xlat_aprint ATTRIBUTE");
1872                 ref = request;
1873                 if (radius_request(&ref, node->ref) < 0) {
1874                         return NULL;
1875                 }
1876
1877                 /*
1878                  *      Some attributes are virtual <sigh>
1879                  */
1880                 str = xlat_getvp(ctx, ref, node->list, node->da, node->tag, node->num, true);
1881                 if (str) {
1882                         XLAT_DEBUG("expand attr %s --> '%s'", node->da->name, str);
1883                 }
1884                 break;
1885
1886         case XLAT_VIRTUAL:
1887                 XLAT_DEBUG("xlat_aprint VIRTUAL");
1888                 str = talloc_array(ctx, char, 1024); /* FIXME: have the module call talloc_asprintf */
1889                 rcode = node->xlat->func(node->xlat->instance, request, NULL, str, 1024);
1890                 if (rcode < 0) {
1891                         talloc_free(str);
1892                         return NULL;
1893                 }
1894                 break;
1895
1896         case XLAT_MODULE:
1897                 XLAT_DEBUG("xlat_aprint MODULE");
1898                 if (xlat_process(&child, request, node->child, node->xlat->escape, node->xlat->instance) == 0) {
1899                         return NULL;
1900                 }
1901
1902                 XLAT_DEBUG("%.*sexpand mod %s --> '%s'", lvl, xlat_spaces, node->fmt, child);
1903
1904                 str = talloc_array(ctx, char, 1024); /* FIXME: have the module call talloc_asprintf */
1905                 *str = '\0';    /* Be sure the string is NULL terminated, we now only free on error */
1906
1907                 rcode = node->xlat->func(node->xlat->instance, request, child, str, 1024);
1908                 talloc_free(child);
1909                 if (rcode < 0) {
1910                         talloc_free(str);
1911                         return NULL;
1912                 }
1913                 break;
1914
1915 #ifdef HAVE_REGEX_H
1916         case XLAT_REGEX:
1917                 XLAT_DEBUG("xlat_aprint REGEX");
1918                 child = request_data_reference(request, request,
1919                                                REQUEST_DATA_REGEX | node->num);
1920                 if (!child) return NULL;
1921
1922                 str = talloc_strdup(ctx, child);
1923                 break;
1924 #endif
1925
1926         case XLAT_ALTERNATE:
1927                 XLAT_DEBUG("xlat_aprint ALTERNATE");
1928                 rad_assert(node->child != NULL);
1929                 rad_assert(node->alternate != NULL);
1930
1931                 str = xlat_aprint(ctx, request, node->child, escape, escape_ctx, lvl);
1932                 if (str) break;
1933
1934                 str = xlat_aprint(ctx, request, node->alternate, escape, escape_ctx, lvl);
1935                 break;
1936
1937         }
1938
1939         /*
1940          *      Escape the non-literals we found above.
1941          */
1942         if (str && escape) {
1943                 char *escaped;
1944
1945                 escaped = talloc_array(ctx, char, 1024); /* FIXME: do something intelligent */
1946                 escape(request, escaped, 1024, str, escape_ctx);
1947                 talloc_free(str);
1948                 str = escaped;
1949         }
1950
1951         return str;
1952 }
1953
1954
1955 static size_t xlat_process(char **out, REQUEST *request, xlat_exp_t const * const head,
1956                            RADIUS_ESCAPE_STRING escape, void *escape_ctx)
1957 {
1958         int i, list;
1959         size_t total;
1960         char **array, *answer;
1961         xlat_exp_t const *node;
1962
1963         *out = NULL;
1964
1965         /*
1966          *      There are no nodes to process, so the result is a zero
1967          *      length string.
1968          */
1969         if (!head) {
1970                 *out = talloc_zero_array(request, char, 1);
1971                 return 0;
1972         }
1973
1974         /*
1975          *      Hack for speed.  If it's one expansion, just allocate
1976          *      that and return, instead of allocating an intermediary
1977          *      array.
1978          */
1979         if (!head->next) {
1980                 /*
1981                  *      Pass the MAIN escape function.  Recursive
1982                  *      calls will call node-specific escape
1983                  *      functions.
1984                  */
1985                 answer = xlat_aprint(request, request, head, escape, escape_ctx, 0);
1986                 if (!answer) {
1987                         *out = talloc_zero_array(request, char, 1);
1988                         return 0;
1989                 }
1990                 *out = answer;
1991                 return strlen(answer);
1992         }
1993
1994         list = 0;               /* FIXME: calculate this once */
1995         for (node = head; node != NULL; node = node->next) {
1996                 list++;
1997         }
1998
1999         array = talloc_array(request, char *, list);
2000         if (!array) return -1;
2001
2002         for (node = head, i = 0; node != NULL; node = node->next, i++) {
2003                 array[i] = xlat_aprint(array, request, node, escape, escape_ctx, 0); /* may be NULL */
2004         }
2005
2006         total = 0;
2007         for (i = 0; i < list; i++) {
2008                 if (array[i]) total += strlen(array[i]); /* FIXME: calculate strlen once */
2009         }
2010
2011         if (!total) {
2012                 talloc_free(array);
2013                 *out = talloc_zero_array(request, char, 1);
2014                 return 0;
2015         }
2016
2017         answer = talloc_array(request, char, total + 1);
2018
2019         total = 0;
2020         for (i = 0; i < list; i++) {
2021                 size_t len;
2022
2023                 if (array[i]) {
2024                         len = strlen(array[i]);
2025                         memcpy(answer + total, array[i], len);
2026                         total += len;
2027                 }
2028         }
2029         answer[total] = '\0';
2030         talloc_free(array);     /* and child entries */
2031
2032         *out = answer;
2033         return total;
2034 }
2035
2036
2037 /** Replace %whatever in a string.
2038  *
2039  * See 'doc/variables.txt' for more information.
2040  *
2041  * @param[out] out Where to write pointer to output buffer.
2042  * @param[in] outlen Size of out.
2043  * @param[in] request current request.
2044  * @param[in] fmt string to expand.
2045  * @param[in] escape function to escape final value e.g. SQL quoting.
2046  * @param[in] escape_ctx pointer to pass to escape function.
2047  * @return length of string written @bug should really have -1 for failure
2048  */
2049 static ssize_t xlat_expand(char **out, size_t outlen, REQUEST *request, char const *fmt,
2050                            RADIUS_ESCAPE_STRING escape, void *escape_ctx)
2051 {
2052         char *buff;
2053         ssize_t len;
2054         xlat_exp_t *node;
2055
2056         rad_assert(fmt);
2057         rad_assert(request);
2058
2059         /*
2060          *      Give better errors than the old code.
2061          */
2062         len = xlat_tokenize_request(request, fmt, &node);
2063         if (len == 0) {
2064                 if (*out) {
2065                         *out[0] = '\0';
2066                 } else {
2067                         *out = talloc_zero_array(request, char, 1);
2068                 }
2069                 return 0;
2070         }
2071
2072         if (len < 0) {
2073                 if (*out) *out[0] = '\0';
2074                 return -1;
2075         }
2076
2077         len = xlat_process(&buff, request, node, escape, escape_ctx);
2078         talloc_free(node);
2079
2080         if ((len < 0) || !buff) {
2081                 rad_assert(buff == NULL);
2082                 if (*out) *out[0] = '\0';
2083                 return len;
2084         }
2085
2086         RDEBUG2("\texpand: \"%s\" -> '%s'", fmt, buff);
2087
2088         if (!*out) {
2089                 *out = buff;
2090         } else {
2091                 strlcpy(*out, buff, outlen);
2092         }
2093
2094         return strlen(*out);
2095 }
2096
2097 ssize_t radius_xlat(char *out, size_t outlen, REQUEST *request, char const *fmt, RADIUS_ESCAPE_STRING escape, void *ctx)
2098 {
2099         return xlat_expand(&out, outlen, request, fmt, escape, ctx);
2100 }
2101
2102 ssize_t radius_axlat(char **out, REQUEST *request, char const *fmt, RADIUS_ESCAPE_STRING escape, void *ctx)
2103 {
2104         return xlat_expand(out, 0, request, fmt, escape, ctx);
2105 }