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