mirror of
https://git.openldap.org/openldap/openldap.git
synced 2024-12-21 03:10:25 +08:00
413 lines
9.4 KiB
C
413 lines
9.4 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"
|
|
#include "rewrite-map.h"
|
|
|
|
/*
|
|
* Global data
|
|
*/
|
|
extern struct rewrite_context *__curr_context;
|
|
|
|
/*
|
|
* Parses a plugin map
|
|
*/
|
|
static int
|
|
rewrite_parse_builtin_map(
|
|
struct rewrite_info *info,
|
|
const char *fname,
|
|
int lineno,
|
|
int argc,
|
|
char **argv
|
|
);
|
|
|
|
/*
|
|
* Parses a config line and takes actions to fit content in rewrite structure;
|
|
* lines handled are of the form:
|
|
*
|
|
* rewriteEngine {on|off}
|
|
* rewriteMaxPasses numPasses
|
|
* rewriteContext contextName [alias aliasedContextName]
|
|
* rewriteRule pattern substPattern [ruleFlags]
|
|
* rewriteMap mapType mapName [mapArgs]
|
|
* rewriteParam paramName paramValue
|
|
*/
|
|
int
|
|
rewrite_parse(
|
|
struct rewrite_info *info,
|
|
const char *fname,
|
|
int lineno,
|
|
int argc,
|
|
char **argv
|
|
)
|
|
{
|
|
int rc = -1;
|
|
|
|
assert( info != NULL );
|
|
assert( fname != NULL );
|
|
assert( argv != NULL );
|
|
assert( argc > 0 );
|
|
|
|
/*
|
|
* Switch on the rewrite engine
|
|
*/
|
|
if ( strcasecmp( argv[ 0 ], "rewriteEngine" ) == 0 ) {
|
|
if ( argc < 2 ) {
|
|
Debug( LDAP_DEBUG_ANY,
|
|
"[%s:%d] rewriteEngine needs 'state'\n%s",
|
|
fname, lineno, "" );
|
|
return -1;
|
|
} else if ( argc > 2 ) {
|
|
Debug( LDAP_DEBUG_ANY,
|
|
"[%s:%d] extra fields in rewriteEngine"
|
|
" will be discarded\n%s",
|
|
fname, lineno, "" );
|
|
}
|
|
|
|
if ( strcasecmp( argv[ 1 ], "on" ) == 0 ) {
|
|
info->li_state = REWRITE_ON;
|
|
} else if ( strcasecmp( argv[ 1 ], "off" ) == 0 ) {
|
|
info->li_state = REWRITE_OFF;
|
|
} else {
|
|
Debug( LDAP_DEBUG_ANY,
|
|
"[%s:%d] unknown 'state' in rewriteEngine;"
|
|
" assuming 'on'\n%s",
|
|
fname, lineno, "" );
|
|
info->li_state = REWRITE_ON;
|
|
}
|
|
rc = REWRITE_SUCCESS;
|
|
|
|
/*
|
|
* Alter max passes
|
|
*/
|
|
} else if ( strcasecmp( argv[ 0 ], "rewriteMaxPasses" ) == 0 ) {
|
|
if ( argc < 2 ) {
|
|
Debug( LDAP_DEBUG_ANY,
|
|
"[%s:%d] rewriteMaxPasses needs 'value'\n%s",
|
|
fname, lineno, "" );
|
|
return -1;
|
|
}
|
|
info->li_max_passes = atoi( argv[ 1 ] );
|
|
rc = REWRITE_SUCCESS;
|
|
|
|
/*
|
|
* Start a new rewrite context and set current context
|
|
*/
|
|
} else if ( strcasecmp( argv[ 0 ], "rewriteContext" ) == 0 ) {
|
|
if ( argc < 2 ) {
|
|
Debug( LDAP_DEBUG_ANY,
|
|
"[%s:%d] rewriteContext needs 'name'\n%s",
|
|
fname, lineno, "" );
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
* Checks for existence (lots of contexts should be
|
|
* available by default ...)
|
|
*/
|
|
__curr_context = rewrite_context_find( info, argv[ 1 ] );
|
|
if ( __curr_context == NULL ) {
|
|
__curr_context = rewrite_context_create( info,
|
|
argv[ 1 ] );
|
|
}
|
|
if ( __curr_context == NULL ) {
|
|
return -1;
|
|
}
|
|
|
|
if ( argc > 2 ) {
|
|
|
|
/*
|
|
* A context can alias another (e.g., the `builtin'
|
|
* contexts for backend operations, if not defined,
|
|
* alias the `default' rewrite context (with the
|
|
* notable exception of the searchResult context,
|
|
* which can be undefined)
|
|
*/
|
|
if ( strcasecmp( argv[ 2 ], "alias" ) == 0 ) {
|
|
struct rewrite_context *aliased;
|
|
|
|
if ( argc == 3 ) {
|
|
Debug( LDAP_DEBUG_ANY,
|
|
"[%s:%d] rewriteContext"
|
|
" needs 'name' after"
|
|
" 'alias'\n%s",
|
|
fname, lineno, "" );
|
|
return -1;
|
|
} else if ( argc > 4 ) {
|
|
Debug( LDAP_DEBUG_ANY,
|
|
"[%s:%d] extra fields in"
|
|
" rewriteContext"
|
|
" after aliased name"
|
|
" will be"
|
|
" discarded\n%s",
|
|
fname, lineno, "" );
|
|
}
|
|
|
|
aliased = rewrite_context_find( info,
|
|
argv[ 3 ] );
|
|
if ( aliased == NULL ) {
|
|
Debug( LDAP_DEBUG_ANY,
|
|
"[%s:%d] aliased"
|
|
" rewriteContext '%s'"
|
|
" does not exists\n",
|
|
fname, lineno,
|
|
argv[ 3 ] );
|
|
return -1;
|
|
}
|
|
|
|
__curr_context->lc_alias = aliased;
|
|
__curr_context = aliased;
|
|
} else {
|
|
Debug( LDAP_DEBUG_ANY,
|
|
"[%s:%d] extra fields"
|
|
" in rewriteContext"
|
|
" will be discarded\n%s",
|
|
fname, lineno, "" );
|
|
}
|
|
}
|
|
rc = REWRITE_SUCCESS;
|
|
|
|
/*
|
|
* Compile a rule in current context
|
|
*/
|
|
} else if ( strcasecmp( argv[ 0 ], "rewriteRule" ) == 0 ) {
|
|
if ( argc < 3 ) {
|
|
Debug( LDAP_DEBUG_ANY,
|
|
"[%s:%d] rewriteRule needs 'pattern'"
|
|
" 'subst' ['flags']\n%s",
|
|
fname, lineno, "" );
|
|
return -1;
|
|
} else if ( argc > 4 ) {
|
|
Debug( LDAP_DEBUG_ANY,
|
|
"[%s:%d] extra fields in rewriteRule"
|
|
" will be discarded\n%s",
|
|
fname, lineno, "" );
|
|
}
|
|
|
|
if ( __curr_context == NULL ) {
|
|
Debug( LDAP_DEBUG_ANY,
|
|
"[%s:%d] rewriteRule outside a"
|
|
" context; will add to default\n%s",
|
|
fname, lineno, "" );
|
|
__curr_context = rewrite_context_find( info,
|
|
REWRITE_DEFAULT_CONTEXT );
|
|
|
|
/*
|
|
* Default context MUST exist in a properly initialized
|
|
* struct rewrite_info
|
|
*/
|
|
assert( __curr_context != NULL );
|
|
}
|
|
|
|
rc = rewrite_rule_compile( info, __curr_context, argv[ 1 ],
|
|
argv[ 2 ], ( argc == 4 ? argv[ 3 ] : "" ) );
|
|
|
|
/*
|
|
* Add a plugin map to the map tree
|
|
*/
|
|
} else if ( strcasecmp( argv[ 0 ], "rewriteMap" ) == 0 ) {
|
|
if ( argc < 3 ) {
|
|
Debug( LDAP_DEBUG_ANY,
|
|
"[%s:%d] rewriteMap needs at least 'type'"
|
|
" and 'name' ['args']\n%s",
|
|
fname, lineno, "" );
|
|
return -1;
|
|
}
|
|
|
|
rc = rewrite_parse_builtin_map( info, fname, lineno,
|
|
argc, argv );
|
|
|
|
/*
|
|
* Set the value of a global scope parameter
|
|
*/
|
|
} else if ( strcasecmp( argv[ 0 ], "rewriteParam" ) == 0 ) {
|
|
if ( argc < 3 ) {
|
|
Debug( LDAP_DEBUG_ANY,
|
|
"[%s:%d] rewriteParam needs 'name'"
|
|
" and 'value'\n%s",
|
|
fname, lineno, "" );
|
|
return -1;
|
|
}
|
|
|
|
rc = rewrite_param_set( info, argv[ 1 ], argv[ 2 ] );
|
|
|
|
/*
|
|
* Error
|
|
*/
|
|
} else {
|
|
Debug( LDAP_DEBUG_ANY,
|
|
"[%s:%d] unknown command '%s'\n",
|
|
fname, lineno, "" );
|
|
return -1;
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
* Compares two maps
|
|
*/
|
|
static int
|
|
rewrite_builtin_map_cmp(
|
|
const void *c1,
|
|
const void *c2
|
|
)
|
|
{
|
|
const struct rewrite_builtin_map *m1, *m2;
|
|
|
|
m1 = ( struct rewrite_builtin_map * )c1;
|
|
m2 = ( struct rewrite_builtin_map * )c2;
|
|
|
|
assert( m1 != NULL );
|
|
assert( m2 != NULL );
|
|
assert( m1->lb_name != NULL );
|
|
assert( m2->lb_name != NULL );
|
|
|
|
return strcasecmp( m1->lb_name, m2->lb_name );
|
|
}
|
|
|
|
/*
|
|
* Duplicate map ?
|
|
*/
|
|
static int
|
|
rewrite_builtin_map_dup(
|
|
void *c1,
|
|
void *c2
|
|
)
|
|
{
|
|
struct rewrite_builtin_map *m1, *m2;
|
|
|
|
m1 = ( struct rewrite_builtin_map * )c1;
|
|
m2 = ( struct rewrite_builtin_map * )c2;
|
|
|
|
assert( m1 != NULL );
|
|
assert( m2 != NULL );
|
|
assert( m1->lb_name != NULL );
|
|
assert( m2->lb_name != NULL );
|
|
|
|
return ( strcasecmp( m1->lb_name, m2->lb_name ) == 0 ? -1 : 0 );
|
|
}
|
|
|
|
/*
|
|
* Adds a map to the info map tree
|
|
*/
|
|
static int
|
|
rewrite_builtin_map_insert(
|
|
struct rewrite_info *info,
|
|
struct rewrite_builtin_map *map
|
|
)
|
|
{
|
|
/*
|
|
* May need a mutex?
|
|
*/
|
|
return avl_insert( &info->li_maps, ( caddr_t )map,
|
|
rewrite_builtin_map_cmp,
|
|
rewrite_builtin_map_dup );
|
|
}
|
|
|
|
/*
|
|
* Retrieves a map
|
|
*/
|
|
struct rewrite_builtin_map *
|
|
rewrite_builtin_map_find(
|
|
struct rewrite_info *info,
|
|
const char *name
|
|
)
|
|
{
|
|
struct rewrite_builtin_map tmp;
|
|
|
|
assert( info != NULL );
|
|
assert( name != NULL );
|
|
|
|
tmp.lb_name = ( char * )name;
|
|
|
|
return ( struct rewrite_builtin_map * )avl_find( info->li_maps,
|
|
( caddr_t )&tmp, rewrite_builtin_map_cmp );
|
|
}
|
|
|
|
/*
|
|
* Parses a plugin map
|
|
*/
|
|
static int
|
|
rewrite_parse_builtin_map(
|
|
struct rewrite_info *info,
|
|
const char *fname,
|
|
int lineno,
|
|
int argc,
|
|
char **argv
|
|
)
|
|
{
|
|
struct rewrite_builtin_map *map;
|
|
|
|
#define MAP_TYPE 1
|
|
#define MAP_NAME 2
|
|
|
|
assert( info != NULL );
|
|
assert( fname != NULL );
|
|
assert( argc > 2 );
|
|
assert( argv != NULL );
|
|
assert( strcasecmp( argv[ 0 ], "rewriteMap" ) == 0 );
|
|
|
|
map = calloc( sizeof( struct rewrite_builtin_map ), 1 );
|
|
if ( map == NULL ) {
|
|
return REWRITE_ERR;
|
|
}
|
|
|
|
map->lb_name = strdup( argv[ MAP_NAME ] );
|
|
if ( map->lb_name == NULL ) {
|
|
free( map );
|
|
return REWRITE_ERR;
|
|
}
|
|
|
|
/*
|
|
* Built-in ldap map
|
|
*/
|
|
if ( strcasecmp( argv[ MAP_TYPE ], "ldap" ) == 0 ) {
|
|
map->lb_type = REWRITE_BUILTIN_MAP_LDAP;
|
|
|
|
#ifdef USE_REWRITE_LDAP_PVT_THREADS
|
|
if ( ldap_pvt_thread_mutex_init( & map->lb_mutex ) ) {
|
|
free( map->lb_name );
|
|
free( map );
|
|
return REWRITE_ERR;
|
|
}
|
|
#endif /* USE_REWRITE_LDAP_PVT_THREADS */
|
|
|
|
map->lb_private = map_ldap_parse( info, fname, lineno,
|
|
argc - 3, argv + 3 );
|
|
|
|
/*
|
|
* Error
|
|
*/
|
|
} else {
|
|
Debug( LDAP_DEBUG_ANY, "[%s:%d] unknown map type\n%s",
|
|
fname, lineno, "" );
|
|
return -1;
|
|
}
|
|
|
|
return rewrite_builtin_map_insert( info, map );
|
|
}
|