1 /******************************************************************************
3 * Copyright (C) 2000 Pierangelo Masarati, <ando@sys-net.it>
6 * Permission is granted to anyone to use this software for any purpose
7 * on any computer system, and to alter it and redistribute it, subject
8 * to the following restrictions:
10 * 1. The author is not responsible for the consequences of use of this
11 * software, no matter how awful, even if they arise from flaws in it.
13 * 2. The origin of this software must not be misrepresented, either by
14 * explicit claim or by omission. Since few users ever read sources,
15 * credits should appear in the documentation.
17 * 3. Altered versions must be plainly marked as such, and must not be
18 * misrepresented as being the original software. Since few users
19 * ever read sources, credits should appear in the documentation.
21 * 4. This notice may not be removed or altered.
23 ******************************************************************************/
29 * These are required by every file of the library, so they're included here
31 #include <ac/stdlib.h>
32 #include <ac/string.h>
33 #include <ac/syslog.h>
35 #include <ac/socket.h>
36 #include <ac/unistd.h>
41 #include "../libldap/ldap-int.h"
47 /* Uncomment to use ldap pvt threads */
48 #define USE_REWRITE_LDAP_PVT_THREADS
49 #include <ldap_pvt_thread.h>
52 * For details, see RATIONALE.
55 #define REWRITE_MAX_MATCH 11 /* 0: overall string; 1-9: submatches */
56 #define REWRITE_MAX_PASSES 100
59 * Submatch escape char
61 /* the '\' conflicts with slapd.conf parsing */
62 /* #define REWRITE_SUBMATCH_ESCAPE '\\' */
63 #define REWRITE_SUBMATCH_ESCAPE '%'
69 #define REWRITE_FLAG_HONORCASE 'C'
70 #define REWRITE_FLAG_BASICREGEX 'R'
75 #define REWRITE_FLAG_EXECONCE ':'
76 #define REWRITE_FLAG_STOP '@'
77 #define REWRITE_FLAG_UNWILLING '#'
78 #define REWRITE_FLAG_GOTO 'G' /* requires an arg */
79 #define REWRITE_FLAG_IGNORE_ERR 'I'
84 #define REWRITE_OPERATOR_SUBCONTEXT '>'
85 #define REWRITE_OPERATOR_COMMAND '|'
86 #define REWRITE_OPERATOR_VARIABLE_SET '&'
87 #define REWRITE_OPERATOR_VARIABLE_GET '*'
88 #define REWRITE_OPERATOR_PARAM_GET '$'
98 struct rewrite_action {
99 struct rewrite_action *la_next;
101 #define REWRITE_ACTION_STOP 0x0001
102 #define REWRITE_ACTION_UNWILLING 0x0002
103 #define REWRITE_ACTION_GOTO 0x0003
104 #define REWRITE_ACTION_IGNORE_ERR 0x0004
117 #define REWRITE_MAP_XFILEMAP 0x0001 /* Rough implementation! */
118 #define REWRITE_MAP_XPWDMAP 0x0002 /* uid -> gecos */
119 #define REWRITE_MAP_XLDAPMAP 0x0003 /* Not implemented yet! */
124 #define REWRITE_MAP_SUBCONTEXT 0x0101
126 #define REWRITE_MAP_SET_OP_VAR 0x0102
127 #define REWRITE_MAP_SETW_OP_VAR 0x0103
128 #define REWRITE_MAP_GET_OP_VAR 0x0104
129 #define REWRITE_MAP_SET_SESN_VAR 0x0105
130 #define REWRITE_MAP_SETW_SESN_VAR 0x0106
131 #define REWRITE_MAP_GET_SESN_VAR 0x0107
132 #define REWRITE_MAP_GET_PARAM 0x0108
133 #define REWRITE_MAP_BUILTIN 0x0109
140 * Old maps store private data in _lm_args;
141 * new maps store the substitution pattern in _lm_subst
145 struct rewrite_subst *_lm_subst;
147 #define lm_args lm_union._lm_args
148 #define lm_subst lm_union._lm_subst
150 #ifdef USE_REWRITE_LDAP_PVT_THREADS
151 ldap_pvt_thread_mutex_t lm_mutex;
152 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
158 struct rewrite_builtin_map {
159 #define REWRITE_BUILTIN_MAP_LDAP 0x0201
164 #ifdef USE_REWRITE_LDAP_PVT_THREADS
165 ldap_pvt_thread_mutex_t lb_mutex;
166 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
170 * Submatch substitution
172 struct rewrite_submatch {
173 #define REWRITE_SUBMATCH_ASIS 0x0000
174 #define REWRITE_SUBMATCH_XMAP 0x0001
175 #define REWRITE_SUBMATCH_MAP_W_ARG 0x0002
177 struct rewrite_map *ls_map;
180 * The first one represents the index of the submatch in case
181 * the map has single submatch as argument;
182 * the latter represents the map argument scheme in case
183 * the map has substitution string argument form
188 * Pattern substitution
190 struct rewrite_subst {
192 struct berval **lt_subs;
195 struct rewrite_submatch **lt_submatch;
201 struct rewrite_rule {
202 struct rewrite_rule *lr_next;
203 struct rewrite_rule *lr_prev;
206 char *lr_subststring;
211 * I was thinking about some kind of per-rule mutex, but there's
212 * probably no need, because rules after compilation are only read;
213 * however, I need to check whether regexec is reentrant ...
216 struct rewrite_subst *lr_subst;
218 #define REWRITE_REGEX_ICASE REG_ICASE
219 #define REWRITE_REGEX_EXTENDED REG_EXTENDED
222 #define REWRITE_RECURSE 0x0001
223 #define REWRITE_EXEC_ONCE 0x0002
226 struct rewrite_action *lr_action;
230 * Rewrite Context (set of rules)
232 struct rewrite_context {
234 struct rewrite_context *lc_alias;
235 struct rewrite_rule *lc_rule;
241 struct rewrite_session {
244 #ifdef USE_REWRITE_LDAP_PVT_THREADS
245 ldap_pvt_thread_rdwr_t ls_vars_mutex;
246 ldap_pvt_thread_mutex_t ls_mutex;
247 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
256 struct berval lv_value;
268 const void *lo_cookie;
279 struct rewrite_info {
283 * No global mutex because maps are read only at
290 #ifdef USE_REWRITE_LDAP_PVT_THREADS
291 ldap_pvt_thread_rdwr_t li_params_mutex;
292 ldap_pvt_thread_rdwr_t li_cookies_mutex;
293 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
297 * use `rewriteEngine {on|off}' directive to alter
302 * Defaults to REWRITE_MAXPASSES;
303 * use `rewriteMaxPasses numPasses' directive to alter
305 #define REWRITE_MAXPASSES 100
309 * Behavior in case a NULL or non-existent context is required
318 LDAP_REWRITE_V (struct rewrite_context*) __curr_context;
325 * Parses a map (also in legacy 'x' version)
327 LDAP_REWRITE_F (struct rewrite_map *)
329 struct rewrite_info *info,
334 LDAP_REWRITE_F (struct rewrite_map *)
336 struct rewrite_info *info,
342 * Resolves key in val by means of map (also in legacy 'x' version)
346 struct rewrite_info *info,
347 struct rewrite_op *op,
348 struct rewrite_map *map,
355 struct rewrite_info *info,
356 struct rewrite_op *op,
357 struct rewrite_map *map,
364 * Submatch substitution
368 * Compiles a substitution pattern
370 LDAP_REWRITE_F (struct rewrite_subst *)
371 rewrite_subst_compile(
372 struct rewrite_info *info,
377 * Substitutes a portion of rewritten string according to substitution
378 * pattern using submatches
382 struct rewrite_info *info,
383 struct rewrite_op *op,
384 struct rewrite_subst *subst,
386 const regmatch_t *match,
396 * Compiles the rule and appends it at the running context
399 rewrite_rule_compile(
400 struct rewrite_info *info,
401 struct rewrite_context *context,
404 const char *flagstring
408 * Rewrites string according to rule; may return:
409 * REWRITE_REGEXEC_OK: fine; if *result != NULL rule matched
410 * and rewrite succeeded.
411 * REWRITE_REGEXEC_STOP: fine, rule matched; stop processing
413 * REWRITE_REGEXEC_UNWILL: rule matched; force 'unwilling to perform'
414 * REWRITE_REGEXEC_ERR: an error occurred
418 struct rewrite_info *info,
419 struct rewrite_op *op,
420 struct rewrite_rule *rule,
430 * Fetches a struct rewrite_session
432 LDAP_REWRITE_F (struct rewrite_session *)
433 rewrite_session_find(
434 struct rewrite_info *info,
439 * Defines and inits a variable with session scope
442 rewrite_session_var_set(
443 struct rewrite_info *info,
450 * Gets a var with session scope
453 rewrite_session_var_get(
454 struct rewrite_info *info,
464 rewrite_session_delete(
465 struct rewrite_info *info,
470 * Destroys the cookie tree
473 rewrite_session_destroy(
474 struct rewrite_info *info
485 LDAP_REWRITE_F (struct rewrite_var *)
492 * Inserts a newly created var
494 LDAP_REWRITE_F (struct rewrite_var *)
504 LDAP_REWRITE_F (struct rewrite_var *)
526 * Finds the context named rewriteContext in the context tree
528 LDAP_REWRITE_F (struct rewrite_context *)
529 rewrite_context_find(
530 struct rewrite_info *info,
531 const char *rewriteContext
535 * Creates a new context called rewriteContext and stores in into the tree
537 LDAP_REWRITE_F (struct rewrite_context *)
538 rewrite_context_create(
539 struct rewrite_info *info,
540 const char *rewriteContext
544 * Rewrites string according to context; may return:
545 * OK: fine; if *result != NULL rule matched and rewrite succeeded.
546 * STOP: fine, rule matched; stop processing following rules
547 * UNWILL: rule matched; force 'unwilling to perform'
550 rewrite_context_apply(
551 struct rewrite_info *info,
552 struct rewrite_op *op,
553 struct rewrite_context *context,
558 #endif /* REWRITE_INT_H */