1 /*	$NetBSD: rewrite-int.h,v 1.3 2021/08/14 16:14:58 christos Exp $	*/
2 
3 /* $OpenLDAP$ */
4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5  *
6  * Copyright 2000-2021 The OpenLDAP Foundation.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted only as authorized by the OpenLDAP
11  * Public License.
12  *
13  * A copy of this license is available in the file LICENSE in the
14  * top-level directory of the distribution or, alternatively, at
15  * <http://www.OpenLDAP.org/license.html>.
16  */
17 /* ACKNOWLEDGEMENT:
18  * This work was initially developed by Pierangelo Masarati for
19  * inclusion in OpenLDAP Software.
20  */
21 
22 #ifndef REWRITE_INT_H
23 #define REWRITE_INT_H
24 
25 /*
26  * These are required by every file of the library, so they're included here
27  */
28 #include <ac/stdlib.h>
29 #include <ac/string.h>
30 #include <ac/syslog.h>
31 #include <ac/regex.h>
32 #include <ac/socket.h>
33 #include <ac/unistd.h>
34 #include <ac/ctype.h>
35 
36 #include <lber.h>
37 #include <ldap.h>
38 #define LDAP_DEFINE_LDAP_DEBUG
39 #include <ldap_log.h>
40 #include <lutil.h>
41 #include <ldap_avl.h>
42 
43 #include <rewrite.h>
44 
45 #define malloc(x)	ber_memalloc(x)
46 #define calloc(x,y)	ber_memcalloc(x,y)
47 #define realloc(x,y)	ber_memrealloc(x,y)
48 #define free(x)	ber_memfree(x)
49 #undef strdup
50 #define	strdup(x)	ber_strdup(x)
51 
52 #ifndef NO_THREADS
53 #define USE_REWRITE_LDAP_PVT_THREADS
54 #include <ldap_pvt_thread.h>
55 #endif
56 
57 /*
58  * For details, see RATIONALE.
59  */
60 
61 #define REWRITE_MAX_MATCH	11	/* 0: overall string; 1-9: submatches */
62 #define REWRITE_MAX_PASSES	100
63 
64 /*
65  * Submatch escape char
66  */
67 /* the '\' conflicts with slapd.conf parsing */
68 /* #define REWRITE_SUBMATCH_ESCAPE			'\\' */
69 #define REWRITE_SUBMATCH_ESCAPE_ORIG		'%'
70 #define REWRITE_SUBMATCH_ESCAPE			'$'
71 #define IS_REWRITE_SUBMATCH_ESCAPE(c) \
72 	((c) == REWRITE_SUBMATCH_ESCAPE || (c) == REWRITE_SUBMATCH_ESCAPE_ORIG)
73 
74 /*
75  * REGEX flags
76  */
77 
78 #define REWRITE_FLAG_HONORCASE			'C'
79 #define REWRITE_FLAG_BASICREGEX			'R'
80 
81 /*
82  * Action flags
83  */
84 #define REWRITE_FLAG_EXECONCE			':'
85 #define REWRITE_FLAG_STOP			'@'
86 #define REWRITE_FLAG_UNWILLING			'#'
87 #define REWRITE_FLAG_GOTO			'G'	/* requires an arg */
88 #define REWRITE_FLAG_USER			'U'	/* requires an arg */
89 #define REWRITE_FLAG_MAX_PASSES			'M'	/* requires an arg */
90 #define REWRITE_FLAG_IGNORE_ERR			'I'
91 
92 /*
93  * Map operators
94  */
95 #define REWRITE_OPERATOR_SUBCONTEXT		'>'
96 #define REWRITE_OPERATOR_COMMAND		'|'
97 #define REWRITE_OPERATOR_VARIABLE_SET		'&'
98 #define REWRITE_OPERATOR_VARIABLE_GET		'*'
99 #define REWRITE_OPERATOR_PARAM_GET		'$'
100 
101 
102 /***********
103  * PRIVATE *
104  ***********/
105 
106 /*
107  * Action
108  */
109 struct rewrite_action {
110 	struct rewrite_action          *la_next;
111 
112 #define REWRITE_ACTION_STOP		0x0001
113 #define REWRITE_ACTION_UNWILLING	0x0002
114 #define REWRITE_ACTION_GOTO		0x0003
115 #define REWRITE_ACTION_IGNORE_ERR	0x0004
116 #define REWRITE_ACTION_USER		0x0005
117 	int                             la_type;
118 	void                           *la_args;
119 };
120 
121 /*
122  * Map
123  */
124 struct rewrite_map {
125 
126 	/*
127 	 * Legacy stuff
128 	 */
129 #define REWRITE_MAP_XFILEMAP		0x0001	/* Rough implementation! */
130 #define REWRITE_MAP_XPWDMAP		0x0002  /* uid -> gecos */
131 #define REWRITE_MAP_XLDAPMAP		0x0003	/* Not implemented yet! */
132 
133 	/*
134 	 * Maps with args
135 	 */
136 #define REWRITE_MAP_SUBCONTEXT		0x0101
137 
138 #define REWRITE_MAP_SET_OP_VAR		0x0102
139 #define REWRITE_MAP_SETW_OP_VAR		0x0103
140 #define REWRITE_MAP_GET_OP_VAR		0x0104
141 #define	REWRITE_MAP_SET_SESN_VAR	0x0105
142 #define REWRITE_MAP_SETW_SESN_VAR	0x0106
143 #define	REWRITE_MAP_GET_SESN_VAR	0x0107
144 #define REWRITE_MAP_GET_PARAM		0x0108
145 #define REWRITE_MAP_BUILTIN		0x0109
146 	int                             lm_type;
147 
148 	char                           *lm_name;
149 	void                           *lm_data;
150 
151 	/*
152 	 * Old maps store private data in _lm_args;
153 	 * new maps store the substitution pattern in _lm_subst
154 	 */
155 	union {
156 	        void                   *_lm_args;
157 		struct rewrite_subst   *_lm_subst;
158 	} lm_union;
159 #define	lm_args lm_union._lm_args
160 #define	lm_subst lm_union._lm_subst
161 
162 #ifdef USE_REWRITE_LDAP_PVT_THREADS
163 	ldap_pvt_thread_mutex_t         lm_mutex;
164 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
165 };
166 
167 /*
168  * Builtin maps
169  */
170 struct rewrite_builtin_map {
171 #define REWRITE_BUILTIN_MAP	0x0200
172 	int                             lb_type;
173 	char                           *lb_name;
174 	void                           *lb_private;
175 	const rewrite_mapper		   *lb_mapper;
176 
177 #ifdef USE_REWRITE_LDAP_PVT_THREADS
178 	ldap_pvt_thread_mutex_t         lb_mutex;
179 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
180 };
181 
182 /*
183  * Submatch substitution
184  */
185 struct rewrite_submatch {
186 #define REWRITE_SUBMATCH_ASIS		0x0000
187 #define REWRITE_SUBMATCH_XMAP		0x0001
188 #define REWRITE_SUBMATCH_MAP_W_ARG	0x0002
189 	int                             ls_type;
190 	struct rewrite_map             *ls_map;
191 	int                             ls_submatch;
192 	/*
193 	 * The first one represents the index of the submatch in case
194 	 * the map has single submatch as argument;
195 	 * the latter represents the map argument scheme in case
196 	 * the map has substitution string argument form
197 	 */
198 };
199 
200 /*
201  * Pattern substitution
202  */
203 struct rewrite_subst {
204 	size_t                          lt_subs_len;
205 	struct berval                  *lt_subs;
206 
207 	int                             lt_num_submatch;
208 	struct rewrite_submatch        *lt_submatch;
209 };
210 
211 /*
212  * Rule
213  */
214 struct rewrite_rule {
215 	struct rewrite_rule            *lr_next;
216 	struct rewrite_rule            *lr_prev;
217 
218 	char                           *lr_pattern;
219 	char                           *lr_subststring;
220 	char                           *lr_flagstring;
221 	regex_t				lr_regex;
222 
223 	/*
224 	 * I was thinking about some kind of per-rule mutex, but there's
225 	 * probably no need, because rules after compilation are only read;
226 	 * however, I need to check whether regexec is reentrant ...
227 	 */
228 
229 	struct rewrite_subst           *lr_subst;
230 
231 #define REWRITE_REGEX_ICASE		REG_ICASE
232 #define REWRITE_REGEX_EXTENDED		REG_EXTENDED
233 	int                             lr_flags;
234 
235 #define REWRITE_RECURSE			0x0001
236 #define REWRITE_EXEC_ONCE          	0x0002
237 	int				lr_mode;
238 	int				lr_max_passes;
239 
240 	struct rewrite_action          *lr_action;
241 };
242 
243 /*
244  * Rewrite Context (set of rules)
245  */
246 struct rewrite_context {
247 	char                           *lc_name;
248 	struct rewrite_context         *lc_alias;
249 	struct rewrite_rule            *lc_rule;
250 };
251 
252 /*
253  * Session
254  */
255 struct rewrite_session {
256 	void                           *ls_cookie;
257 	Avlnode                        *ls_vars;
258 #ifdef USE_REWRITE_LDAP_PVT_THREADS
259 	ldap_pvt_thread_rdwr_t          ls_vars_mutex;
260 	ldap_pvt_thread_mutex_t		ls_mutex;
261 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
262 	int				ls_count;
263 };
264 
265 /*
266  * Variable
267  */
268 struct rewrite_var {
269 	char                           *lv_name;
270 	int				lv_flags;
271 	struct berval                   lv_value;
272 };
273 
274 /*
275  * Operation
276  */
277 struct rewrite_op {
278 	int                             lo_num_passes;
279 	int                             lo_depth;
280 #if 0 /* FIXME: not used anywhere! (debug? then, why strdup?) */
281 	char                           *lo_string;
282 #endif
283 	char                           *lo_result;
284 	Avlnode                        *lo_vars;
285 	const void                     *lo_cookie;
286 };
287 
288 
289 /**********
290  * PUBLIC *
291  **********/
292 
293 /*
294  * Rewrite info
295  */
296 struct rewrite_info {
297 	Avlnode                        *li_context;
298 	Avlnode                        *li_maps;
299 	/*
300 	 * No global mutex because maps are read only at
301 	 * config time
302 	 */
303 	Avlnode                        *li_params;
304 	Avlnode                        *li_cookies;
305 	int                             li_num_cookies;
306 
307 #ifdef USE_REWRITE_LDAP_PVT_THREADS
308 	ldap_pvt_thread_rdwr_t          li_params_mutex;
309         ldap_pvt_thread_rdwr_t          li_cookies_mutex;
310 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
311 
312 	/*
313 	 * Default to `off';
314 	 * use `rewriteEngine {on|off}' directive to alter
315 	 */
316 	int				li_state;
317 
318 	/*
319 	 * Defaults to REWRITE_MAXPASSES;
320 	 * use `rewriteMaxPasses numPasses' directive to alter
321 	 */
322 #define REWRITE_MAXPASSES		100
323 	int                             li_max_passes;
324 	int                             li_max_passes_per_rule;
325 
326 	/*
327 	 * Behavior in case a NULL or non-existent context is required
328 	 */
329 	int                             li_rewrite_mode;
330 };
331 
332 /***********
333  * PRIVATE *
334  ***********/
335 
336 LDAP_REWRITE_V (struct rewrite_context*) rewrite_int_curr_context;
337 
338 /*
339  * Maps
340  */
341 
342 /*
343  * Parses a map (also in legacy 'x' version)
344  */
345 LDAP_REWRITE_F (struct rewrite_map *)
346 rewrite_map_parse(
347 		struct rewrite_info *info,
348 		const char *s,
349 		const char **end
350 );
351 
352 LDAP_REWRITE_F (struct rewrite_map *)
353 rewrite_xmap_parse(
354 		struct rewrite_info *info,
355 		const char *s,
356 		const char **end
357 );
358 
359 /*
360  * Resolves key in val by means of map (also in legacy 'x' version)
361  */
362 LDAP_REWRITE_F (int)
363 rewrite_map_apply(
364 		struct rewrite_info *info,
365 		struct rewrite_op *op,
366 		struct rewrite_map *map,
367 		struct berval *key,
368 		struct berval *val
369 );
370 
371 LDAP_REWRITE_F (int)
372 rewrite_xmap_apply(
373 		struct rewrite_info *info,
374 		struct rewrite_op *op,
375 		struct rewrite_map *map,
376 		struct berval *key,
377 		struct berval *val
378 );
379 
380 LDAP_REWRITE_F (int)
381 rewrite_map_destroy(
382 		struct rewrite_map **map
383 );
384 
385 LDAP_REWRITE_F (int)
386 rewrite_xmap_destroy(
387 		struct rewrite_map **map
388 );
389 
390 LDAP_REWRITE_F (void)
391 rewrite_builtin_map_free(
392 		void *map
393 );
394 /*
395  * Submatch substitution
396  */
397 
398 /*
399  * Compiles a substitution pattern
400  */
401 LDAP_REWRITE_F (struct rewrite_subst *)
402 rewrite_subst_compile(
403 		struct rewrite_info *info,
404 		const char *result
405 );
406 
407 /*
408  * Substitutes a portion of rewritten string according to substitution
409  * pattern using submatches
410  */
411 LDAP_REWRITE_F (int)
412 rewrite_subst_apply(
413 		struct rewrite_info *info,
414 		struct rewrite_op *op,
415 		struct rewrite_subst *subst,
416 		const char *string,
417 		const regmatch_t *match,
418 		struct berval *val
419 );
420 
421 LDAP_REWRITE_F (int)
422 rewrite_subst_destroy(
423 		struct rewrite_subst **subst
424 );
425 
426 
427 /*
428  * Rules
429  */
430 
431 /*
432  * Compiles the rule and appends it at the running context
433  */
434 LDAP_REWRITE_F (int)
435 rewrite_rule_compile(
436 		struct rewrite_info *info,
437 		struct rewrite_context *context,
438 		const char *pattern,
439 		const char *result,
440 		const char *flagstring
441 );
442 
443 /*
444  * Rewrites string according to rule; may return:
445  *      REWRITE_REGEXEC_OK:	fine; if *result != NULL rule matched
446  *      			and rewrite succeeded.
447  *      REWRITE_REGEXEC_STOP:   fine, rule matched; stop processing
448  *      			following rules
449  *      REWRITE_REGEXEC_UNWILL: rule matched; force 'unwilling to perform'
450  *      REWRITE_REGEXEC_ERR:	an error occurred
451  */
452 LDAP_REWRITE_F (int)
453 rewrite_rule_apply(
454 		struct rewrite_info *info,
455 		struct rewrite_op *op,
456 		struct rewrite_rule *rule,
457 		const char *string,
458 		char **result
459 );
460 
461 LDAP_REWRITE_F (int)
462 rewrite_rule_destroy(
463 		struct rewrite_rule **rule
464 );
465 
466 /*
467  * Sessions
468  */
469 
470 /*
471  * Fetches a struct rewrite_session
472  */
473 LDAP_REWRITE_F (struct rewrite_session *)
474 rewrite_session_find(
475                 struct rewrite_info *info,
476                 const void *cookie
477 );
478 
479 /*
480  * Defines and inits a variable with session scope
481  */
482 LDAP_REWRITE_F (int)
483 rewrite_session_var_set_f(
484                 struct rewrite_info *info,
485                 const void *cookie,
486                 const char *name,
487                 const char *value,
488 		int flags
489 );
490 
491 /*
492  * Gets a var with session scope
493  */
494 LDAP_REWRITE_F (int)
495 rewrite_session_var_get(
496                 struct rewrite_info *info,
497                 const void *cookie,
498                 const char *name,
499                 struct berval *val
500 );
501 
502 /*
503  * Deletes a session
504  */
505 LDAP_REWRITE_F (int)
506 rewrite_session_delete(
507                 struct rewrite_info *info,
508                 const void *cookie
509 );
510 
511 /*
512  * Destroys the cookie tree
513  */
514 LDAP_REWRITE_F (int)
515 rewrite_session_destroy(
516                 struct rewrite_info *info
517 );
518 
519 
520 /*
521  * Vars
522  */
523 
524 /*
525  * Finds a var
526  */
527 LDAP_REWRITE_F (struct rewrite_var *)
528 rewrite_var_find(
529                 Avlnode *tree,
530                 const char *name
531 );
532 
533 /*
534  * Replaces the value of a variable
535  */
536 LDAP_REWRITE_F (int)
537 rewrite_var_replace(
538 		struct rewrite_var *var,
539 		const char *value,
540 		int flags
541 );
542 
543 /*
544  * Inserts a newly created var
545  */
546 LDAP_REWRITE_F (struct rewrite_var *)
547 rewrite_var_insert_f(
548                 Avlnode **tree,
549                 const char *name,
550                 const char *value,
551 		int flags
552 );
553 
554 #define rewrite_var_insert(tree, name, value) \
555 	rewrite_var_insert_f((tree), (name), (value), \
556 			REWRITE_VAR_UPDATE|REWRITE_VAR_COPY_NAME|REWRITE_VAR_COPY_VALUE)
557 
558 /*
559  * Sets/inserts a var
560  */
561 LDAP_REWRITE_F (struct rewrite_var *)
562 rewrite_var_set_f(
563                 Avlnode **tree,
564                 const char *name,
565                 const char *value,
566                 int flags
567 );
568 
569 #define rewrite_var_set(tree, name, value, insert) \
570 	rewrite_var_set_f((tree), (name), (value), \
571 			REWRITE_VAR_UPDATE|REWRITE_VAR_COPY_NAME|REWRITE_VAR_COPY_VALUE|((insert)? REWRITE_VAR_INSERT : 0))
572 
573 /*
574  * Deletes a var tree
575  */
576 LDAP_REWRITE_F (int)
577 rewrite_var_delete(
578                 Avlnode *tree
579 );
580 
581 
582 /*
583  * Contexts
584  */
585 
586 /*
587  * Finds the context named rewriteContext in the context tree
588  */
589 LDAP_REWRITE_F (struct rewrite_context *)
590 rewrite_context_find(
591 		struct rewrite_info *info,
592 		const char *rewriteContext
593 );
594 
595 /*
596  * Creates a new context called rewriteContext and stores in into the tree
597  */
598 LDAP_REWRITE_F (struct rewrite_context *)
599 rewrite_context_create(
600 		struct rewrite_info *info,
601 		const char *rewriteContext
602 );
603 
604 /*
605  * Rewrites string according to context; may return:
606  *      OK:     fine; if *result != NULL rule matched and rewrite succeeded.
607  *      STOP:   fine, rule matched; stop processing following rules
608  *      UNWILL: rule matched; force 'unwilling to perform'
609  */
610 LDAP_REWRITE_F (int)
611 rewrite_context_apply(
612 		struct rewrite_info *info,
613 		struct rewrite_op *op,
614 		struct rewrite_context *context,
615 		const char *string,
616 		char **result
617 );
618 
619 LDAP_REWRITE_F (int)
620 rewrite_context_destroy(
621 		struct rewrite_context **context
622 );
623 
624 LDAP_REWRITE_F (void)
625 rewrite_context_free(
626 		void *tmp
627 );
628 
629 #endif /* REWRITE_INT_H */
630 
631