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