The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
rlm_unpack.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: 9c61cedb3d767ad9dc5f9adb428fd9c8730c219e $
19 * @file rlm_unpack.c
20 * @brief Unpack binary data
21 *
22 * @copyright 2014 The FreeRADIUS server project
23 * @copyright 2014 Alan DeKok (aland@freeradius.org)
24 */
25RCSID("$Id: 9c61cedb3d767ad9dc5f9adb428fd9c8730c219e $")
26
27#include <freeradius-devel/server/base.h>
28#include <freeradius-devel/server/module_rlm.h>
29#include <freeradius-devel/unlang/xlat_func.h>
30#include <freeradius-devel/util/base16.h>
31
32
34 { .required = true, .single = true, .type = FR_TYPE_VOID },
35 { .required = true, .single = true, .type = FR_TYPE_UINT32 },
36 { .required = true, .single = true, .type = FR_TYPE_STRING },
37 { .single = true, .type = FR_TYPE_VOID },
39};
40
41/** Unpack data
42 *
43 * Example:
44@verbatim
45%unpack(%{Class}, 0, integer)
46@endverbatim
47 * Expands Class, treating octet at offset 0 (bytes 0-3) as an "integer".
48 *
49 * @ingroup xlat_functions
50 */
51static xlat_action_t unpack_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out,
52 UNUSED xlat_ctx_t const *xctx, request_t *request,
53 fr_value_box_list_t *in)
54{
55 size_t len, input_len, offset;
57 uint8_t const *input;
58 uint8_t blob[256];
59 uint32_t repeat = 1, count = 1;
60 fr_value_box_t *data_vb = fr_value_box_list_head(in);
61 fr_value_box_t *offset_vb = fr_value_box_list_next(in, data_vb);
62 fr_value_box_t *type_vb = fr_value_box_list_next(in, offset_vb);
63 fr_value_box_t *repeat_vb = fr_value_box_list_next(in, type_vb);
66
67 if ((data_vb->type != FR_TYPE_OCTETS) && (data_vb->type != FR_TYPE_STRING)) {
68 REDEBUG("unpack requires the input attribute to be 'string' or 'octets'");
69 return XLAT_ACTION_FAIL;
70 }
71
72 if ((data_vb->type == FR_TYPE_STRING) && (data_vb->vb_length > 1) &&
73 (data_vb->vb_strvalue[0] == '0') && (data_vb->vb_strvalue[1] == 'x')) {
74 fr_slen_t slen;
76
77 /*
78 * Hex data.
79 */
80 len = strlen(data_vb->vb_strvalue + 2);
81 if (len <= 0) {
82 REDEBUG("Zero length hex string in '%s'", data_vb->vb_strvalue);
83 return XLAT_ACTION_FAIL;
84 }
85
86 input = blob;
87 slen = fr_base16_decode(&err, &FR_DBUFF_TMP(blob, sizeof(blob)),
88 &FR_SBUFF_IN(data_vb->vb_strvalue + 2, len), true);
89 if ((slen < 0) || err) {
90 REDEBUG("Invalid hex string in '%s'", data_vb->vb_strvalue);
91 return XLAT_ACTION_FAIL;
92 }
93 input_len = slen;
94
95 } else if (data_vb->type == FR_TYPE_STRING) {
96 input = (uint8_t const *)data_vb->vb_strvalue;
97 input_len = data_vb->vb_length;
98 } else {
99 input = data_vb->vb_octets;
100 input_len = data_vb->vb_length;
101 }
102
103 offset = offset_vb->vb_uint32;
104
105 if (offset >= input_len) {
106 REDEBUG("unpack offset %zu is larger than input data length %zu", offset, input_len);
107 return XLAT_ACTION_FAIL;
108 }
109
110 /* coverity[dereference] */
111 type = fr_type_from_str(type_vb->vb_strvalue);
112 if (fr_type_is_null(type)) {
113 REDEBUG("Invalid data type '%s'", type_vb->vb_strvalue);
114 return XLAT_ACTION_FAIL;
115 }
116
117 if (repeat_vb) {
118 if ((repeat_vb->type == FR_TYPE_STRING) && (strcmp(repeat_vb->vb_strvalue, "*") == 0)) {
119 repeat = UINT32_MAX;
120 } else {
121 if (fr_value_box_cast_in_place(repeat_vb, repeat_vb, FR_TYPE_UINT32, NULL) < 0) {
122 REDEBUG("Invalid value for limit");
123 return XLAT_ACTION_FAIL;
124 }
125 repeat = repeat_vb->vb_uint32;
126 }
127 }
128
129 while (true) {
130 MEM(vb = fr_value_box_alloc_null(ctx));
131
132 /*
133 * Call the generic routines to get data from the
134 * "network" buffer.
135 */
136 used = fr_value_box_from_network(ctx, vb, type, NULL,
137 &FR_DBUFF_TMP(input + offset, input_len - offset),
138 input_len - offset, data_vb->tainted);
139 if (used < 0) {
140 RPEDEBUG("Failed decoding %s", type_vb->vb_strvalue);
141 talloc_free(vb);
142 return XLAT_ACTION_FAIL;
143 }
144
146 if (count == repeat) break;
147
148 offset += used;
149 if (offset + used > input_len) break;
150 count++;
151 }
152
153 return XLAT_ACTION_DONE;
154}
155
156/*
157 * Register the xlats
158 */
159static int mod_load(void)
160{
161 xlat_t *xlat;
162
163 if (unlikely(!(xlat = xlat_func_register(NULL, "unpack", unpack_xlat, FR_TYPE_VOID)))) return -1;
166
167 return 0;
168}
169
170static void mod_unload(void)
171{
172 xlat_func_unregister("unpack");
173}
174
175/*
176 * The module name should be the only globally exported symbol.
177 * That is, everything else should be 'static'.
178 *
179 * If the module needs to temporarily modify it's instantiation
180 * data, the type should be changed to MODULE_TYPE_THREAD_UNSAFE.
181 * The server will then take care of ensuring that the module
182 * is single-threaded.
183 */
186 .common = {
187 .magic = MODULE_MAGIC_INIT,
188 .name = "unpack",
189 .onload = mod_load,
190 .unload = mod_unload
191 }
192};
#define fr_base16_decode(_err, _out, _in, _no_trailing)
Definition base16.h:92
#define RCSID(id)
Definition build.h:488
#define unlikely(_x)
Definition build.h:384
#define UNUSED
Definition build.h:318
#define FR_DBUFF_TMP(_start, _len_or_end)
Creates a compound literal to pass into functions which accept a dbuff.
Definition dbuff.h:522
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
#define MEM(x)
Definition debug.h:46
static fr_slen_t err
Definition dict.h:882
static fr_slen_t in
Definition dict.h:882
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
Definition dl_module.h:63
static xlat_action_t unpack_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
Unpack data.
Definition rlm_unpack.c:51
talloc_free(hp)
#define RPEDEBUG(fmt,...)
Definition log.h:388
fr_type_t
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
@ FR_TYPE_VOID
User data.
@ FR_TYPE_OCTETS
Raw octets.
unsigned int uint32_t
long int ssize_t
unsigned char uint8_t
ssize_t fr_slen_t
fr_sbuff_parse_error_t
static size_t used
module_t common
Common fields presented by all modules.
Definition module_rlm.h:39
#define REDEBUG(fmt,...)
static int mod_load(void)
Definition rlm_unpack.c:159
module_rlm_t rlm_unpack
Definition rlm_unpack.c:185
static xlat_arg_parser_t const unpack_xlat_args[]
Definition rlm_unpack.c:33
static void mod_unload(void)
Definition rlm_unpack.c:170
#define FR_SBUFF_IN(_start, _len_or_end)
return count
Definition module.c:155
fr_aka_sim_id_type_t type
unsigned int required
Argument must be present, and non-empty.
Definition xlat.h:146
#define XLAT_ARG_PARSER_TERMINATOR
Definition xlat.h:170
xlat_action_t
Definition xlat.h:37
@ XLAT_ACTION_FAIL
An xlat function failed.
Definition xlat.h:44
@ XLAT_ACTION_DONE
We're done evaluating this level of nesting.
Definition xlat.h:43
Definition for a single argument consumend by an xlat function.
Definition xlat.h:145
#define fr_type_is_null(_x)
Definition types.h:347
static fr_type_t fr_type_from_str(char const *type)
Return the constant value representing a type.
Definition types.h:464
ssize_t fr_value_box_from_network(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t type, fr_dict_attr_t const *enumv, fr_dbuff_t *dbuff, size_t len, bool tainted)
Decode a fr_value_box_t from serialized binary data.
Definition value.c:1921
int fr_value_box_cast_in_place(TALLOC_CTX *ctx, fr_value_box_t *vb, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv)
Convert one type of fr_value_box_t to another in place.
Definition value.c:4210
#define fr_value_box_alloc_null(_ctx)
Allocate a value box for later use with a value assignment function.
Definition value.h:655
static size_t char ** out
Definition value.h:1030
An xlat calling ctx.
Definition xlat_ctx.h:49
void xlat_func_flags_set(xlat_t *x, xlat_func_flags_t flags)
Specify flags that alter the xlat's behaviour.
Definition xlat_func.c:399
int xlat_func_args_set(xlat_t *x, xlat_arg_parser_t const args[])
Register the arguments of an xlat.
Definition xlat_func.c:363
xlat_t * xlat_func_register(TALLOC_CTX *ctx, char const *name, xlat_func_t func, fr_type_t return_type)
Register an xlat function.
Definition xlat_func.c:216
void xlat_func_unregister(char const *name)
Unregister an xlat function.
Definition xlat_func.c:516
@ XLAT_FUNC_FLAG_PURE
Definition xlat_func.h:38