2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 * Copyright 2000-2018 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 #define LDAP_DEFINE_LDAP_DEBUG
43 #define malloc(x) ber_memalloc(x)
44 #define calloc(x,y) ber_memcalloc(x,y)
45 #define realloc(x,y) ber_memrealloc(x,y)
46 #define free(x) ber_memfree(x)
48 #define strdup(x) ber_strdup(x)
50 /* Uncomment to use ldap pvt threads */
51 #define USE_REWRITE_LDAP_PVT_THREADS
52 #include <ldap_pvt_thread.h>
55 * For details, see RATIONALE.
58 #define REWRITE_MAX_MATCH 11 /* 0: overall string; 1-9: submatches */
59 #define REWRITE_MAX_PASSES 100
62 * Submatch escape char
64 /* the '\' conflicts with slapd.conf parsing */
65 /* #define REWRITE_SUBMATCH_ESCAPE '\\' */
66 #define REWRITE_SUBMATCH_ESCAPE_ORIG '%'
67 #define REWRITE_SUBMATCH_ESCAPE '$'
68 #define IS_REWRITE_SUBMATCH_ESCAPE(c) \
69 ((c) == REWRITE_SUBMATCH_ESCAPE || (c) == REWRITE_SUBMATCH_ESCAPE_ORIG)
75 #define REWRITE_FLAG_HONORCASE 'C'
76 #define REWRITE_FLAG_BASICREGEX 'R'
81 #define REWRITE_FLAG_EXECONCE ':'
82 #define REWRITE_FLAG_STOP '@'
83 #define REWRITE_FLAG_UNWILLING '#'
84 #define REWRITE_FLAG_GOTO 'G' /* requires an arg */
85 #define REWRITE_FLAG_USER 'U' /* requires an arg */
86 #define REWRITE_FLAG_MAX_PASSES 'M' /* requires an arg */
87 #define REWRITE_FLAG_IGNORE_ERR 'I'
92 #define REWRITE_OPERATOR_SUBCONTEXT '>'
93 #define REWRITE_OPERATOR_COMMAND '|'
94 #define REWRITE_OPERATOR_VARIABLE_SET '&'
95 #define REWRITE_OPERATOR_VARIABLE_GET '*'
96 #define REWRITE_OPERATOR_PARAM_GET '$'
106 struct rewrite_action {
107 struct rewrite_action *la_next;
109 #define REWRITE_ACTION_STOP 0x0001
110 #define REWRITE_ACTION_UNWILLING 0x0002
111 #define REWRITE_ACTION_GOTO 0x0003
112 #define REWRITE_ACTION_IGNORE_ERR 0x0004
113 #define REWRITE_ACTION_USER 0x0005
126 #define REWRITE_MAP_XFILEMAP 0x0001 /* Rough implementation! */
127 #define REWRITE_MAP_XPWDMAP 0x0002 /* uid -> gecos */
128 #define REWRITE_MAP_XLDAPMAP 0x0003 /* Not implemented yet! */
133 #define REWRITE_MAP_SUBCONTEXT 0x0101
135 #define REWRITE_MAP_SET_OP_VAR 0x0102
136 #define REWRITE_MAP_SETW_OP_VAR 0x0103
137 #define REWRITE_MAP_GET_OP_VAR 0x0104
138 #define REWRITE_MAP_SET_SESN_VAR 0x0105
139 #define REWRITE_MAP_SETW_SESN_VAR 0x0106
140 #define REWRITE_MAP_GET_SESN_VAR 0x0107
141 #define REWRITE_MAP_GET_PARAM 0x0108
142 #define REWRITE_MAP_BUILTIN 0x0109
149 * Old maps store private data in _lm_args;
150 * new maps store the substitution pattern in _lm_subst
154 struct rewrite_subst *_lm_subst;
156 #define lm_args lm_union._lm_args
157 #define lm_subst lm_union._lm_subst
159 #ifdef USE_REWRITE_LDAP_PVT_THREADS
160 ldap_pvt_thread_mutex_t lm_mutex;
161 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
167 struct rewrite_builtin_map {
168 #define REWRITE_BUILTIN_MAP 0x0200
172 const rewrite_mapper *lb_mapper;
174 #ifdef USE_REWRITE_LDAP_PVT_THREADS
175 ldap_pvt_thread_mutex_t lb_mutex;
176 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
180 * Submatch substitution
182 struct rewrite_submatch {
183 #define REWRITE_SUBMATCH_ASIS 0x0000
184 #define REWRITE_SUBMATCH_XMAP 0x0001
185 #define REWRITE_SUBMATCH_MAP_W_ARG 0x0002
187 struct rewrite_map *ls_map;
190 * The first one represents the index of the submatch in case
191 * the map has single submatch as argument;
192 * the latter represents the map argument scheme in case
193 * the map has substitution string argument form
198 * Pattern substitution
200 struct rewrite_subst {
202 struct berval *lt_subs;
205 struct rewrite_submatch *lt_submatch;
211 struct rewrite_rule {
212 struct rewrite_rule *lr_next;
213 struct rewrite_rule *lr_prev;
216 char *lr_subststring;
221 * I was thinking about some kind of per-rule mutex, but there's
222 * probably no need, because rules after compilation are only read;
223 * however, I need to check whether regexec is reentrant ...
226 struct rewrite_subst *lr_subst;
228 #define REWRITE_REGEX_ICASE REG_ICASE
229 #define REWRITE_REGEX_EXTENDED REG_EXTENDED
232 #define REWRITE_RECURSE 0x0001
233 #define REWRITE_EXEC_ONCE 0x0002
237 struct rewrite_action *lr_action;
241 * Rewrite Context (set of rules)
243 struct rewrite_context {
245 struct rewrite_context *lc_alias;
246 struct rewrite_rule *lc_rule;
252 struct rewrite_session {
255 #ifdef USE_REWRITE_LDAP_PVT_THREADS
256 ldap_pvt_thread_rdwr_t ls_vars_mutex;
257 ldap_pvt_thread_mutex_t ls_mutex;
258 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
268 struct berval lv_value;
277 #if 0 /* FIXME: not used anywhere! (debug? then, why strdup?) */
282 const void *lo_cookie;
293 struct rewrite_info {
297 * No global mutex because maps are read only at
304 #ifdef USE_REWRITE_LDAP_PVT_THREADS
305 ldap_pvt_thread_rdwr_t li_params_mutex;
306 ldap_pvt_thread_rdwr_t li_cookies_mutex;
307 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
311 * use `rewriteEngine {on|off}' directive to alter
316 * Defaults to REWRITE_MAXPASSES;
317 * use `rewriteMaxPasses numPasses' directive to alter
319 #define REWRITE_MAXPASSES 100
321 int li_max_passes_per_rule;
324 * Behavior in case a NULL or non-existent context is required
333 LDAP_REWRITE_V (struct rewrite_context*) rewrite_int_curr_context;
340 * Parses a map (also in legacy 'x' version)
342 LDAP_REWRITE_F (struct rewrite_map *)
344 struct rewrite_info *info,
349 LDAP_REWRITE_F (struct rewrite_map *)
351 struct rewrite_info *info,
357 * Resolves key in val by means of map (also in legacy 'x' version)
361 struct rewrite_info *info,
362 struct rewrite_op *op,
363 struct rewrite_map *map,
370 struct rewrite_info *info,
371 struct rewrite_op *op,
372 struct rewrite_map *map,
379 struct rewrite_map **map
383 rewrite_xmap_destroy(
384 struct rewrite_map **map
387 LDAP_REWRITE_F (void)
388 rewrite_builtin_map_free(
392 * Submatch substitution
396 * Compiles a substitution pattern
398 LDAP_REWRITE_F (struct rewrite_subst *)
399 rewrite_subst_compile(
400 struct rewrite_info *info,
405 * Substitutes a portion of rewritten string according to substitution
406 * pattern using submatches
410 struct rewrite_info *info,
411 struct rewrite_op *op,
412 struct rewrite_subst *subst,
414 const regmatch_t *match,
419 rewrite_subst_destroy(
420 struct rewrite_subst **subst
429 * Compiles the rule and appends it at the running context
432 rewrite_rule_compile(
433 struct rewrite_info *info,
434 struct rewrite_context *context,
437 const char *flagstring
441 * Rewrites string according to rule; may return:
442 * REWRITE_REGEXEC_OK: fine; if *result != NULL rule matched
443 * and rewrite succeeded.
444 * REWRITE_REGEXEC_STOP: fine, rule matched; stop processing
446 * REWRITE_REGEXEC_UNWILL: rule matched; force 'unwilling to perform'
447 * REWRITE_REGEXEC_ERR: an error occurred
451 struct rewrite_info *info,
452 struct rewrite_op *op,
453 struct rewrite_rule *rule,
459 rewrite_rule_destroy(
460 struct rewrite_rule **rule
468 * Fetches a struct rewrite_session
470 LDAP_REWRITE_F (struct rewrite_session *)
471 rewrite_session_find(
472 struct rewrite_info *info,
477 * Defines and inits a variable with session scope
480 rewrite_session_var_set_f(
481 struct rewrite_info *info,
489 * Gets a var with session scope
492 rewrite_session_var_get(
493 struct rewrite_info *info,
503 rewrite_session_delete(
504 struct rewrite_info *info,
509 * Destroys the cookie tree
512 rewrite_session_destroy(
513 struct rewrite_info *info
524 LDAP_REWRITE_F (struct rewrite_var *)
531 * Replaces the value of a variable
535 struct rewrite_var *var,
541 * Inserts a newly created var
543 LDAP_REWRITE_F (struct rewrite_var *)
544 rewrite_var_insert_f(
551 #define rewrite_var_insert(tree, name, value) \
552 rewrite_var_insert_f((tree), (name), (value), \
553 REWRITE_VAR_UPDATE|REWRITE_VAR_COPY_NAME|REWRITE_VAR_COPY_VALUE)
558 LDAP_REWRITE_F (struct rewrite_var *)
566 #define rewrite_var_set(tree, name, value, insert) \
567 rewrite_var_set_f((tree), (name), (value), \
568 REWRITE_VAR_UPDATE|REWRITE_VAR_COPY_NAME|REWRITE_VAR_COPY_VALUE|((insert)? REWRITE_VAR_INSERT : 0))
584 * Finds the context named rewriteContext in the context tree
586 LDAP_REWRITE_F (struct rewrite_context *)
587 rewrite_context_find(
588 struct rewrite_info *info,
589 const char *rewriteContext
593 * Creates a new context called rewriteContext and stores in into the tree
595 LDAP_REWRITE_F (struct rewrite_context *)
596 rewrite_context_create(
597 struct rewrite_info *info,
598 const char *rewriteContext
602 * Rewrites string according to context; may return:
603 * OK: fine; if *result != NULL rule matched and rewrite succeeded.
604 * STOP: fine, rule matched; stop processing following rules
605 * UNWILL: rule matched; force 'unwilling to perform'
608 rewrite_context_apply(
609 struct rewrite_info *info,
610 struct rewrite_op *op,
611 struct rewrite_context *context,
617 rewrite_context_destroy(
618 struct rewrite_context **context
621 LDAP_REWRITE_F (void)
622 rewrite_context_free(
626 #endif /* REWRITE_INT_H */