The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
rlm_dict.c
Go to the documentation of this file.
1 /*
2  * This program is 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 (at
5  * 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: f95cedb1e85d180651987a4ffa161e87b4b2de04 $
19  * @file rlm_dict.c
20  * @brief Retrieve attributes from a dict.
21  *
22  * @copyright 2016 Arran Cudbard-Bell (a.cudbardb@freeradius.org)
23  */
24 RCSID("$Id: f95cedb1e85d180651987a4ffa161e87b4b2de04 $")
25 
26 #include <freeradius-devel/server/base.h>
27 #include <freeradius-devel/server/module_rlm.h>
28 #include <freeradius-devel/server/log.h>
29 #include <freeradius-devel/util/debug.h>
30 #include <freeradius-devel/util/sbuff.h>
31 #include <freeradius-devel/util/value.h>
32 #include <freeradius-devel/unlang/xlat.h>
33 #include <freeradius-devel/unlang/xlat_func.h>
34 
35 /** Return a VP from the specified request.
36  *
37  * @param out where to write the pointer to the resolved VP. Will be NULL if the attribute couldn't
38  * be resolved.
39  * @param request current request.
40  * @param name attribute name including qualifiers.
41  * @return
42  * - -4 if either the attribute or qualifier were invalid.
43  * - The same error codes as #tmpl_find_vp for other error conditions.
44  */
45 static int xlat_fmt_get_vp(fr_pair_t **out, request_t *request, char const *name)
46 {
47  int ret;
48  tmpl_t *vpt;
49 
50  *out = NULL;
51 
52  if (tmpl_afrom_attr_str(request, NULL, &vpt, name,
53  &(tmpl_rules_t){
54  .attr = {
55  .dict_def = request->dict,
56  .list_def = request_attr_request,
58  }
59  }) <= 0) return -4;
60 
61  ret = tmpl_find_vp(out, request, vpt);
63 
64  return ret;
65 }
66 
67 
69  { .required = true, .single = true, .type = FR_TYPE_UINT32 },
71 };
72 
73 /** Xlat for %attr_by_num(<number>)
74  *
75  * @ingroup xlat_functions
76  */
78  UNUSED xlat_ctx_t const *xctx,
79  request_t *request, fr_value_box_list_t *in)
80 {
81  fr_dict_attr_t const *da;
82  fr_value_box_t *attr = fr_value_box_list_head(in);
83  fr_value_box_t *vb;
84 
85  da = fr_dict_attr_child_by_num(fr_dict_root(request->dict), attr->vb_uint32);
86  if (!da) {
87  REDEBUG("No attribute found with number %pV", attr);
88  return XLAT_ACTION_FAIL;
89  }
90 
91  MEM(vb = fr_value_box_alloc_null(ctx));
92 
93  if (fr_value_box_bstrndup(vb, vb, NULL, da->name, strlen(da->name), false) < 0) {
94  talloc_free(vb);
95  return XLAT_ACTION_FAIL;
96  }
97 
99  return XLAT_ACTION_DONE;
100 }
101 
103  { .required = true, .single = true, .type = FR_TYPE_STRING },
105 };
106 
107 /** Xlat for %attr_by_oid(<oid>)
108  *
109  * @ingroup xlat_functions
110  */
112  UNUSED xlat_ctx_t const *xctx,
113  request_t *request, fr_value_box_list_t *in)
114 {
115  unsigned int attr = 0;
116  fr_dict_attr_t const *parent = fr_dict_root(request->dict);
117  fr_dict_attr_t const *da;
118  ssize_t ret;
119  fr_value_box_t *attr_vb = fr_value_box_list_head(in);
120  fr_value_box_t *vb;
121 
122  ret = fr_dict_attr_by_oid_legacy(fr_dict_internal(), &parent, &attr, attr_vb->vb_strvalue);
123  if (ret <= 0) {
124  REMARKER(attr_vb->vb_strvalue, -(ret), "%s", fr_strerror());
125  return XLAT_ACTION_FAIL;
126  }
127 
128  MEM(da = fr_dict_attr_child_by_num(parent, attr));
129 
130  MEM(vb = fr_value_box_alloc_null(ctx));
131 
132  if (fr_value_box_bstrndup(vb, vb, NULL, da->name, strlen(da->name), false) < 0) {
133  talloc_free(vb);
134  return XLAT_ACTION_FAIL;
135  }
136 
137  fr_dcursor_append(out, vb);
138  return XLAT_ACTION_DONE;
139 }
140 
142  { .required = true, .single = true, .type = FR_TYPE_STRING },
144 };
145 
146 /** Return the vendor of an attribute reference
147  *
148  * @ingroup xlat_functions
149  */
150 static xlat_action_t xlat_vendor(TALLOC_CTX *ctx, fr_dcursor_t *out,
151  UNUSED xlat_ctx_t const *xctx,
152  request_t *request, fr_value_box_list_t *in)
153 {
154  fr_pair_t *vp;
155  fr_dict_vendor_t const *vendor;
156  fr_value_box_t *attr = fr_value_box_list_head(in);
157  fr_value_box_t *vb;
158 
159  if ((xlat_fmt_get_vp(&vp, request, attr->vb_strvalue) < 0) || !vp) return XLAT_ACTION_FAIL;
160 
161  vendor = fr_dict_vendor_by_da(vp->da);
162  if (!vendor) return XLAT_ACTION_FAIL;
163 
164  MEM(vb = fr_value_box_alloc_null(ctx));
165 
166  if (fr_value_box_bstrndup(vb, vb, NULL, vendor->name, strlen(vendor->name), false) < 0) {
167  talloc_free(vb);
168  return XLAT_ACTION_FAIL;
169  }
170 
171  fr_dcursor_append(out, vb);
172  return XLAT_ACTION_DONE;
173 }
174 
176  { .required = true, .single = true, .type = FR_TYPE_STRING },
178 };
179 
180 /** Return the vendor number of an attribute reference
181  *
182  * @ingroup xlat_functions
183  */
185  UNUSED xlat_ctx_t const *xctx,
186  request_t *request, fr_value_box_list_t *in)
187 {
188  fr_pair_t *vp;
189  fr_value_box_t *attr = fr_value_box_list_head(in);
190  fr_value_box_t *vb;
191 
192  if ((xlat_fmt_get_vp(&vp, request, attr->vb_strvalue) < 0) || !vp) return XLAT_ACTION_FAIL;
193 
194  MEM(vb = fr_value_box_alloc_null(ctx));
195  fr_value_box_uint32(vb, NULL, fr_dict_vendor_num_by_da(vp->da), false);
196  fr_dcursor_append(out, vb);
197  return XLAT_ACTION_DONE;
198 }
199 
201  { .required = true, .single = true, .type = FR_TYPE_STRING },
203 };
204 
205 /** Return the attribute name of an attribute reference
206  *
207  * @ingroup xlat_functions
208  */
209 static xlat_action_t xlat_attr(TALLOC_CTX *ctx, fr_dcursor_t *out,
210  UNUSED xlat_ctx_t const *xctx,
211  request_t *request, fr_value_box_list_t *in)
212 {
213  fr_pair_t *vp;
214  fr_value_box_t *attr = fr_value_box_list_head(in);
215  fr_value_box_t *vb;
216 
217  if ((xlat_fmt_get_vp(&vp, request, attr->vb_strvalue) < 0) || !vp) return XLAT_ACTION_FAIL;
218 
219  MEM(vb = fr_value_box_alloc_null(ctx));
220 
221  if (fr_value_box_bstrndup(vb, vb, NULL, vp->da->name, strlen(vp->da->name), false) < 0) {
222  talloc_free(vb);
223  return XLAT_ACTION_FAIL;
224  }
225 
226  fr_dcursor_append(out, vb);
227  return XLAT_ACTION_DONE;
228 }
229 
231  { .required = true, .single = true, .type = FR_TYPE_STRING },
233 };
234 
235 /** Return the attribute number of an attribute reference
236  *
237  * @ingroup xlat_functions
238  */
239 static xlat_action_t xlat_attr_num(TALLOC_CTX *ctx, fr_dcursor_t *out,
240  UNUSED xlat_ctx_t const *xctx,
241  request_t *request, fr_value_box_list_t *in)
242 {
243  fr_pair_t *vp;
244  fr_value_box_t *attr = fr_value_box_list_head(in);
245  fr_value_box_t *vb;
246 
247  if ((xlat_fmt_get_vp(&vp, request, attr->vb_strvalue) < 0) || !vp) return XLAT_ACTION_FAIL;
248 
249  MEM(vb = fr_value_box_alloc_null(ctx));
250 
251  fr_value_box_uint32(vb, NULL, vp->da->attr, false);
252  fr_dcursor_append(out, vb);
253  return XLAT_ACTION_DONE;
254 }
255 
257  { .required = true, .single = true, .type = FR_TYPE_STRING },
259 };
260 
261 /** Return the attribute number of an attribute reference
262  *
263  * @ingroup xlat_functions
264  */
265 static xlat_action_t xlat_attr_oid(TALLOC_CTX *ctx, fr_dcursor_t *out,
266  UNUSED xlat_ctx_t const *xctx,
267  request_t *request, fr_value_box_list_t *in)
268 {
269  fr_pair_t *vp;
270  fr_value_box_t *attr = fr_value_box_list_head(in);
271  fr_value_box_t *vb;
272  fr_sbuff_t *oid_buff;
273 
274  FR_SBUFF_TALLOC_THREAD_LOCAL(&oid_buff, 50, SIZE_MAX);
275 
276  if ((xlat_fmt_get_vp(&vp, request, attr->vb_strvalue) < 0) || !vp) return XLAT_ACTION_FAIL;
277 
278  MEM(vb = fr_value_box_alloc_null(ctx));
279 
280  /*
281  * Print to an extendable buffer, so we don't have to worry
282  * about the size of the OID.
283  */
284  if (fr_dict_attr_oid_print(oid_buff, NULL, vp->da, true) < 0) {
285  RPEDEBUG("Printing OID for '%s' failed", vp->da->name);
286  return XLAT_ACTION_FAIL;
287  }
288 
289  fr_value_box_strdup(vb, vb, NULL, fr_sbuff_start(oid_buff), false);
290  fr_dcursor_append(out, vb);
291 
292  return XLAT_ACTION_DONE;
293 }
294 
295 /** Return the data type of an attribute reference
296  *
297  * @ingroup xlat_functions
298  */
299 static xlat_action_t xlat_attr_type(TALLOC_CTX *ctx, fr_dcursor_t *out,
300  UNUSED xlat_ctx_t const *xctx,
301  request_t *request, fr_value_box_list_t *in)
302 {
303  fr_pair_t *vp;
304  fr_value_box_t *attr = fr_value_box_list_head(in);
305  fr_value_box_t *vb;
306 
307  if ((xlat_fmt_get_vp(&vp, request, attr->vb_strvalue) < 0) || !vp) return XLAT_ACTION_FAIL;
308 
309  MEM(vb = fr_value_box_alloc_null(ctx));
310 
311  fr_value_box_strdup(vb, vb, vp->da, fr_type_to_str(vp->vp_type), false);
312  fr_dcursor_append(out, vb);
313  return XLAT_ACTION_DONE;
314 }
315 
316 #define XLAT_REGISTER(_name, _func, _type, _args) \
317 if (unlikely(!(xlat = xlat_func_register(NULL, _name, _func, _type)))) return -1; \
318 xlat_func_args_set(xlat, _args)
319 
320 static int mod_load(void)
321 {
322  xlat_t *xlat;
323 
332  return 0;
333 }
334 
335 static void mod_unload(void)
336 {
337  xlat_func_unregister("dict.attr.by_num");
338  xlat_func_unregister("dict.attr.by_oid");
339  xlat_func_unregister("dict.vendor");
340  xlat_func_unregister("dict.vendor.num");
341  xlat_func_unregister("dict.attr");
342  xlat_func_unregister("dict.attr.num");
343  xlat_func_unregister("dict.attr.oid");
344  xlat_func_unregister("dict.attr.type");
345 }
346 
347 extern module_rlm_t rlm_dict;
349  .common = {
350  .magic = MODULE_MAGIC_INIT,
351  .name = "dict",
352  .onload = mod_load,
353  .unload = mod_unload
354  }
355 };
#define RCSID(id)
Definition: build.h:481
#define UNUSED
Definition: build.h:313
static int fr_dcursor_append(fr_dcursor_t *cursor, void *v)
Insert a single item at the end of the list.
Definition: dcursor.h:406
char const * name
Vendor name.
Definition: dict.h:249
fr_slen_t fr_dict_attr_by_oid_legacy(fr_dict_t const *dict, fr_dict_attr_t const **parent, unsigned int *attr, char const *oid)
Get the leaf attribute of an OID string.
Definition: dict_util.c:2125
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
Definition: dict_util.c:2400
fr_dict_t const * fr_dict_internal(void)
Definition: dict_util.c:4610
fr_dict_vendor_t const * fr_dict_vendor_by_da(fr_dict_attr_t const *da)
Look up a vendor by one of its child attributes.
Definition: dict_util.c:2635
fr_dict_attr_t const * fr_dict_attr_child_by_num(fr_dict_attr_t const *parent, unsigned int attr)
Check if a child attribute exists in a parent using an attribute number.
Definition: dict_util.c:3328
static fr_slen_t in
Definition: dict.h:821
Private enterprise.
Definition: dict.h:244
static uint32_t fr_dict_vendor_num_by_da(fr_dict_attr_t const *da)
Return the vendor number for an attribute.
Definition: dict_ext.h:212
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
Definition: dl_module.h:63
static xlat_action_t xlat_attr_num(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
Return the attribute number of an attribute reference.
Definition: rlm_dict.c:239
static xlat_action_t xlat_dict_attr_by_num(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
Xlat for attr_by_num(<number>)
Definition: rlm_dict.c:77
static xlat_action_t xlat_attr(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
Return the attribute name of an attribute reference.
Definition: rlm_dict.c:209
static xlat_action_t xlat_attr_oid(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
Return the attribute number of an attribute reference.
Definition: rlm_dict.c:265
static xlat_action_t xlat_attr_type(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
Return the data type of an attribute reference.
Definition: rlm_dict.c:299
static xlat_action_t xlat_dict_attr_by_oid(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
Xlat for attr_by_oid(<oid>)
Definition: rlm_dict.c:111
static xlat_action_t xlat_vendor_num(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
Return the vendor number of an attribute reference.
Definition: rlm_dict.c:184
static xlat_action_t xlat_vendor(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
Return the vendor of an attribute reference.
Definition: rlm_dict.c:150
#define REMARKER(_str, _marker_idx, _marker,...)
Output string with error marker, showing where format error occurred.
Definition: log.h:498
#define RPEDEBUG(fmt,...)
Definition: log.h:376
talloc_free(reap)
@ TMPL_ATTR_REF_PREFIX_AUTO
Attribute refs may have a '&' prefix.
Definition: merged_model.c:231
@ FR_TYPE_STRING
String of printable characters.
Definition: merged_model.c:83
@ FR_TYPE_UINT32
32 Bit unsigned integer.
Definition: merged_model.c:99
long int ssize_t
Definition: merged_model.c:24
ssize_t fr_dict_attr_oid_print(fr_sbuff_t *out, fr_dict_attr_t const *ancestor, fr_dict_attr_t const *da, bool numeric)
Definition: merged_model.c:188
module_t common
Common fields presented by all modules.
Definition: module_rlm.h:39
#define REDEBUG(fmt,...)
Definition: radclient.h:52
fr_dict_attr_t const * request_attr_request
Definition: request.c:45
static xlat_arg_parser_t const xlat_attr_oid_args[]
Definition: rlm_dict.c:256
static xlat_arg_parser_t const xlat_vendor_num_args[]
Definition: rlm_dict.c:175
static int mod_load(void)
Definition: rlm_dict.c:320
static xlat_arg_parser_t const xlat_attr_num_args[]
Definition: rlm_dict.c:230
static xlat_arg_parser_t const xlat_vendor_args[]
Definition: rlm_dict.c:141
static xlat_arg_parser_t const xlat_attr_args[]
Definition: rlm_dict.c:200
static xlat_arg_parser_t const xlat_dict_attr_by_oid_args[]
Definition: rlm_dict.c:102
#define XLAT_REGISTER(_name, _func, _type, _args)
Definition: rlm_dict.c:316
static void mod_unload(void)
Definition: rlm_dict.c:335
static xlat_arg_parser_t const xlat_dict_attr_by_num_args[]
Definition: rlm_dict.c:68
module_rlm_t rlm_dict
Definition: rlm_dict.c:348
static int xlat_fmt_get_vp(fr_pair_t **out, request_t *request, char const *name)
Return a VP from the specified request.
Definition: rlm_dict.c:45
static char const * name
#define fr_sbuff_start(_sbuff_or_marker)
#define FR_SBUFF_TALLOC_THREAD_LOCAL(_out, _init, _max)
int tmpl_find_vp(fr_pair_t **out, request_t *request, tmpl_t const *vpt))
Returns the first VP matching a tmpl_t.
Definition: tmpl_eval.c:889
static fr_slen_t vpt
Definition: tmpl.h:1272
ssize_t tmpl_afrom_attr_str(TALLOC_CTX *ctx, tmpl_attr_error_t *err, tmpl_t **out, char const *name, tmpl_rules_t const *rules))
Parse a string into a TMPL_TYPE_ATTR_* type tmpl_t.
Optional arguments passed to vp_tmpl functions.
Definition: tmpl.h:341
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
fr_pair_t * vp
Stores an attribute, a value and various bits of other data.
Definition: pair.h:68
fr_dict_attr_t const *_CONST da
Dictionary attribute defines the attribute number, vendor and type of the pair.
Definition: pair.h:69
bool required
Argument must be present, and non-empty.
Definition: xlat.h:146
#define XLAT_ARG_PARSER_TERMINATOR
Definition: xlat.h:166
xlat_action_t
Definition: xlat.h:35
@ XLAT_ACTION_FAIL
An xlat function failed.
Definition: xlat.h:42
@ XLAT_ACTION_DONE
We're done evaluating this level of nesting.
Definition: xlat.h:41
Definition for a single argument consumend by an xlat function.
Definition: xlat.h:145
static fr_slen_t parent
Definition: pair.h:851
char const * fr_strerror(void)
Get the last library error.
Definition: strerror.c:554
static char const * fr_type_to_str(fr_type_t type)
Return a static string containing the type name.
Definition: types.h:433
int fr_value_box_strdup(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, bool tainted)
Copy a nul terminated string to a fr_value_box_t.
Definition: value.c:3927
int fr_value_box_bstrndup(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, size_t len, bool tainted)
Copy a string to to a fr_value_box_t.
Definition: value.c:4148
#define fr_value_box_alloc_null(_ctx)
Allocate a value box for later use with a value assignment function.
Definition: value.h:632
static size_t char ** out
Definition: value.h:997
An xlat calling ctx.
Definition: xlat_ctx.h:49
void xlat_func_unregister(char const *name)
Unregister an xlat function.
Definition: xlat_func.c:519