diff options
Diffstat (limited to 'libraries/librewrite/config.c')
-rw-r--r-- | libraries/librewrite/config.c | 441 |
1 files changed, 441 insertions, 0 deletions
diff --git a/libraries/librewrite/config.c b/libraries/librewrite/config.c new file mode 100644 index 0000000..bf3d85d --- /dev/null +++ b/libraries/librewrite/config.c @@ -0,0 +1,441 @@ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software <http://www.openldap.org/>. + * + * Copyright 2000-2021 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" +#include "rewrite-map.h" + +/* + * 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 [numPassesPerRule] + * 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; + } + + if ( lutil_atoi( &info->li_max_passes, argv[ 1 ] ) != 0 ) { + Debug( LDAP_DEBUG_ANY, + "[%s:%d] unable to parse rewriteMaxPasses=\"%s\"\n", + fname, lineno, argv[ 1 ] ); + return -1; + } + + if ( info->li_max_passes <= 0 ) { + Debug( LDAP_DEBUG_ANY, + "[%s:%d] negative or null rewriteMaxPasses\n", + fname, lineno, 0 ); + return -1; + } + + if ( argc > 2 ) { + if ( lutil_atoi( &info->li_max_passes_per_rule, argv[ 2 ] ) != 0 ) { + Debug( LDAP_DEBUG_ANY, + "[%s:%d] unable to parse rewriteMaxPassesPerRule=\"%s\"\n", + fname, lineno, argv[ 2 ] ); + return -1; + } + + if ( info->li_max_passes_per_rule <= 0 ) { + Debug( LDAP_DEBUG_ANY, + "[%s:%d] negative or null rewriteMaxPassesPerRule\n", + fname, lineno, 0 ); + return -1; + } + + } else { + info->li_max_passes_per_rule = info->li_max_passes; + } + 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 ...) + */ + rewrite_int_curr_context = rewrite_context_find( info, argv[ 1 ] ); + if ( rewrite_int_curr_context == NULL ) { + rewrite_int_curr_context = rewrite_context_create( info, + argv[ 1 ] ); + } + if ( rewrite_int_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; + } + + rewrite_int_curr_context->lc_alias = aliased; + rewrite_int_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 ( rewrite_int_curr_context == NULL ) { + Debug( LDAP_DEBUG_ANY, + "[%s:%d] rewriteRule outside a" + " context; will add to default\n%s", + fname, lineno, "" ); + rewrite_int_curr_context = rewrite_context_find( info, + REWRITE_DEFAULT_CONTEXT ); + + /* + * Default context MUST exist in a properly initialized + * struct rewrite_info + */ + assert( rewrite_int_curr_context != NULL ); + } + + rc = rewrite_rule_compile( info, rewrite_int_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 = ( const struct rewrite_builtin_map * )c1; + m2 = ( const 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 (( map->lb_mapper = rewrite_mapper_find( argv[ MAP_TYPE ] ))) { + map->lb_type = REWRITE_BUILTIN_MAP; + +#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->lb_mapper->rm_config( fname, lineno, + argc - 3, argv + 3 ); + + /* + * Error + */ + } else { + free( map ); + Debug( LDAP_DEBUG_ANY, "[%s:%d] unknown map type\n%s", + fname, lineno, "" ); + return -1; + } + + return rewrite_builtin_map_insert( info, map ); +} |