1 /*
2  *   This program 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
5  *   (at 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 #ifndef TMPL_H
17 #define TMPL_H
18 /**
19  * $Id: 92884b186bddef23432c4ad74bd1dc1d10c6466c $
20  *
21  * @file tmpl.h
22  * @brief Structures and prototypes for templates
23  *
24  * These functions are used to work with #vp_tmpl_t structs.
25  *
26  * #vp_tmpl_t (VPTs) specify either a data source, or a data sink.
27  *
28  * Examples of sources are #TMPL_TYPE_XLAT, #TMPL_TYPE_EXEC and #TMPL_TYPE_ATTR.
29  * Examples of sinks are #TMPL_TYPE_ATTR, #TMPL_TYPE_LIST.
30  *
31  * VPTs are used to gather values or attributes for evaluation, or copying, and to specify
32  * where values or #VALUE_PAIR should be copied to.
33  *
34  * To create new #vp_tmpl_t use one of the tmpl_*from_* functions.  These parse
35  * strings into VPTs. The main parsing function is #tmpl_afrom_str, which can produce
36  * most types of VPTs. It uses the type of quoting (passed as an #FR_TOKEN) to determine
37  * what type of VPT to parse the string as. For example a #T_DOUBLE_QUOTED_STRING will
38  * produce either a #TMPL_TYPE_XLAT or a #TMPL_TYPE_LITERAL (depending if the string
39  * contained a non-literal expansion).
40  *
41  * @see tmpl_afrom_str
42  * @see tmpl_afrom_attr_str
43  * @see tmpl_from_attr_str
44  * @see tmpl_from_attr_substr
45  *
46  * In the case of #TMPL_TYPE_ATTR and #TMPL_TYPE_LIST, there are special cursor overlay
47  * functions which can be used to iterate over only the #VALUE_PAIR that match a
48  * vp_tmpl_t in a given list.
49  *
50  * @see tmpl_cursor_init
51  * @see tmpl_cursor_next
52  *
53  * Or for simplicity, there are functions which wrap the cursor functions, to copy or
54  * return the #VALUE_PAIR that match the VPT.
55  *
56  * @see tmpl_copy_vps
57  * @see tmpl_find_vp
58  *
59  * If you just need the string value of whatever the VPT refers to, the tmpl_*expand
60  * functions may be used. These functions evaluate the VPT, execing, and xlat expanding
61  * as necessary. In the case of #TMPL_TYPE_ATTR, and #PW_TYPE_STRING or #PW_TYPE_OCTETS
62  * #tmpl_expand will return a pointer to the raw #VALUE_PAIR buffer. This can be very
63  * useful when using the #PW_TYPE_TMPL type in #CONF_PARSER structs, as it allows the
64  * user to determine whether they want the module to sanitise the value using presentation
65  * format specific #xlat_escape_t function, or to operate on the raw value.
66  *
67  * @see tmpl_expand
68  * @see tmpl_aexpand
69  *
70  * @copyright 2014-2015 The FreeRADIUS server project
71  */
72 
73 RCSIDH(tmpl_h, "$Id: 92884b186bddef23432c4ad74bd1dc1d10c6466c $")
74 
75 #include <freeradius-devel/xlat.h>
76 
77 #ifdef __cplusplus
78 extern "C" {
79 #endif
80 #
81 typedef enum pair_lists {
82 	PAIR_LIST_UNKNOWN = 0,		//!< Unknown list.
83 	PAIR_LIST_REQUEST,		//!< Attributes in incoming or internally proxied
84 					///< request.
85 	PAIR_LIST_REPLY,		//!< Attributes to send in the response.
86 	PAIR_LIST_CONTROL,		//!< Attributes that change the behaviour of
87 					///< modules.
88 	PAIR_LIST_STATE,		//!< Attributes to store multiple rounds of
89 					///< challenges/responses.
90 #ifdef WITH_PROXY
91 	PAIR_LIST_PROXY_REQUEST,	//!< A copy of attributes in the request list
92 					///< that may be modified in pre-proxy before
93 					//!< proxying the request.
94 	PAIR_LIST_PROXY_REPLY,		//!< Attributes sent in response to the proxied
95 					///< request.
96 #endif
97 #ifdef WITH_COA
98 	PAIR_LIST_COA,			//!< Attributes to send in a forked CoA-Request.
99 	PAIR_LIST_COA_REPLY,		//!< Attributes sent in response to the forked
100 					///< CoA-Request.
101 	PAIR_LIST_DM,			//!< Attributes to send in a forked Disconnect-Request.
102 	PAIR_LIST_DM_REPLY		//!< Attributes sent in response to the forked
103 					//!< Disconnect-Request.
104 #endif
105 } pair_lists_t;
106 
107 extern const FR_NAME_NUMBER pair_lists[];
108 
109 typedef enum requests {
110 	REQUEST_UNKNOWN = 0,		//!< Unknown request.
111 	REQUEST_OUTER,			//!< #REQUEST containing the outer layer of the EAP
112 					//!< conversation. Usually the RADIUS request sent
113 					//!< by the NAS.
114 	REQUEST_CURRENT,		//!< The current request.
115 	REQUEST_PARENT			//!< Not currently used.
116 } request_refs_t;
117 
118 extern const FR_NAME_NUMBER request_refs[];
119 
120 typedef struct pair_list {
121 	char const		*name;
122 	VALUE_PAIR		*check;
123 	VALUE_PAIR		*reply;
124 	int			order;		/* for ordering! */
125 	int			lineno;
126 	struct pair_list	*next;
127 } PAIR_LIST;
128 
129 /** Types of #vp_tmpl_t
130  */
131 typedef enum tmpl_type {
132 	TMPL_TYPE_UNKNOWN = 0,		//!< Uninitialised.
133 	TMPL_TYPE_LITERAL,		//!< Literal string.
134 	TMPL_TYPE_XLAT,			//!< XLAT expansion.
135 	TMPL_TYPE_ATTR,			//!< Dictionary attribute.
136 	TMPL_TYPE_ATTR_UNDEFINED,	//!< Attribute not found in the global dictionary.
137 	TMPL_TYPE_LIST,			//!< Attribute list.
138 	TMPL_TYPE_REGEX,		//!< Regular expression.
139 	TMPL_TYPE_EXEC,			//!< Callout to an external script or program.
140 	TMPL_TYPE_DATA,			//!< Value in native format.
141 	TMPL_TYPE_XLAT_STRUCT,	      	//!< Pre-parsed XLAT expansion.
142 	TMPL_TYPE_REGEX_STRUCT,	      	//!< Pre-parsed regular expression.
143 	TMPL_TYPE_NULL			//!< Has no value.
144 } tmpl_type_t;
145 
146 extern const FR_NAME_NUMBER tmpl_names[];
147 
148 /** Describes a #TMPL_TYPE_ATTR, #TMPL_TYPE_ATTR_UNDEFINED or #TMPL_TYPE_LIST
149  */
150 typedef struct {
151 	request_refs_t		request;		//!< Request to search or insert in.
152 	pair_lists_t		list;			//!< List to search or insert in.
153 
154 	DICT_ATTR const		*da;			//!< Resolved dictionary attribute.
155 	union {
156 		uint8_t			da[DICT_ATTR_SIZE];	//!< Unknown dictionary attribute buffer.
157 		char			name[DICT_ATTR_SIZE];	//!< Raw unknown dictionary name.
158 	} unknown;
159 	int			num;			 //!< For array references.
160 	int8_t			tag;			 //!< For tag references.
161 } value_pair_tmpl_attr_t;
162 
163 /** A source or sink of value data.
164  *
165  * Is used as both the RHS and LHS of a map (both update, and conditional types)
166  *
167  * @section update_maps Use in update vp_map_t
168  * When used on the LHS it describes an attribute to create and should be one of these types:
169  * - #TMPL_TYPE_ATTR
170  * - #TMPL_TYPE_LIST
171  *
172  * When used on the RHS it describes the value to assign to the attribute being created and
173  * should be one of these types:
174  * - #TMPL_TYPE_LITERAL
175  * - #TMPL_TYPE_XLAT
176  * - #TMPL_TYPE_ATTR
177  * - #TMPL_TYPE_LIST
178  * - #TMPL_TYPE_EXEC
179  * - #TMPL_TYPE_DATA
180  * - #TMPL_TYPE_XLAT_STRUCT (pre-parsed xlat)
181  *
182  * @section conditional_maps Use in conditional vp_map_t
183  * When used as part of a condition it may be any of the RHS side types, as well as:
184  * - #TMPL_TYPE_REGEX_STRUCT (pre-parsed regex)
185  *
186  * @see vp_map_t
187  */
188 typedef struct vp_tmpl_t {
189 	tmpl_type_t	type;		//!< What type of value tmpl refers to.
190 	char const	*name;		//!< Original attribute ref string, or
191 					//!< where this refers to a none FR
192 					//!< attribute, just the string id for
193 					//!< the attribute.
194 	size_t		len;		//!< Name length.
195 	char		quote;		//!< Quotation character for "name"
196 	bool		auto_converted; //!< Attr-26.9.1 --> Cisco-AVPair
197 
198 #ifdef HAVE_REGEX
199 	bool		iflag;		//!< regex - case insensitive (if operand is used in regex comparison)
200 	bool		mflag;		//!< regex - multiline flags (controls $ matching)
201 #endif
202 
203 	union {
204 		/*
205 		 *  Attribute reference. Either an attribute currently in the request
206 		 *  or an attribute to create.
207 		 */
208 		value_pair_tmpl_attr_t attribute;
209 
210 		/*
211 		 *  Attribute value. Typically used as the RHS of an update map.
212 		 */
213 		struct {
214 			PW_TYPE			type;			 //!< Type of data.
215 			size_t			length;			 //!< of the vpd data.
216 			value_data_t		data;			 //!< Value data.
217 		} literal;
218 
219 		xlat_exp_t	*xlat;	 //!< pre-parsed xlat_exp_t
220 
221 #ifdef HAVE_REGEX
222 		regex_t		*preg;	//!< pre-parsed regex_t
223 #endif
224 	} data;
225 } vp_tmpl_t;
226 
227 /** @name Field accessors for #TMPL_TYPE_ATTR, #TMPL_TYPE_ATTR_UNDEFINED, #TMPL_TYPE_LIST
228  *
229  * @{
230  */
231 #define tmpl_request		data.attribute.request
232 #define tmpl_list		data.attribute.list
233 #define tmpl_da			data.attribute.da
234 #define tmpl_unknown		data.attribute.unknown.da
235 #define tmpl_unknown_name      	data.attribute.unknown.name
236 #define tmpl_num		data.attribute.num
237 #define tmpl_tag		data.attribute.tag
238 /* @} **/
239 
240 /** @name Field accessors for #TMPL_TYPE_XLAT_STRUCT
241  *
242  * @{
243  */
244 #define tmpl_xlat		data.xlat
245 /* @} **/
246 
247 /** @name Field accessors for #TMPL_TYPE_DATA
248  *
249  * @{
250  */
251 #define tmpl_data		data.literal
252 #define tmpl_data_type		data.literal.type
253 #define tmpl_data_length	data.literal.length
254 #define tmpl_data_value		data.literal.data
255 /* @} **/
256 
257 /** @name Field accessors for #TMPL_TYPE_REGEX_STRUCT and #TMPL_TYPE_REGEX
258  *
259  * @{
260  */
261 #ifdef HAVE_REGEX
262 #  define tmpl_preg		data.preg	//!< #TMPL_TYPE_REGEX_STRUCT only.
263 #  define tmpl_iflag		iflag
264 #  define tmpl_mflag		mflag
265 #endif
266 /* @} **/
267 
268 #ifndef WITH_VERIFY_PTR
269 #  define VERIFY_TMPL(_x)
270 #else
271 #  define VERIFY_TMPL(_x) tmpl_verify(__FILE__,  __LINE__, _x)
272 void tmpl_verify(char const *file, int line, vp_tmpl_t const *vpt);
273 #endif
274 
275 VALUE_PAIR		**radius_list(REQUEST *request, pair_lists_t list);
276 
277 RADIUS_PACKET		*radius_packet(REQUEST *request, pair_lists_t list_name);
278 
279 TALLOC_CTX		*radius_list_ctx(REQUEST *request, pair_lists_t list_name);
280 
281 size_t			radius_list_name(pair_lists_t *out, char const *name, pair_lists_t default_list);
282 
283 int			radius_request(REQUEST **request, request_refs_t name);
284 
285 size_t			radius_request_name(request_refs_t *out, char const *name, request_refs_t unknown);
286 
287 vp_tmpl_t		*tmpl_init(vp_tmpl_t *vpt, tmpl_type_t type,
288 				   char const *name, ssize_t len);
289 
290 vp_tmpl_t		*tmpl_alloc(TALLOC_CTX *ctx, tmpl_type_t type, char const *name,
291 				    ssize_t len);
292 
293 ssize_t			tmpl_from_attr_substr(vp_tmpl_t *vpt, char const *name,
294 					      request_refs_t request_def, pair_lists_t list_def,
295 					      bool allow_unknown, bool allow_undefined);
296 
297 ssize_t			tmpl_from_attr_str(vp_tmpl_t *vpt, char const *name,
298 					   request_refs_t request_def,
299 					   pair_lists_t list_def,
300 					   bool allow_unknown, bool allow_undefined);
301 
302 ssize_t			tmpl_afrom_attr_substr(TALLOC_CTX *ctx, vp_tmpl_t **out, char const *name,
303 					       request_refs_t request_def, pair_lists_t list_def,
304 					       bool allow_unknown, bool allow_undefined);
305 
306 ssize_t			tmpl_afrom_attr_str(TALLOC_CTX *ctx, vp_tmpl_t **out, char const *name,
307 					    request_refs_t request_def,
308 					    pair_lists_t list_def,
309 					    bool allow_unknown, bool allow_undefined);
310 
311 ssize_t			tmpl_afrom_str(TALLOC_CTX *ctx, vp_tmpl_t **out, char const *name, size_t inlen,
312 				       FR_TOKEN type, request_refs_t request_def, pair_lists_t list_def, bool do_escape);
313 
314 int			tmpl_cast_in_place(vp_tmpl_t *vpt, PW_TYPE type, DICT_ATTR const *enumv);
315 
316 void			tmpl_cast_in_place_str(vp_tmpl_t *vpt);
317 
318 int			tmpl_cast_to_vp(VALUE_PAIR **out, REQUEST *request,
319 					vp_tmpl_t const *vpt, DICT_ATTR const *cast);
320 
321 size_t			tmpl_prints(char *buffer, size_t bufsize, vp_tmpl_t const *vpt,
322 				    DICT_ATTR const *values);
323 
324 ssize_t			tmpl_expand(char const **out, char *buff, size_t outlen, REQUEST *request,
325 				    vp_tmpl_t const *vpt, xlat_escape_t escape, void *escape_ctx);
326 
327 ssize_t			tmpl_aexpand(TALLOC_CTX *ctx, char **out, REQUEST *request, vp_tmpl_t const *vpt,
328 				     xlat_escape_t escape, void *escape_ctx);
329 
330 VALUE_PAIR		*tmpl_cursor_init(int *err, vp_cursor_t *cursor, REQUEST *request,
331 					  vp_tmpl_t const *vpt);
332 
333 VALUE_PAIR		*tmpl_cursor_next(vp_cursor_t *cursor, vp_tmpl_t const *vpt);
334 
335 int			tmpl_copy_vps(TALLOC_CTX *ctx, VALUE_PAIR **out, REQUEST *request,
336 				      vp_tmpl_t const *vpt);
337 
338 int			tmpl_find_vp(VALUE_PAIR **out, REQUEST *request, vp_tmpl_t const *vpt);
339 
340 int			tmpl_define_unknown_attr(vp_tmpl_t *vpt);
341 
342 #ifdef __cplusplus
343 }
344 #endif
345 #endif	/* TMPL_H */
346