/****************************************************************************** * * Copyright (C) 2000 Pierangelo Masarati, * All rights reserved. * * Permission is granted to anyone to use this software for any purpose * on any computer system, and to alter it and redistribute it, subject * to the following restrictions: * * 1. The author is not responsible for the consequences of use of this * software, no matter how awful, even if they arise from flaws in it. * * 2. The origin of this software must not be misrepresented, either by * explicit claim or by omission. Since few users ever read sources, * credits should appear in the documentation. * * 3. Altered versions must be plainly marked as such, and must not be * misrepresented as being the original software. Since few users * ever read sources, credits should appear in the documentation. * * 4. This notice may not be removed or altered. * ******************************************************************************/ #ifndef REWRITE_INT_H #define REWRITE_INT_H /* * These are required by every file of the library, so they're included here */ #include #include #include #include #include #include #include #include #include #include "../libldap/ldap-int.h" #include #include /* Uncomment to use ldap pvt threads */ #define USE_REWRITE_LDAP_PVT_THREADS #include /* * For details, see RATIONALE. */ #define REWRITE_MAX_MATCH 11 /* 0: overall string; 1-9: submatches */ #define REWRITE_MAX_PASSES 100 /* * Submatch escape char */ /* the '\' conflicts with slapd.conf parsing */ /* #define REWRITE_SUBMATCH_ESCAPE '\\' */ #define REWRITE_SUBMATCH_ESCAPE '%' /* * REGEX flags */ #define REWRITE_FLAG_HONORCASE 'C' #define REWRITE_FLAG_BASICREGEX 'R' /* * Action flags */ #define REWRITE_FLAG_EXECONCE ':' #define REWRITE_FLAG_STOP '@' #define REWRITE_FLAG_UNWILLING '#' #define REWRITE_FLAG_GOTO 'G' /* requires an arg */ #define REWRITE_FLAG_IGNORE_ERR 'I' /* * Map operators */ #define REWRITE_OPERATOR_SUBCONTEXT '>' #define REWRITE_OPERATOR_COMMAND '|' #define REWRITE_OPERATOR_VARIABLE_SET '&' #define REWRITE_OPERATOR_VARIABLE_GET '*' #define REWRITE_OPERATOR_PARAM_GET '$' /*********** * PRIVATE * ***********/ /* * Action */ struct rewrite_action { struct rewrite_action *la_next; #define REWRITE_ACTION_STOP 0x0001 #define REWRITE_ACTION_UNWILLING 0x0002 #define REWRITE_ACTION_GOTO 0x0003 #define REWRITE_ACTION_IGNORE_ERR 0x0004 int la_type; void *la_args; }; /* * Map */ struct rewrite_map { /* * Legacy stuff */ #define REWRITE_MAP_XFILEMAP 0x0001 /* Rough implementation! */ #define REWRITE_MAP_XPWDMAP 0x0002 /* uid -> gecos */ #define REWRITE_MAP_XLDAPMAP 0x0003 /* Not implemented yet! */ /* * Maps with args */ #define REWRITE_MAP_SUBCONTEXT 0x0101 #define REWRITE_MAP_SET_OP_VAR 0x0102 #define REWRITE_MAP_SETW_OP_VAR 0x0103 #define REWRITE_MAP_GET_OP_VAR 0x0104 #define REWRITE_MAP_SET_SESN_VAR 0x0105 #define REWRITE_MAP_SETW_SESN_VAR 0x0106 #define REWRITE_MAP_GET_SESN_VAR 0x0107 #define REWRITE_MAP_GET_PARAM 0x0108 #define REWRITE_MAP_BUILTIN 0x0109 int lm_type; char *lm_name; void *lm_data; /* * Old maps store private data in _lm_args; * new maps store the substitution pattern in _lm_subst */ union { void *_lm_args; struct rewrite_subst *_lm_subst; } lm_union; #define lm_args lm_union._lm_args #define lm_subst lm_union._lm_subst #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_mutex_t lm_mutex; #endif /* USE_REWRITE_LDAP_PVT_THREADS */ }; /* * Builtin maps */ struct rewrite_builtin_map { #define REWRITE_BUILTIN_MAP_LDAP 0x0201 int lb_type; char *lb_name; void *lb_private; #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_mutex_t lb_mutex; #endif /* USE_REWRITE_LDAP_PVT_THREADS */ }; /* * Submatch substitution */ struct rewrite_submatch { #define REWRITE_SUBMATCH_ASIS 0x0000 #define REWRITE_SUBMATCH_XMAP 0x0001 #define REWRITE_SUBMATCH_MAP_W_ARG 0x0002 int ls_type; struct rewrite_map *ls_map; int ls_submatch; /* * The first one represents the index of the submatch in case * the map has single submatch as argument; * the latter represents the map argument scheme in case * the map has substitution string argument form */ }; /* * Pattern substitution */ struct rewrite_subst { size_t lt_subs_len; struct berval **lt_subs; int lt_num_submatch; struct rewrite_submatch **lt_submatch; }; /* * Rule */ struct rewrite_rule { struct rewrite_rule *lr_next; struct rewrite_rule *lr_prev; char *lr_pattern; char *lr_subststring; char *lr_flagstring; regex_t lr_regex; /* * I was thinking about some kind of per-rule mutex, but there's * probably no need, because rules after compilation are only read; * however, I need to check whether regexec is reentrant ... */ struct rewrite_subst *lr_subst; #define REWRITE_REGEX_ICASE REG_ICASE #define REWRITE_REGEX_EXTENDED REG_EXTENDED int lr_flags; #define REWRITE_RECURSE 0x0001 #define REWRITE_EXEC_ONCE 0x0002 int lr_mode; struct rewrite_action *lr_action; }; /* * Rewrite Context (set of rules) */ struct rewrite_context { char *lc_name; struct rewrite_context *lc_alias; struct rewrite_rule *lc_rule; }; /* * Session */ struct rewrite_session { void *ls_cookie; Avlnode *ls_vars; #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_rdwr_t ls_vars_mutex; #endif /* USE_REWRITE_LDAP_PVT_THREADS */ }; /* * Variable */ struct rewrite_var { char *lv_name; struct berval lv_value; }; /* * Operation */ struct rewrite_op { int lo_num_passes; int lo_depth; char *lo_string; char *lo_result; Avlnode *lo_vars; const void *lo_cookie; }; /********** * PUBLIC * **********/ /* * Rewrite info */ struct rewrite_info { Avlnode *li_context; Avlnode *li_maps; /* * No global mutex because maps are read only at * config time */ Avlnode *li_params; Avlnode *li_cookies; int li_num_cookies; #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_rdwr_t li_params_mutex; ldap_pvt_thread_rdwr_t li_cookies_mutex; #endif /* USE_REWRITE_LDAP_PVT_THREADS */ /* * Default to `off'; * use `rewriteEngine {on|off}' directive to alter */ int li_state; /* * Defaults to REWRITE_MAXPASSES; * use `rewriteMaxPasses numPasses' directive to alter */ #define REWRITE_MAXPASSES 100 int li_max_passes; /* * Behavior in case a NULL or non-existent context is required */ int li_rewrite_mode; }; /*********** * PRIVATE * ***********/ /* * Maps */ /* * Parses a map (also in legacy 'x' version) */ extern struct rewrite_map * rewrite_map_parse( struct rewrite_info *info, const char *s, const char **end ); extern struct rewrite_map * rewrite_xmap_parse( struct rewrite_info *info, const char *s, const char **end ); /* * Resolves key in val by means of map (also in legacy 'x' version) */ extern int rewrite_map_apply( struct rewrite_info *info, struct rewrite_op *op, struct rewrite_map *map, struct berval *key, struct berval *val ); extern int rewrite_xmap_apply( struct rewrite_info *info, struct rewrite_op *op, struct rewrite_map *map, struct berval *key, struct berval *val ); /* * Submatch substitution */ /* * Compiles a substitution pattern */ extern struct rewrite_subst * rewrite_subst_compile( struct rewrite_info *info, const char *result ); /* * Substitutes a portion of rewritten string according to substitution * pattern using submatches */ extern int rewrite_subst_apply( struct rewrite_info *info, struct rewrite_op *op, struct rewrite_subst *subst, const char *string, const regmatch_t *match, struct berval *val ); /* * Rules */ /* * Compiles the rule and appends it at the running context */ extern int rewrite_rule_compile( struct rewrite_info *info, struct rewrite_context *context, const char *pattern, const char *result, const char *flagstring ); /* * Rewrites string according to rule; may return: * REWRITE_REGEXEC_OK: fine; if *result != NULL rule matched * and rewrite succeeded. * REWRITE_REGEXEC_STOP: fine, rule matched; stop processing * following rules * REWRITE_REGEXEC_UNWILL: rule matched; force 'unwilling to perform' * REWRITE_REGEXEC_ERR: an error occurred */ extern int rewrite_rule_apply( struct rewrite_info *info, struct rewrite_op *op, struct rewrite_rule *rule, const char *string, char **result ); /* * Sessions */ /* * Fetches a struct rewrite_session */ extern struct rewrite_session * rewrite_session_find( struct rewrite_info *info, const void *cookie ); /* * Defines and inits a variable with session scope */ extern int rewrite_session_var_set( struct rewrite_info *info, const void *cookie, const char *name, const char *value ); /* * Gets a var with session scope */ extern int rewrite_session_var_get( struct rewrite_info *info, const void *cookie, const char *name, struct berval *val ); /* * Deletes a session */ extern int rewrite_session_delete( struct rewrite_info *info, const void *cookie ); /* * Destroys the cookie tree */ extern int rewrite_session_destroy( struct rewrite_info *info ); /* * Vars */ /* * Finds a var */ extern struct rewrite_var * rewrite_var_find( Avlnode *tree, const char *name ); /* * Inserts a newly created var */ extern struct rewrite_var * rewrite_var_insert( Avlnode **tree, const char *name, const char *value ); /* * Sets/inserts a var */ extern struct rewrite_var * rewrite_var_set( Avlnode **tree, const char *name, const char *value, int insert ); /* * Deletes a var tree */ extern int rewrite_var_delete( Avlnode *tree ); /* * Contexts */ /* * Finds the context named rewriteContext in the context tree */ extern struct rewrite_context * rewrite_context_find( struct rewrite_info *info, const char *rewriteContext ); /* * Creates a new context called rewriteContext and stores in into the tree */ extern struct rewrite_context * rewrite_context_create( struct rewrite_info *info, const char *rewriteContext ); /* * Rewrites string according to context; may return: * OK: fine; if *result != NULL rule matched and rewrite succeeded. * STOP: fine, rule matched; stop processing following rules * UNWILL: rule matched; force 'unwilling to perform' */ extern int rewrite_context_apply( struct rewrite_info *info, struct rewrite_op *op, struct rewrite_context *context, const char *string, char **result ); #endif /* REWRITE_INT_H */