7106f00aacf3fac165b61e9c18cadad2eeaac13a
[freeradius.git] / src / main / tmpl.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  * @brief #VALUE_PAIR template functions
21  * @file main/tmpl.c
22  *
23  * @ingroup AVP
24  *
25  * @copyright 2014-2015 The FreeRADIUS server project
26  */
27 RCSID("$Id$")
28
29 #include <freeradius-devel/radiusd.h>
30 #include <freeradius-devel/rad_assert.h>
31
32 #include <ctype.h>
33
34 /** Map #tmpl_type_t values to descriptive strings
35  */
36 FR_NAME_NUMBER const tmpl_names[] = {
37         { "literal",            TMPL_TYPE_LITERAL       },
38         { "xlat",               TMPL_TYPE_XLAT          },
39         { "attr",               TMPL_TYPE_ATTR          },
40         { "unknown attr",       TMPL_TYPE_ATTR_UNDEFINED        },
41         { "list",               TMPL_TYPE_LIST          },
42         { "regex",              TMPL_TYPE_REGEX         },
43         { "exec",               TMPL_TYPE_EXEC          },
44         { "data",               TMPL_TYPE_DATA          },
45         { "parsed xlat",        TMPL_TYPE_XLAT_STRUCT   },
46         { "parsed regex",       TMPL_TYPE_REGEX_STRUCT  },
47         { "null",               TMPL_TYPE_NULL          },
48         { NULL, 0 }
49 };
50
51 /** Map keywords to #pair_lists_t values
52  */
53 const FR_NAME_NUMBER pair_lists[] = {
54         { "request",            PAIR_LIST_REQUEST },
55         { "reply",              PAIR_LIST_REPLY },
56         { "control",            PAIR_LIST_CONTROL },            /* New name should have priority */
57         { "config",             PAIR_LIST_CONTROL },
58         { "session-state",      PAIR_LIST_STATE },
59 #ifdef WITH_PROXY
60         { "proxy-request",      PAIR_LIST_PROXY_REQUEST },
61         { "proxy-reply",        PAIR_LIST_PROXY_REPLY },
62 #endif
63 #ifdef WITH_COA
64         { "coa",                PAIR_LIST_COA },
65         { "coa-reply",          PAIR_LIST_COA_REPLY },
66         { "disconnect",         PAIR_LIST_DM },
67         { "disconnect-reply",   PAIR_LIST_DM_REPLY },
68 #endif
69         {  NULL , -1 }
70 };
71
72 /** Map keywords to #request_refs_t values
73  */
74 const FR_NAME_NUMBER request_refs[] = {
75         { "outer",              REQUEST_OUTER },
76         { "current",            REQUEST_CURRENT },
77         { "parent",             REQUEST_PARENT },
78         {  NULL , -1 }
79 };
80
81 /** @name Parse list and request qualifiers to #pair_lists_t and #request_refs_t values
82  *
83  * These functions also resolve #pair_lists_t and #request_refs_t values to #REQUEST
84  * structs and the head of #VALUE_PAIR lists in those structs.
85  *
86  * For adding new #VALUE_PAIR to the lists, the #radius_list_ctx function can be used
87  * to obtain the appropriate TALLOC_CTX pointer.
88  *
89  * @note These don't really have much to do with #vp_tmpl_t. They're in the same
90  *      file as they're used almost exclusively by the tmpl_* functions.
91  * @{
92  */
93
94 /** Resolve attribute name to a #pair_lists_t value.
95  *
96  * Check the name string for #pair_lists qualifiers and write a #pair_lists_t value
97  * for that list to out. This value may be passed to #radius_list, along with the current
98  * #REQUEST, to get a pointer to the actual list in the #REQUEST.
99  *
100  * If we're sure we've definitely found a list qualifier token delimiter (``:``) but the
101  * string doesn't match a #radius_list qualifier, return 0 and write #PAIR_LIST_UNKNOWN
102  * to out.
103  *
104  * If we can't find a string that looks like a request qualifier, set out to def, and
105  * return 0.
106  *
107  * @note #radius_list_name should be called before passing a name string that may
108  *      contain qualifiers to #dict_attrbyname.
109  *
110  * @param[out] out Where to write the list qualifier.
111  * @param[in] name String containing list qualifiers to parse.
112  * @param[in] def the list to return if no qualifiers were found.
113  * @return 0 if no valid list qualifier could be found, else the number of bytes consumed.
114  *      The caller may then advanced the name pointer by the value returned, to get the
115  *      start of the attribute name (if any).
116  *
117  * @see pair_list
118  * @see radius_list
119  */
120 size_t radius_list_name(pair_lists_t *out, char const *name, pair_lists_t def)
121 {
122         char const *p = name;
123         char const *q;
124
125         /* This should never be a NULL pointer */
126         rad_assert(name);
127
128         /*
129          *      Try and determine the end of the token
130          */
131         for (q = p; dict_attr_allowed_chars[(uint8_t) *q]; q++);
132
133         switch (*q) {
134         /*
135          *      It's a bareword made up entirely of dictionary chars
136          *      check and see if it's a list qualifier, and if it's
137          *      not, return the def and say we couldn't parse
138          *      anything.
139          */
140         case '\0':
141                 *out = fr_substr2int(pair_lists, p, PAIR_LIST_UNKNOWN, (q - p));
142                 if (*out != PAIR_LIST_UNKNOWN) return q - p;
143                 *out = def;
144                 return 0;
145
146         /*
147          *      It may be a list qualifier delimiter. Because of tags
148          *      We need to check that it doesn't look like a tag suffix.
149          *      We do this by looking at the chars between ':' and the
150          *      next token delimiter, and seeing if they're all digits.
151          */
152         case ':':
153         {
154                 char const *d = q + 1;
155
156                 if (isdigit((int) *d)) {
157                         while (isdigit((int) *d)) d++;
158
159                         /*
160                          *      Char after the number string
161                          *      was a token delimiter, so this is a
162                          *      tag, not a list qualifier.
163                          */
164                         if (!dict_attr_allowed_chars[(uint8_t) *d]) {
165                                 *out = def;
166                                 return 0;
167                         }
168                 }
169
170                 *out = fr_substr2int(pair_lists, p, PAIR_LIST_UNKNOWN, (q - p));
171                 if (*out == PAIR_LIST_UNKNOWN) return 0;
172
173                 return (q + 1) - name; /* Consume the list and delimiter */
174         }
175
176         default:
177                 *out = def;
178                 return 0;
179         }
180 }
181
182 /** Resolve attribute #pair_lists_t value to an attribute list.
183  *
184  * The value returned is a pointer to the pointer of the HEAD of a #VALUE_PAIR list in the
185  * #REQUEST. If the head of the list changes, the pointer will still be valid.
186  *
187  * @param[in] request containing the target lists.
188  * @param[in] list #pair_lists_t value to resolve to #VALUE_PAIR list. Will be NULL if list
189  *      name couldn't be resolved.
190  * @return a pointer to the HEAD of a list in the #REQUEST.
191  *
192  * @see tmpl_cursor_init
193  * @see fr_cursor_init
194  */
195 VALUE_PAIR **radius_list(REQUEST *request, pair_lists_t list)
196 {
197         if (!request) return NULL;
198
199         switch (list) {
200         /* Don't add default */
201         case PAIR_LIST_UNKNOWN:
202                 break;
203
204         case PAIR_LIST_REQUEST:
205                 if (!request->packet) return NULL;
206                 return &request->packet->vps;
207
208         case PAIR_LIST_REPLY:
209                 if (!request->reply) return NULL;
210                 return &request->reply->vps;
211
212         case PAIR_LIST_CONTROL:
213                 return &request->config;
214
215         case PAIR_LIST_STATE:
216                 return &request->state;
217
218 #ifdef WITH_PROXY
219         case PAIR_LIST_PROXY_REQUEST:
220                 if (!request->proxy) break;
221                 return &request->proxy->vps;
222
223         case PAIR_LIST_PROXY_REPLY:
224                 if (!request->proxy_reply) break;
225                 return &request->proxy_reply->vps;
226 #endif
227 #ifdef WITH_COA
228         case PAIR_LIST_COA:
229                 if (request->coa &&
230                     (request->coa->proxy->code == PW_CODE_COA_REQUEST)) {
231                         return &request->coa->proxy->vps;
232                 }
233                 break;
234
235         case PAIR_LIST_COA_REPLY:
236                 if (request->coa && /* match reply with request */
237                     (request->coa->proxy->code == PW_CODE_COA_REQUEST) &&
238                     request->coa->proxy_reply) {
239                         return &request->coa->proxy_reply->vps;
240                 }
241                 break;
242
243         case PAIR_LIST_DM:
244                 if (request->coa &&
245                     (request->coa->proxy->code == PW_CODE_DISCONNECT_REQUEST)) {
246                         return &request->coa->proxy->vps;
247                 }
248                 break;
249
250         case PAIR_LIST_DM_REPLY:
251                 if (request->coa && /* match reply with request */
252                     (request->coa->proxy->code == PW_CODE_DISCONNECT_REQUEST) &&
253                     request->coa->proxy_reply) {
254                         return &request->coa->proxy->vps;
255                 }
256                 break;
257 #endif
258         }
259
260         RWDEBUG2("List \"%s\" is not available",
261                 fr_int2str(pair_lists, list, "<INVALID>"));
262
263         return NULL;
264 }
265
266 /** Resolve a list to the #RADIUS_PACKET holding the HEAD pointer for a #VALUE_PAIR list
267  *
268  * Returns a pointer to the #RADIUS_PACKET that holds the HEAD pointer of a given list,
269  * for the current #REQUEST.
270  *
271  * @param[in] request To resolve list in.
272  * @param[in] list #pair_lists_t value to resolve to #RADIUS_PACKET.
273  * @return a #RADIUS_PACKET on success, else NULL.
274  *
275  * @see radius_list
276  */
277 RADIUS_PACKET *radius_packet(REQUEST *request, pair_lists_t list)
278 {
279         switch (list) {
280         /* Don't add default */
281         case PAIR_LIST_STATE:
282         case PAIR_LIST_CONTROL:
283         case PAIR_LIST_UNKNOWN:
284                 return NULL;
285
286         case PAIR_LIST_REQUEST:
287                 return request->packet;
288
289         case PAIR_LIST_REPLY:
290                 return request->reply;
291
292 #ifdef WITH_PROXY
293         case PAIR_LIST_PROXY_REQUEST:
294                 return request->proxy;
295
296         case PAIR_LIST_PROXY_REPLY:
297                 return request->proxy_reply;
298 #endif
299
300 #ifdef WITH_COA
301         case PAIR_LIST_COA:
302         case PAIR_LIST_DM:
303                 return request->coa->packet;
304
305         case PAIR_LIST_COA_REPLY:
306         case PAIR_LIST_DM_REPLY:
307                 return request->coa->reply;
308 #endif
309         }
310
311         return NULL;
312 }
313
314 /** Return the correct TALLOC_CTX to alloc #VALUE_PAIR in, for a list
315  *
316  * Allocating new #VALUE_PAIR in the context of a #REQUEST is usually wrong.
317  * #VALUE_PAIR should be allocated in the context of a #RADIUS_PACKET, so that if the
318  * #RADIUS_PACKET is freed before the #REQUEST, the associated #VALUE_PAIR lists are
319  * freed too.
320  *
321  * @param[in] request containing the target lists.
322  * @param[in] list #pair_lists_t value to resolve to TALLOC_CTX.
323  * @return a TALLOC_CTX on success, else NULL.
324  *
325  * @see radius_list
326  */
327 TALLOC_CTX *radius_list_ctx(REQUEST *request, pair_lists_t list)
328 {
329         if (!request) return NULL;
330
331         switch (list) {
332         case PAIR_LIST_REQUEST:
333                 return request->packet;
334
335         case PAIR_LIST_REPLY:
336                 return request->reply;
337
338         case PAIR_LIST_CONTROL:
339                 return request;
340
341         case PAIR_LIST_STATE:
342                 return request;
343
344 #ifdef WITH_PROXY
345         case PAIR_LIST_PROXY_REQUEST:
346                 return request->proxy;
347
348         case PAIR_LIST_PROXY_REPLY:
349                 return request->proxy_reply;
350 #endif
351
352 #ifdef WITH_COA
353         case PAIR_LIST_COA:
354                 if (!request->coa) return NULL;
355                 rad_assert(request->coa->proxy != NULL);
356                 if (request->coa->proxy->code != PW_CODE_COA_REQUEST) return NULL;
357                 return request->coa->proxy;
358
359         case PAIR_LIST_COA_REPLY:
360                 if (!request->coa) return NULL;
361                 rad_assert(request->coa->proxy != NULL);
362                 if (request->coa->proxy->code != PW_CODE_COA_REQUEST) return NULL;
363                 return request->coa->proxy_reply;
364
365         case PAIR_LIST_DM:
366                 if (!request->coa) return NULL;
367                 rad_assert(request->coa->proxy != NULL);
368                 if (request->coa->proxy->code != PW_CODE_DISCONNECT_REQUEST) return NULL;
369                 return request->coa->proxy;
370
371         case PAIR_LIST_DM_REPLY:
372                 if (!request->coa) return NULL;
373                 rad_assert(request->coa->proxy != NULL);
374                 if (request->coa->proxy->code != PW_CODE_DISCONNECT_REQUEST) return NULL;
375                 return request->coa->proxy_reply;
376 #endif
377         /* Don't add default */
378         case PAIR_LIST_UNKNOWN:
379                 break;
380         }
381
382         return NULL;
383 }
384
385 /** Resolve attribute name to a #request_refs_t value.
386  *
387  * Check the name string for qualifiers that reference a parent #REQUEST.
388  *
389  * If we find a string that matches a #request_refs qualifier, return the number of chars
390  * we consumed.
391  *
392  * If we're sure we've definitely found a list qualifier token delimiter (``*``) but the
393  * qualifier doesn't match one of the #request_refs qualifiers, return 0 and set out to
394  * #REQUEST_UNKNOWN.
395  *
396  * If we can't find a string that looks like a request qualifier, set out to def, and
397  * return 0.
398  *
399  * @param[out] out The #request_refs_t value the name resolved to (or #REQUEST_UNKNOWN).
400  * @param[in] name of attribute.
401  * @param[in] def default request ref to return if no request qualifier is present.
402  * @return 0 if no valid request qualifier could be found, else the number of bytes consumed.
403  *      The caller may then advanced the name pointer by the value returned, to get the
404  *      start of the attribute list or attribute name(if any).
405  *
406  * @see radius_list_name
407  * @see request_refs
408  */
409 size_t radius_request_name(request_refs_t *out, char const *name, request_refs_t def)
410 {
411         char const *p, *q;
412
413         p = name;
414         /*
415          *      Try and determine the end of the token
416          */
417         for (q = p; dict_attr_allowed_chars[(uint8_t) *q] && (*q != '.') && (*q != '-'); q++);
418
419         /*
420          *      First token delimiter wasn't a '.'
421          */
422         if (*q != '.') {
423                 *out = def;
424                 return 0;
425         }
426
427         *out = fr_substr2int(request_refs, name, REQUEST_UNKNOWN, q - p);
428         if (*out == REQUEST_UNKNOWN) return 0;
429
430         return (q + 1) - p;
431 }
432
433 /** Resolve a #request_refs_t to a #REQUEST.
434  *
435  * Sometimes #REQUEST structs may be chained to each other, as is the case
436  * when internally proxying EAP. This function resolves a #request_refs_t
437  * to a #REQUEST higher in the chain than the current #REQUEST.
438  *
439  * @see radius_list
440  * @param[in,out] context #REQUEST to start resolving from, and where to write
441  *      a pointer to the resolved #REQUEST back to.
442  * @param[in] name (request) to resolve.
443  * @return 0 if request is valid in this context, else -1.
444  */
445 int radius_request(REQUEST **context, request_refs_t name)
446 {
447         REQUEST *request = *context;
448
449         switch (name) {
450         case REQUEST_CURRENT:
451                 return 0;
452
453         case REQUEST_PARENT:    /* for future use in request chaining */
454         case REQUEST_OUTER:
455                 if (!request->parent) {
456                         return -1;
457                 }
458                 *context = request->parent;
459                 break;
460
461         case REQUEST_UNKNOWN:
462         default:
463                 rad_assert(0);
464                 return -1;
465         }
466
467         return 0;
468 }
469 /** @} */
470
471 /** @name Alloc or initialise #vp_tmpl_t
472  *
473  * @note Should not usually be called outside of tmpl_* functions, use one of
474  *      the tmpl_*from_* functions instead.
475  * @{
476  */
477
478 /** Initialise stack allocated #vp_tmpl_t
479  *
480  * @note Name is not strdupe'd or memcpy'd so must be available, and must not change
481  *      for the lifetime of the #vp_tmpl_t.
482  *
483  * @param[out] vpt to initialise.
484  * @param[in] type to set in the #vp_tmpl_t.
485  * @param[in] name of the #vp_tmpl_t.
486  * @param[in] len The length of the buffer (or a substring of the buffer) pointed to by name.
487  *      If < 0 strlen will be used to determine the length.
488  * @return a pointer to the initialised #vp_tmpl_t. The same value as
489  *      vpt.
490  */
491 vp_tmpl_t *tmpl_init(vp_tmpl_t *vpt, tmpl_type_t type, char const *name, ssize_t len)
492 {
493         rad_assert(vpt);
494         rad_assert(type != TMPL_TYPE_UNKNOWN);
495         rad_assert(type <= TMPL_TYPE_NULL);
496
497         memset(vpt, 0, sizeof(vp_tmpl_t));
498         vpt->type = type;
499
500         if (name) {
501                 vpt->name = name;
502                 vpt->len = len < 0 ? strlen(name) :
503                                      (size_t) len;
504         }
505         return vpt;
506 }
507
508 /** Create a new heap allocated #vp_tmpl_t
509  *
510  * @param[in,out] ctx to allocate in.
511  * @param[in] type to set in the #vp_tmpl_t.
512  * @param[in] name of the #vp_tmpl_t (will be copied to a new talloc buffer parented
513  *      by the #vp_tmpl_t).
514  * @param[in] len The length of the buffer (or a substring of the buffer) pointed to by name.
515  *      If < 0 strlen will be used to determine the length.
516  * @return the newly allocated #vp_tmpl_t.
517  */
518 vp_tmpl_t *tmpl_alloc(TALLOC_CTX *ctx, tmpl_type_t type, char const *name, ssize_t len)
519 {
520         vp_tmpl_t *vpt;
521
522         rad_assert(type != TMPL_TYPE_UNKNOWN);
523         rad_assert(type <= TMPL_TYPE_NULL);
524
525         vpt = talloc_zero(ctx, vp_tmpl_t);
526         if (!vpt) return NULL;
527         vpt->type = type;
528         if (name) {
529                 vpt->name = talloc_bstrndup(vpt, name, len < 0 ? strlen(name) : (size_t)len);
530                 vpt->len = talloc_array_length(vpt->name) - 1;
531         }
532
533         return vpt;
534 }
535 /* @} **/
536
537 /** @name Create new #vp_tmpl_t from a string
538  *
539  * @{
540  */
541 /** Parse a string into a TMPL_TYPE_ATTR_* or #TMPL_TYPE_LIST type #vp_tmpl_t
542  *
543  * @note The name field is just a copy of the input pointer, if you know that string might be
544  *      freed before you're done with the #vp_tmpl_t use #tmpl_afrom_attr_str
545  *      instead.
546  *
547  * @param[out] vpt to modify.
548  * @param[in] name of attribute including #request_refs and #pair_lists qualifiers.
549  *      If only #request_refs and #pair_lists qualifiers are found, a #TMPL_TYPE_LIST
550  *      #vp_tmpl_t will be produced.
551  * @param[in] request_def The default #REQUEST to set if no #request_refs qualifiers are
552  *      found in name.
553  * @param[in] list_def The default list to set if no #pair_lists qualifiers are found in
554  *      name.
555  * @param[in] allow_unknown If true attributes in the format accepted by
556  *      #dict_unknown_from_substr will be allowed, even if they're not in the main
557  *      dictionaries.
558  *      If an unknown attribute is found a #TMPL_TYPE_ATTR #vp_tmpl_t will be
559  *      produced with the unknown #DICT_ATTR stored in the ``unknown.da`` buffer.
560  *      This #DICT_ATTR will have its ``flags.is_unknown`` field set to true.
561  *      If #tmpl_from_attr_substr is being called on startup, the #vp_tmpl_t may be
562  *      passed to #tmpl_define_unknown_attr to add the unknown attribute to the main
563  *      dictionary.
564  *      If the unknown attribute is not added to the main dictionary the #vp_tmpl_t
565  *      cannot be used to search for a #VALUE_PAIR in a #REQUEST.
566  * @param[in] allow_undefined If true, we don't generate a parse error on unknown attributes.
567  *      If an unknown attribute is found a #TMPL_TYPE_ATTR_UNDEFINED #vp_tmpl_t
568  *      will be produced.
569  * @return <= 0 on error (offset as negative integer), > 0 on success
570  *      (number of bytes parsed).
571  *
572  * @see REMARKER to produce pretty error markers from the return value.
573  */
574 ssize_t tmpl_from_attr_substr(vp_tmpl_t *vpt, char const *name,
575                               request_refs_t request_def, pair_lists_t list_def,
576                               bool allow_unknown, bool allow_undefined)
577 {
578         char const *p;
579         long num;
580         char *q;
581         tmpl_type_t type = TMPL_TYPE_ATTR;
582
583         value_pair_tmpl_attr_t attr;    /* So we don't fill the tmpl with junk and then error out */
584
585         memset(vpt, 0, sizeof(*vpt));
586         memset(&attr, 0, sizeof(attr));
587
588         p = name;
589
590         if (*p == '&') p++;
591
592         p += radius_request_name(&attr.request, p, request_def);
593         if (attr.request == REQUEST_UNKNOWN) {
594                 fr_strerror_printf("Invalid request qualifier");
595                 return -(p - name);
596         }
597
598         /*
599          *      Finding a list qualifier is optional
600          */
601         p += radius_list_name(&attr.list, p, list_def);
602         if (attr.list == PAIR_LIST_UNKNOWN) {
603                 fr_strerror_printf("Invalid list qualifier");
604                 return -(p - name);
605         }
606
607         attr.tag = TAG_ANY;
608         attr.num = NUM_ANY;
609
610         /*
611          *      This may be just a bare list, but it can still
612          *      have instance selectors and tag selectors.
613          */
614         switch (*p) {
615         case '\0':
616                 type = TMPL_TYPE_LIST;
617                 attr.num = NUM_ALL;     /* Hack - Should be removed once tests are updated */
618                 goto finish;
619
620         case '[':
621                 type = TMPL_TYPE_LIST;
622                 attr.num = NUM_ALL;     /* Hack - Should be removed once tests are updated */
623                 goto do_num;
624
625         default:
626                 break;
627         }
628
629         attr.da = dict_attrbyname_substr(&p);
630         if (!attr.da) {
631                 char const *a;
632
633                 /*
634                  *      Record start of attribute in case we need to error out.
635                  */
636                 a = p;
637
638                 fr_strerror();  /* Clear out any existing errors */
639
640                 /*
641                  *      Attr-1.2.3.4 is OK.
642                  */
643                 if (dict_unknown_from_substr((DICT_ATTR *)&attr.unknown.da, &p) == 0) {
644                         /*
645                          *      Check what we just parsed really hasn't been defined
646                          *      in the main dictionaries.
647                          *
648                          *      If it has, parsing is the same as if the attribute
649                          *      name had been used instead of its OID.
650                          */
651                         attr.da = dict_attrbyvalue(((DICT_ATTR *)&attr.unknown.da)->attr,
652                                                    ((DICT_ATTR *)&attr.unknown.da)->vendor);
653                         if (attr.da) {
654                                 vpt->auto_converted = true;
655                                 goto do_num;
656                         }
657
658                         if (!allow_unknown) {
659                                 fr_strerror_printf("Unknown attribute");
660                                 return -(a - name);
661                         }
662
663                         /*
664                          *      Unknown attributes can't be encoded, as we don't
665                          *      know how to encode them!
666                          */
667                         attr.da = (DICT_ATTR *)&attr.unknown.da;
668
669                         goto do_num; /* unknown attributes can't have tags */
670                 }
671
672                 /*
673                  *      Can't parse it as an attribute, might be a literal string
674                  *      let the caller decide.
675                  *
676                  *      Don't alter the fr_strerror buffer, should contain the parse
677                  *      error from dict_unknown_from_substr.
678                  */
679                 if (!allow_undefined) return -(a - name);
680
681                 /*
682                  *      Copy the name to a field for later resolution
683                  */
684                 type = TMPL_TYPE_ATTR_UNDEFINED;
685                 for (q = attr.unknown.name; dict_attr_allowed_chars[(int) *p]; *q++ = *p++) {
686                         if (q >= (attr.unknown.name + sizeof(attr.unknown.name) - 1)) {
687                                 fr_strerror_printf("Attribute name is too long");
688                                 return -(p - name);
689                         }
690                 }
691                 *q = '\0';
692
693                 goto do_num;
694         }
695
696         /*
697          *      The string MIGHT have a tag.
698          */
699         if (*p == ':') {
700                 if (attr.da && !attr.da->flags.has_tag) { /* Lists don't have a da */
701                         fr_strerror_printf("Attribute '%s' cannot have a tag", attr.da->name);
702                         return -(p - name);
703                 }
704
705                 num = strtol(p + 1, &q, 10);
706                 if ((num > 0x1f) || (num < 0)) {
707                         fr_strerror_printf("Invalid tag value '%li' (should be between 0-31)", num);
708                         return -((p + 1)- name);
709                 }
710
711                 attr.tag = num;
712                 p = q;
713         }
714
715 do_num:
716         if (*p == '\0') goto finish;
717
718         if (*p == '[') {
719                 p++;
720
721                 switch (*p) {
722                 case '#':
723                         attr.num = NUM_COUNT;
724                         p++;
725                         break;
726
727                 case '*':
728                         attr.num = NUM_ALL;
729                         p++;
730                         break;
731
732                 case 'n':
733                         attr.num = NUM_LAST;
734                         p++;
735                         break;
736
737                 default:
738                         num = strtol(p, &q, 10);
739                         if (p == q) {
740                                 fr_strerror_printf("Array index is not an integer");
741                                 return -(p - name);
742                         }
743
744                         if ((num > 1000) || (num < 0)) {
745                                 fr_strerror_printf("Invalid array reference '%li' (should be between 0-1000)", num);
746                                 return -(p - name);
747                         }
748                         attr.num = num;
749                         p = q;
750                         break;
751                 }
752
753                 if (*p != ']') {
754                         fr_strerror_printf("No closing ']' for array index");
755                         return -(p - name);
756                 }
757                 p++;
758         }
759
760 finish:
761         vpt->type = type;
762         vpt->name = name;
763         vpt->len = p - name;
764
765         /*
766          *      Copy over the attribute definition, now we're
767          *      sure what we were passed is valid.
768          */
769         memcpy(&vpt->data.attribute, &attr, sizeof(vpt->data.attribute));
770         if ((vpt->type == TMPL_TYPE_ATTR) && attr.da->flags.is_unknown) {
771                 vpt->tmpl_da = (DICT_ATTR *)&vpt->data.attribute.unknown.da;
772         }
773
774         VERIFY_TMPL(vpt);
775
776         return vpt->len;
777 }
778
779 /** Parse a string into a TMPL_TYPE_ATTR_* or #TMPL_TYPE_LIST type #vp_tmpl_t
780  *
781  * @note Unlike #tmpl_from_attr_substr this function will error out if the entire
782  *      name string isn't parsed.
783  *
784  * @copydetails tmpl_from_attr_substr
785  */
786 ssize_t tmpl_from_attr_str(vp_tmpl_t *vpt, char const *name,
787                            request_refs_t request_def, pair_lists_t list_def,
788                            bool allow_unknown, bool allow_undefined)
789 {
790         ssize_t slen;
791
792         slen = tmpl_from_attr_substr(vpt, name, request_def, list_def, allow_unknown, allow_undefined);
793         if (slen <= 0) return slen;
794         if (name[slen] != '\0') {
795                 /* This looks wrong, but it produces meaningful errors for unknown attrs with tags */
796                 fr_strerror_printf("Unexpected text after %s", fr_int2str(tmpl_names, vpt->type, "<INVALID>"));
797                 return -slen;
798         }
799
800         VERIFY_TMPL(vpt);
801
802         return slen;
803 }
804
805 /** Parse a string into a TMPL_TYPE_ATTR_* or #TMPL_TYPE_LIST type #vp_tmpl_t
806  *
807  * @param[in,out] ctx to allocate #vp_tmpl_t in.
808  * @param[out] out Where to write pointer to new #vp_tmpl_t.
809  * @param[in] name of attribute including #request_refs and #pair_lists qualifiers.
810  *      If only #request_refs #pair_lists qualifiers are found, a #TMPL_TYPE_LIST
811  *      #vp_tmpl_t will be produced.
812  * @param[in] request_def The default #REQUEST to set if no #request_refs qualifiers are
813  *      found in name.
814  * @param[in] list_def The default list to set if no #pair_lists qualifiers are found in
815  *      name.
816  * @param[in] allow_unknown If true attributes in the format accepted by
817  *      #dict_unknown_from_substr will be allowed, even if they're not in the main
818  *      dictionaries.
819  *      If an unknown attribute is found a #TMPL_TYPE_ATTR #vp_tmpl_t will be
820  *      produced with the unknown #DICT_ATTR stored in the ``unknown.da`` buffer.
821  *      This #DICT_ATTR will have its ``flags.is_unknown`` field set to true.
822  *      If #tmpl_from_attr_substr is being called on startup, the #vp_tmpl_t may be
823  *      passed to #tmpl_define_unknown_attr to add the unknown attribute to the main
824  *      dictionary.
825  *      If the unknown attribute is not added to the main dictionary the #vp_tmpl_t
826  *      cannot be used to search for a #VALUE_PAIR in a #REQUEST.
827  * @param[in] allow_undefined If true, we don't generate a parse error on unknown attributes.
828  *      If an unknown attribute is found a #TMPL_TYPE_ATTR_UNDEFINED #vp_tmpl_t
829  *      will be produced.
830  * @return <= 0 on error (offset as negative integer), > 0 on success
831  *      (number of bytes parsed).
832  *
833  * @see REMARKER to produce pretty error markers from the return value.
834  */
835 ssize_t tmpl_afrom_attr_substr(TALLOC_CTX *ctx, vp_tmpl_t **out, char const *name,
836                                request_refs_t request_def, pair_lists_t list_def,
837                                bool allow_unknown, bool allow_undefined)
838 {
839         ssize_t slen;
840         vp_tmpl_t *vpt;
841
842         MEM(vpt = talloc(ctx, vp_tmpl_t)); /* tmpl_from_attr_substr zeros it */
843
844         slen = tmpl_from_attr_substr(vpt, name, request_def, list_def, allow_unknown, allow_undefined);
845         if (slen <= 0) {
846                 TALLOC_FREE(vpt);
847                 return slen;
848         }
849         vpt->name = talloc_strndup(vpt, vpt->name, slen);
850
851         VERIFY_TMPL(vpt);
852
853         *out = vpt;
854
855         return slen;
856 }
857
858 /** Parse a string into a TMPL_TYPE_ATTR_* or #TMPL_TYPE_LIST type #vp_tmpl_t
859  *
860  * @note Unlike #tmpl_afrom_attr_substr this function will error out if the entire
861  *      name string isn't parsed.
862  *
863  * @copydetails tmpl_afrom_attr_substr
864  */
865 ssize_t tmpl_afrom_attr_str(TALLOC_CTX *ctx, vp_tmpl_t **out, char const *name,
866                             request_refs_t request_def, pair_lists_t list_def,
867                             bool allow_unknown, bool allow_undefined)
868 {
869         ssize_t slen;
870         vp_tmpl_t *vpt;
871
872         MEM(vpt = talloc(ctx, vp_tmpl_t)); /* tmpl_from_attr_substr zeros it */
873
874         slen = tmpl_from_attr_substr(vpt, name, request_def, list_def, allow_unknown, allow_undefined);
875         if (slen <= 0) {
876                 TALLOC_FREE(vpt);
877                 return slen;
878         }
879         if (name[slen] != '\0') {
880                 /* This looks wrong, but it produces meaningful errors for unknown attrs with tags */
881                 fr_strerror_printf("Unexpected text after %s", fr_int2str(tmpl_names, vpt->type, "<INVALID>"));
882                 TALLOC_FREE(vpt);
883                 return -slen;
884         }
885         vpt->name = talloc_strndup(vpt, vpt->name, vpt->len);
886
887         VERIFY_TMPL(vpt);
888
889         *out = vpt;
890
891         return slen;
892 }
893
894 /** Convert an arbitrary string into a #vp_tmpl_t
895  *
896  * @note Unlike #tmpl_afrom_attr_str return code 0 doesn't necessarily indicate failure,
897  *      may just mean a 0 length string was parsed.
898  *
899  * @note xlats and regexes are left uncompiled.  This is to support the two pass parsing
900  *      done by the modcall code.  Compilation on pass1 of that code could fail, as
901  *      attributes or xlat functions registered by modules may not be available (yet).
902  *
903  * @note For details of attribute parsing see #tmpl_from_attr_substr.
904  *
905  * @param[in,out] ctx To allocate #vp_tmpl_t in.
906  * @param[out] out Where to write the pointer to the new #vp_tmpl_t.
907  * @param[in] in String to convert to a #vp_tmpl_t.
908  * @param[in] inlen length of string to convert.
909  * @param[in] type of quoting around value. May be one of:
910  *      - #T_BARE_WORD - If string begins with ``&`` produces #TMPL_TYPE_ATTR,
911  *        #TMPL_TYPE_ATTR_UNDEFINED, #TMPL_TYPE_LIST or error.
912  *        If string does not begin with ``&`` produces #TMPL_TYPE_LITERAL,
913  *        #TMPL_TYPE_ATTR or #TMPL_TYPE_LIST.
914  *      - #T_SINGLE_QUOTED_STRING - Produces #TMPL_TYPE_LITERAL
915  *      - #T_DOUBLE_QUOTED_STRING - Produces #TMPL_TYPE_XLAT or #TMPL_TYPE_LITERAL (if
916  *        string doesn't contain ``%``).
917  *      - #T_BACK_QUOTED_STRING - Produces #TMPL_TYPE_EXEC
918  *      - #T_OP_REG_EQ - Produces #TMPL_TYPE_REGEX
919  * @param[in] request_def The default #REQUEST to set if no #request_refs qualifiers are
920  *      found in name.
921  * @param[in] list_def The default list to set if no #pair_lists qualifiers are found in
922  *      name.
923  * @param[in] do_unescape whether or not we should do unescaping. Should be false if the
924  *      caller already did it.
925  * @return <= 0 on error (offset as negative integer), > 0 on success
926  *      (number of bytes parsed).
927  *      @see REMARKER to produce pretty error markers from the return value.
928  *
929  * @see tmpl_from_attr_substr
930  */
931 ssize_t tmpl_afrom_str(TALLOC_CTX *ctx, vp_tmpl_t **out, char const *in, size_t inlen, FR_TOKEN type,
932                        request_refs_t request_def, pair_lists_t list_def, bool do_unescape)
933 {
934         bool do_xlat;
935         char quote;
936         char const *p;
937         ssize_t slen;
938         PW_TYPE data_type = PW_TYPE_STRING;
939         vp_tmpl_t *vpt = NULL;
940         value_data_t data;
941
942         switch (type) {
943         case T_BARE_WORD:
944                 /*
945                  *      If we can parse it as an attribute, it's an attribute.
946                  *      Otherwise, treat it as a literal.
947                  */
948                 quote = '\0';
949
950                 slen = tmpl_afrom_attr_str(ctx, &vpt, in, request_def, list_def, true, (in[0] == '&'));
951                 if ((in[0] == '&') && (slen <= 0)) return slen;
952                 if (slen > 0) break;
953                 goto parse;
954
955         case T_SINGLE_QUOTED_STRING:
956                 quote = '\'';
957
958         parse:
959                 if (cf_new_escape && do_unescape) {
960                         slen = value_data_from_str(ctx, &data, &data_type, NULL, in, inlen, quote);
961                         if (slen < 0) return 0;
962
963                         vpt = tmpl_alloc(ctx, TMPL_TYPE_LITERAL, data.strvalue, talloc_array_length(data.strvalue) - 1);
964                         talloc_free(data.ptr);
965                 } else {
966                         vpt = tmpl_alloc(ctx, TMPL_TYPE_LITERAL, in, inlen);
967                 }
968                 vpt->quote = quote;
969                 slen = vpt->len;
970                 break;
971
972         case T_DOUBLE_QUOTED_STRING:
973                 do_xlat = false;
974
975                 p = in;
976                 while (*p) {
977                         if (do_unescape) { /* otherwise \ is just another character */
978                                 if (*p == '\\') {
979                                         if (!p[1]) break;
980                                         p += 2;
981                                         continue;
982                                 }
983                         }
984
985                         if (*p == '%') {
986                                 do_xlat = true;
987                                 break;
988                         }
989
990                         p++;
991                 }
992
993                 /*
994                  *      If the double quoted string needs to be
995                  *      expanded at run time, make it an xlat
996                  *      expansion.  Otherwise, convert it to be a
997                  *      literal.
998                  */
999                 if (cf_new_escape && do_unescape) {
1000                         slen = value_data_from_str(ctx, &data, &data_type, NULL, in, inlen, '"');
1001                         if (slen < 0) return slen;
1002
1003                         if (do_xlat) {
1004                                 vpt = tmpl_alloc(ctx, TMPL_TYPE_XLAT, data.strvalue,
1005                                                  talloc_array_length(data.strvalue) - 1);
1006                         } else {
1007                                 vpt = tmpl_alloc(ctx, TMPL_TYPE_LITERAL, data.strvalue,
1008                                                  talloc_array_length(data.strvalue) - 1);
1009                                 vpt->quote = '"';
1010                         }
1011                         talloc_free(data.ptr);
1012                 } else {
1013                         if (do_xlat) {
1014                                 vpt = tmpl_alloc(ctx, TMPL_TYPE_XLAT, in, inlen);
1015                         } else {
1016                                 vpt = tmpl_alloc(ctx, TMPL_TYPE_LITERAL, in, inlen);
1017                                 vpt->quote = '"';
1018                         }
1019                 }
1020                 slen = vpt->len;
1021                 break;
1022
1023         case T_BACK_QUOTED_STRING:
1024                 if (cf_new_escape && do_unescape) {
1025                         slen = value_data_from_str(ctx, &data, &data_type, NULL, in, inlen, '`');
1026                         if (slen < 0) return slen;
1027
1028                         vpt = tmpl_alloc(ctx, TMPL_TYPE_EXEC, data.strvalue, talloc_array_length(data.strvalue) - 1);
1029                         talloc_free(data.ptr);
1030                 } else {
1031                         vpt = tmpl_alloc(ctx, TMPL_TYPE_EXEC, in, inlen);
1032                 }
1033                 slen = vpt->len;
1034                 break;
1035
1036         case T_OP_REG_EQ: /* hack */
1037                 vpt = tmpl_alloc(ctx, TMPL_TYPE_REGEX, in, inlen);
1038                 slen = vpt->len;
1039                 break;
1040
1041         default:
1042                 rad_assert(0);
1043                 return 0;       /* 0 is an error here too */
1044         }
1045
1046         rad_assert((slen >= 0) && (vpt != NULL));
1047
1048         VERIFY_TMPL(vpt);
1049
1050         *out = vpt;
1051
1052         return slen;
1053 }
1054 /* @} **/
1055
1056 /** @name Cast or convert #vp_tmpl_t
1057  *
1058  * #tmpl_cast_in_place can be used to convert #TMPL_TYPE_LITERAL to a #TMPL_TYPE_DATA of a
1059  *  specified #PW_TYPE.
1060  *
1061  * #tmpl_cast_in_place_str does the same as #tmpl_cast_in_place, but will always convert to
1062  * #PW_TYPE #PW_TYPE_STRING.
1063  *
1064  * #tmpl_cast_to_vp does the same as #tmpl_cast_in_place, but outputs a #VALUE_PAIR.
1065  *
1066  * #tmpl_define_unknown_attr converts a #TMPL_TYPE_ATTR with an unknown #DICT_ATTR to a
1067  * #TMPL_TYPE_ATTR with a known #DICT_ATTR, by adding the unknown #DICT_ATTR to the main
1068  * dictionary, and updating the ``tmpl_da`` pointer.
1069  * @{
1070  */
1071
1072 /** Convert #vp_tmpl_t of type #TMPL_TYPE_LITERAL or #TMPL_TYPE_DATA to #TMPL_TYPE_DATA of type specified
1073  *
1074  * @note Conversion is done in place.
1075  * @note Irrespective of whether the #vp_tmpl_t was #TMPL_TYPE_LITERAL or #TMPL_TYPE_DATA,
1076  *      on successful cast it will be #TMPL_TYPE_DATA.
1077  *
1078  * @param[in,out] vpt The template to modify. Must be of type #TMPL_TYPE_LITERAL
1079  *      or #TMPL_TYPE_DATA.
1080  * @param[in] type to cast to.
1081  * @param[in] enumv Enumerated dictionary values associated with a #DICT_ATTR.
1082  * @return 0 on success, -1 on failure.
1083  */
1084 int tmpl_cast_in_place(vp_tmpl_t *vpt, PW_TYPE type, DICT_ATTR const *enumv)
1085 {
1086         ssize_t ret;
1087
1088         VERIFY_TMPL(vpt);
1089
1090         rad_assert(vpt != NULL);
1091         rad_assert((vpt->type == TMPL_TYPE_LITERAL) || (vpt->type == TMPL_TYPE_DATA));
1092
1093         switch (vpt->type) {
1094         case TMPL_TYPE_LITERAL:
1095                 vpt->tmpl_data_type = type;
1096
1097                 /*
1098                  *      Why do we pass a pointer to the tmpl type? Goddamn WiMAX.
1099                  */
1100                 ret = value_data_from_str(vpt, &vpt->tmpl_data_value, &vpt->tmpl_data_type,
1101                                           enumv, vpt->name, vpt->len, '\0');
1102                 if (ret < 0) return -1;
1103
1104                 vpt->type = TMPL_TYPE_DATA;
1105                 vpt->tmpl_data_length = (size_t) ret;
1106                 break;
1107
1108         case TMPL_TYPE_DATA:
1109         {
1110                 value_data_t new;
1111
1112                 if (type == vpt->tmpl_data_type) return 0;      /* noop */
1113
1114                 ret = value_data_cast(vpt, &new, type, enumv, vpt->tmpl_data_type,
1115                                       NULL, &vpt->tmpl_data_value, vpt->tmpl_data_length);
1116                 if (ret < 0) return -1;
1117
1118                 /*
1119                  *      Free old value buffers
1120                  */
1121                 switch (vpt->tmpl_data_type) {
1122                 case PW_TYPE_STRING:
1123                 case PW_TYPE_OCTETS:
1124                         talloc_free(vpt->tmpl_data_value.ptr);
1125                         break;
1126
1127                 default:
1128                         break;
1129                 }
1130
1131                 memcpy(&vpt->tmpl_data_value, &new, sizeof(vpt->tmpl_data_value));
1132                 vpt->tmpl_data_type = type;
1133                 vpt->tmpl_data_length = (size_t) ret;
1134         }
1135                 break;
1136
1137         default:
1138                 rad_assert(0);
1139         }
1140
1141         VERIFY_TMPL(vpt);
1142
1143         return 0;
1144 }
1145
1146 /** Convert #vp_tmpl_t of type #TMPL_TYPE_LITERAL to #TMPL_TYPE_DATA of type #PW_TYPE_STRING
1147  *
1148  * @note Conversion is done in place.
1149  *
1150  * @param[in,out] vpt The template to modify. Must be of type #TMPL_TYPE_LITERAL.
1151  */
1152 void tmpl_cast_in_place_str(vp_tmpl_t *vpt)
1153 {
1154         rad_assert(vpt != NULL);
1155         rad_assert(vpt->type == TMPL_TYPE_LITERAL);
1156
1157         vpt->tmpl_data.vp_strvalue = talloc_typed_strdup(vpt, vpt->name);
1158         rad_assert(vpt->tmpl_data.vp_strvalue != NULL);
1159
1160         vpt->type = TMPL_TYPE_DATA;
1161         vpt->tmpl_data_type = PW_TYPE_STRING;
1162         vpt->tmpl_data_length = talloc_array_length(vpt->tmpl_data.vp_strvalue) - 1;
1163 }
1164
1165 /** Expand a #vp_tmpl_t to a string, parse it as an attribute of type cast, create a #VALUE_PAIR from the result
1166  *
1167  * @note Like #tmpl_expand, but produces a #VALUE_PAIR.
1168  *
1169  * @param out Where to write pointer to the new #VALUE_PAIR.
1170  * @param request The current #REQUEST.
1171  * @param vpt to cast. Must be one of the following types:
1172  *      - #TMPL_TYPE_LITERAL
1173  *      - #TMPL_TYPE_EXEC
1174  *      - #TMPL_TYPE_XLAT
1175  *      - #TMPL_TYPE_XLAT_STRUCT
1176  *      - #TMPL_TYPE_ATTR
1177  *      - #TMPL_TYPE_DATA
1178  * @param cast type of #VALUE_PAIR to create.
1179  * @return 0 on success, -1 on failure.
1180  */
1181 int tmpl_cast_to_vp(VALUE_PAIR **out, REQUEST *request,
1182                     vp_tmpl_t const *vpt, DICT_ATTR const *cast)
1183 {
1184         int rcode;
1185         VALUE_PAIR *vp;
1186         value_data_t data;
1187         char *p;
1188
1189         VERIFY_TMPL(vpt);
1190
1191         *out = NULL;
1192
1193         vp = fr_pair_afrom_da(request, cast);
1194         if (!vp) return -1;
1195
1196         if (vpt->type == TMPL_TYPE_DATA) {
1197                 VERIFY_VP(vp);
1198                 rad_assert(vp->da->type == vpt->tmpl_data_type);
1199
1200                 value_data_copy(vp, &vp->data, vpt->tmpl_data_type, &vpt->tmpl_data_value, vpt->tmpl_data_length);
1201                 *out = vp;
1202                 return 0;
1203         }
1204
1205         rcode = tmpl_aexpand(vp, &p, request, vpt, NULL, NULL);
1206         if (rcode < 0) {
1207                 fr_pair_list_free(&vp);
1208                 return rcode;
1209         }
1210         data.strvalue = p;
1211
1212         /*
1213          *      New escapes: strings are in binary form.
1214          */
1215         if (cf_new_escape && (vp->da->type == PW_TYPE_STRING)) {
1216                 vp->data.ptr = talloc_steal(vp, data.ptr);
1217                 vp->vp_length = rcode;
1218
1219         } else if (fr_pair_value_from_str(vp, data.strvalue, rcode) < 0) {
1220                 talloc_free(data.ptr);
1221                 fr_pair_list_free(&vp);
1222                 return -1;
1223         }
1224
1225         *out = vp;
1226         return 0;
1227 }
1228
1229 /** Add an unknown #DICT_ATTR specified by a #vp_tmpl_t to the main dictionary
1230  *
1231  * @param vpt to add. ``tmpl_da`` pointer will be updated to point to the
1232  *      #DICT_ATTR inserted into the dictionary.
1233  * @return 0 on success, -1 on failure.
1234  */
1235 int tmpl_define_unknown_attr(vp_tmpl_t *vpt)
1236 {
1237         DICT_ATTR const *da;
1238
1239         if (!vpt) return -1;
1240
1241         VERIFY_TMPL(vpt);
1242
1243         if (vpt->type != TMPL_TYPE_ATTR) return 0;
1244
1245         if (!vpt->tmpl_da->flags.is_unknown) return 0;
1246
1247         da = dict_unknown_add(vpt->tmpl_da);
1248         if (!da) return -1;
1249         vpt->tmpl_da = da;
1250         return 0;
1251 }
1252 /* @} **/
1253
1254 /** @name Resolve a #vp_tmpl_t outputting the result in various formats
1255  *
1256  * @{
1257  */
1258
1259 /** Expand a #vp_tmpl_t to a string writing the result to a buffer
1260  *
1261  * The intended use of #tmpl_expand and #tmpl_aexpand is for modules to easily convert a #vp_tmpl_t
1262  * provided by the conf parser, into a usable value.
1263  * The value returned should be raw and undoctored for #PW_TYPE_STRING and #PW_TYPE_OCTETS types,
1264  * and the printable (string) version of the data for all others.
1265  *
1266  * Depending what arguments are passed, either copies the value to buff, or writes a pointer
1267  * to a string buffer to out. This allows the most efficient access to the value resolved by
1268  * the #vp_tmpl_t, avoiding unecessary string copies.
1269  *
1270  * @note This function is used where raw string values are needed, which may mean the string
1271  *      returned may be binary data or contain unprintable chars. #fr_prints or #fr_aprints should
1272  *      be used before using these values in debug statements. #is_printable can be used to check
1273  *      if the string only contains printable chars.
1274  *
1275  * @param out Where to write a pointer to the string buffer. On return may point to buff if
1276  *      buff was used to store the value. Otherwise will point to a #value_data_t buffer,
1277  *      or the name of the template. To force copying to buff, out should be NULL.
1278  * @param buff Expansion buffer, may be NULL if out is not NULL, and processing #TMPL_TYPE_LITERAL
1279  *      or string types.
1280  * @param bufflen Length of expansion buffer.
1281  * @param request Current request.
1282  * @param vpt to expand. Must be one of the following types:
1283  *      - #TMPL_TYPE_LITERAL
1284  *      - #TMPL_TYPE_EXEC
1285  *      - #TMPL_TYPE_XLAT
1286  *      - #TMPL_TYPE_XLAT_STRUCT
1287  *      - #TMPL_TYPE_ATTR
1288  *      - #TMPL_TYPE_DATA
1289  * @param escape xlat escape function (only used for xlat types).
1290  * @param escape_ctx xlat escape function data.
1291  * @return -1 on error, else the length of data written to buff, or pointed to by out.
1292  */
1293 ssize_t tmpl_expand(char const **out, char *buff, size_t bufflen, REQUEST *request,
1294                     vp_tmpl_t const *vpt, xlat_escape_t escape, void *escape_ctx)
1295 {
1296         VALUE_PAIR *vp;
1297         ssize_t slen = -1;      /* quiet compiler */
1298
1299         VERIFY_TMPL(vpt);
1300
1301         rad_assert(vpt->type != TMPL_TYPE_LIST);
1302
1303         if (out) *out = NULL;
1304
1305         switch (vpt->type) {
1306         case TMPL_TYPE_LITERAL:
1307                 RDEBUG4("EXPAND TMPL LITERAL");
1308
1309                 if (!out) {
1310                         rad_assert(buff);
1311                         memcpy(buff, vpt->name, vpt->len >= bufflen ? bufflen : vpt->len + 1);
1312                 } else {
1313                         *out = vpt->name;
1314                 }
1315                 return vpt->len;
1316
1317         case TMPL_TYPE_EXEC:
1318         {
1319                 RDEBUG4("EXPAND TMPL EXEC");
1320                 rad_assert(buff);
1321                 if (radius_exec_program(request, buff, bufflen, NULL, request, vpt->name, NULL,
1322                                         true, false, EXEC_TIMEOUT) != 0) {
1323                         return -1;
1324                 }
1325                 slen = strlen(buff);
1326                 if (out) *out = buff;
1327         }
1328                 break;
1329
1330         case TMPL_TYPE_XLAT:
1331                 RDEBUG4("EXPAND TMPL XLAT");
1332                 rad_assert(buff);
1333                 /* Error in expansion, this is distinct from zero length expansion */
1334                 slen = radius_xlat(buff, bufflen, request, vpt->name, escape, escape_ctx);
1335                 if (slen < 0) return slen;
1336                 if (out) *out = buff;
1337                 break;
1338
1339         case TMPL_TYPE_XLAT_STRUCT:
1340                 RDEBUG4("EXPAND TMPL XLAT STRUCT");
1341                 rad_assert(buff);
1342                 /* Error in expansion, this is distinct from zero length expansion */
1343                 slen = radius_xlat_struct(buff, bufflen, request, vpt->tmpl_xlat, escape, escape_ctx);
1344                 if (slen < 0) {
1345                         return slen;
1346                 }
1347                 slen = strlen(buff);
1348                 if (out) *out = buff;
1349                 break;
1350
1351         case TMPL_TYPE_ATTR:
1352         {
1353                 int ret;
1354
1355                 RDEBUG4("EXPAND TMPL ATTR");
1356                 rad_assert(buff);
1357                 ret = tmpl_find_vp(&vp, request, vpt);
1358                 if (ret < 0) return -2;
1359
1360                 if (out && ((vp->da->type == PW_TYPE_STRING) || (vp->da->type == PW_TYPE_OCTETS))) {
1361                         *out = vp->data.ptr;
1362                         slen = vp->vp_length;
1363                 } else {
1364                         if (out) *out = buff;
1365                         slen = vp_prints_value(buff, bufflen, vp, '\0');
1366                 }
1367         }
1368                 break;
1369
1370         case TMPL_TYPE_DATA:
1371         {
1372                 RDEBUG4("EXPAND TMPL DATA");
1373
1374                 if (out && ((vpt->tmpl_data_type == PW_TYPE_STRING) || (vpt->tmpl_data_type == PW_TYPE_OCTETS))) {
1375                         *out = vpt->tmpl_data_value.ptr;
1376                         slen = vpt->tmpl_data_length;
1377                 } else {
1378                         if (out) *out = buff;
1379                         /**
1380                          *  @todo tmpl_expand should accept an enumv da from the lhs of the map.
1381                          */
1382                         slen = value_data_prints(buff, bufflen, vpt->tmpl_data_type, NULL, &vpt->tmpl_data_value, vpt->tmpl_data_length, '\0');
1383                 }
1384         }
1385                 break;
1386
1387         /*
1388          *      We should never be expanding these.
1389          */
1390         case TMPL_TYPE_UNKNOWN:
1391         case TMPL_TYPE_NULL:
1392         case TMPL_TYPE_LIST:
1393         case TMPL_TYPE_REGEX:
1394         case TMPL_TYPE_ATTR_UNDEFINED:
1395         case TMPL_TYPE_REGEX_STRUCT:
1396                 rad_assert(0 == 1);
1397                 slen = -1;
1398                 break;
1399         }
1400
1401         if (slen < 0) return slen;
1402
1403
1404 #if 0
1405         /*
1406          *      If we're doing correct escapes, we may have to re-parse the string.
1407          *      If the string is from another expansion, it needs re-parsing.
1408          *      Or, if it's from a "string" attribute, it needs re-parsing.
1409          *      Integers, IP addresses, etc. don't need re-parsing.
1410          */
1411         if (cf_new_escape && (vpt->type != TMPL_TYPE_ATTR)) {
1412                 value_data_t    vd;
1413                 int             ret;
1414
1415                 PW_TYPE type = PW_TYPE_STRING;
1416
1417                 slen = value_data_from_str(ctx, &vd, &type, NULL, *out, slen, '"');
1418                 talloc_free(*out);      /* free the old value */
1419                 *out = vd.ptr;
1420         }
1421 #endif
1422
1423         if (vpt->type == TMPL_TYPE_XLAT_STRUCT) {
1424                 RDEBUG2("EXPAND %s", vpt->name); /* xlat_struct doesn't do this */
1425                 RDEBUG2("   --> %s", buff);
1426         }
1427
1428         return slen;
1429 }
1430
1431 /** Expand a template to a string, allocing a new buffer to hold the string
1432  *
1433  * The intended use of #tmpl_expand and #tmpl_aexpand is for modules to easily convert a #vp_tmpl_t
1434  * provided by the conf parser, into a usable value.
1435  * The value returned should be raw and undoctored for #PW_TYPE_STRING and #PW_TYPE_OCTETS types,
1436  * and the printable (string) version of the data for all others.
1437  *
1438  * This function will always duplicate values, whereas #tmpl_expand may return a pointer to an
1439  * existing buffer.
1440  *
1441  * @note This function is used where raw string values are needed, which may mean the string
1442  *      returned may be binary data or contain unprintable chars. #fr_prints or #fr_aprints should
1443  *      be used before using these values in debug statements. #is_printable can be used to check
1444  *      if the string only contains printable chars.
1445  *
1446  * @note The type (char or uint8_t) can be obtained with talloc_get_type, and may be used as a
1447  *      hint as to how to process or print the data.
1448  *
1449  * @param ctx to allocate new buffer in.
1450  * @param out Where to write pointer to the new buffer.
1451  * @param request Current request.
1452  * @param vpt to expand. Must be one of the following types:
1453  *      - #TMPL_TYPE_LITERAL
1454  *      - #TMPL_TYPE_EXEC
1455  *      - #TMPL_TYPE_XLAT
1456  *      - #TMPL_TYPE_XLAT_STRUCT
1457  *      - #TMPL_TYPE_ATTR
1458  *      - #TMPL_TYPE_DATA
1459  * @param escape xlat escape function (only used for xlat types).
1460  * @param escape_ctx xlat escape function data (only used for xlat types).
1461  * @return
1462  *      - -1 on failure.
1463  *      - The length of data written to buff, or pointed to by out.
1464  */
1465 ssize_t tmpl_aexpand(TALLOC_CTX *ctx, char **out, REQUEST *request, vp_tmpl_t const *vpt,
1466                      xlat_escape_t escape, void *escape_ctx)
1467 {
1468         VALUE_PAIR *vp;
1469         ssize_t slen = -1;      /* quiet compiler */
1470
1471         rad_assert(vpt->type != TMPL_TYPE_LIST);
1472
1473         VERIFY_TMPL(vpt);
1474
1475         *out = NULL;
1476
1477         switch (vpt->type) {
1478         case TMPL_TYPE_LITERAL:
1479                 RDEBUG4("EXPAND TMPL LITERAL");
1480                 *out = talloc_bstrndup(ctx, vpt->name, vpt->len);
1481                 return vpt->len;
1482
1483         case TMPL_TYPE_EXEC:
1484         {
1485                 char *buff = NULL;
1486
1487                 RDEBUG4("EXPAND TMPL EXEC");
1488                 buff = talloc_array(ctx, char, 1024);
1489                 if (radius_exec_program(request, buff, 1024, NULL, request, vpt->name, NULL,
1490                                         true, false, EXEC_TIMEOUT) != 0) {
1491                         TALLOC_FREE(buff);
1492                         return -1;
1493                 }
1494                 slen = strlen(buff);
1495                 *out = buff;
1496         }
1497                 break;
1498
1499         case TMPL_TYPE_XLAT:
1500                 RDEBUG4("EXPAND TMPL XLAT");
1501                 /* Error in expansion, this is distinct from zero length expansion */
1502                 slen = radius_axlat(out, request, vpt->name, escape, escape_ctx);
1503                 if (slen < 0) {
1504                         rad_assert(!*out);
1505                         return slen;
1506                 }
1507                 rad_assert(*out);
1508                 slen = strlen(*out);
1509                 break;
1510
1511         case TMPL_TYPE_XLAT_STRUCT:
1512                 RDEBUG4("EXPAND TMPL XLAT STRUCT");
1513                 /* Error in expansion, this is distinct from zero length expansion */
1514                 slen = radius_axlat_struct(out, request, vpt->tmpl_xlat, escape, escape_ctx);
1515                 if (slen < 0) {
1516                         rad_assert(!*out);
1517                         return slen;
1518                 }
1519                 slen = strlen(*out);
1520                 break;
1521
1522         case TMPL_TYPE_ATTR:
1523         {
1524                 int ret;
1525
1526                 RDEBUG4("EXPAND TMPL ATTR");
1527                 ret = tmpl_find_vp(&vp, request, vpt);
1528                 if (ret < 0) return -2;
1529
1530                 switch (vpt->tmpl_da->type) {
1531                 case PW_TYPE_STRING:
1532                         *out = talloc_bstrndup(ctx, vp->vp_strvalue, vp->vp_length);
1533                         if (!*out) return -1;
1534                         slen = vp->vp_length;
1535                         break;
1536
1537                 case PW_TYPE_OCTETS:
1538                         *out = talloc_memdup(ctx, vp->vp_octets, vp->vp_length);
1539                         if (!*out) return -1;
1540                         slen = vp->vp_length;
1541                         break;
1542
1543                 default:
1544                         *out = vp_aprints_value(ctx, vp, '\0');
1545                         if (!*out) return -1;
1546                         slen = talloc_array_length(*out) - 1;
1547                         break;
1548                 }
1549         }
1550                 break;
1551
1552         case TMPL_TYPE_DATA:
1553         {
1554                 RDEBUG4("EXPAND TMPL DATA");
1555
1556                 switch (vpt->tmpl_data_type) {
1557                 case PW_TYPE_STRING:
1558                         *out = talloc_bstrndup(ctx, vpt->tmpl_data_value.strvalue, vpt->tmpl_data_length);
1559                         if (!*out) return -1;
1560                         slen = vpt->tmpl_data_length;
1561                         break;
1562
1563                 case PW_TYPE_OCTETS:
1564                         *out = talloc_memdup(ctx, vpt->tmpl_data_value.octets, vpt->tmpl_data_length);
1565                         if (!*out) return -1;
1566                         slen = vpt->tmpl_data_length;
1567                         break;
1568
1569                 default:
1570                         *out = value_data_aprints(ctx, vpt->tmpl_data_type, NULL, &vpt->tmpl_data_value, vpt->tmpl_data_length, '\0');
1571                         if (!*out) return -1;
1572                         slen = talloc_array_length(*out) - 1;
1573                         break;
1574                 }
1575         }
1576                 break;
1577
1578         /*
1579          *      We should never be expanding these.
1580          */
1581         case TMPL_TYPE_UNKNOWN:
1582         case TMPL_TYPE_NULL:
1583         case TMPL_TYPE_LIST:
1584         case TMPL_TYPE_REGEX:
1585         case TMPL_TYPE_ATTR_UNDEFINED:
1586         case TMPL_TYPE_REGEX_STRUCT:
1587                 rad_assert(0 == 1);
1588                 slen = -1;
1589                 break;
1590         }
1591
1592         if (slen < 0) return slen;
1593
1594         /*
1595          *      If we're doing correct escapes, we may have to re-parse the string.
1596          *      If the string is from another expansion, it needs re-parsing.
1597          *      Or, if it's from a "string" attribute, it needs re-parsing.
1598          *      Integers, IP addresses, etc. don't need re-parsing.
1599          */
1600         if (cf_new_escape && (vpt->type != TMPL_TYPE_ATTR)) {
1601                 value_data_t    vd;
1602
1603                 PW_TYPE type = PW_TYPE_STRING;
1604
1605                 slen = value_data_from_str(ctx, &vd, &type, NULL, *out, slen, '"');
1606                 talloc_free(*out);      /* free the old value */
1607                 *out = vd.ptr;
1608         }
1609
1610         if (vpt->type == TMPL_TYPE_XLAT_STRUCT) {
1611                 RDEBUG2("EXPAND %s", vpt->name); /* xlat_struct doesn't do this */
1612                 RDEBUG2("   --> %s", *out);
1613         }
1614
1615         return slen;
1616 }
1617
1618 /** Print a #vp_tmpl_t to a string
1619  *
1620  * @param[out] out Where to write the presentation format #vp_tmpl_t string.
1621  * @param[in] outlen Size of output buffer.
1622  * @param[in] vpt to print
1623  * @param[in] values Used for integer attributes only. #DICT_ATTR to use when mapping integer
1624  *      values to strings.
1625  * @return the size of the string written to the output buffer.
1626  */
1627 size_t tmpl_prints(char *out, size_t outlen, vp_tmpl_t const *vpt, DICT_ATTR const *values)
1628 {
1629         size_t len;
1630         char c;
1631         char const *p;
1632         char *q = out;
1633
1634         if (!vpt) {
1635                 *out = '\0';
1636                 return 0;
1637         }
1638
1639         VERIFY_TMPL(vpt);
1640
1641         switch (vpt->type) {
1642         default:
1643                 return 0;
1644
1645         case TMPL_TYPE_REGEX:
1646         case TMPL_TYPE_REGEX_STRUCT:
1647                 c = '/';
1648                 break;
1649
1650         case TMPL_TYPE_XLAT:
1651         case TMPL_TYPE_XLAT_STRUCT:
1652                 c = '"';
1653                 break;
1654         case TMPL_TYPE_LITERAL: /* single-quoted or bare word */
1655                 /*
1656                  *      Hack
1657                  */
1658                 for (p = vpt->name; *p != '\0'; p++) {
1659                         if (*p == ' ') break;
1660                         if (*p == '\'') break;
1661                         if (!dict_attr_allowed_chars[(int) *p]) break;
1662                 }
1663
1664                 if (!*p) {
1665                         strlcpy(out, vpt->name, outlen);
1666                         return strlen(out);
1667                 }
1668
1669                 c = vpt->quote;
1670                 break;
1671
1672         case TMPL_TYPE_EXEC:
1673                 c = '`';
1674                 break;
1675
1676         case TMPL_TYPE_LIST:
1677                 out[0] = '&';
1678                 if (vpt->tmpl_request == REQUEST_CURRENT) {
1679                         snprintf(out + 1, outlen - 1, "%s",
1680                                  fr_int2str(pair_lists, vpt->tmpl_list, ""));
1681                 } else {
1682                         snprintf(out + 1, outlen - 1, "%s.%s",
1683                                  fr_int2str(request_refs, vpt->tmpl_request, ""),
1684                                  fr_int2str(pair_lists, vpt->tmpl_list, ""));
1685                 }
1686                 len = strlen(out);
1687                 goto attr_inst_tag;
1688
1689         case TMPL_TYPE_ATTR:
1690                 out[0] = '&';
1691                 if (vpt->tmpl_request == REQUEST_CURRENT) {
1692                         if (vpt->tmpl_list == PAIR_LIST_REQUEST) {
1693                                 strlcpy(out + 1, vpt->tmpl_da->name, outlen - 1);
1694                         } else {
1695                                 snprintf(out + 1, outlen - 1, "%s:%s",
1696                                          fr_int2str(pair_lists, vpt->tmpl_list, ""),
1697                                          vpt->tmpl_da->name);
1698                         }
1699
1700                 } else {
1701                         snprintf(out + 1, outlen - 1, "%s.%s:%s",
1702                                  fr_int2str(request_refs, vpt->tmpl_request, ""),
1703                                  fr_int2str(pair_lists, vpt->tmpl_list, ""),
1704                                  vpt->tmpl_da->name);
1705                 }
1706
1707                 len = strlen(out);
1708
1709         attr_inst_tag:
1710                 if ((vpt->tmpl_tag == TAG_ANY) && (vpt->tmpl_num == NUM_ANY)) return len;
1711
1712                 q = out + len;
1713                 outlen -= len;
1714
1715                 if (vpt->tmpl_tag != TAG_ANY) {
1716                         snprintf(q, outlen, ":%d", vpt->tmpl_tag);
1717                         len = strlen(q);
1718                         q += len;
1719                         outlen -= len;
1720                 }
1721
1722                 switch (vpt->tmpl_num) {
1723                 case NUM_ANY:
1724                         break;
1725
1726                 case NUM_ALL:
1727                         snprintf(q, outlen, "[*]");
1728                         len = strlen(q);
1729                         q += len;
1730                         break;
1731
1732                 case NUM_COUNT:
1733                         snprintf(q, outlen, "[#]");
1734                         len = strlen(q);
1735                         q += len;
1736                         break;
1737
1738                 case NUM_LAST:
1739                         snprintf(q, outlen, "[n]");
1740                         len = strlen(q);
1741                         q += len;
1742                         break;
1743
1744                 default:
1745                         snprintf(q, outlen, "[%i]", vpt->tmpl_num);
1746                         len = strlen(q);
1747                         q += len;
1748                         break;
1749                 }
1750
1751                 return (q - out);
1752
1753         case TMPL_TYPE_ATTR_UNDEFINED:
1754                 out[0] = '&';
1755                 if (vpt->tmpl_request == REQUEST_CURRENT) {
1756                         if (vpt->tmpl_list == PAIR_LIST_REQUEST) {
1757                                 strlcpy(out + 1, vpt->tmpl_unknown_name, outlen - 1);
1758                         } else {
1759                                 snprintf(out + 1, outlen - 1, "%s:%s",
1760                                          fr_int2str(pair_lists, vpt->tmpl_list, ""),
1761                                          vpt->tmpl_unknown_name);
1762                         }
1763
1764                 } else {
1765                         snprintf(out + 1, outlen - 1, "%s.%s:%s",
1766                                  fr_int2str(request_refs, vpt->tmpl_request, ""),
1767                                  fr_int2str(pair_lists, vpt->tmpl_list, ""),
1768                                  vpt->tmpl_unknown_name);
1769                 }
1770
1771                 len = strlen(out);
1772
1773                 if (vpt->tmpl_num == NUM_ANY) {
1774                         return len;
1775                 }
1776
1777                 q = out + len;
1778                 outlen -= len;
1779
1780                 if (vpt->tmpl_num != NUM_ANY) {
1781                         snprintf(q, outlen, "[%i]", vpt->tmpl_num);
1782                         len = strlen(q);
1783                         q += len;
1784                 }
1785
1786                 return (q - out);
1787
1788         case TMPL_TYPE_DATA:
1789                 return value_data_prints(out, outlen, vpt->tmpl_data_type, values, &vpt->tmpl_data_value,
1790                                          vpt->tmpl_data_length, vpt->quote);
1791         }
1792
1793         if (outlen <= 3) {
1794                 *out = '\0';
1795                 return 0;
1796         }
1797
1798         *(q++) = c;
1799
1800         /*
1801          *      Print it with appropriate escaping
1802          */
1803         if (cf_new_escape && (c == '/')) {
1804                 len = fr_prints(q, outlen - 3, vpt->name, vpt->len, '\0');
1805         } else {
1806                 len = fr_prints(q, outlen - 3, vpt->name, vpt->len, c);
1807         }
1808
1809         q += len;
1810         *(q++) = c;
1811         *q = '\0';
1812
1813         return q - out;
1814 }
1815
1816 /** Initialise a #vp_cursor_t to the #VALUE_PAIR specified by a #vp_tmpl_t
1817  *
1818  * This makes iterating over the one or more #VALUE_PAIR specified by a #vp_tmpl_t
1819  * significantly easier.
1820  *
1821  * @param err May be NULL if no error code is required. Will be set to:
1822  *      - 0 on success.
1823  *      - -1 if no matching #VALUE_PAIR could be found.
1824  *      - -2 if list could not be found (doesn't exist in current #REQUEST).
1825  *      - -3 if context could not be found (no parent #REQUEST available).
1826  * @param cursor to store iterator state.
1827  * @param request The current #REQUEST.
1828  * @param vpt specifying the #VALUE_PAIR type/tag or list to iterate over.
1829  * @return the first #VALUE_PAIR specified by the #vp_tmpl_t, or NULL if no matching
1830  *      #VALUE_PAIR found, and NULL on error.
1831  *
1832  * @see tmpl_cursor_next
1833  */
1834 VALUE_PAIR *tmpl_cursor_init(int *err, vp_cursor_t *cursor, REQUEST *request, vp_tmpl_t const *vpt)
1835 {
1836         VALUE_PAIR **vps, *vp = NULL;
1837         int num;
1838
1839         VERIFY_TMPL(vpt);
1840
1841         rad_assert((vpt->type == TMPL_TYPE_ATTR) || (vpt->type == TMPL_TYPE_LIST));
1842
1843         if (err) *err = 0;
1844
1845         if (radius_request(&request, vpt->tmpl_request) < 0) {
1846                 if (err) *err = -3;
1847                 return NULL;
1848         }
1849         vps = radius_list(request, vpt->tmpl_list);
1850         if (!vps) {
1851                 if (err) *err = -2;
1852                 return NULL;
1853         }
1854         (void) fr_cursor_init(cursor, vps);
1855
1856         switch (vpt->type) {
1857         /*
1858          *      May not may not be found, but it *is* a known name.
1859          */
1860         case TMPL_TYPE_ATTR:
1861                 switch (vpt->tmpl_num) {
1862                 case NUM_ANY:
1863                         vp = fr_cursor_next_by_da(cursor, vpt->tmpl_da, vpt->tmpl_tag);
1864                         if (!vp) {
1865                                 if (err) *err = -1;
1866                                 return NULL;
1867                         }
1868                         VERIFY_VP(vp);
1869                         return vp;
1870
1871                 /*
1872                  *      Get the last instance of a VALUE_PAIR.
1873                  */
1874                 case NUM_LAST:
1875                 {
1876                         VALUE_PAIR *last = NULL;
1877
1878                         while ((vp = fr_cursor_next_by_da(cursor, vpt->tmpl_da, vpt->tmpl_tag))) {
1879                                 VERIFY_VP(vp);
1880                                 last = vp;
1881                         }
1882                         VERIFY_VP(last);
1883                         if (!last) break;
1884                         return last;
1885                 }
1886
1887                 /*
1888                  *      Callers expect NUM_COUNT to setup the cursor to point
1889                  *      to the first attribute in the list we're meant to be
1890                  *      counting.
1891                  *
1892                  *      It does not produce a virtual attribute containing the
1893                  *      total number of attributes.
1894                  */
1895                 case NUM_COUNT:
1896                         return fr_cursor_next_by_da(cursor, vpt->tmpl_da, vpt->tmpl_tag);
1897
1898                 default:
1899                         num = vpt->tmpl_num;
1900                         while ((vp = fr_cursor_next_by_da(cursor, vpt->tmpl_da, vpt->tmpl_tag))) {
1901                                 VERIFY_VP(vp);
1902                                 if (num-- <= 0) return vp;
1903                         }
1904                         break;
1905                 }
1906
1907                 if (err) *err = -1;
1908                 return NULL;
1909
1910         case TMPL_TYPE_LIST:
1911                 switch (vpt->tmpl_num) {
1912                 case NUM_COUNT:
1913                 case NUM_ANY:
1914                 case NUM_ALL:
1915                         vp = fr_cursor_init(cursor, vps);
1916                         if (!vp) {
1917                                 if (err) *err = -1;
1918                                 return NULL;
1919                         }
1920                         VERIFY_VP(vp);
1921                         return vp;
1922
1923                 /*
1924                  *      Get the last instance of a VALUE_PAIR.
1925                  */
1926                 case NUM_LAST:
1927                 {
1928                         VALUE_PAIR *last = NULL;
1929
1930                         for (vp = fr_cursor_init(cursor, vps);
1931                              vp;
1932                              vp = fr_cursor_next(cursor)) {
1933                                 VERIFY_VP(vp);
1934                                 last = vp;
1935                         }
1936                         if (!last) break;
1937                         VERIFY_VP(last);
1938                         return last;
1939                 }
1940
1941                 default:
1942                         num = vpt->tmpl_num;
1943                         for (vp = fr_cursor_init(cursor, vps);
1944                              vp;
1945                              vp = fr_cursor_next(cursor)) {
1946                                 VERIFY_VP(vp);
1947                                 if (num-- <= 0) return vp;
1948                         }
1949                         break;
1950                 }
1951
1952                 break;
1953
1954         default:
1955                 rad_assert(0);
1956         }
1957
1958         return vp;
1959 }
1960
1961 /** Returns the next #VALUE_PAIR specified by vpt
1962  *
1963  * @param cursor initialised with #tmpl_cursor_init.
1964  * @param vpt specifying the #VALUE_PAIR type/tag to iterate over.
1965  *      Must be one of the following types:
1966  *      - #TMPL_TYPE_LIST
1967  *      - #TMPL_TYPE_ATTR
1968  * @return NULL if no more matching #VALUE_PAIR of the specified type/tag are found.
1969  */
1970 VALUE_PAIR *tmpl_cursor_next(vp_cursor_t *cursor, vp_tmpl_t const *vpt)
1971 {
1972         rad_assert((vpt->type == TMPL_TYPE_ATTR) || (vpt->type == TMPL_TYPE_LIST));
1973
1974         VERIFY_TMPL(vpt);
1975
1976         switch (vpt->type) {
1977         /*
1978          *      May not may not be found, but it *is* a known name.
1979          */
1980         case TMPL_TYPE_ATTR:
1981                 switch (vpt->tmpl_num) {
1982                 default:
1983                         return NULL;
1984
1985                 case NUM_ALL:
1986                 case NUM_COUNT: /* This cursor is being used to count matching attrs */
1987                         break;
1988                 }
1989                 return fr_cursor_next_by_da(cursor, vpt->tmpl_da, vpt->tmpl_tag);
1990
1991         case TMPL_TYPE_LIST:
1992                 switch (vpt->tmpl_num) {
1993                 default:
1994                         return NULL;
1995
1996                 case NUM_ALL:
1997                 case NUM_COUNT: /* This cursor is being used to count matching attrs */
1998                         break;
1999                 }
2000                 return fr_cursor_next(cursor);
2001
2002         default:
2003                 rad_assert(0);
2004                 return NULL;    /* Older versions of GCC flag the lack of return as an error */
2005         }
2006 }
2007
2008 /** Copy pairs matching a #vp_tmpl_t in the current #REQUEST
2009  *
2010  * @param ctx to allocate new #VALUE_PAIR in.
2011  * @param out Where to write the copied #VALUE_PAIR (s).
2012  * @param request The current #REQUEST.
2013  * @param vpt specifying the #VALUE_PAIR type/tag or list to copy.
2014  *      Must be one of the following types:
2015  *      - #TMPL_TYPE_LIST
2016  *      - #TMPL_TYPE_ATTR
2017  * @return
2018  *      - -1 if no matching #VALUE_PAIR could be found.
2019  *      - -2 if list could not be found (doesn't exist in current #REQUEST).
2020  *      - -3 if context could not be found (no parent #REQUEST available).
2021  *      - -4 on memory allocation error.
2022  */
2023 int tmpl_copy_vps(TALLOC_CTX *ctx, VALUE_PAIR **out, REQUEST *request, vp_tmpl_t const *vpt)
2024 {
2025         VALUE_PAIR *vp;
2026         vp_cursor_t from, to;
2027
2028         VERIFY_TMPL(vpt);
2029
2030         int err;
2031
2032         rad_assert((vpt->type == TMPL_TYPE_ATTR) || (vpt->type == TMPL_TYPE_LIST));
2033
2034         *out = NULL;
2035
2036         fr_cursor_init(&to, out);
2037
2038         for (vp = tmpl_cursor_init(&err, &from, request, vpt);
2039              vp;
2040              vp = tmpl_cursor_next(&from, vpt)) {
2041                 vp = fr_pair_copy(ctx, vp);
2042                 if (!vp) {
2043                         fr_pair_list_free(out);
2044                         return -4;
2045                 }
2046                 fr_cursor_insert(&to, vp);
2047         }
2048
2049         return err;
2050 }
2051
2052 /** Returns the first VP matching a #vp_tmpl_t
2053  *
2054  * @param out where to write the retrieved vp.
2055  * @param request The current #REQUEST.
2056  * @param vpt specifying the #VALUE_PAIR type/tag to find.
2057  *      Must be one of the following types:
2058  *      - #TMPL_TYPE_LIST
2059  *      - #TMPL_TYPE_ATTR
2060  * @return
2061  *      - -1 if no matching #VALUE_PAIR could be found.
2062  *      - -2 if list could not be found (doesn't exist in current #REQUEST).
2063  *      - -3 if context could not be found (no parent #REQUEST available).
2064  */
2065 int tmpl_find_vp(VALUE_PAIR **out, REQUEST *request, vp_tmpl_t const *vpt)
2066 {
2067         vp_cursor_t cursor;
2068         VALUE_PAIR *vp;
2069
2070         VERIFY_TMPL(vpt);
2071
2072         int err;
2073
2074         vp = tmpl_cursor_init(&err, &cursor, request, vpt);
2075         if (out) *out = vp;
2076
2077         return err;
2078 }
2079 /* @} **/
2080
2081 #ifdef WITH_VERIFY_PTR
2082 /** Used to check whether areas of a vp_tmpl_t are zeroed out
2083  *
2084  * @param ptr Offset to begin checking at.
2085  * @param len How many bytes to check.
2086  * @return pointer to the first non-zero byte, or NULL if all bytes were zero.
2087  */
2088 static uint8_t const *not_zeroed(uint8_t const *ptr, size_t len)
2089 {
2090         size_t i;
2091
2092         for (i = 0; i < len; i++) {
2093                 if (ptr[i] != 0x00) return ptr + i;
2094         }
2095
2096         return NULL;
2097 }
2098 #define CHECK_ZEROED(_x) not_zeroed((uint8_t const *)&_x + sizeof(_x), sizeof(vpt->data) - sizeof(_x))
2099
2100 /** Verify fields of a vp_tmpl_t make sense
2101  *
2102  * @note If the #vp_tmpl_t is invalid, causes the server to exit.
2103  *
2104  * @param file obtained with __FILE__.
2105  * @param line obtained with __LINE__.
2106  * @param vpt to check.
2107  */
2108 void tmpl_verify(char const *file, int line, vp_tmpl_t const *vpt)
2109 {
2110         rad_assert(vpt);
2111
2112         if (vpt->type == TMPL_TYPE_UNKNOWN) {
2113                 FR_FAULT_LOG("CONSISTENCY CHECK FAILED %s[%u]: vp_tmpl_t type was "
2114                              "TMPL_TYPE_UNKNOWN (uninitialised)", file, line);
2115                 fr_assert(0);
2116                 fr_exit_now(1);
2117         }
2118
2119         if (vpt->type > TMPL_TYPE_NULL) {
2120                 FR_FAULT_LOG("CONSISTENCY CHECK FAILED %s[%u]: vp_tmpl_t type was %i "
2121                              "(outside range of tmpl_names)", file, line, vpt->type);
2122                 fr_assert(0);
2123                 fr_exit_now(1);
2124         }
2125
2126         /*
2127          *  Do a memcmp of the bytes after where the space allocated for
2128          *  the union member should have ended and the end of the union.
2129          *  These should always be zero if the union has been initialised
2130          *  properly.
2131          *
2132          *  If they're still all zero, do TMPL_TYPE specific checks.
2133          */
2134         switch (vpt->type) {
2135         case TMPL_TYPE_NULL:
2136                 if (not_zeroed((uint8_t const *)&vpt->data, sizeof(vpt->data))) {
2137                         FR_FAULT_LOG("CONSISTENCY CHECK FAILED %s[%u]: TMPL_TYPE_NULL "
2138                                      "has non-zero bytes in its data union", file, line);
2139                         fr_assert(0);
2140                         fr_exit_now(1);
2141                 }
2142                 break;
2143
2144         case TMPL_TYPE_LITERAL:
2145                 if (not_zeroed((uint8_t const *)&vpt->data, sizeof(vpt->data))) {
2146                         FR_FAULT_LOG("CONSISTENCY CHECK FAILED %s[%u]: TMPL_TYPE_LITERAL "
2147                                      "has non-zero bytes in its data union", file, line);
2148                         fr_assert(0);
2149                         fr_exit_now(1);
2150                 }
2151                 break;
2152
2153         case TMPL_TYPE_XLAT:
2154         case TMPL_TYPE_XLAT_STRUCT:
2155                 break;
2156
2157 /* @todo When regexes get converted to xlat the flags field of the regex union is used
2158         case TMPL_TYPE_XLAT:
2159                 if (not_zeroed((uint8_t const *)&vpt->data, sizeof(vpt->data))) {
2160                         FR_FAULT_LOG("CONSISTENCY CHECK FAILED %s[%u]: TMPL_TYPE_XLAT "
2161                                      "has non-zero bytes in its data union", file, line);
2162                         fr_assert(0);
2163                         fr_exit_now(1);
2164                 }
2165                 break;
2166
2167         case TMPL_TYPE_XLAT_STRUCT:
2168                 if (CHECK_ZEROED(vpt->data.xlat)) {
2169                         FR_FAULT_LOG("CONSISTENCY CHECK FAILED %s[%u]: TMPL_TYPE_XLAT_STRUCT "
2170                                      "has non-zero bytes after the data.xlat pointer in the union", file, line);
2171                         fr_assert(0);
2172                         fr_exit_now(1);
2173                 }
2174                 break;
2175 */
2176
2177         case TMPL_TYPE_EXEC:
2178                 if (not_zeroed((uint8_t const *)&vpt->data, sizeof(vpt->data))) {
2179                         FR_FAULT_LOG("CONSISTENCY CHECK FAILED %s[%u]: TMPL_TYPE_EXEC "
2180                                      "has non-zero bytes in its data union", file, line);
2181                         fr_assert(0);
2182                         fr_exit_now(1);
2183                 }
2184                 break;
2185
2186         case TMPL_TYPE_ATTR_UNDEFINED:
2187                 rad_assert(vpt->tmpl_da == NULL);
2188                 break;
2189
2190         case TMPL_TYPE_ATTR:
2191                 if (CHECK_ZEROED(vpt->data.attribute)) {
2192                         FR_FAULT_LOG("CONSISTENCY CHECK FAILED %s[%u]: TMPL_TYPE_ATTR "
2193                                      "has non-zero bytes after the data.attribute struct in the union",
2194                                      file, line);
2195                         fr_assert(0);
2196                         fr_exit_now(1);
2197                 }
2198
2199                 if (vpt->tmpl_da->flags.is_unknown) {
2200                         if (vpt->tmpl_da != (DICT_ATTR *)&vpt->data.attribute.unknown.da) {
2201                                 FR_FAULT_LOG("CONSISTENCY CHECK FAILED %s[%u]: TMPL_TYPE_ATTR "
2202                                              "da is marked as unknown, but does not point to the template's "
2203                                              "unknown da buffer", file, line);
2204                                 fr_assert(0);
2205                                 fr_exit_now(1);
2206                         }
2207
2208                 } else {
2209                         DICT_ATTR const *da;
2210
2211                         /*
2212                          *      Attribute may be present with multiple names
2213                          */
2214                         da = dict_attrbyname(vpt->tmpl_da->name);
2215                         if (!da) {
2216                                 FR_FAULT_LOG("CONSISTENCY CHECK FAILED %s[%u]: TMPL_TYPE_ATTR "
2217                                              "attribute \"%s\" (%s) not found in global dictionary",
2218                                              file, line, vpt->tmpl_da->name,
2219                                              fr_int2str(dict_attr_types, vpt->tmpl_da->type, "<INVALID>"));
2220                                 fr_assert(0);
2221                                 fr_exit_now(1);
2222                         }
2223
2224                         if ((da->type == PW_TYPE_COMBO_IP_ADDR) && (da->type != vpt->tmpl_da->type)) {
2225                                 da = dict_attrbytype(vpt->tmpl_da->attr, vpt->tmpl_da->vendor, vpt->tmpl_da->type);
2226                                 if (!da) {
2227                                         FR_FAULT_LOG("CONSISTENCY CHECK FAILED %s[%u]: TMPL_TYPE_ATTR "
2228                                                      "attribute \"%s\" variant (%s) not found in global dictionary",
2229                                                      file, line, vpt->tmpl_da->name,
2230                                                      fr_int2str(dict_attr_types, vpt->tmpl_da->type, "<INVALID>"));
2231                                         fr_assert(0);
2232                                         fr_exit_now(1);
2233                                 }
2234                         }
2235
2236                         if (da != vpt->tmpl_da) {
2237                                 FR_FAULT_LOG("CONSISTENCY CHECK FAILED %s[%u]: TMPL_TYPE_ATTR "
2238                                              "dictionary pointer %p \"%s\" (%s) "
2239                                              "and global dictionary pointer %p \"%s\" (%s) differ",
2240                                              file, line,
2241                                              vpt->tmpl_da, vpt->tmpl_da->name,
2242                                              fr_int2str(dict_attr_types, vpt->tmpl_da->type, "<INVALID>"),
2243                                              da, da->name,
2244                                              fr_int2str(dict_attr_types, da->type, "<INVALID>"));
2245                                 fr_assert(0);
2246                                 fr_exit_now(1);
2247                         }
2248                 }
2249                 break;
2250
2251         case TMPL_TYPE_LIST:
2252                 if (CHECK_ZEROED(vpt->data.attribute)) {
2253                         FR_FAULT_LOG("CONSISTENCY CHECK FAILED %s[%u]: TMPL_TYPE_LIST"
2254                                      "has non-zero bytes after the data.attribute struct in the union", file, line);
2255                         fr_assert(0);
2256                         fr_exit_now(1);
2257                 }
2258
2259                 if (vpt->tmpl_da != NULL) {
2260                         FR_FAULT_LOG("CONSISTENCY CHECK FAILED %s[%u]: TMPL_TYPE_LIST da pointer was NULL", file, line);
2261                         fr_assert(0);
2262                         fr_exit_now(1);
2263                 }
2264                 break;
2265
2266         case TMPL_TYPE_DATA:
2267                 if (CHECK_ZEROED(vpt->data.literal)) {
2268                         FR_FAULT_LOG("CONSISTENCY CHECK FAILED %s[%u]: TMPL_TYPE_DATA "
2269                                      "has non-zero bytes after the data.literal struct in the union",
2270                                      file, line);
2271                         fr_assert(0);
2272                         fr_exit_now(1);
2273                 }
2274
2275                 if (vpt->tmpl_data_type == PW_TYPE_INVALID) {
2276                         FR_FAULT_LOG("CONSISTENCY CHECK FAILED %s[%u]: TMPL_TYPE_DATA type was "
2277                                      "PW_TYPE_INVALID (uninitialised)", file, line);
2278                         fr_assert(0);
2279                         fr_exit_now(1);
2280                 }
2281
2282                 if (vpt->tmpl_data_type >= PW_TYPE_MAX) {
2283                         FR_FAULT_LOG("CONSISTENCY CHECK FAILED %s[%u]: TMPL_TYPE_DATA type was "
2284                                      "%i (outside the range of PW_TYPEs)", file, line, vpt->tmpl_data_type);
2285                         fr_assert(0);
2286                         fr_exit_now(1);
2287                 }
2288                 /*
2289                  *      Unlike VALUE_PAIRs we can't guarantee that VALUE_PAIR_TMPL buffers will
2290                  *      be talloced. They may be allocated on the stack or in global variables.
2291                  */
2292                 switch (vpt->tmpl_data_type) {
2293                 case PW_TYPE_STRING:
2294                 if (vpt->tmpl_data.vp_strvalue[vpt->tmpl_data_length] != '\0') {
2295                         FR_FAULT_LOG("CONSISTENCY CHECK FAILED %s[%u]: TMPL_TYPE_DATA char buffer not \\0 "
2296                                      "terminated", file, line);
2297                         fr_assert(0);
2298                         fr_exit_now(1);
2299                 }
2300                         break;
2301
2302                 case PW_TYPE_TLV:
2303                         FR_FAULT_LOG("CONSISTENCY CHECK FAILED %s[%u]: TMPL_TYPE_DATA is of type TLV",
2304                                      file, line);
2305                         fr_assert(0);
2306                         fr_exit_now(1);
2307
2308                 case PW_TYPE_OCTETS:
2309                         break;
2310
2311                 default:
2312                         if (vpt->tmpl_data_length == 0) {
2313                                 FR_FAULT_LOG("CONSISTENCY CHECK FAILED %s[%u]: TMPL_TYPE_DATA data pointer not NULL "
2314                                              "but len field is zero", file, line);
2315                                 fr_assert(0);
2316                                 fr_exit_now(1);
2317                         }
2318                 }
2319
2320                 break;
2321
2322         case TMPL_TYPE_REGEX:
2323                 /*
2324                  *      iflag field is used for non compiled regexes too.
2325                  */
2326                 if (CHECK_ZEROED(vpt->data.preg)) {
2327                         FR_FAULT_LOG("CONSISTENCY CHECK FAILED %s[%u]: TMPL_TYPE_REGEX "
2328                                      "has non-zero bytes after the data.preg struct in the union", file, line);
2329                         fr_assert(0);
2330                         fr_exit_now(1);
2331                 }
2332
2333                 if (vpt->tmpl_preg != NULL) {
2334                         FR_FAULT_LOG("CONSISTENCY CHECK FAILED %s[%u]: TMPL_TYPE_REGEX "
2335                                      "preg field was not nULL", file, line);
2336                         fr_assert(0);
2337                         fr_exit_now(1);
2338                 }
2339
2340                 if ((vpt->tmpl_iflag != true) && (vpt->tmpl_iflag != false)) {
2341                         FR_FAULT_LOG("CONSISTENCY CHECK FAILED %s[%u]: TMPL_TYPE_REGEX "
2342                                      "iflag field was neither true or false", file, line);
2343                         fr_assert(0);
2344                         fr_exit_now(1);
2345                 }
2346
2347                 if ((vpt->tmpl_mflag != true) && (vpt->tmpl_mflag != false)) {
2348                         FR_FAULT_LOG("CONSISTENCY CHECK FAILED %s[%u]: TMPL_TYPE_REGEX "
2349                                      "mflag field was neither true or false", file, line);
2350                         fr_assert(0);
2351                         fr_exit_now(1);
2352                 }
2353
2354                 break;
2355
2356         case TMPL_TYPE_REGEX_STRUCT:
2357                 if (CHECK_ZEROED(vpt->data.preg)) {
2358                         FR_FAULT_LOG("CONSISTENCY CHECK FAILED %s[%u]: TMPL_TYPE_REGEX_STRUCT "
2359                                      "has non-zero bytes after the data.preg struct in the union", file, line);
2360                         fr_assert(0);
2361                         fr_exit_now(1);
2362                 }
2363
2364                 if (vpt->tmpl_preg == NULL) {
2365                         FR_FAULT_LOG("CONSISTENCY CHECK FAILED %s[%u]: TMPL_TYPE_REGEX_STRUCT "
2366                                      "comp field was NULL", file, line);
2367                         fr_assert(0);
2368                         fr_exit_now(1);
2369                 }
2370
2371                 if ((vpt->tmpl_iflag != true) && (vpt->tmpl_iflag != false)) {
2372                         FR_FAULT_LOG("CONSISTENCY CHECK FAILED %s[%u]: TMPL_TYPE_REGEX_STRUCT "
2373                                      "iflag field was neither true or false", file, line);
2374                         fr_assert(0);
2375                         fr_exit_now(1);
2376                 }
2377
2378                 if ((vpt->tmpl_mflag != true) && (vpt->tmpl_mflag != false)) {
2379                         FR_FAULT_LOG("CONSISTENCY CHECK FAILED %s[%u]: TMPL_TYPE_REGEX "
2380                                      "mflag field was neither true or false", file, line);
2381                         fr_assert(0);
2382                         fr_exit_now(1);
2383                 }
2384                 break;
2385
2386         case TMPL_TYPE_UNKNOWN:
2387                 rad_assert(0);
2388         }
2389 }
2390 #endif