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: cad6d9c8bdc58c06e644b93fef195be8c634d526 $
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: cad6d9c8bdc58c06e644b93fef195be8c634d526 $")
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#include <ctype.h>
33
35 { .required = true, .single = true, .type = FR_TYPE_VOID },
36 { .required = true, .single = true, .type = FR_TYPE_UINT32 },
37 { .required = true, .single = true, .type = FR_TYPE_STRING },
38 { .single = true, .type = FR_TYPE_VOID },
40};
41
42/** Unpack data
43 *
44 * Example:
45@verbatim
46%unpack(%{Class}, 0, integer)
47@endverbatim
48 * Expands Class, treating octet at offset 0 (bytes 0-3) as an "integer".
49 *
50 * @ingroup xlat_functions
51 */
52static xlat_action_t unpack_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out,
53 UNUSED xlat_ctx_t const *xctx, request_t *request,
54 fr_value_box_list_t *in)
55{
56 size_t len, input_len, offset;
58 uint8_t const *input;
59 uint8_t blob[256];
60 uint32_t repeat = 1, count = 1;
61 fr_value_box_t *data_vb = fr_value_box_list_head(in);
62 fr_value_box_t *offset_vb = fr_value_box_list_next(in, data_vb);
63 fr_value_box_t *type_vb = fr_value_box_list_next(in, offset_vb);
64 fr_value_box_t *repeat_vb = fr_value_box_list_next(in, type_vb);
67
68 if ((data_vb->type != FR_TYPE_OCTETS) && (data_vb->type != FR_TYPE_STRING)) {
69 REDEBUG("unpack requires the input attribute to be 'string' or 'octets'");
70 return XLAT_ACTION_FAIL;
71 }
72
73 if ((data_vb->type == FR_TYPE_STRING) && (data_vb->vb_length > 1) &&
74 (data_vb->vb_strvalue[0] == '0') && (data_vb->vb_strvalue[1] == 'x')) {
75 /*
76 * Hex data.
77 */
78 len = strlen(data_vb->vb_strvalue + 2);
79 if (len > 0) {
81
82 input = blob;
83 input_len = fr_base16_decode(&err, &FR_DBUFF_TMP(blob, sizeof(blob)),
84 &FR_SBUFF_IN(data_vb->vb_strvalue + 2, len), true);
85 if (err) {
86 REDEBUG("Invalid hex string in '%s'", data_vb->vb_strvalue);
87 return XLAT_ACTION_FAIL;
88 }
89 } else {
90 REDEBUG("Zero length hex string in '%s'", data_vb->vb_strvalue);
91 return XLAT_ACTION_FAIL;
92 }
93 } else if (data_vb->type == FR_TYPE_STRING) {
94 input = (uint8_t const *)data_vb->vb_strvalue;
95 input_len = data_vb->vb_length;
96 } else {
97 input = data_vb->vb_octets;
98 input_len = data_vb->vb_length;
99 }
100
101 offset = offset_vb->vb_uint32;
102
103 if (offset >= input_len) {
104 REDEBUG("unpack offset %zu is larger than input data length %zu", offset, input_len);
105 return XLAT_ACTION_FAIL;
106 }
107
108 /* coverity[dereference] */
109 type = fr_type_from_str(type_vb->vb_strvalue);
110 if (fr_type_is_null(type)) {
111 REDEBUG("Invalid data type '%s'", type_vb->vb_strvalue);
112 return XLAT_ACTION_FAIL;
113 }
114
115 if (repeat_vb) {
116 if ((repeat_vb->type == FR_TYPE_STRING) && (strcmp(repeat_vb->vb_strvalue, "*") == 0)) {
117 repeat = UINT32_MAX;
118 } else {
119 if (fr_value_box_cast_in_place(repeat_vb, repeat_vb, FR_TYPE_UINT32, NULL) < 0) {
120 REDEBUG("Invalid value for limit");
121 return XLAT_ACTION_FAIL;
122 }
123 repeat = repeat_vb->vb_uint32;
124 }
125 }
126
127 while (true) {
128 MEM(vb = fr_value_box_alloc_null(ctx));
129
130 /*
131 * Call the generic routines to get data from the
132 * "network" buffer.
133 */
134 used = fr_value_box_from_network(ctx, vb, type, NULL,
135 &FR_DBUFF_TMP(input + offset, input_len - offset),
136 input_len - offset, data_vb->tainted);
137 if (used < 0) {
138 RPEDEBUG("Failed decoding %s", type_vb->vb_strvalue);
139 talloc_free(vb);
140 return XLAT_ACTION_FAIL;
141 }
142
144 if (count == repeat) break;
145
146 offset += used;
147 if (offset + used > input_len) break;
148 count++;
149 }
150
151 return XLAT_ACTION_DONE;
152}
153
154/*
155 * Register the xlats
156 */
157static int mod_load(void)
158{
159 xlat_t *xlat;
160
161 if (unlikely(!(xlat = xlat_func_register(NULL, "unpack", unpack_xlat, FR_TYPE_VOID)))) return -1;
164
165 return 0;
166}
167
168static void mod_unload(void)
169{
170 xlat_func_unregister("unpack");
171}
172
173/*
174 * The module name should be the only globally exported symbol.
175 * That is, everything else should be 'static'.
176 *
177 * If the module needs to temporarily modify it's instantiation
178 * data, the type should be changed to MODULE_TYPE_THREAD_UNSAFE.
179 * The server will then take care of ensuring that the module
180 * is single-threaded.
181 */
184 .common = {
185 .magic = MODULE_MAGIC_INIT,
186 .name = "unpack",
187 .onload = mod_load,
188 .unload = mod_unload
189 }
190};
#define fr_base16_decode(_err, _out, _in, _no_trailing)
Definition base16.h:95
#define RCSID(id)
Definition build.h:483
#define unlikely(_x)
Definition build.h:381
#define UNUSED
Definition build.h:315
#define FR_DBUFF_TMP(_start, _len_or_end)
Creates a compound literal to pass into functions which accept a dbuff.
Definition dbuff.h:514
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:36
static fr_slen_t err
Definition dict.h:824
static fr_slen_t in
Definition dict.h:824
#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:52
#define RPEDEBUG(fmt,...)
Definition log.h:376
talloc_free(reap)
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
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,...)
Definition radclient.h:52
static int mod_load(void)
Definition rlm_unpack.c:157
module_rlm_t rlm_unpack
Definition rlm_unpack.c:183
static xlat_arg_parser_t const unpack_xlat_args[]
Definition rlm_unpack.c:34
static void mod_unload(void)
Definition rlm_unpack.c:168
#define FR_SBUFF_IN(_start, _len_or_end)
return count
Definition module.c:163
fr_aka_sim_id_type_t type
bool required
Argument must be present, and non-empty.
Definition xlat.h:148
#define XLAT_ARG_PARSER_TERMINATOR
Definition xlat.h:168
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:147
#define fr_type_is_null(_x)
Definition types.h:326
static fr_type_t fr_type_from_str(char const *type)
Return the constant value representing a type.
Definition types.h:443
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:1754
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:3572
#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_flags_set(xlat_t *x, xlat_func_flags_t flags)
Specify flags that alter the xlat's behaviour.
Definition xlat_func.c:402
int xlat_func_args_set(xlat_t *x, xlat_arg_parser_t const args[])
Register the arguments of an xlat.
Definition xlat_func.c:365
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:218
void xlat_func_unregister(char const *name)
Unregister an xlat function.
Definition xlat_func.c:519
@ XLAT_FUNC_FLAG_PURE
Definition xlat_func.h:38