2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 * Copyright 2000-2004 The OpenLDAP Foundation.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted only as authorized by the OpenLDAP
11 * A copy of this license is available in the file LICENSE in the
12 * top-level directory of the distribution or, alternatively, at
13 * <http://www.OpenLDAP.org/license.html>.
16 * This work was initially developed by Pierangelo Masarati for
17 * inclusion in OpenLDAP Software.
24 * These are required by every file of the library, so they're included here
26 #include <ac/stdlib.h>
27 #include <ac/string.h>
28 #include <ac/syslog.h>
30 #include <ac/socket.h>
31 #include <ac/unistd.h>
36 #include "../libldap/ldap-int.h"
42 /* Uncomment to use ldap pvt threads */
43 #define USE_REWRITE_LDAP_PVT_THREADS
44 #include <ldap_pvt_thread.h>
47 * For details, see RATIONALE.
50 #define REWRITE_MAX_MATCH 11 /* 0: overall string; 1-9: submatches */
51 #define REWRITE_MAX_PASSES 100
54 * Submatch escape char
56 /* the '\' conflicts with slapd.conf parsing */
57 /* #define REWRITE_SUBMATCH_ESCAPE '\\' */
58 #define REWRITE_SUBMATCH_ESCAPE '%'
64 #define REWRITE_FLAG_HONORCASE 'C'
65 #define REWRITE_FLAG_BASICREGEX 'R'
70 #define REWRITE_FLAG_EXECONCE ':'
71 #define REWRITE_FLAG_STOP '@'
72 #define REWRITE_FLAG_UNWILLING '#'
73 #define REWRITE_FLAG_GOTO 'G' /* requires an arg */
74 #define REWRITE_FLAG_USER 'U' /* requires an arg */
75 #define REWRITE_FLAG_MAX_PASSES 'M' /* requires an arg */
76 #define REWRITE_FLAG_IGNORE_ERR 'I'
81 #define REWRITE_OPERATOR_SUBCONTEXT '>'
82 #define REWRITE_OPERATOR_COMMAND '|'
83 #define REWRITE_OPERATOR_VARIABLE_SET '&'
84 #define REWRITE_OPERATOR_VARIABLE_GET '*'
85 #define REWRITE_OPERATOR_PARAM_GET '$'
95 struct rewrite_action {
96 struct rewrite_action *la_next;
98 #define REWRITE_ACTION_STOP 0x0001
99 #define REWRITE_ACTION_UNWILLING 0x0002
100 #define REWRITE_ACTION_GOTO 0x0003
101 #define REWRITE_ACTION_IGNORE_ERR 0x0004
102 #define REWRITE_ACTION_USER 0x0005
115 #define REWRITE_MAP_XFILEMAP 0x0001 /* Rough implementation! */
116 #define REWRITE_MAP_XPWDMAP 0x0002 /* uid -> gecos */
117 #define REWRITE_MAP_XLDAPMAP 0x0003 /* Not implemented yet! */
122 #define REWRITE_MAP_SUBCONTEXT 0x0101
124 #define REWRITE_MAP_SET_OP_VAR 0x0102
125 #define REWRITE_MAP_SETW_OP_VAR 0x0103
126 #define REWRITE_MAP_GET_OP_VAR 0x0104
127 #define REWRITE_MAP_SET_SESN_VAR 0x0105
128 #define REWRITE_MAP_SETW_SESN_VAR 0x0106
129 #define REWRITE_MAP_GET_SESN_VAR 0x0107
130 #define REWRITE_MAP_GET_PARAM 0x0108
131 #define REWRITE_MAP_BUILTIN 0x0109
138 * Old maps store private data in _lm_args;
139 * new maps store the substitution pattern in _lm_subst
143 struct rewrite_subst *_lm_subst;
145 #define lm_args lm_union._lm_args
146 #define lm_subst lm_union._lm_subst
148 #ifdef USE_REWRITE_LDAP_PVT_THREADS
149 ldap_pvt_thread_mutex_t lm_mutex;
150 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
156 struct rewrite_builtin_map {
157 #define REWRITE_BUILTIN_MAP_LDAP 0x0201
162 #ifdef USE_REWRITE_LDAP_PVT_THREADS
163 ldap_pvt_thread_mutex_t lb_mutex;
164 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
168 * Submatch substitution
170 struct rewrite_submatch {
171 #define REWRITE_SUBMATCH_ASIS 0x0000
172 #define REWRITE_SUBMATCH_XMAP 0x0001
173 #define REWRITE_SUBMATCH_MAP_W_ARG 0x0002
175 struct rewrite_map *ls_map;
178 * The first one represents the index of the submatch in case
179 * the map has single submatch as argument;
180 * the latter represents the map argument scheme in case
181 * the map has substitution string argument form
186 * Pattern substitution
188 struct rewrite_subst {
190 struct berval *lt_subs;
193 struct rewrite_submatch *lt_submatch;
199 struct rewrite_rule {
200 struct rewrite_rule *lr_next;
201 struct rewrite_rule *lr_prev;
204 char *lr_subststring;
209 * I was thinking about some kind of per-rule mutex, but there's
210 * probably no need, because rules after compilation are only read;
211 * however, I need to check whether regexec is reentrant ...
214 struct rewrite_subst *lr_subst;
216 #define REWRITE_REGEX_ICASE REG_ICASE
217 #define REWRITE_REGEX_EXTENDED REG_EXTENDED
220 #define REWRITE_RECURSE 0x0001
221 #define REWRITE_EXEC_ONCE 0x0002
225 struct rewrite_action *lr_action;
229 * Rewrite Context (set of rules)
231 struct rewrite_context {
233 struct rewrite_context *lc_alias;
234 struct rewrite_rule *lc_rule;
240 struct rewrite_session {
243 #ifdef USE_REWRITE_LDAP_PVT_THREADS
244 ldap_pvt_thread_rdwr_t ls_vars_mutex;
245 ldap_pvt_thread_mutex_t ls_mutex;
246 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
256 struct berval lv_value;
265 #if 0 /* FIXME: not used anywhere! (debug? then, why strdup?) */
270 const void *lo_cookie;
281 struct rewrite_info {
285 * No global mutex because maps are read only at
292 #ifdef USE_REWRITE_LDAP_PVT_THREADS
293 ldap_pvt_thread_rdwr_t li_params_mutex;
294 ldap_pvt_thread_rdwr_t li_cookies_mutex;
295 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
299 * use `rewriteEngine {on|off}' directive to alter
304 * Defaults to REWRITE_MAXPASSES;
305 * use `rewriteMaxPasses numPasses' directive to alter
307 #define REWRITE_MAXPASSES 100
309 int li_max_passes_per_rule;
312 * Behavior in case a NULL or non-existent context is required
321 LDAP_REWRITE_V (struct rewrite_context*) rewrite_int_curr_context;
328 * Parses a map (also in legacy 'x' version)
330 LDAP_REWRITE_F (struct rewrite_map *)
332 struct rewrite_info *info,
337 LDAP_REWRITE_F (struct rewrite_map *)
339 struct rewrite_info *info,
345 * Resolves key in val by means of map (also in legacy 'x' version)
349 struct rewrite_info *info,
350 struct rewrite_op *op,
351 struct rewrite_map *map,
358 struct rewrite_info *info,
359 struct rewrite_op *op,
360 struct rewrite_map *map,
367 struct rewrite_map **map
371 rewrite_xmap_destroy(
372 struct rewrite_map **map
375 LDAP_REWRITE_F (void)
376 rewrite_builtin_map_free(
380 * Submatch substitution
384 * Compiles a substitution pattern
386 LDAP_REWRITE_F (struct rewrite_subst *)
387 rewrite_subst_compile(
388 struct rewrite_info *info,
393 * Substitutes a portion of rewritten string according to substitution
394 * pattern using submatches
398 struct rewrite_info *info,
399 struct rewrite_op *op,
400 struct rewrite_subst *subst,
402 const regmatch_t *match,
407 rewrite_subst_destroy(
408 struct rewrite_subst **subst
417 * Compiles the rule and appends it at the running context
420 rewrite_rule_compile(
421 struct rewrite_info *info,
422 struct rewrite_context *context,
425 const char *flagstring
429 * Rewrites string according to rule; may return:
430 * REWRITE_REGEXEC_OK: fine; if *result != NULL rule matched
431 * and rewrite succeeded.
432 * REWRITE_REGEXEC_STOP: fine, rule matched; stop processing
434 * REWRITE_REGEXEC_UNWILL: rule matched; force 'unwilling to perform'
435 * REWRITE_REGEXEC_ERR: an error occurred
439 struct rewrite_info *info,
440 struct rewrite_op *op,
441 struct rewrite_rule *rule,
447 rewrite_rule_destroy(
448 struct rewrite_rule **rule
456 * Fetches a struct rewrite_session
458 LDAP_REWRITE_F (struct rewrite_session *)
459 rewrite_session_find(
460 struct rewrite_info *info,
465 * Defines and inits a variable with session scope
468 rewrite_session_var_set_f(
469 struct rewrite_info *info,
477 * Gets a var with session scope
480 rewrite_session_var_get(
481 struct rewrite_info *info,
491 rewrite_session_delete(
492 struct rewrite_info *info,
497 * Destroys the cookie tree
500 rewrite_session_destroy(
501 struct rewrite_info *info
512 LDAP_REWRITE_F (struct rewrite_var *)
519 * Replaces the value of a variable
523 struct rewrite_var *var,
529 * Inserts a newly created var
531 LDAP_REWRITE_F (struct rewrite_var *)
532 rewrite_var_insert_f(
539 #define rewrite_var_insert(tree, name, value) \
540 rewrite_var_insert_f((tree), (name), (value), \
541 REWRITE_VAR_UPDATE|REWRITE_VAR_COPY_NAME|REWRITE_VAR_COPY_VALUE)
546 LDAP_REWRITE_F (struct rewrite_var *)
554 #define rewrite_var_set(tree, name, value, insert) \
555 rewrite_var_set_f((tree), (name), (value), \
556 REWRITE_VAR_UPDATE|REWRITE_VAR_COPY_NAME|REWRITE_VAR_COPY_VALUE|((insert)? REWRITE_VAR_INSERT : 0))
572 * Finds the context named rewriteContext in the context tree
574 LDAP_REWRITE_F (struct rewrite_context *)
575 rewrite_context_find(
576 struct rewrite_info *info,
577 const char *rewriteContext
581 * Creates a new context called rewriteContext and stores in into the tree
583 LDAP_REWRITE_F (struct rewrite_context *)
584 rewrite_context_create(
585 struct rewrite_info *info,
586 const char *rewriteContext
590 * Rewrites string according to context; may return:
591 * OK: fine; if *result != NULL rule matched and rewrite succeeded.
592 * STOP: fine, rule matched; stop processing following rules
593 * UNWILL: rule matched; force 'unwilling to perform'
596 rewrite_context_apply(
597 struct rewrite_info *info,
598 struct rewrite_op *op,
599 struct rewrite_context *context,
605 rewrite_context_destroy(
606 struct rewrite_context **context
609 LDAP_REWRITE_F (void)
610 rewrite_context_free(
614 #endif /* REWRITE_INT_H */