mirror of
https://git.openldap.org/openldap/openldap.git
synced 2024-12-21 03:10:25 +08:00
285 lines
6.0 KiB
C
285 lines
6.0 KiB
C
/* $OpenLDAP$ */
|
|
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
|
*
|
|
* Copyright 2000-2020 The OpenLDAP Foundation.
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted only as authorized by the OpenLDAP
|
|
* Public License.
|
|
*
|
|
* A copy of this license is available in the file LICENSE in the
|
|
* top-level directory of the distribution or, alternatively, at
|
|
* <http://www.OpenLDAP.org/license.html>.
|
|
*/
|
|
/* ACKNOWLEDGEMENT:
|
|
* This work was initially developed by Pierangelo Masarati for
|
|
* inclusion in OpenLDAP Software.
|
|
*/
|
|
|
|
#include <portable.h>
|
|
|
|
#include "rewrite-int.h"
|
|
|
|
/*
|
|
* Global data
|
|
*/
|
|
|
|
/*
|
|
* This becomes the running context for subsequent calls to
|
|
* rewrite_parse; it can be altered only by a
|
|
* rewriteContext config line or by a change in info.
|
|
*/
|
|
struct rewrite_context *rewrite_int_curr_context = NULL;
|
|
|
|
/*
|
|
* Inits the info
|
|
*/
|
|
struct rewrite_info *
|
|
rewrite_info_init(
|
|
int mode
|
|
)
|
|
{
|
|
struct rewrite_info *info;
|
|
struct rewrite_context *context;
|
|
|
|
switch ( mode ) {
|
|
case REWRITE_MODE_ERR:
|
|
case REWRITE_MODE_OK:
|
|
case REWRITE_MODE_COPY_INPUT:
|
|
case REWRITE_MODE_USE_DEFAULT:
|
|
break;
|
|
default:
|
|
mode = REWRITE_MODE_USE_DEFAULT;
|
|
break;
|
|
/* return NULL */
|
|
}
|
|
|
|
/*
|
|
* Resets the running context for parsing ...
|
|
*/
|
|
rewrite_int_curr_context = NULL;
|
|
|
|
info = calloc( sizeof( struct rewrite_info ), 1 );
|
|
if ( info == NULL ) {
|
|
return NULL;
|
|
}
|
|
|
|
info->li_state = REWRITE_DEFAULT;
|
|
info->li_max_passes = REWRITE_MAX_PASSES;
|
|
info->li_max_passes_per_rule = REWRITE_MAX_PASSES;
|
|
info->li_rewrite_mode = mode;
|
|
|
|
/*
|
|
* Add the default (empty) rule
|
|
*/
|
|
context = rewrite_context_create( info, REWRITE_DEFAULT_CONTEXT );
|
|
if ( context == NULL ) {
|
|
free( info );
|
|
return NULL;
|
|
}
|
|
|
|
#ifdef USE_REWRITE_LDAP_PVT_THREADS
|
|
if ( ldap_pvt_thread_rdwr_init( &info->li_cookies_mutex ) ) {
|
|
avl_free( info->li_context, rewrite_context_free );
|
|
free( info );
|
|
return NULL;
|
|
}
|
|
if ( ldap_pvt_thread_rdwr_init( &info->li_params_mutex ) ) {
|
|
ldap_pvt_thread_rdwr_destroy( &info->li_cookies_mutex );
|
|
avl_free( info->li_context, rewrite_context_free );
|
|
free( info );
|
|
return NULL;
|
|
}
|
|
#endif /* USE_REWRITE_LDAP_PVT_THREADS */
|
|
|
|
return info;
|
|
}
|
|
|
|
/*
|
|
* Cleans up the info structure
|
|
*/
|
|
int
|
|
rewrite_info_delete(
|
|
struct rewrite_info **pinfo
|
|
)
|
|
{
|
|
struct rewrite_info *info;
|
|
|
|
assert( pinfo != NULL );
|
|
assert( *pinfo != NULL );
|
|
|
|
info = *pinfo;
|
|
|
|
if ( info->li_context ) {
|
|
avl_free( info->li_context, rewrite_context_free );
|
|
}
|
|
info->li_context = NULL;
|
|
|
|
if ( info->li_maps ) {
|
|
avl_free( info->li_maps, rewrite_builtin_map_free );
|
|
}
|
|
info->li_maps = NULL;
|
|
|
|
rewrite_session_destroy( info );
|
|
|
|
#ifdef USE_REWRITE_LDAP_PVT_THREADS
|
|
ldap_pvt_thread_rdwr_destroy( &info->li_cookies_mutex );
|
|
#endif /* USE_REWRITE_LDAP_PVT_THREADS */
|
|
|
|
rewrite_param_destroy( info );
|
|
|
|
#ifdef USE_REWRITE_LDAP_PVT_THREADS
|
|
ldap_pvt_thread_rdwr_destroy( &info->li_params_mutex );
|
|
#endif /* USE_REWRITE_LDAP_PVT_THREADS */
|
|
|
|
free( info );
|
|
*pinfo = NULL;
|
|
|
|
return REWRITE_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
* Rewrites a string according to context.
|
|
* If the engine is off, OK is returned, but the return string will be NULL.
|
|
* In case of 'unwilling to perform', UNWILLING is returned, and the
|
|
* return string will also be null. The same in case of error.
|
|
* Otherwise, OK is returned, and result will hold a newly allocated string
|
|
* with the rewriting.
|
|
*
|
|
* What to do in case of non-existing rewrite context is still an issue.
|
|
* Four possibilities:
|
|
* - error,
|
|
* - ok with NULL result,
|
|
* - ok with copy of string as result,
|
|
* - use the default rewrite context.
|
|
*/
|
|
int
|
|
rewrite(
|
|
struct rewrite_info *info,
|
|
const char *rewriteContext,
|
|
const char *string,
|
|
char **result
|
|
)
|
|
{
|
|
return rewrite_session( info, rewriteContext,
|
|
string, NULL, result );
|
|
}
|
|
|
|
int
|
|
rewrite_session(
|
|
struct rewrite_info *info,
|
|
const char *rewriteContext,
|
|
const char *string,
|
|
const void *cookie,
|
|
char **result
|
|
)
|
|
{
|
|
struct rewrite_context *context;
|
|
struct rewrite_op op = { 0, 0, NULL, NULL, NULL };
|
|
int rc;
|
|
|
|
assert( info != NULL );
|
|
assert( rewriteContext != NULL );
|
|
assert( string != NULL );
|
|
assert( result != NULL );
|
|
|
|
/*
|
|
* cookie can be null; means: don't care about session stuff
|
|
*/
|
|
|
|
*result = NULL;
|
|
op.lo_cookie = cookie;
|
|
|
|
/*
|
|
* Engine not on means no failure, but explicit no rewriting
|
|
*/
|
|
if ( info->li_state != REWRITE_ON ) {
|
|
rc = REWRITE_REGEXEC_OK;
|
|
goto rc_return;
|
|
}
|
|
|
|
/*
|
|
* Undefined context means no rewriting also
|
|
* (conservative, are we sure it's what we want?)
|
|
*/
|
|
context = rewrite_context_find( info, rewriteContext );
|
|
if ( context == NULL ) {
|
|
switch ( info->li_rewrite_mode ) {
|
|
case REWRITE_MODE_ERR:
|
|
rc = REWRITE_REGEXEC_ERR;
|
|
goto rc_return;
|
|
|
|
case REWRITE_MODE_OK:
|
|
rc = REWRITE_REGEXEC_OK;
|
|
goto rc_return;
|
|
|
|
case REWRITE_MODE_COPY_INPUT:
|
|
*result = strdup( string );
|
|
rc = ( *result != NULL ) ? REWRITE_REGEXEC_OK : REWRITE_REGEXEC_ERR;
|
|
goto rc_return;
|
|
|
|
case REWRITE_MODE_USE_DEFAULT:
|
|
context = rewrite_context_find( info,
|
|
REWRITE_DEFAULT_CONTEXT );
|
|
break;
|
|
}
|
|
}
|
|
|
|
#if 0 /* FIXME: not used anywhere! (debug? then, why strdup?) */
|
|
op.lo_string = strdup( string );
|
|
if ( op.lo_string == NULL ) {
|
|
rc = REWRITE_REGEXEC_ERR;
|
|
goto rc_return;
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* Applies rewrite context
|
|
*/
|
|
rc = rewrite_context_apply( info, &op, context, string, result );
|
|
assert( op.lo_depth == 0 );
|
|
|
|
#if 0 /* FIXME: not used anywhere! (debug? then, why strdup?) */
|
|
free( op.lo_string );
|
|
#endif
|
|
|
|
switch ( rc ) {
|
|
/*
|
|
* Success
|
|
*/
|
|
case REWRITE_REGEXEC_OK:
|
|
case REWRITE_REGEXEC_STOP:
|
|
/*
|
|
* If rewrite succeeded return OK regardless of how
|
|
* the successful rewriting was obtained!
|
|
*/
|
|
rc = REWRITE_REGEXEC_OK;
|
|
break;
|
|
|
|
|
|
/*
|
|
* Internal or forced error, return = NULL; rc already OK.
|
|
*/
|
|
case REWRITE_REGEXEC_UNWILLING:
|
|
case REWRITE_REGEXEC_ERR:
|
|
if ( *result != NULL ) {
|
|
if ( *result != string ) {
|
|
free( *result );
|
|
}
|
|
*result = NULL;
|
|
}
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
rc_return:;
|
|
if ( op.lo_vars ) {
|
|
rewrite_var_delete( op.lo_vars );
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|