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