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