Back to index

openldap  2.4.31
config.c
Go to the documentation of this file.
00001 /* $OpenLDAP$ */
00002 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
00003  *
00004  * Copyright 2000-2012 The OpenLDAP Foundation.
00005  * All rights reserved.
00006  *
00007  * Redistribution and use in source and binary forms, with or without
00008  * modification, are permitted only as authorized by the OpenLDAP
00009  * Public License.
00010  *
00011  * A copy of this license is available in the file LICENSE in the
00012  * top-level directory of the distribution or, alternatively, at
00013  * <http://www.OpenLDAP.org/license.html>.
00014  */
00015 /* ACKNOWLEDGEMENT:
00016  * This work was initially developed by Pierangelo Masarati for
00017  * inclusion in OpenLDAP Software.
00018  */
00019 
00020 #include <portable.h>
00021 
00022 #include "rewrite-int.h"
00023 #include "rewrite-map.h"
00024 
00025 /*
00026  * Parses a plugin map
00027  */
00028 static int
00029 rewrite_parse_builtin_map(
00030               struct rewrite_info *info,
00031               const char *fname,
00032               int lineno,
00033               int argc,
00034               char **argv
00035 );
00036 
00037 /*
00038  * Parses a config line and takes actions to fit content in rewrite structure;
00039  * lines handled are of the form:
00040  *
00041  *      rewriteEngine              {on|off}
00042  *      rewriteMaxPasses        numPasses [numPassesPerRule]
00043  *      rewriteContext             contextName [alias aliasedContextName]
00044  *      rewriteRule         pattern substPattern [ruleFlags]
00045  *      rewriteMap          mapType mapName [mapArgs]
00046  *      rewriteParam        paramName paramValue
00047  */
00048 int
00049 rewrite_parse(
00050               struct rewrite_info *info,
00051               const char *fname,
00052               int lineno,
00053               int argc,
00054               char **argv
00055 )
00056 {
00057        int rc = -1;
00058 
00059        assert( info != NULL );
00060        assert( fname != NULL );
00061        assert( argv != NULL );
00062        assert( argc > 0 );
00063        
00064        /*
00065         * Switch on the rewrite engine
00066         */
00067        if ( strcasecmp( argv[ 0 ], "rewriteEngine" ) == 0 ) {
00068               if ( argc < 2 ) {
00069                      Debug( LDAP_DEBUG_ANY,
00070                                    "[%s:%d] rewriteEngine needs 'state'\n%s",
00071                                    fname, lineno, "" );
00072                      return -1;
00073 
00074               } else if ( argc > 2 ) {
00075                      Debug( LDAP_DEBUG_ANY,
00076                                    "[%s:%d] extra fields in rewriteEngine"
00077                                    " will be discarded\n%s",
00078                                    fname, lineno, "" );
00079               }
00080 
00081               if ( strcasecmp( argv[ 1 ], "on" ) == 0 ) {
00082                      info->li_state = REWRITE_ON;
00083 
00084               } else if ( strcasecmp( argv[ 1 ], "off" ) == 0 ) {
00085                      info->li_state = REWRITE_OFF;
00086 
00087               } else {
00088                      Debug( LDAP_DEBUG_ANY,
00089                                    "[%s:%d] unknown 'state' in rewriteEngine;"
00090                                    " assuming 'on'\n%s",
00091                                    fname, lineno, "" );
00092                      info->li_state = REWRITE_ON;
00093               }
00094               rc = REWRITE_SUCCESS;
00095        
00096        /*
00097         * Alter max passes
00098         */
00099        } else if ( strcasecmp( argv[ 0 ], "rewriteMaxPasses" ) == 0 ) {
00100               if ( argc < 2 ) {
00101                      Debug( LDAP_DEBUG_ANY,
00102                                    "[%s:%d] rewriteMaxPasses needs 'value'\n%s",
00103                                    fname, lineno, "" );
00104                      return -1;
00105               }
00106 
00107               if ( lutil_atoi( &info->li_max_passes, argv[ 1 ] ) != 0 ) {
00108                      Debug( LDAP_DEBUG_ANY,
00109                                    "[%s:%d] unable to parse rewriteMaxPasses=\"%s\"\n",
00110                                    fname, lineno, argv[ 1 ] );
00111                      return -1;
00112               }
00113 
00114               if ( info->li_max_passes <= 0 ) {
00115                      Debug( LDAP_DEBUG_ANY,
00116                                    "[%s:%d] negative or null rewriteMaxPasses\n",
00117                                    fname, lineno, 0 );
00118                      return -1;
00119               }
00120 
00121               if ( argc > 2 ) {
00122                      if ( lutil_atoi( &info->li_max_passes_per_rule, argv[ 2 ] ) != 0 ) {
00123                             Debug( LDAP_DEBUG_ANY,
00124                                           "[%s:%d] unable to parse rewriteMaxPassesPerRule=\"%s\"\n",
00125                                           fname, lineno, argv[ 2 ] );
00126                             return -1;
00127                      }
00128 
00129                      if ( info->li_max_passes_per_rule <= 0 ) {
00130                             Debug( LDAP_DEBUG_ANY,
00131                                           "[%s:%d] negative or null rewriteMaxPassesPerRule\n",
00132                                           fname, lineno, 0 );
00133                             return -1;
00134                      }
00135 
00136               } else {
00137                      info->li_max_passes_per_rule = info->li_max_passes;
00138               }
00139               rc = REWRITE_SUCCESS;
00140        
00141        /*
00142         * Start a new rewrite context and set current context
00143         */
00144        } else if ( strcasecmp( argv[ 0 ], "rewriteContext" ) == 0 ) {
00145               if ( argc < 2 ) {
00146                      Debug( LDAP_DEBUG_ANY,
00147                                    "[%s:%d] rewriteContext needs 'name'\n%s",
00148                                    fname, lineno, "" );
00149                      return -1;
00150               } 
00151 
00152               /*
00153                * Checks for existence (lots of contexts should be
00154                * available by default ...)
00155                */
00156                rewrite_int_curr_context = rewrite_context_find( info, argv[ 1 ] );
00157                if ( rewrite_int_curr_context == NULL ) {
00158                       rewrite_int_curr_context = rewrite_context_create( info,
00159                                     argv[ 1 ] );                       
00160                }
00161                if ( rewrite_int_curr_context == NULL ) {
00162                       return -1;
00163                }
00164                                           
00165                if ( argc > 2 ) {
00166 
00167                       /*
00168                        * A context can alias another (e.g., the `builtin'
00169                        * contexts for backend operations, if not defined,
00170                        * alias the `default' rewrite context (with the
00171                        * notable exception of the searchResult context,
00172                        * which can be undefined)
00173                        */
00174                       if ( strcasecmp( argv[ 2 ], "alias" ) == 0 ) {
00175                              struct rewrite_context *aliased;
00176                              
00177                              if ( argc == 3 ) {
00178                                     Debug( LDAP_DEBUG_ANY,
00179                                                   "[%s:%d] rewriteContext"
00180                                                   " needs 'name' after"
00181                                                   " 'alias'\n%s",
00182                                                   fname, lineno, "" );
00183                                     return -1;
00184 
00185                              } else if ( argc > 4 ) {
00186                                     Debug( LDAP_DEBUG_ANY,
00187                                                   "[%s:%d] extra fields in"
00188                                                   " rewriteContext"
00189                                                   " after aliased name"
00190                                                   " will be"
00191                                                   " discarded\n%s",
00192                                                   fname, lineno, "" );
00193                              }
00194                              
00195                              aliased = rewrite_context_find( info, 
00196                                            argv[ 3 ] );
00197                              if ( aliased == NULL ) {
00198                                     Debug( LDAP_DEBUG_ANY,
00199                                                   "[%s:%d] aliased"
00200                                                   " rewriteContext '%s'"
00201                                                   " does not exists\n",
00202                                                   fname, lineno,
00203                                                   argv[ 3 ] );
00204                                     return -1;
00205                              }
00206                              
00207                              rewrite_int_curr_context->lc_alias = aliased;
00208                              rewrite_int_curr_context = aliased;
00209 
00210                       } else {
00211                              Debug( LDAP_DEBUG_ANY,
00212                                            "[%s:%d] extra fields"
00213                                            " in rewriteContext"
00214                                            " will be discarded\n%s",
00215                                            fname, lineno, "" );
00216                       }
00217                }
00218                rc = REWRITE_SUCCESS;
00219                
00220        /*
00221         * Compile a rule in current context
00222         */
00223        } else if ( strcasecmp( argv[ 0 ], "rewriteRule" ) == 0 ) {
00224               if ( argc < 3 ) {
00225                      Debug( LDAP_DEBUG_ANY,
00226                                    "[%s:%d] rewriteRule needs 'pattern'"
00227                                    " 'subst' ['flags']\n%s",
00228                                    fname, lineno, "" );
00229                      return -1;
00230 
00231               } else if ( argc > 4 ) {
00232                      Debug( LDAP_DEBUG_ANY,
00233                                    "[%s:%d] extra fields in rewriteRule"
00234                                    " will be discarded\n%s",
00235                                    fname, lineno, "" );
00236               }
00237 
00238               if ( rewrite_int_curr_context == NULL ) {
00239                      Debug( LDAP_DEBUG_ANY,
00240                                    "[%s:%d] rewriteRule outside a"
00241                                    " context; will add to default\n%s",
00242                                    fname, lineno, "" );
00243                      rewrite_int_curr_context = rewrite_context_find( info,
00244                                    REWRITE_DEFAULT_CONTEXT );
00245 
00246                      /*
00247                       * Default context MUST exist in a properly initialized
00248                       * struct rewrite_info
00249                       */
00250                      assert( rewrite_int_curr_context != NULL );
00251               }
00252               
00253               rc = rewrite_rule_compile( info, rewrite_int_curr_context, argv[ 1 ],
00254                             argv[ 2 ], ( argc == 4 ? argv[ 3 ] : "" ) );
00255        
00256        /*
00257         * Add a plugin map to the map tree
00258         */
00259        } else if ( strcasecmp( argv[ 0 ], "rewriteMap" ) == 0 ) {
00260               if ( argc < 3 ) {
00261                      Debug( LDAP_DEBUG_ANY,
00262                                    "[%s:%d] rewriteMap needs at least 'type'"
00263                                    " and 'name' ['args']\n%s",
00264                                    fname, lineno, "" );
00265                      return -1;
00266               }
00267 
00268               rc = rewrite_parse_builtin_map( info, fname, lineno,
00269                             argc, argv );
00270 
00271        /*
00272         * Set the value of a global scope parameter
00273         */
00274        } else if ( strcasecmp( argv[ 0 ], "rewriteParam" ) == 0 ) {
00275               if ( argc < 3 ) {
00276                      Debug( LDAP_DEBUG_ANY,
00277                                    "[%s:%d] rewriteParam needs 'name'"
00278                                    " and 'value'\n%s",
00279                                    fname, lineno, "" );
00280                      return -1;
00281               }
00282 
00283               rc = rewrite_param_set( info, argv[ 1 ], argv[ 2 ] );
00284               
00285        /*
00286         * Error
00287         */
00288        } else {
00289               Debug( LDAP_DEBUG_ANY,
00290                             "[%s:%d] unknown command '%s'\n",
00291                             fname, lineno, "" );
00292               return -1;
00293        }
00294 
00295        return rc;
00296 }
00297 
00298 /*
00299  * Compares two maps
00300  */
00301 static int
00302 rewrite_builtin_map_cmp(
00303               const void *c1,
00304                 const void *c2
00305 )
00306 {
00307        const struct rewrite_builtin_map *m1, *m2;
00308 
00309         m1 = ( const struct rewrite_builtin_map * )c1;
00310         m2 = ( const struct rewrite_builtin_map * )c2;
00311 
00312         assert( m1 != NULL );
00313         assert( m2 != NULL );
00314         assert( m1->lb_name != NULL );
00315         assert( m2->lb_name != NULL );
00316 
00317         return strcasecmp( m1->lb_name, m2->lb_name );
00318 }
00319 
00320 /*
00321  * Duplicate map ?
00322  */
00323 static int
00324 rewrite_builtin_map_dup(
00325                        void *c1,
00326                        void *c2
00327 )
00328 {
00329         struct rewrite_builtin_map *m1, *m2;
00330 
00331         m1 = ( struct rewrite_builtin_map * )c1;
00332         m2 = ( struct rewrite_builtin_map * )c2;
00333 
00334         assert( m1 != NULL );
00335         assert( m2 != NULL );
00336         assert( m1->lb_name != NULL );
00337         assert( m2->lb_name != NULL );
00338 
00339         return ( strcasecmp( m1->lb_name, m2->lb_name ) == 0 ? -1 : 0 );
00340 }
00341 
00342 /*
00343  * Adds a map to the info map tree
00344  */
00345 static int
00346 rewrite_builtin_map_insert(
00347               struct rewrite_info *info,
00348               struct rewrite_builtin_map *map
00349 )
00350 {
00351        /*
00352         * May need a mutex?
00353         */
00354        return avl_insert( &info->li_maps, ( caddr_t )map,
00355                      rewrite_builtin_map_cmp,
00356                             rewrite_builtin_map_dup );
00357 }
00358 
00359 /*
00360  * Retrieves a map
00361  */
00362 struct rewrite_builtin_map *
00363 rewrite_builtin_map_find(
00364               struct rewrite_info *info,
00365               const char *name
00366 )
00367 {
00368        struct rewrite_builtin_map tmp;
00369 
00370        assert( info != NULL );
00371        assert( name != NULL );
00372 
00373        tmp.lb_name = ( char * )name;
00374 
00375        return ( struct rewrite_builtin_map * )avl_find( info->li_maps,
00376                      ( caddr_t )&tmp, rewrite_builtin_map_cmp );
00377 }
00378 
00379 /*
00380  * Parses a plugin map
00381  */
00382 static int
00383 rewrite_parse_builtin_map(
00384               struct rewrite_info *info,
00385               const char *fname,
00386               int lineno,
00387               int argc,
00388               char **argv
00389 )
00390 {
00391        struct rewrite_builtin_map *map;
00392        
00393 #define MAP_TYPE     1
00394 #define MAP_NAME     2
00395        
00396        assert( info != NULL );
00397        assert( fname != NULL );
00398        assert( argc > 2 );
00399        assert( argv != NULL );
00400        assert( strcasecmp( argv[ 0 ], "rewriteMap" ) == 0 );
00401 
00402        map = calloc( sizeof( struct rewrite_builtin_map ), 1 );
00403        if ( map == NULL ) {
00404               return REWRITE_ERR;
00405        }
00406 
00407        map->lb_name = strdup( argv[ MAP_NAME ] );
00408        if ( map->lb_name == NULL ) {
00409               free( map );
00410               return REWRITE_ERR;
00411        }
00412        
00413        /*
00414         * Built-in ldap map
00415         */
00416        if (( map->lb_mapper = rewrite_mapper_find( argv[ MAP_TYPE ] ))) {
00417               map->lb_type = REWRITE_BUILTIN_MAP;
00418 
00419 #ifdef USE_REWRITE_LDAP_PVT_THREADS
00420               if ( ldap_pvt_thread_mutex_init( & map->lb_mutex ) ) {
00421                      free( map->lb_name );
00422                      free( map );
00423                      return REWRITE_ERR;
00424               }
00425 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
00426               
00427               map->lb_private = map->lb_mapper->rm_config( fname, lineno,
00428                             argc - 3, argv + 3 );
00429               
00430        /* 
00431         * Error
00432         */    
00433        } else {
00434               free( map );
00435               Debug( LDAP_DEBUG_ANY, "[%s:%d] unknown map type\n%s",
00436                             fname, lineno, "" );
00437               return -1;
00438        }
00439 
00440        return rewrite_builtin_map_insert( info, map );
00441 }