2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 * Copyright 2000-2003 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_IGNORE_ERR 'I'
79 #define REWRITE_OPERATOR_SUBCONTEXT '>'
80 #define REWRITE_OPERATOR_COMMAND '|'
81 #define REWRITE_OPERATOR_VARIABLE_SET '&'
82 #define REWRITE_OPERATOR_VARIABLE_GET '*'
83 #define REWRITE_OPERATOR_PARAM_GET '$'
93 struct rewrite_action {
94 struct rewrite_action *la_next;
96 #define REWRITE_ACTION_STOP 0x0001
97 #define REWRITE_ACTION_UNWILLING 0x0002
98 #define REWRITE_ACTION_GOTO 0x0003
99 #define REWRITE_ACTION_IGNORE_ERR 0x0004
112 #define REWRITE_MAP_XFILEMAP 0x0001 /* Rough implementation! */
113 #define REWRITE_MAP_XPWDMAP 0x0002 /* uid -> gecos */
114 #define REWRITE_MAP_XLDAPMAP 0x0003 /* Not implemented yet! */
119 #define REWRITE_MAP_SUBCONTEXT 0x0101
121 #define REWRITE_MAP_SET_OP_VAR 0x0102
122 #define REWRITE_MAP_SETW_OP_VAR 0x0103
123 #define REWRITE_MAP_GET_OP_VAR 0x0104
124 #define REWRITE_MAP_SET_SESN_VAR 0x0105
125 #define REWRITE_MAP_SETW_SESN_VAR 0x0106
126 #define REWRITE_MAP_GET_SESN_VAR 0x0107
127 #define REWRITE_MAP_GET_PARAM 0x0108
128 #define REWRITE_MAP_BUILTIN 0x0109
135 * Old maps store private data in _lm_args;
136 * new maps store the substitution pattern in _lm_subst
140 struct rewrite_subst *_lm_subst;
142 #define lm_args lm_union._lm_args
143 #define lm_subst lm_union._lm_subst
145 #ifdef USE_REWRITE_LDAP_PVT_THREADS
146 ldap_pvt_thread_mutex_t lm_mutex;
147 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
153 struct rewrite_builtin_map {
154 #define REWRITE_BUILTIN_MAP_LDAP 0x0201
159 #ifdef USE_REWRITE_LDAP_PVT_THREADS
160 ldap_pvt_thread_mutex_t lb_mutex;
161 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
165 * Submatch substitution
167 struct rewrite_submatch {
168 #define REWRITE_SUBMATCH_ASIS 0x0000
169 #define REWRITE_SUBMATCH_XMAP 0x0001
170 #define REWRITE_SUBMATCH_MAP_W_ARG 0x0002
172 struct rewrite_map *ls_map;
175 * The first one represents the index of the submatch in case
176 * the map has single submatch as argument;
177 * the latter represents the map argument scheme in case
178 * the map has substitution string argument form
183 * Pattern substitution
185 struct rewrite_subst {
187 struct berval *lt_subs;
190 struct rewrite_submatch *lt_submatch;
196 struct rewrite_rule {
197 struct rewrite_rule *lr_next;
198 struct rewrite_rule *lr_prev;
201 char *lr_subststring;
206 * I was thinking about some kind of per-rule mutex, but there's
207 * probably no need, because rules after compilation are only read;
208 * however, I need to check whether regexec is reentrant ...
211 struct rewrite_subst *lr_subst;
213 #define REWRITE_REGEX_ICASE REG_ICASE
214 #define REWRITE_REGEX_EXTENDED REG_EXTENDED
217 #define REWRITE_RECURSE 0x0001
218 #define REWRITE_EXEC_ONCE 0x0002
221 struct rewrite_action *lr_action;
225 * Rewrite Context (set of rules)
227 struct rewrite_context {
229 struct rewrite_context *lc_alias;
230 struct rewrite_rule *lc_rule;
236 struct rewrite_session {
239 #ifdef USE_REWRITE_LDAP_PVT_THREADS
240 ldap_pvt_thread_rdwr_t ls_vars_mutex;
241 ldap_pvt_thread_mutex_t ls_mutex;
242 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
252 struct berval lv_value;
261 #if 0 /* FIXME: not used anywhere! (debug? then, why strdup?) */
266 const void *lo_cookie;
277 struct rewrite_info {
281 * No global mutex because maps are read only at
288 #ifdef USE_REWRITE_LDAP_PVT_THREADS
289 ldap_pvt_thread_rdwr_t li_params_mutex;
290 ldap_pvt_thread_rdwr_t li_cookies_mutex;
291 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
295 * use `rewriteEngine {on|off}' directive to alter
300 * Defaults to REWRITE_MAXPASSES;
301 * use `rewriteMaxPasses numPasses' directive to alter
303 #define REWRITE_MAXPASSES 100
307 * Behavior in case a NULL or non-existent context is required
316 LDAP_REWRITE_V (struct rewrite_context*) rewrite_int_curr_context;
323 * Parses a map (also in legacy 'x' version)
325 LDAP_REWRITE_F (struct rewrite_map *)
327 struct rewrite_info *info,
332 LDAP_REWRITE_F (struct rewrite_map *)
334 struct rewrite_info *info,
340 * Resolves key in val by means of map (also in legacy 'x' version)
344 struct rewrite_info *info,
345 struct rewrite_op *op,
346 struct rewrite_map *map,
353 struct rewrite_info *info,
354 struct rewrite_op *op,
355 struct rewrite_map *map,
362 struct rewrite_map **map
366 rewrite_xmap_destroy(
367 struct rewrite_map **map
370 LDAP_REWRITE_F (void)
371 rewrite_builtin_map_free(
375 * Submatch substitution
379 * Compiles a substitution pattern
381 LDAP_REWRITE_F (struct rewrite_subst *)
382 rewrite_subst_compile(
383 struct rewrite_info *info,
388 * Substitutes a portion of rewritten string according to substitution
389 * pattern using submatches
393 struct rewrite_info *info,
394 struct rewrite_op *op,
395 struct rewrite_subst *subst,
397 const regmatch_t *match,
402 rewrite_subst_destroy(
403 struct rewrite_subst **subst
412 * Compiles the rule and appends it at the running context
415 rewrite_rule_compile(
416 struct rewrite_info *info,
417 struct rewrite_context *context,
420 const char *flagstring
424 * Rewrites string according to rule; may return:
425 * REWRITE_REGEXEC_OK: fine; if *result != NULL rule matched
426 * and rewrite succeeded.
427 * REWRITE_REGEXEC_STOP: fine, rule matched; stop processing
429 * REWRITE_REGEXEC_UNWILL: rule matched; force 'unwilling to perform'
430 * REWRITE_REGEXEC_ERR: an error occurred
434 struct rewrite_info *info,
435 struct rewrite_op *op,
436 struct rewrite_rule *rule,
442 rewrite_rule_destroy(
443 struct rewrite_rule **rule
451 * Fetches a struct rewrite_session
453 LDAP_REWRITE_F (struct rewrite_session *)
454 rewrite_session_find(
455 struct rewrite_info *info,
460 * Defines and inits a variable with session scope
463 rewrite_session_var_set_f(
464 struct rewrite_info *info,
472 * Gets a var with session scope
475 rewrite_session_var_get(
476 struct rewrite_info *info,
486 rewrite_session_delete(
487 struct rewrite_info *info,
492 * Destroys the cookie tree
495 rewrite_session_destroy(
496 struct rewrite_info *info
507 LDAP_REWRITE_F (struct rewrite_var *)
514 * Replaces the value of a variable
518 struct rewrite_var *var,
524 * Inserts a newly created var
526 LDAP_REWRITE_F (struct rewrite_var *)
527 rewrite_var_insert_f(
534 #define rewrite_var_insert(tree, name, value) \
535 rewrite_var_insert_f((tree), (name), (value), \
536 REWRITE_VAR_UPDATE|REWRITE_VAR_COPY_NAME|REWRITE_VAR_COPY_VALUE)
541 LDAP_REWRITE_F (struct rewrite_var *)
549 #define rewrite_var_set(tree, name, value, insert) \
550 rewrite_var_set_f((tree), (name), (value), \
551 REWRITE_VAR_UPDATE|REWRITE_VAR_COPY_NAME|REWRITE_VAR_COPY_VALUE|((insert)? REWRITE_VAR_INSERT : 0))
567 * Finds the context named rewriteContext in the context tree
569 LDAP_REWRITE_F (struct rewrite_context *)
570 rewrite_context_find(
571 struct rewrite_info *info,
572 const char *rewriteContext
576 * Creates a new context called rewriteContext and stores in into the tree
578 LDAP_REWRITE_F (struct rewrite_context *)
579 rewrite_context_create(
580 struct rewrite_info *info,
581 const char *rewriteContext
585 * Rewrites string according to context; may return:
586 * OK: fine; if *result != NULL rule matched and rewrite succeeded.
587 * STOP: fine, rule matched; stop processing following rules
588 * UNWILL: rule matched; force 'unwilling to perform'
591 rewrite_context_apply(
592 struct rewrite_info *info,
593 struct rewrite_op *op,
594 struct rewrite_context *context,
600 rewrite_context_destroy(
601 struct rewrite_context **context
604 LDAP_REWRITE_F (void)
605 rewrite_context_free(
609 #endif /* REWRITE_INT_H */