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: 514598e551e7ae91e15b6aaf930aac2d3613edd5 $
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: 514598e551e7ae91e15b6aaf930aac2d3613edd5 $")
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 
36  { .required = true, .single = true, .type = FR_TYPE_UINT32 },
38 };
39 
40 /** Xlat for %attr_by_num(<number>)
41  *
42  * @ingroup xlat_functions
43  */
45  UNUSED xlat_ctx_t const *xctx,
46  request_t *request, fr_value_box_list_t *in)
47 {
48  fr_dict_attr_t const *da;
49  fr_value_box_t *attr = fr_value_box_list_head(in);
50  fr_value_box_t *vb;
51 
52  da = fr_dict_attr_child_by_num(fr_dict_root(request->dict), attr->vb_uint32);
53  if (!da) {
54  REDEBUG("No attribute found with number %pV", attr);
55  return XLAT_ACTION_FAIL;
56  }
57 
58  MEM(vb = fr_value_box_alloc_null(ctx));
59 
60  if (fr_value_box_bstrndup(vb, vb, NULL, da->name, strlen(da->name), false) < 0) {
61  talloc_free(vb);
62  return XLAT_ACTION_FAIL;
63  }
64 
66  return XLAT_ACTION_DONE;
67 }
68 
70  { .required = true, .single = true, .type = FR_TYPE_STRING },
72 };
73 
74 /** Xlat for %attr_by_oid(<oid>)
75  *
76  * @ingroup xlat_functions
77  */
79  UNUSED xlat_ctx_t const *xctx,
80  request_t *request, fr_value_box_list_t *in)
81 {
82  unsigned int attr = 0;
83  fr_dict_attr_t const *parent = fr_dict_root(request->dict);
84  fr_dict_attr_t const *da;
85  ssize_t ret;
86  fr_value_box_t *attr_vb = fr_value_box_list_head(in);
87  fr_value_box_t *vb;
88 
89  ret = fr_dict_attr_by_oid_legacy(fr_dict_internal(), &parent, &attr, attr_vb->vb_strvalue);
90  if (ret <= 0) {
91  REMARKER(attr_vb->vb_strvalue, -(ret), "%s", fr_strerror());
92  return XLAT_ACTION_FAIL;
93  }
94 
96 
97  MEM(vb = fr_value_box_alloc_null(ctx));
98 
99  if (fr_value_box_bstrndup(vb, vb, NULL, da->name, strlen(da->name), false) < 0) {
100  talloc_free(vb);
101  return XLAT_ACTION_FAIL;
102  }
103 
104  fr_dcursor_append(out, vb);
105  return XLAT_ACTION_DONE;
106 }
107 
109  { .required = true, .single = true, .type = FR_TYPE_STRING },
111 };
112 
113 /** Return the vendor of an attribute reference
114  *
115  * @ingroup xlat_functions
116  */
117 static xlat_action_t xlat_vendor(TALLOC_CTX *ctx, fr_dcursor_t *out,
118  UNUSED xlat_ctx_t const *xctx,
119  request_t *request, fr_value_box_list_t *in)
120 {
121  fr_pair_t *vp;
122  fr_dict_vendor_t const *vendor;
123  fr_value_box_t *attr = fr_value_box_list_head(in);
124  fr_value_box_t *vb;
125 
126  if ((xlat_fmt_get_vp(&vp, request, attr->vb_strvalue) < 0) || !vp) return XLAT_ACTION_FAIL;
127 
128  vendor = fr_dict_vendor_by_da(vp->da);
129  if (!vendor) return XLAT_ACTION_FAIL;
130 
131  MEM(vb = fr_value_box_alloc_null(ctx));
132 
133  if (fr_value_box_bstrndup(vb, vb, NULL, vendor->name, strlen(vendor->name), false) < 0) {
134  talloc_free(vb);
135  return XLAT_ACTION_FAIL;
136  }
137 
138  fr_dcursor_append(out, vb);
139  return XLAT_ACTION_DONE;
140 }
141 
143  { .required = true, .single = true, .type = FR_TYPE_STRING },
145 };
146 
147 /** Return the vendor number of an attribute reference
148  *
149  * @ingroup xlat_functions
150  */
152  UNUSED xlat_ctx_t const *xctx,
153  request_t *request, fr_value_box_list_t *in)
154 {
155  fr_pair_t *vp;
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  MEM(vb = fr_value_box_alloc_null(ctx));
162  fr_value_box_uint32(vb, NULL, fr_dict_vendor_num_by_da(vp->da), false);
163  fr_dcursor_append(out, vb);
164  return XLAT_ACTION_DONE;
165 }
166 
168  { .required = true, .single = true, .type = FR_TYPE_STRING },
170 };
171 
172 /** Return the attribute name of an attribute reference
173  *
174  * @ingroup xlat_functions
175  */
176 static xlat_action_t xlat_attr(TALLOC_CTX *ctx, fr_dcursor_t *out,
177  UNUSED xlat_ctx_t const *xctx,
178  request_t *request, fr_value_box_list_t *in)
179 {
180  fr_pair_t *vp;
181  fr_value_box_t *attr = fr_value_box_list_head(in);
182  fr_value_box_t *vb;
183 
184  if ((xlat_fmt_get_vp(&vp, request, attr->vb_strvalue) < 0) || !vp) return XLAT_ACTION_FAIL;
185 
186  MEM(vb = fr_value_box_alloc_null(ctx));
187 
188  if (fr_value_box_bstrndup(vb, vb, NULL, vp->da->name, strlen(vp->da->name), false) < 0) {
189  talloc_free(vb);
190  return XLAT_ACTION_FAIL;
191  }
192 
193  fr_dcursor_append(out, vb);
194  return XLAT_ACTION_DONE;
195 }
196 
198  { .required = true, .single = true, .type = FR_TYPE_STRING },
200 };
201 
202 /** Return the attribute number of an attribute reference
203  *
204  * @ingroup xlat_functions
205  */
206 static xlat_action_t xlat_attr_num(TALLOC_CTX *ctx, fr_dcursor_t *out,
207  UNUSED xlat_ctx_t const *xctx,
208  request_t *request, fr_value_box_list_t *in)
209 {
210  fr_pair_t *vp;
211  fr_value_box_t *attr = fr_value_box_list_head(in);
212  fr_value_box_t *vb;
213 
214  if ((xlat_fmt_get_vp(&vp, request, attr->vb_strvalue) < 0) || !vp) return XLAT_ACTION_FAIL;
215 
216  MEM(vb = fr_value_box_alloc_null(ctx));
217 
218  fr_value_box_uint32(vb, NULL, vp->da->attr, false);
219  fr_dcursor_append(out, vb);
220  return XLAT_ACTION_DONE;
221 }
222 
224  { .required = true, .single = true, .type = FR_TYPE_STRING },
226 };
227 
228 /** Return the attribute number of an attribute reference
229  *
230  * @ingroup xlat_functions
231  */
232 static xlat_action_t xlat_attr_oid(TALLOC_CTX *ctx, fr_dcursor_t *out,
233  UNUSED xlat_ctx_t const *xctx,
234  request_t *request, fr_value_box_list_t *in)
235 {
236  fr_pair_t *vp;
237  fr_value_box_t *attr = fr_value_box_list_head(in);
238  fr_value_box_t *vb;
239  fr_sbuff_t *oid_buff;
240 
241  FR_SBUFF_TALLOC_THREAD_LOCAL(&oid_buff, 50, SIZE_MAX);
242 
243  if ((xlat_fmt_get_vp(&vp, request, attr->vb_strvalue) < 0) || !vp) return XLAT_ACTION_FAIL;
244 
245  MEM(vb = fr_value_box_alloc_null(ctx));
246 
247  /*
248  * Print to an extendable buffer, so we don't have to worry
249  * about the size of the OID.
250  */
251  if (fr_dict_attr_oid_print(oid_buff, NULL, vp->da, true) < 0) {
252  RPEDEBUG("Printing OID for '%s' failed", vp->da->name);
253  return XLAT_ACTION_FAIL;
254  }
255 
256  fr_value_box_strdup(vb, vb, NULL, fr_sbuff_start(oid_buff), false);
257  fr_dcursor_append(out, vb);
258 
259  return XLAT_ACTION_DONE;
260 }
261 
262 /** Return the data type of an attribute reference
263  *
264  * @ingroup xlat_functions
265  */
266 static xlat_action_t xlat_attr_type(TALLOC_CTX *ctx, fr_dcursor_t *out,
267  UNUSED xlat_ctx_t const *xctx,
268  request_t *request, fr_value_box_list_t *in)
269 {
270  fr_pair_t *vp;
271  fr_value_box_t *attr = fr_value_box_list_head(in);
272  fr_value_box_t *vb;
273 
274  if ((xlat_fmt_get_vp(&vp, request, attr->vb_strvalue) < 0) || !vp) return XLAT_ACTION_FAIL;
275 
276  MEM(vb = fr_value_box_alloc_null(ctx));
277 
278  fr_value_box_strdup(vb, vb, vp->da, fr_type_to_str(vp->vp_type), false);
279  fr_dcursor_append(out, vb);
280  return XLAT_ACTION_DONE;
281 }
282 
283 #define XLAT_REGISTER(_name, _func, _type, _args) \
284 if (unlikely(!(xlat = xlat_func_register(NULL, _name, _func, _type)))) return -1; \
285 xlat_func_args_set(xlat, _args)
286 
287 static int mod_load(void)
288 {
289  xlat_t *xlat;
290 
299  return 0;
300 }
301 
302 static void mod_unload(void)
303 {
304  xlat_func_unregister("dict.attr.by_num");
305  xlat_func_unregister("dict.attr.by_oid");
306  xlat_func_unregister("dict.vendor");
307  xlat_func_unregister("dict.vendor.num");
308  xlat_func_unregister("dict.attr");
309  xlat_func_unregister("dict.attr.num");
310  xlat_func_unregister("dict.attr.oid");
311  xlat_func_unregister("dict.attr.type");
312 }
313 
314 extern module_rlm_t rlm_dict;
316  .common = {
317  .magic = MODULE_MAGIC_INIT,
318  .name = "dict",
319  .onload = mod_load,
320  .unload = mod_unload
321  }
322 };
#define RCSID(id)
Definition: build.h:444
#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:405
char const * name
Vendor name.
Definition: dict.h:232
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:1719
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
Definition: dict_util.c:1997
fr_dict_t const * fr_dict_internal(void)
Definition: dict_util.c:4204
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:2232
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:2925
static fr_slen_t in
Definition: dict.h:645
Private enterprise.
Definition: dict.h:227
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:182
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
Definition: dl_module.h:65
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:206
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:44
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:176
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:232
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:266
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:78
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:151
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:117
#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)
@ 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:37
#define REDEBUG(fmt,...)
Definition: radclient.h:52
static xlat_arg_parser_t const xlat_attr_oid_args[]
Definition: rlm_dict.c:223
static xlat_arg_parser_t const xlat_vendor_num_args[]
Definition: rlm_dict.c:142
static int mod_load(void)
Definition: rlm_dict.c:287
static xlat_arg_parser_t const xlat_attr_num_args[]
Definition: rlm_dict.c:197
static xlat_arg_parser_t const xlat_vendor_args[]
Definition: rlm_dict.c:108
static xlat_arg_parser_t const xlat_attr_args[]
Definition: rlm_dict.c:167
static xlat_arg_parser_t const xlat_dict_attr_by_oid_args[]
Definition: rlm_dict.c:69
#define XLAT_REGISTER(_name, _func, _type, _args)
Definition: rlm_dict.c:283
static void mod_unload(void)
Definition: rlm_dict.c:302
static xlat_arg_parser_t const xlat_dict_attr_by_num_args[]
Definition: rlm_dict.c:35
module_rlm_t rlm_dict
Definition: rlm_dict.c:315
#define fr_sbuff_start(_sbuff_or_marker)
#define FR_SBUFF_TALLOC_THREAD_LOCAL(_out, _init, _max)
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
int xlat_fmt_get_vp(fr_pair_t **out, request_t *request, char const *name)
Return a VP from the specified request.
Definition: xlat_builtin.c:76
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:844
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:3876
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:4097
#define fr_value_box_alloc_null(_ctx)
Allocate a value box for later use with a value assignment function.
Definition: value.h:619
static size_t char ** out
Definition: value.h:984
An xlat calling ctx.
Definition: xlat_ctx.h:42
void xlat_func_unregister(char const *name)
Unregister an xlat function.
Definition: xlat_func.c:531