Home | History | Annotate | Line # | Download | only in librewrite
config.c revision 1.1.1.2
      1 /*	$NetBSD: config.c,v 1.1.1.2 2010/03/08 02:14:20 lukem Exp $	*/
      2 
      3 /* OpenLDAP: pkg/ldap/libraries/librewrite/config.c,v 1.14.2.4 2009/01/22 00:00:58 kurt Exp */
      4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
      5  *
      6  * Copyright 2000-2009 The OpenLDAP Foundation.
      7  * All rights reserved.
      8  *
      9  * Redistribution and use in source and binary forms, with or without
     10  * modification, are permitted only as authorized by the OpenLDAP
     11  * Public License.
     12  *
     13  * A copy of this license is available in the file LICENSE in the
     14  * top-level directory of the distribution or, alternatively, at
     15  * <http://www.OpenLDAP.org/license.html>.
     16  */
     17 /* ACKNOWLEDGEMENT:
     18  * This work was initially developed by Pierangelo Masarati for
     19  * inclusion in OpenLDAP Software.
     20  */
     21 
     22 #include <portable.h>
     23 
     24 #include "rewrite-int.h"
     25 #include "rewrite-map.h"
     26 
     27 /*
     28  * Parses a plugin map
     29  */
     30 static int
     31 rewrite_parse_builtin_map(
     32 		struct rewrite_info *info,
     33 		const char *fname,
     34 		int lineno,
     35 		int argc,
     36 		char **argv
     37 );
     38 
     39 /*
     40  * Parses a config line and takes actions to fit content in rewrite structure;
     41  * lines handled are of the form:
     42  *
     43  *      rewriteEngine 		{on|off}
     44  *      rewriteMaxPasses        numPasses [numPassesPerRule]
     45  *      rewriteContext 		contextName [alias aliasedContextName]
     46  *      rewriteRule 		pattern substPattern [ruleFlags]
     47  *      rewriteMap 		mapType mapName [mapArgs]
     48  *      rewriteParam		paramName paramValue
     49  */
     50 int
     51 rewrite_parse(
     52 		struct rewrite_info *info,
     53 		const char *fname,
     54 		int lineno,
     55 		int argc,
     56 		char **argv
     57 )
     58 {
     59 	int rc = -1;
     60 
     61 	assert( info != NULL );
     62 	assert( fname != NULL );
     63 	assert( argv != NULL );
     64 	assert( argc > 0 );
     65 
     66 	/*
     67 	 * Switch on the rewrite engine
     68 	 */
     69 	if ( strcasecmp( argv[ 0 ], "rewriteEngine" ) == 0 ) {
     70 		if ( argc < 2 ) {
     71 			Debug( LDAP_DEBUG_ANY,
     72 					"[%s:%d] rewriteEngine needs 'state'\n%s",
     73 					fname, lineno, "" );
     74 			return -1;
     75 
     76 		} else if ( argc > 2 ) {
     77 			Debug( LDAP_DEBUG_ANY,
     78 					"[%s:%d] extra fields in rewriteEngine"
     79 					" will be discarded\n%s",
     80 					fname, lineno, "" );
     81 		}
     82 
     83 		if ( strcasecmp( argv[ 1 ], "on" ) == 0 ) {
     84 			info->li_state = REWRITE_ON;
     85 
     86 		} else if ( strcasecmp( argv[ 1 ], "off" ) == 0 ) {
     87 			info->li_state = REWRITE_OFF;
     88 
     89 		} else {
     90 			Debug( LDAP_DEBUG_ANY,
     91 					"[%s:%d] unknown 'state' in rewriteEngine;"
     92 					" assuming 'on'\n%s",
     93 					fname, lineno, "" );
     94 			info->li_state = REWRITE_ON;
     95 		}
     96 		rc = REWRITE_SUCCESS;
     97 
     98 	/*
     99 	 * Alter max passes
    100 	 */
    101 	} else if ( strcasecmp( argv[ 0 ], "rewriteMaxPasses" ) == 0 ) {
    102 		if ( argc < 2 ) {
    103 			Debug( LDAP_DEBUG_ANY,
    104 					"[%s:%d] rewriteMaxPasses needs 'value'\n%s",
    105 					fname, lineno, "" );
    106 			return -1;
    107 		}
    108 
    109 		if ( lutil_atoi( &info->li_max_passes, argv[ 1 ] ) != 0 ) {
    110 			Debug( LDAP_DEBUG_ANY,
    111 					"[%s:%d] unable to parse rewriteMaxPasses=\"%s\"\n",
    112 					fname, lineno, argv[ 1 ] );
    113 			return -1;
    114 		}
    115 
    116 		if ( info->li_max_passes <= 0 ) {
    117 			Debug( LDAP_DEBUG_ANY,
    118 					"[%s:%d] negative or null rewriteMaxPasses\n",
    119 					fname, lineno, 0 );
    120 			return -1;
    121 		}
    122 
    123 		if ( argc > 2 ) {
    124 			if ( lutil_atoi( &info->li_max_passes_per_rule, argv[ 2 ] ) != 0 ) {
    125 				Debug( LDAP_DEBUG_ANY,
    126 						"[%s:%d] unable to parse rewriteMaxPassesPerRule=\"%s\"\n",
    127 						fname, lineno, argv[ 2 ] );
    128 				return -1;
    129 			}
    130 
    131 			if ( info->li_max_passes_per_rule <= 0 ) {
    132 				Debug( LDAP_DEBUG_ANY,
    133 						"[%s:%d] negative or null rewriteMaxPassesPerRule\n",
    134 						fname, lineno, 0 );
    135 				return -1;
    136 			}
    137 
    138 		} else {
    139 			info->li_max_passes_per_rule = info->li_max_passes;
    140 		}
    141 		rc = REWRITE_SUCCESS;
    142 
    143 	/*
    144 	 * Start a new rewrite context and set current context
    145 	 */
    146 	} else if ( strcasecmp( argv[ 0 ], "rewriteContext" ) == 0 ) {
    147 		if ( argc < 2 ) {
    148 			Debug( LDAP_DEBUG_ANY,
    149 					"[%s:%d] rewriteContext needs 'name'\n%s",
    150 					fname, lineno, "" );
    151 			return -1;
    152 		}
    153 
    154 		/*
    155 		 * Checks for existence (lots of contexts should be
    156 		 * available by default ...)
    157 		 */
    158 		 rewrite_int_curr_context = rewrite_context_find( info, argv[ 1 ] );
    159 		 if ( rewrite_int_curr_context == NULL ) {
    160 			 rewrite_int_curr_context = rewrite_context_create( info,
    161 					 argv[ 1 ] );
    162 		 }
    163 		 if ( rewrite_int_curr_context == NULL ) {
    164 			 return -1;
    165 		 }
    166 
    167 		 if ( argc > 2 ) {
    168 
    169 			 /*
    170 			  * A context can alias another (e.g., the `builtin'
    171 			  * contexts for backend operations, if not defined,
    172 			  * alias the `default' rewrite context (with the
    173 			  * notable exception of the searchResult context,
    174 			  * which can be undefined)
    175 			  */
    176 			 if ( strcasecmp( argv[ 2 ], "alias" ) == 0 ) {
    177 				 struct rewrite_context *aliased;
    178 
    179 				 if ( argc == 3 ) {
    180 					 Debug( LDAP_DEBUG_ANY,
    181 							 "[%s:%d] rewriteContext"
    182 							 " needs 'name' after"
    183 							 " 'alias'\n%s",
    184 							 fname, lineno, "" );
    185 					 return -1;
    186 
    187 				 } else if ( argc > 4 ) {
    188 					 Debug( LDAP_DEBUG_ANY,
    189 							 "[%s:%d] extra fields in"
    190 							 " rewriteContext"
    191 							 " after aliased name"
    192 							 " will be"
    193 							 " discarded\n%s",
    194 							 fname, lineno, "" );
    195 				 }
    196 
    197 				 aliased = rewrite_context_find( info,
    198 						 argv[ 3 ] );
    199 				 if ( aliased == NULL ) {
    200 					 Debug( LDAP_DEBUG_ANY,
    201 							 "[%s:%d] aliased"
    202 							 " rewriteContext '%s'"
    203 							 " does not exists\n",
    204 							 fname, lineno,
    205 							 argv[ 3 ] );
    206 					 return -1;
    207 				 }
    208 
    209 				 rewrite_int_curr_context->lc_alias = aliased;
    210 				 rewrite_int_curr_context = aliased;
    211 
    212 			 } else {
    213 				 Debug( LDAP_DEBUG_ANY,
    214 						 "[%s:%d] extra fields"
    215 						 " in rewriteContext"
    216 						 " will be discarded\n%s",
    217 						 fname, lineno, "" );
    218 			 }
    219 		 }
    220 		 rc = REWRITE_SUCCESS;
    221 
    222 	/*
    223 	 * Compile a rule in current context
    224 	 */
    225 	} else if ( strcasecmp( argv[ 0 ], "rewriteRule" ) == 0 ) {
    226 		if ( argc < 3 ) {
    227 			Debug( LDAP_DEBUG_ANY,
    228 					"[%s:%d] rewriteRule needs 'pattern'"
    229 					" 'subst' ['flags']\n%s",
    230 					fname, lineno, "" );
    231 			return -1;
    232 
    233 		} else if ( argc > 4 ) {
    234 			Debug( LDAP_DEBUG_ANY,
    235 					"[%s:%d] extra fields in rewriteRule"
    236 					" will be discarded\n%s",
    237 					fname, lineno, "" );
    238 		}
    239 
    240 		if ( rewrite_int_curr_context == NULL ) {
    241 			Debug( LDAP_DEBUG_ANY,
    242 					"[%s:%d] rewriteRule outside a"
    243 					" context; will add to default\n%s",
    244 					fname, lineno, "" );
    245 			rewrite_int_curr_context = rewrite_context_find( info,
    246 					REWRITE_DEFAULT_CONTEXT );
    247 
    248 			/*
    249 			 * Default context MUST exist in a properly initialized
    250 			 * struct rewrite_info
    251 			 */
    252 			assert( rewrite_int_curr_context != NULL );
    253 		}
    254 
    255 		rc = rewrite_rule_compile( info, rewrite_int_curr_context, argv[ 1 ],
    256 				argv[ 2 ], ( argc == 4 ? argv[ 3 ] : "" ) );
    257 
    258 	/*
    259 	 * Add a plugin map to the map tree
    260 	 */
    261 	} else if ( strcasecmp( argv[ 0 ], "rewriteMap" ) == 0 ) {
    262 		if ( argc < 3 ) {
    263 			Debug( LDAP_DEBUG_ANY,
    264 					"[%s:%d] rewriteMap needs at least 'type'"
    265 					" and 'name' ['args']\n%s",
    266 					fname, lineno, "" );
    267 			return -1;
    268 		}
    269 
    270 		rc = rewrite_parse_builtin_map( info, fname, lineno,
    271 				argc, argv );
    272 
    273 	/*
    274 	 * Set the value of a global scope parameter
    275 	 */
    276 	} else if ( strcasecmp( argv[ 0 ], "rewriteParam" ) == 0 ) {
    277 		if ( argc < 3 ) {
    278 			Debug( LDAP_DEBUG_ANY,
    279 					"[%s:%d] rewriteParam needs 'name'"
    280 					" and 'value'\n%s",
    281 					fname, lineno, "" );
    282 			return -1;
    283 		}
    284 
    285 		rc = rewrite_param_set( info, argv[ 1 ], argv[ 2 ] );
    286 
    287 	/*
    288 	 * Error
    289 	 */
    290 	} else {
    291 		Debug( LDAP_DEBUG_ANY,
    292 				"[%s:%d] unknown command '%s'\n",
    293 				fname, lineno, "" );
    294 		return -1;
    295 	}
    296 
    297 	return rc;
    298 }
    299 
    300 /*
    301  * Compares two maps
    302  */
    303 static int
    304 rewrite_builtin_map_cmp(
    305 		const void *c1,
    306                 const void *c2
    307 )
    308 {
    309 	const struct rewrite_builtin_map *m1, *m2;
    310 
    311         m1 = ( const struct rewrite_builtin_map * )c1;
    312         m2 = ( const struct rewrite_builtin_map * )c2;
    313 
    314         assert( m1 != NULL );
    315         assert( m2 != NULL );
    316         assert( m1->lb_name != NULL );
    317         assert( m2->lb_name != NULL );
    318 
    319         return strcasecmp( m1->lb_name, m2->lb_name );
    320 }
    321 
    322 /*
    323  * Duplicate map ?
    324  */
    325 static int
    326 rewrite_builtin_map_dup(
    327 	                void *c1,
    328 	                void *c2
    329 )
    330 {
    331         struct rewrite_builtin_map *m1, *m2;
    332 
    333         m1 = ( struct rewrite_builtin_map * )c1;
    334         m2 = ( struct rewrite_builtin_map * )c2;
    335 
    336         assert( m1 != NULL );
    337         assert( m2 != NULL );
    338         assert( m1->lb_name != NULL );
    339         assert( m2->lb_name != NULL );
    340 
    341         return ( strcasecmp( m1->lb_name, m2->lb_name ) == 0 ? -1 : 0 );
    342 }
    343 
    344 /*
    345  * Adds a map to the info map tree
    346  */
    347 static int
    348 rewrite_builtin_map_insert(
    349 		struct rewrite_info *info,
    350 		struct rewrite_builtin_map *map
    351 )
    352 {
    353 	/*
    354 	 * May need a mutex?
    355 	 */
    356 	return avl_insert( &info->li_maps, ( caddr_t )map,
    357 			rewrite_builtin_map_cmp,
    358 		       	rewrite_builtin_map_dup );
    359 }
    360 
    361 /*
    362  * Retrieves a map
    363  */
    364 struct rewrite_builtin_map *
    365 rewrite_builtin_map_find(
    366 		struct rewrite_info *info,
    367 		const char *name
    368 )
    369 {
    370 	struct rewrite_builtin_map tmp;
    371 
    372 	assert( info != NULL );
    373 	assert( name != NULL );
    374 
    375 	tmp.lb_name = ( char * )name;
    376 
    377 	return ( struct rewrite_builtin_map * )avl_find( info->li_maps,
    378 			( caddr_t )&tmp, rewrite_builtin_map_cmp );
    379 }
    380 
    381 /*
    382  * Parses a plugin map
    383  */
    384 static int
    385 rewrite_parse_builtin_map(
    386 		struct rewrite_info *info,
    387 		const char *fname,
    388 		int lineno,
    389 		int argc,
    390 		char **argv
    391 )
    392 {
    393 	struct rewrite_builtin_map *map;
    394 
    395 #define MAP_TYPE	1
    396 #define MAP_NAME	2
    397 
    398 	assert( info != NULL );
    399 	assert( fname != NULL );
    400 	assert( argc > 2 );
    401 	assert( argv != NULL );
    402 	assert( strcasecmp( argv[ 0 ], "rewriteMap" ) == 0 );
    403 
    404 	map = calloc( sizeof( struct rewrite_builtin_map ), 1 );
    405 	if ( map == NULL ) {
    406 		return REWRITE_ERR;
    407 	}
    408 
    409 	map->lb_name = strdup( argv[ MAP_NAME ] );
    410 	if ( map->lb_name == NULL ) {
    411 		free( map );
    412 		return REWRITE_ERR;
    413 	}
    414 
    415 	/*
    416 	 * Built-in ldap map
    417 	 */
    418 	if (( map->lb_mapper = rewrite_mapper_find( argv[ MAP_TYPE ] ))) {
    419 		map->lb_type = REWRITE_BUILTIN_MAP;
    420 
    421 #ifdef USE_REWRITE_LDAP_PVT_THREADS
    422 		if ( ldap_pvt_thread_mutex_init( & map->lb_mutex ) ) {
    423 			free( map->lb_name );
    424 			free( map );
    425 			return REWRITE_ERR;
    426 		}
    427 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
    428 
    429 		map->lb_private = map->lb_mapper->rm_config( fname, lineno,
    430 				argc - 3, argv + 3 );
    431 
    432 	/*
    433 	 * Error
    434 	 */
    435 	} else {
    436 		free( map );
    437 		Debug( LDAP_DEBUG_ANY, "[%s:%d] unknown map type\n%s",
    438 				fname, lineno, "" );
    439 		return -1;
    440 	}
    441 
    442 	return rewrite_builtin_map_insert( info, map );
    443 }
    444