openldap/libraries/librewrite/config.c
Pierangelo Masarati 74fa239a20 This is the commit of:
- 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 :)
2001-05-12 00:51:28 +00:00

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 );
}