Home | History | Annotate | Line # | Download | only in librewrite
      1 /*	$NetBSD: info.c,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 #include <portable.h>
     23 
     24 #include "rewrite-int.h"
     25 
     26 /*
     27  * Global data
     28  */
     29 
     30 /*
     31  * This becomes the running context for subsequent calls to
     32  * rewrite_parse; it can be altered only by a
     33  * rewriteContext config line or by a change in info.
     34  */
     35 struct rewrite_context *rewrite_int_curr_context = NULL;
     36 
     37 /*
     38  * Inits the info
     39  */
     40 struct rewrite_info *
     41 rewrite_info_init(
     42 		int mode
     43 )
     44 {
     45 	struct rewrite_info *info;
     46 	struct rewrite_context *context;
     47 
     48 	switch ( mode ) {
     49 	case REWRITE_MODE_ERR:
     50 	case REWRITE_MODE_OK:
     51 	case REWRITE_MODE_COPY_INPUT:
     52 	case REWRITE_MODE_USE_DEFAULT:
     53 		break;
     54 	default:
     55 		mode = REWRITE_MODE_USE_DEFAULT;
     56 		break;
     57 		/* return NULL */
     58 	}
     59 
     60 	/*
     61 	 * Resets the running context for parsing ...
     62 	 */
     63 	rewrite_int_curr_context = NULL;
     64 
     65 	info = calloc( sizeof( struct rewrite_info ), 1 );
     66 	if ( info == NULL ) {
     67 		return NULL;
     68 	}
     69 
     70 	info->li_state = REWRITE_DEFAULT;
     71 	info->li_max_passes = REWRITE_MAX_PASSES;
     72 	info->li_max_passes_per_rule = REWRITE_MAX_PASSES;
     73 	info->li_rewrite_mode = mode;
     74 
     75 	/*
     76 	 * Add the default (empty) rule
     77 	 */
     78 	context = rewrite_context_create( info, REWRITE_DEFAULT_CONTEXT );
     79 	if ( context == NULL ) {
     80 		free( info );
     81 		return NULL;
     82 	}
     83 
     84 #ifdef USE_REWRITE_LDAP_PVT_THREADS
     85 	if ( ldap_pvt_thread_rdwr_init( &info->li_cookies_mutex ) ) {
     86 		ldap_avl_free( info->li_context, rewrite_context_free );
     87 		free( info );
     88 		return NULL;
     89 	}
     90 	if ( ldap_pvt_thread_rdwr_init( &info->li_params_mutex ) ) {
     91 		ldap_pvt_thread_rdwr_destroy( &info->li_cookies_mutex );
     92 		ldap_avl_free( info->li_context, rewrite_context_free );
     93 		free( info );
     94 		return NULL;
     95 	}
     96 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
     97 
     98 	return info;
     99 }
    100 
    101 /*
    102  * Cleans up the info structure
    103  */
    104 int
    105 rewrite_info_delete(
    106 		struct rewrite_info **pinfo
    107 )
    108 {
    109 	struct rewrite_info	*info;
    110 
    111 	assert( pinfo != NULL );
    112 	assert( *pinfo != NULL );
    113 
    114 	info = *pinfo;
    115 
    116 	if ( info->li_context ) {
    117 		ldap_avl_free( info->li_context, rewrite_context_free );
    118 	}
    119 	info->li_context = NULL;
    120 
    121 	if ( info->li_maps ) {
    122 		ldap_avl_free( info->li_maps, rewrite_builtin_map_free );
    123 	}
    124 	info->li_maps = NULL;
    125 
    126 	rewrite_session_destroy( info );
    127 
    128 #ifdef USE_REWRITE_LDAP_PVT_THREADS
    129 	ldap_pvt_thread_rdwr_destroy( &info->li_cookies_mutex );
    130 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
    131 
    132 	rewrite_param_destroy( info );
    133 
    134 #ifdef USE_REWRITE_LDAP_PVT_THREADS
    135 	ldap_pvt_thread_rdwr_destroy( &info->li_params_mutex );
    136 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
    137 
    138 	free( info );
    139 	*pinfo = NULL;
    140 
    141 	return REWRITE_SUCCESS;
    142 }
    143 
    144 /*
    145  * Rewrites a string according to context.
    146  * If the engine is off, OK is returned, but the return string will be NULL.
    147  * In case of 'unwilling to perform', UNWILLING is returned, and the
    148  * return string will also be null. The same in case of error.
    149  * Otherwise, OK is returned, and result will hold a newly allocated string
    150  * with the rewriting.
    151  *
    152  * What to do in case of non-existing rewrite context is still an issue.
    153  * Four possibilities:
    154  * 	- error,
    155  * 	- ok with NULL result,
    156  * 	- ok with copy of string as result,
    157  * 	- use the default rewrite context.
    158  */
    159 int
    160 rewrite(
    161 		struct rewrite_info *info,
    162 		const char *rewriteContext,
    163 		const char *string,
    164 		char **result
    165 )
    166 {
    167 	return rewrite_session( info, rewriteContext,
    168 			string, NULL, result );
    169 }
    170 
    171 int
    172 rewrite_session(
    173 		struct rewrite_info *info,
    174 		const char *rewriteContext,
    175 		const char *string,
    176 		const void *cookie,
    177 		char **result
    178 )
    179 {
    180 	struct rewrite_context *context;
    181 	struct rewrite_op op = { 0, 0, NULL, NULL, NULL };
    182 	int rc;
    183 
    184 	assert( info != NULL );
    185 	assert( rewriteContext != NULL );
    186 	assert( string != NULL );
    187 	assert( result != NULL );
    188 
    189 	/*
    190 	 * cookie can be null; means: don't care about session stuff
    191 	 */
    192 
    193 	*result = NULL;
    194 	op.lo_cookie = cookie;
    195 
    196 	/*
    197 	 * Engine not on means no failure, but explicit no rewriting
    198 	 */
    199 	if ( info->li_state != REWRITE_ON ) {
    200 		rc = REWRITE_REGEXEC_OK;
    201 		goto rc_return;
    202 	}
    203 
    204 	/*
    205 	 * Undefined context means no rewriting also
    206 	 * (conservative, are we sure it's what we want?)
    207 	 */
    208 	context = rewrite_context_find( info, rewriteContext );
    209 	if ( context == NULL ) {
    210 		switch ( info->li_rewrite_mode ) {
    211 		case REWRITE_MODE_ERR:
    212 			rc = REWRITE_REGEXEC_ERR;
    213 			goto rc_return;
    214 
    215 		case REWRITE_MODE_OK:
    216 			rc = REWRITE_REGEXEC_OK;
    217 			goto rc_return;
    218 
    219 		case REWRITE_MODE_COPY_INPUT:
    220 			*result = strdup( string );
    221 			rc = ( *result != NULL ) ? REWRITE_REGEXEC_OK : REWRITE_REGEXEC_ERR;
    222 			goto rc_return;
    223 
    224 		case REWRITE_MODE_USE_DEFAULT:
    225 			context = rewrite_context_find( info,
    226 					REWRITE_DEFAULT_CONTEXT );
    227 			break;
    228 		}
    229 	}
    230 
    231 #if 0 /* FIXME: not used anywhere! (debug? then, why strdup?) */
    232 	op.lo_string = strdup( string );
    233 	if ( op.lo_string == NULL ) {
    234 		rc = REWRITE_REGEXEC_ERR;
    235 		goto rc_return;
    236 	}
    237 #endif
    238 
    239 	/*
    240 	 * Applies rewrite context
    241 	 */
    242 	rc = rewrite_context_apply( info, &op, context, string, result );
    243 	assert( op.lo_depth == 0 );
    244 
    245 #if 0 /* FIXME: not used anywhere! (debug? then, why strdup?) */
    246 	free( op.lo_string );
    247 #endif
    248 
    249 	switch ( rc ) {
    250 	/*
    251 	 * Success
    252 	 */
    253 	case REWRITE_REGEXEC_OK:
    254 	case REWRITE_REGEXEC_STOP:
    255 		/*
    256 		 * If rewrite succeeded return OK regardless of how
    257 		 * the successful rewriting was obtained!
    258 		 */
    259 		rc = REWRITE_REGEXEC_OK;
    260 		break;
    261 
    262 
    263 	/*
    264 	 * Internal or forced error, return = NULL; rc already OK.
    265 	 */
    266 	case REWRITE_REGEXEC_UNWILLING:
    267 	case REWRITE_REGEXEC_ERR:
    268 		if ( *result != NULL ) {
    269 			if ( *result != string ) {
    270 				free( *result );
    271 			}
    272 			*result = NULL;
    273 		}
    274 
    275 	default:
    276 		break;
    277 	}
    278 
    279 rc_return:;
    280 	if ( op.lo_vars ) {
    281 		rewrite_var_delete( op.lo_vars );
    282 	}
    283 
    284 	return rc;
    285 }
    286 
    287