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