xref: /netbsd-src/external/bsd/openldap/dist/libraries/librewrite/info.c (revision 549b59ed3ccf0d36d3097190a0db27b770f3a839)
1*549b59edSchristos /*	$NetBSD: info.c,v 1.3 2021/08/14 16:14:58 christos Exp $	*/
24e6df137Slukem 
3d11b170bStron /* $OpenLDAP$ */
42de962bdSlukem /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
52de962bdSlukem  *
6*549b59edSchristos  * Copyright 2000-2021 The OpenLDAP Foundation.
72de962bdSlukem  * All rights reserved.
82de962bdSlukem  *
92de962bdSlukem  * Redistribution and use in source and binary forms, with or without
102de962bdSlukem  * modification, are permitted only as authorized by the OpenLDAP
112de962bdSlukem  * Public License.
122de962bdSlukem  *
132de962bdSlukem  * A copy of this license is available in the file LICENSE in the
142de962bdSlukem  * top-level directory of the distribution or, alternatively, at
152de962bdSlukem  * <http://www.OpenLDAP.org/license.html>.
162de962bdSlukem  */
172de962bdSlukem /* ACKNOWLEDGEMENT:
182de962bdSlukem  * This work was initially developed by Pierangelo Masarati for
192de962bdSlukem  * inclusion in OpenLDAP Software.
202de962bdSlukem  */
212de962bdSlukem 
222de962bdSlukem #include <portable.h>
232de962bdSlukem 
242de962bdSlukem #include "rewrite-int.h"
252de962bdSlukem 
262de962bdSlukem /*
272de962bdSlukem  * Global data
282de962bdSlukem  */
292de962bdSlukem 
302de962bdSlukem /*
312de962bdSlukem  * This becomes the running context for subsequent calls to
322de962bdSlukem  * rewrite_parse; it can be altered only by a
332de962bdSlukem  * rewriteContext config line or by a change in info.
342de962bdSlukem  */
352de962bdSlukem struct rewrite_context *rewrite_int_curr_context = NULL;
362de962bdSlukem 
372de962bdSlukem /*
382de962bdSlukem  * Inits the info
392de962bdSlukem  */
402de962bdSlukem struct rewrite_info *
rewrite_info_init(int mode)412de962bdSlukem rewrite_info_init(
422de962bdSlukem 		int mode
432de962bdSlukem )
442de962bdSlukem {
452de962bdSlukem 	struct rewrite_info *info;
462de962bdSlukem 	struct rewrite_context *context;
472de962bdSlukem 
482de962bdSlukem 	switch ( mode ) {
492de962bdSlukem 	case REWRITE_MODE_ERR:
502de962bdSlukem 	case REWRITE_MODE_OK:
512de962bdSlukem 	case REWRITE_MODE_COPY_INPUT:
522de962bdSlukem 	case REWRITE_MODE_USE_DEFAULT:
532de962bdSlukem 		break;
542de962bdSlukem 	default:
552de962bdSlukem 		mode = REWRITE_MODE_USE_DEFAULT;
562de962bdSlukem 		break;
572de962bdSlukem 		/* return NULL */
582de962bdSlukem 	}
592de962bdSlukem 
602de962bdSlukem 	/*
612de962bdSlukem 	 * Resets the running context for parsing ...
622de962bdSlukem 	 */
632de962bdSlukem 	rewrite_int_curr_context = NULL;
642de962bdSlukem 
652de962bdSlukem 	info = calloc( sizeof( struct rewrite_info ), 1 );
662de962bdSlukem 	if ( info == NULL ) {
672de962bdSlukem 		return NULL;
682de962bdSlukem 	}
692de962bdSlukem 
702de962bdSlukem 	info->li_state = REWRITE_DEFAULT;
712de962bdSlukem 	info->li_max_passes = REWRITE_MAX_PASSES;
722de962bdSlukem 	info->li_max_passes_per_rule = REWRITE_MAX_PASSES;
732de962bdSlukem 	info->li_rewrite_mode = mode;
742de962bdSlukem 
752de962bdSlukem 	/*
762de962bdSlukem 	 * Add the default (empty) rule
772de962bdSlukem 	 */
782de962bdSlukem 	context = rewrite_context_create( info, REWRITE_DEFAULT_CONTEXT );
792de962bdSlukem 	if ( context == NULL ) {
802de962bdSlukem 		free( info );
812de962bdSlukem 		return NULL;
822de962bdSlukem 	}
832de962bdSlukem 
842de962bdSlukem #ifdef USE_REWRITE_LDAP_PVT_THREADS
852de962bdSlukem 	if ( ldap_pvt_thread_rdwr_init( &info->li_cookies_mutex ) ) {
86*549b59edSchristos 		ldap_avl_free( info->li_context, rewrite_context_free );
872de962bdSlukem 		free( info );
882de962bdSlukem 		return NULL;
892de962bdSlukem 	}
902de962bdSlukem 	if ( ldap_pvt_thread_rdwr_init( &info->li_params_mutex ) ) {
912de962bdSlukem 		ldap_pvt_thread_rdwr_destroy( &info->li_cookies_mutex );
92*549b59edSchristos 		ldap_avl_free( info->li_context, rewrite_context_free );
932de962bdSlukem 		free( info );
942de962bdSlukem 		return NULL;
952de962bdSlukem 	}
962de962bdSlukem #endif /* USE_REWRITE_LDAP_PVT_THREADS */
972de962bdSlukem 
982de962bdSlukem 	return info;
992de962bdSlukem }
1002de962bdSlukem 
1012de962bdSlukem /*
1022de962bdSlukem  * Cleans up the info structure
1032de962bdSlukem  */
1042de962bdSlukem int
rewrite_info_delete(struct rewrite_info ** pinfo)1052de962bdSlukem rewrite_info_delete(
1062de962bdSlukem 		struct rewrite_info **pinfo
1072de962bdSlukem )
1082de962bdSlukem {
1092de962bdSlukem 	struct rewrite_info	*info;
1102de962bdSlukem 
1112de962bdSlukem 	assert( pinfo != NULL );
1122de962bdSlukem 	assert( *pinfo != NULL );
1132de962bdSlukem 
1142de962bdSlukem 	info = *pinfo;
1152de962bdSlukem 
1162de962bdSlukem 	if ( info->li_context ) {
117*549b59edSchristos 		ldap_avl_free( info->li_context, rewrite_context_free );
1182de962bdSlukem 	}
1192de962bdSlukem 	info->li_context = NULL;
1202de962bdSlukem 
1212de962bdSlukem 	if ( info->li_maps ) {
122*549b59edSchristos 		ldap_avl_free( info->li_maps, rewrite_builtin_map_free );
1232de962bdSlukem 	}
1242de962bdSlukem 	info->li_maps = NULL;
1252de962bdSlukem 
1262de962bdSlukem 	rewrite_session_destroy( info );
1272de962bdSlukem 
1282de962bdSlukem #ifdef USE_REWRITE_LDAP_PVT_THREADS
1292de962bdSlukem 	ldap_pvt_thread_rdwr_destroy( &info->li_cookies_mutex );
1302de962bdSlukem #endif /* USE_REWRITE_LDAP_PVT_THREADS */
1312de962bdSlukem 
1322de962bdSlukem 	rewrite_param_destroy( info );
1332de962bdSlukem 
1342de962bdSlukem #ifdef USE_REWRITE_LDAP_PVT_THREADS
1352de962bdSlukem 	ldap_pvt_thread_rdwr_destroy( &info->li_params_mutex );
1362de962bdSlukem #endif /* USE_REWRITE_LDAP_PVT_THREADS */
1372de962bdSlukem 
1382de962bdSlukem 	free( info );
1392de962bdSlukem 	*pinfo = NULL;
1402de962bdSlukem 
1412de962bdSlukem 	return REWRITE_SUCCESS;
1422de962bdSlukem }
1432de962bdSlukem 
1442de962bdSlukem /*
1452de962bdSlukem  * Rewrites a string according to context.
1462de962bdSlukem  * If the engine is off, OK is returned, but the return string will be NULL.
1472de962bdSlukem  * In case of 'unwilling to perform', UNWILLING is returned, and the
1482de962bdSlukem  * return string will also be null. The same in case of error.
1492de962bdSlukem  * Otherwise, OK is returned, and result will hold a newly allocated string
1502de962bdSlukem  * with the rewriting.
1512de962bdSlukem  *
1522de962bdSlukem  * What to do in case of non-existing rewrite context is still an issue.
1532de962bdSlukem  * Four possibilities:
1542de962bdSlukem  * 	- error,
1552de962bdSlukem  * 	- ok with NULL result,
1562de962bdSlukem  * 	- ok with copy of string as result,
1572de962bdSlukem  * 	- use the default rewrite context.
1582de962bdSlukem  */
1592de962bdSlukem int
rewrite(struct rewrite_info * info,const char * rewriteContext,const char * string,char ** result)1602de962bdSlukem rewrite(
1612de962bdSlukem 		struct rewrite_info *info,
1622de962bdSlukem 		const char *rewriteContext,
1632de962bdSlukem 		const char *string,
1642de962bdSlukem 		char **result
1652de962bdSlukem )
1662de962bdSlukem {
1672de962bdSlukem 	return rewrite_session( info, rewriteContext,
1682de962bdSlukem 			string, NULL, result );
1692de962bdSlukem }
1702de962bdSlukem 
1712de962bdSlukem int
rewrite_session(struct rewrite_info * info,const char * rewriteContext,const char * string,const void * cookie,char ** result)1722de962bdSlukem rewrite_session(
1732de962bdSlukem 		struct rewrite_info *info,
1742de962bdSlukem 		const char *rewriteContext,
1752de962bdSlukem 		const char *string,
1762de962bdSlukem 		const void *cookie,
1772de962bdSlukem 		char **result
1782de962bdSlukem )
1792de962bdSlukem {
1802de962bdSlukem 	struct rewrite_context *context;
1812de962bdSlukem 	struct rewrite_op op = { 0, 0, NULL, NULL, NULL };
1822de962bdSlukem 	int rc;
1832de962bdSlukem 
1842de962bdSlukem 	assert( info != NULL );
1852de962bdSlukem 	assert( rewriteContext != NULL );
1862de962bdSlukem 	assert( string != NULL );
1872de962bdSlukem 	assert( result != NULL );
1882de962bdSlukem 
1892de962bdSlukem 	/*
1902de962bdSlukem 	 * cookie can be null; means: don't care about session stuff
1912de962bdSlukem 	 */
1922de962bdSlukem 
1932de962bdSlukem 	*result = NULL;
1942de962bdSlukem 	op.lo_cookie = cookie;
1952de962bdSlukem 
1962de962bdSlukem 	/*
1972de962bdSlukem 	 * Engine not on means no failure, but explicit no rewriting
1982de962bdSlukem 	 */
1992de962bdSlukem 	if ( info->li_state != REWRITE_ON ) {
2002de962bdSlukem 		rc = REWRITE_REGEXEC_OK;
2012de962bdSlukem 		goto rc_return;
2022de962bdSlukem 	}
2032de962bdSlukem 
2042de962bdSlukem 	/*
2052de962bdSlukem 	 * Undefined context means no rewriting also
2062de962bdSlukem 	 * (conservative, are we sure it's what we want?)
2072de962bdSlukem 	 */
2082de962bdSlukem 	context = rewrite_context_find( info, rewriteContext );
2092de962bdSlukem 	if ( context == NULL ) {
2102de962bdSlukem 		switch ( info->li_rewrite_mode ) {
2112de962bdSlukem 		case REWRITE_MODE_ERR:
2122de962bdSlukem 			rc = REWRITE_REGEXEC_ERR;
2132de962bdSlukem 			goto rc_return;
2142de962bdSlukem 
2152de962bdSlukem 		case REWRITE_MODE_OK:
2162de962bdSlukem 			rc = REWRITE_REGEXEC_OK;
2172de962bdSlukem 			goto rc_return;
2182de962bdSlukem 
2192de962bdSlukem 		case REWRITE_MODE_COPY_INPUT:
2202de962bdSlukem 			*result = strdup( string );
2214e6df137Slukem 			rc = ( *result != NULL ) ? REWRITE_REGEXEC_OK : REWRITE_REGEXEC_ERR;
2222de962bdSlukem 			goto rc_return;
2232de962bdSlukem 
2242de962bdSlukem 		case REWRITE_MODE_USE_DEFAULT:
2252de962bdSlukem 			context = rewrite_context_find( info,
2262de962bdSlukem 					REWRITE_DEFAULT_CONTEXT );
2272de962bdSlukem 			break;
2282de962bdSlukem 		}
2292de962bdSlukem 	}
2302de962bdSlukem 
2312de962bdSlukem #if 0 /* FIXME: not used anywhere! (debug? then, why strdup?) */
2322de962bdSlukem 	op.lo_string = strdup( string );
2332de962bdSlukem 	if ( op.lo_string == NULL ) {
2342de962bdSlukem 		rc = REWRITE_REGEXEC_ERR;
2352de962bdSlukem 		goto rc_return;
2362de962bdSlukem 	}
2372de962bdSlukem #endif
2382de962bdSlukem 
2392de962bdSlukem 	/*
2402de962bdSlukem 	 * Applies rewrite context
2412de962bdSlukem 	 */
2422de962bdSlukem 	rc = rewrite_context_apply( info, &op, context, string, result );
2432de962bdSlukem 	assert( op.lo_depth == 0 );
2442de962bdSlukem 
2452de962bdSlukem #if 0 /* FIXME: not used anywhere! (debug? then, why strdup?) */
2462de962bdSlukem 	free( op.lo_string );
2472de962bdSlukem #endif
2482de962bdSlukem 
2492de962bdSlukem 	switch ( rc ) {
2502de962bdSlukem 	/*
2512de962bdSlukem 	 * Success
2522de962bdSlukem 	 */
2532de962bdSlukem 	case REWRITE_REGEXEC_OK:
2542de962bdSlukem 	case REWRITE_REGEXEC_STOP:
2552de962bdSlukem 		/*
2562de962bdSlukem 		 * If rewrite succeeded return OK regardless of how
2572de962bdSlukem 		 * the successful rewriting was obtained!
2582de962bdSlukem 		 */
2592de962bdSlukem 		rc = REWRITE_REGEXEC_OK;
2602de962bdSlukem 		break;
2612de962bdSlukem 
2622de962bdSlukem 
2632de962bdSlukem 	/*
2642de962bdSlukem 	 * Internal or forced error, return = NULL; rc already OK.
2652de962bdSlukem 	 */
2662de962bdSlukem 	case REWRITE_REGEXEC_UNWILLING:
2672de962bdSlukem 	case REWRITE_REGEXEC_ERR:
2682de962bdSlukem 		if ( *result != NULL ) {
2692de962bdSlukem 			if ( *result != string ) {
2702de962bdSlukem 				free( *result );
2712de962bdSlukem 			}
2722de962bdSlukem 			*result = NULL;
2732de962bdSlukem 		}
2742de962bdSlukem 
2752de962bdSlukem 	default:
2762de962bdSlukem 		break;
2772de962bdSlukem 	}
2782de962bdSlukem 
2792de962bdSlukem rc_return:;
2802de962bdSlukem 	if ( op.lo_vars ) {
2812de962bdSlukem 		rewrite_var_delete( op.lo_vars );
2822de962bdSlukem 	}
2832de962bdSlukem 
2842de962bdSlukem 	return rc;
2852de962bdSlukem }
2862de962bdSlukem 
287