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