mirror of
https://git.openldap.org/openldap/openldap.git
synced 2024-12-21 03:10:25 +08:00
74fa239a20
- librewrite, for string rewriting; it may be used in back-ldap by configuring with '--enable-rewrite'. It must be used in back-meta. There's a text file, 'libraries/librewrite/RATIONALE', that explains the usage and the features. More comprehensive documentation will follow. - enhancements of back-ldap (ITS#989,ITS#998,ITS#1002,ITS#1054 and ITS#1137) including dn rewriting, a fix to group acl matching and so - back-meta: a new backend that proxies a set of remote servers by spawning queries. It uses portions of back-ldap and the rewrite capabilities of librewrite. It can be compiled by configuring with `--enable-ldap --enable-rewrite --enable-meta'. There's a text file, 'servers/slapd/back-meta/Documentation', that describes the main features and config statements. Note: someone (Kurt?) should run 'autoconf' and commit 'configure' as my autoconf version must be different: my configures contain a number of differences and I didn't feel comfortable in adding them :)
255 lines
5.5 KiB
C
255 lines
5.5 KiB
C
/******************************************************************************
|
|
*
|
|
* Copyright (C) 2000 Pierangelo Masarati, <ando@sys-net.it>
|
|
* 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.
|
|
*
|
|
******************************************************************************/
|
|
|
|
#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 *__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 ...
|
|
*/
|
|
__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_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 ) ) {
|
|
free( info );
|
|
return NULL;
|
|
}
|
|
if ( ldap_pvt_thread_rdwr_init( &info->li_params_mutex ) ) {
|
|
free( info );
|
|
return NULL;
|
|
}
|
|
#endif /* USE_REWRITE_LDAP_PVT_THREADS */
|
|
|
|
return info;
|
|
}
|
|
|
|
/*
|
|
* Cleans up the info structure
|
|
*/
|
|
int
|
|
rewrite_info_delete(
|
|
struct rewrite_info *info
|
|
)
|
|
{
|
|
assert( info != NULL );
|
|
|
|
rewrite_session_destroy( info );
|
|
|
|
rewrite_param_destroy( info );
|
|
|
|
#ifdef USE_REWRITE_LDAP_PVT_THREADS
|
|
ldap_pvt_thread_rdwr_destroy( &info->li_cookies_mutex );
|
|
ldap_pvt_thread_rdwr_destroy( &info->li_params_mutex );
|
|
#endif /* USE_REWRITE_LDAP_PVT_THREADS */
|
|
|
|
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, 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 = REWRITE_REGEXEC_OK;
|
|
goto rc_return;
|
|
case REWRITE_MODE_USE_DEFAULT:
|
|
context = rewrite_context_find( info,
|
|
REWRITE_DEFAULT_CONTEXT );
|
|
break;
|
|
}
|
|
}
|
|
|
|
op.lo_string = strdup( string );
|
|
if ( op.lo_string == NULL ) {
|
|
rc = REWRITE_REGEXEC_ERR;
|
|
goto rc_return;
|
|
}
|
|
|
|
/*
|
|
* Applies rewrite context
|
|
*/
|
|
rc = rewrite_context_apply(info, &op, context, string, result );
|
|
assert( op.lo_depth == 0 );
|
|
|
|
/* ?!? */
|
|
free( op.lo_string );
|
|
|
|
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:
|
|
default:
|
|
if ( *result != NULL ) {
|
|
free( *result );
|
|
*result = NULL;
|
|
}
|
|
}
|
|
|
|
rc_return:
|
|
if ( op.lo_vars ) {
|
|
rewrite_var_delete( op.lo_vars );
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|