Home | History | Annotate | Line # | Download | only in librewrite
      1 /*	$NetBSD: rewrite-int.h,v 1.4 2025/09/05 21:16:23 christos Exp $	*/
      2 
      3 /* $OpenLDAP$ */
      4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
      5  *
      6  * Copyright 2000-2024 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 #ifndef NO_THREADS
     46 #define USE_REWRITE_LDAP_PVT_THREADS
     47 #include <ldap_pvt_thread.h>
     48 #endif
     49 
     50 #define malloc(x)	ber_memalloc(x)
     51 #define calloc(x,y)	ber_memcalloc(x,y)
     52 #define realloc(x,y)	ber_memrealloc(x,y)
     53 #define free(x)	ber_memfree(x)
     54 #undef strdup
     55 #define	strdup(x)	ber_strdup(x)
     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  */
    109 struct 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  */
    124 struct 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  */
    170 struct 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  */
    185 struct 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  */
    203 struct 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  */
    214 struct 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  */
    246 struct rewrite_context {
    247 	char                           *lc_name;
    248 	struct rewrite_context         *lc_alias;
    249 	struct rewrite_rule            *lc_rule;
    250 };
    251 
    252 /*
    253  * Session
    254  */
    255 struct 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  */
    268 struct rewrite_var {
    269 	char                           *lv_name;
    270 	int				lv_flags;
    271 	struct berval                   lv_value;
    272 };
    273 
    274 /*
    275  * Operation
    276  */
    277 struct 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  */
    296 struct 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 
    336 LDAP_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  */
    345 LDAP_REWRITE_F (struct rewrite_map *)
    346 rewrite_map_parse(
    347 		struct rewrite_info *info,
    348 		const char *s,
    349 		const char **end
    350 );
    351 
    352 LDAP_REWRITE_F (struct rewrite_map *)
    353 rewrite_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  */
    362 LDAP_REWRITE_F (int)
    363 rewrite_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 
    371 LDAP_REWRITE_F (int)
    372 rewrite_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 
    380 LDAP_REWRITE_F (int)
    381 rewrite_map_destroy(
    382 		struct rewrite_map **map
    383 );
    384 
    385 LDAP_REWRITE_F (int)
    386 rewrite_xmap_destroy(
    387 		struct rewrite_map **map
    388 );
    389 
    390 LDAP_REWRITE_F (void)
    391 rewrite_builtin_map_free(
    392 		void *map
    393 );
    394 /*
    395  * Submatch substitution
    396  */
    397 
    398 /*
    399  * Compiles a substitution pattern
    400  */
    401 LDAP_REWRITE_F (struct rewrite_subst *)
    402 rewrite_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  */
    411 LDAP_REWRITE_F (int)
    412 rewrite_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 
    421 LDAP_REWRITE_F (int)
    422 rewrite_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  */
    434 LDAP_REWRITE_F (int)
    435 rewrite_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  */
    452 LDAP_REWRITE_F (int)
    453 rewrite_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 
    461 LDAP_REWRITE_F (int)
    462 rewrite_rule_destroy(
    463 		struct rewrite_rule **rule
    464 );
    465 
    466 /*
    467  * Sessions
    468  */
    469 
    470 /*
    471  * Fetches a struct rewrite_session
    472  */
    473 LDAP_REWRITE_F (struct rewrite_session *)
    474 rewrite_session_find(
    475                 struct rewrite_info *info,
    476                 const void *cookie
    477 );
    478 
    479 /*
    480  * Defines and inits a variable with session scope
    481  */
    482 LDAP_REWRITE_F (int)
    483 rewrite_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  */
    494 LDAP_REWRITE_F (int)
    495 rewrite_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  */
    505 LDAP_REWRITE_F (int)
    506 rewrite_session_delete(
    507                 struct rewrite_info *info,
    508                 const void *cookie
    509 );
    510 
    511 /*
    512  * Destroys the cookie tree
    513  */
    514 LDAP_REWRITE_F (int)
    515 rewrite_session_destroy(
    516                 struct rewrite_info *info
    517 );
    518 
    519 
    520 /*
    521  * Vars
    522  */
    523 
    524 /*
    525  * Finds a var
    526  */
    527 LDAP_REWRITE_F (struct rewrite_var *)
    528 rewrite_var_find(
    529                 Avlnode *tree,
    530                 const char *name
    531 );
    532 
    533 /*
    534  * Replaces the value of a variable
    535  */
    536 LDAP_REWRITE_F (int)
    537 rewrite_var_replace(
    538 		struct rewrite_var *var,
    539 		const char *value,
    540 		int flags
    541 );
    542 
    543 /*
    544  * Inserts a newly created var
    545  */
    546 LDAP_REWRITE_F (struct rewrite_var *)
    547 rewrite_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  */
    561 LDAP_REWRITE_F (struct rewrite_var *)
    562 rewrite_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  */
    576 LDAP_REWRITE_F (int)
    577 rewrite_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  */
    589 LDAP_REWRITE_F (struct rewrite_context *)
    590 rewrite_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  */
    598 LDAP_REWRITE_F (struct rewrite_context *)
    599 rewrite_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  */
    610 LDAP_REWRITE_F (int)
    611 rewrite_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 
    619 LDAP_REWRITE_F (int)
    620 rewrite_context_destroy(
    621 		struct rewrite_context **context
    622 );
    623 
    624 LDAP_REWRITE_F (void)
    625 rewrite_context_free(
    626 		void *tmp
    627 );
    628 
    629 #endif /* REWRITE_INT_H */
    630 
    631