1/* $NetBSD: config.c,v 1.1.1.3 2010/12/12 15:22:12 adam Exp $ */ 2 3/* OpenLDAP: pkg/ldap/libraries/librewrite/config.c,v 1.14.2.5 2010/04/13 20:23:08 kurt Exp */ 4/* This work is part of OpenLDAP Software <http://www.openldap.org/>. 5 * 6 * Copyright 2000-2010 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 */ 30static int 31rewrite_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 */ 50int 51rewrite_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 */ 303static int 304rewrite_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 */ 325static int 326rewrite_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 */ 347static int 348rewrite_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 */ 364struct rewrite_builtin_map * 365rewrite_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 */ 384static int 385rewrite_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