summaryrefslogtreecommitdiffstats
path: root/src/include/tmpl.h
blob: 92884b186bddef23432c4ad74bd1dc1d10c6466c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
/*
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */
#ifndef TMPL_H
#define TMPL_H
/**
 * $Id$
 *
 * @file tmpl.h
 * @brief Structures and prototypes for templates
 *
 * These functions are used to work with #vp_tmpl_t structs.
 *
 * #vp_tmpl_t (VPTs) specify either a data source, or a data sink.
 *
 * Examples of sources are #TMPL_TYPE_XLAT, #TMPL_TYPE_EXEC and #TMPL_TYPE_ATTR.
 * Examples of sinks are #TMPL_TYPE_ATTR, #TMPL_TYPE_LIST.
 *
 * VPTs are used to gather values or attributes for evaluation, or copying, and to specify
 * where values or #VALUE_PAIR should be copied to.
 *
 * To create new #vp_tmpl_t use one of the tmpl_*from_* functions.  These parse
 * strings into VPTs. The main parsing function is #tmpl_afrom_str, which can produce
 * most types of VPTs. It uses the type of quoting (passed as an #FR_TOKEN) to determine
 * what type of VPT to parse the string as. For example a #T_DOUBLE_QUOTED_STRING will
 * produce either a #TMPL_TYPE_XLAT or a #TMPL_TYPE_LITERAL (depending if the string
 * contained a non-literal expansion).
 *
 * @see tmpl_afrom_str
 * @see tmpl_afrom_attr_str
 * @see tmpl_from_attr_str
 * @see tmpl_from_attr_substr
 *
 * In the case of #TMPL_TYPE_ATTR and #TMPL_TYPE_LIST, there are special cursor overlay
 * functions which can be used to iterate over only the #VALUE_PAIR that match a
 * vp_tmpl_t in a given list.
 *
 * @see tmpl_cursor_init
 * @see tmpl_cursor_next
 *
 * Or for simplicity, there are functions which wrap the cursor functions, to copy or
 * return the #VALUE_PAIR that match the VPT.
 *
 * @see tmpl_copy_vps
 * @see tmpl_find_vp
 *
 * If you just need the string value of whatever the VPT refers to, the tmpl_*expand
 * functions may be used. These functions evaluate the VPT, execing, and xlat expanding
 * as necessary. In the case of #TMPL_TYPE_ATTR, and #PW_TYPE_STRING or #PW_TYPE_OCTETS
 * #tmpl_expand will return a pointer to the raw #VALUE_PAIR buffer. This can be very
 * useful when using the #PW_TYPE_TMPL type in #CONF_PARSER structs, as it allows the
 * user to determine whether they want the module to sanitise the value using presentation
 * format specific #xlat_escape_t function, or to operate on the raw value.
 *
 * @see tmpl_expand
 * @see tmpl_aexpand
 *
 * @copyright 2014-2015 The FreeRADIUS server project
 */

RCSIDH(tmpl_h, "$Id$")

#include <freeradius-devel/xlat.h>

#ifdef __cplusplus
extern "C" {
#endif
#
typedef enum pair_lists {
	PAIR_LIST_UNKNOWN = 0,		//!< Unknown list.
	PAIR_LIST_REQUEST,		//!< Attributes in incoming or internally proxied
					///< request.
	PAIR_LIST_REPLY,		//!< Attributes to send in the response.
	PAIR_LIST_CONTROL,		//!< Attributes that change the behaviour of
					///< modules.
	PAIR_LIST_STATE,		//!< Attributes to store multiple rounds of
					///< challenges/responses.
#ifdef WITH_PROXY
	PAIR_LIST_PROXY_REQUEST,	//!< A copy of attributes in the request list
					///< that may be modified in pre-proxy before
					//!< proxying the request.
	PAIR_LIST_PROXY_REPLY,		//!< Attributes sent in response to the proxied
					///< request.
#endif
#ifdef WITH_COA
	PAIR_LIST_COA,			//!< Attributes to send in a forked CoA-Request.
	PAIR_LIST_COA_REPLY,		//!< Attributes sent in response to the forked
					///< CoA-Request.
	PAIR_LIST_DM,			//!< Attributes to send in a forked Disconnect-Request.
	PAIR_LIST_DM_REPLY		//!< Attributes sent in response to the forked
					//!< Disconnect-Request.
#endif
} pair_lists_t;

extern const FR_NAME_NUMBER pair_lists[];

typedef enum requests {
	REQUEST_UNKNOWN = 0,		//!< Unknown request.
	REQUEST_OUTER,			//!< #REQUEST containing the outer layer of the EAP
					//!< conversation. Usually the RADIUS request sent
					//!< by the NAS.
	REQUEST_CURRENT,		//!< The current request.
	REQUEST_PARENT			//!< Not currently used.
} request_refs_t;

extern const FR_NAME_NUMBER request_refs[];

typedef struct pair_list {
	char const		*name;
	VALUE_PAIR		*check;
	VALUE_PAIR		*reply;
	int			order;		/* for ordering! */
	int			lineno;
	struct pair_list	*next;
} PAIR_LIST;

/** Types of #vp_tmpl_t
 */
typedef enum tmpl_type {
	TMPL_TYPE_UNKNOWN = 0,		//!< Uninitialised.
	TMPL_TYPE_LITERAL,		//!< Literal string.
	TMPL_TYPE_XLAT,			//!< XLAT expansion.
	TMPL_TYPE_ATTR,			//!< Dictionary attribute.
	TMPL_TYPE_ATTR_UNDEFINED,	//!< Attribute not found in the global dictionary.
	TMPL_TYPE_LIST,			//!< Attribute list.
	TMPL_TYPE_REGEX,		//!< Regular expression.
	TMPL_TYPE_EXEC,			//!< Callout to an external script or program.
	TMPL_TYPE_DATA,			//!< Value in native format.
	TMPL_TYPE_XLAT_STRUCT,	      	//!< Pre-parsed XLAT expansion.
	TMPL_TYPE_REGEX_STRUCT,	      	//!< Pre-parsed regular expression.
	TMPL_TYPE_NULL			//!< Has no value.
} tmpl_type_t;

extern const FR_NAME_NUMBER tmpl_names[];

/** Describes a #TMPL_TYPE_ATTR, #TMPL_TYPE_ATTR_UNDEFINED or #TMPL_TYPE_LIST
 */
typedef struct {
	request_refs_t		request;		//!< Request to search or insert in.
	pair_lists_t		list;			//!< List to search or insert in.

	DICT_ATTR const		*da;			//!< Resolved dictionary attribute.
	union {
		uint8_t			da[DICT_ATTR_SIZE];	//!< Unknown dictionary attribute buffer.
		char			name[DICT_ATTR_SIZE];	//!< Raw unknown dictionary name.
	} unknown;
	int			num;			 //!< For array references.
	int8_t			tag;			 //!< For tag references.
} value_pair_tmpl_attr_t;

/** A source or sink of value data.
 *
 * Is used as both the RHS and LHS of a map (both update, and conditional types)
 *
 * @section update_maps Use in update vp_map_t
 * When used on the LHS it describes an attribute to create and should be one of these types:
 * - #TMPL_TYPE_ATTR
 * - #TMPL_TYPE_LIST
 *
 * When used on the RHS it describes the value to assign to the attribute being created and
 * should be one of these types:
 * - #TMPL_TYPE_LITERAL
 * - #TMPL_TYPE_XLAT
 * - #TMPL_TYPE_ATTR
 * - #TMPL_TYPE_LIST
 * - #TMPL_TYPE_EXEC
 * - #TMPL_TYPE_DATA
 * - #TMPL_TYPE_XLAT_STRUCT (pre-parsed xlat)
 *
 * @section conditional_maps Use in conditional vp_map_t
 * When used as part of a condition it may be any of the RHS side types, as well as:
 * - #TMPL_TYPE_REGEX_STRUCT (pre-parsed regex)
 *
 * @see vp_map_t
 */
typedef struct vp_tmpl_t {
	tmpl_type_t	type;		//!< What type of value tmpl refers to.
	char const	*name;		//!< Original attribute ref string, or
					//!< where this refers to a none FR
					//!< attribute, just the string id for
					//!< the attribute.
	size_t		len;		//!< Name length.
	char		quote;		//!< Quotation character for "name"
	bool		auto_converted; //!< Attr-26.9.1 --> Cisco-AVPair

#ifdef HAVE_REGEX
	bool		iflag;		//!< regex - case insensitive (if operand is used in regex comparison)
	bool		mflag;		//!< regex - multiline flags (controls $ matching)
#endif

	union {
		/*
		 *  Attribute reference. Either an attribute currently in the request
		 *  or an attribute to create.
		 */
		value_pair_tmpl_attr_t attribute;

		/*
		 *  Attribute value. Typically used as the RHS of an update map.
		 */
		struct {
			PW_TYPE			type;			 //!< Type of data.
			size_t			length;			 //!< of the vpd data.
			value_data_t		data;			 //!< Value data.
		} literal;

		xlat_exp_t	*xlat;	 //!< pre-parsed xlat_exp_t

#ifdef HAVE_REGEX
		regex_t		*preg;	//!< pre-parsed regex_t
#endif
	} data;
} vp_tmpl_t;

/** @name Field accessors for #TMPL_TYPE_ATTR, #TMPL_TYPE_ATTR_UNDEFINED, #TMPL_TYPE_LIST
 *
 * @{
 */
#define tmpl_request		data.attribute.request
#define tmpl_list		data.attribute.list
#define tmpl_da			data.attribute.da
#define tmpl_unknown		data.attribute.unknown.da
#define tmpl_unknown_name      	data.attribute.unknown.name
#define tmpl_num		data.attribute.num
#define tmpl_tag		data.attribute.tag
/* @} **/

/** @name Field accessors for #TMPL_TYPE_XLAT_STRUCT
 *
 * @{
 */
#define tmpl_xlat		data.xlat
/* @} **/

/** @name Field accessors for #TMPL_TYPE_DATA
 *
 * @{
 */
#define tmpl_data		data.literal
#define tmpl_data_type		data.literal.type
#define tmpl_data_length	data.literal.length
#define tmpl_data_value		data.literal.data
/* @} **/

/** @name Field accessors for #TMPL_TYPE_REGEX_STRUCT and #TMPL_TYPE_REGEX
 *
 * @{
 */
#ifdef HAVE_REGEX
#  define tmpl_preg		data.preg	//!< #TMPL_TYPE_REGEX_STRUCT only.
#  define tmpl_iflag		iflag
#  define tmpl_mflag		mflag
#endif
/* @} **/

#ifndef WITH_VERIFY_PTR
#  define VERIFY_TMPL(_x)
#else
#  define VERIFY_TMPL(_x) tmpl_verify(__FILE__,  __LINE__, _x)
void tmpl_verify(char const *file, int line, vp_tmpl_t const *vpt);
#endif

VALUE_PAIR		**radius_list(REQUEST *request, pair_lists_t list);

RADIUS_PACKET		*radius_packet(REQUEST *request, pair_lists_t list_name);

TALLOC_CTX		*radius_list_ctx(REQUEST *request, pair_lists_t list_name);

size_t			radius_list_name(pair_lists_t *out, char const *name, pair_lists_t default_list);

int			radius_request(REQUEST **request, request_refs_t name);

size_t			radius_request_name(request_refs_t *out, char const *name, request_refs_t unknown);

vp_tmpl_t		*tmpl_init(vp_tmpl_t *vpt, tmpl_type_t type,
				   char const *name, ssize_t len);

vp_tmpl_t		*tmpl_alloc(TALLOC_CTX *ctx, tmpl_type_t type, char const *name,
				    ssize_t len);

ssize_t			tmpl_from_attr_substr(vp_tmpl_t *vpt, char const *name,
					      request_refs_t request_def, pair_lists_t list_def,
					      bool allow_unknown, bool allow_undefined);

ssize_t			tmpl_from_attr_str(vp_tmpl_t *vpt, char const *name,
					   request_refs_t request_def,
					   pair_lists_t list_def,
					   bool allow_unknown, bool allow_undefined);

ssize_t			tmpl_afrom_attr_substr(TALLOC_CTX *ctx, vp_tmpl_t **out, char const *name,
					       request_refs_t request_def, pair_lists_t list_def,
					       bool allow_unknown, bool allow_undefined);

ssize_t			tmpl_afrom_attr_str(TALLOC_CTX *ctx, vp_tmpl_t **out, char const *name,
					    request_refs_t request_def,
					    pair_lists_t list_def,
					    bool allow_unknown, bool allow_undefined);

ssize_t			tmpl_afrom_str(TALLOC_CTX *ctx, vp_tmpl_t **out, char const *name, size_t inlen,
				       FR_TOKEN type, request_refs_t request_def, pair_lists_t list_def, bool do_escape);

int			tmpl_cast_in_place(vp_tmpl_t *vpt, PW_TYPE type, DICT_ATTR const *enumv);

void			tmpl_cast_in_place_str(vp_tmpl_t *vpt);

int			tmpl_cast_to_vp(VALUE_PAIR **out, REQUEST *request,
					vp_tmpl_t const *vpt, DICT_ATTR const *cast);

size_t			tmpl_prints(char *buffer, size_t bufsize, vp_tmpl_t const *vpt,
				    DICT_ATTR const *values);

ssize_t			tmpl_expand(char const **out, char *buff, size_t outlen, REQUEST *request,
				    vp_tmpl_t const *vpt, xlat_escape_t escape, void *escape_ctx);

ssize_t			tmpl_aexpand(TALLOC_CTX *ctx, char **out, REQUEST *request, vp_tmpl_t const *vpt,
				     xlat_escape_t escape, void *escape_ctx);

VALUE_PAIR		*tmpl_cursor_init(int *err, vp_cursor_t *cursor, REQUEST *request,
					  vp_tmpl_t const *vpt);

VALUE_PAIR		*tmpl_cursor_next(vp_cursor_t *cursor, vp_tmpl_t const *vpt);

int			tmpl_copy_vps(TALLOC_CTX *ctx, VALUE_PAIR **out, REQUEST *request,
				      vp_tmpl_t const *vpt);

int			tmpl_find_vp(VALUE_PAIR **out, REQUEST *request, vp_tmpl_t const *vpt);

int			tmpl_define_unknown_attr(vp_tmpl_t *vpt);

#ifdef __cplusplus
}
#endif
#endif	/* TMPL_H */