Back to index

openldap  2.4.31
map.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 <stdio.h>
00023 
00024 #ifdef HAVE_PWD_H
00025 #include <pwd.h>
00026 #endif
00027 
00028 #include "rewrite-int.h"
00029 #include "rewrite-map.h"
00030 
00031 static int num_mappers;
00032 static const rewrite_mapper **mappers;
00033 #define       MAPPER_ALLOC  8
00034 
00035 struct rewrite_map *
00036 rewrite_map_parse(
00037               struct rewrite_info *info,
00038               const char *string,
00039               const char **currpos
00040 )
00041 {
00042        struct rewrite_map *map = NULL;
00043        struct rewrite_subst *subst = NULL;
00044        char *s, *begin = NULL, *end;
00045        const char *p;
00046        int l, cnt, mtx = 0, rc = 0;
00047 
00048        assert( info != NULL );
00049        assert( string != NULL );
00050        assert( currpos != NULL );
00051 
00052        *currpos = NULL;
00053 
00054        /*
00055         * Go to the end of the map invocation (the right closing brace)
00056         */
00057        for ( p = string, cnt = 1; p[ 0 ] != '\0' && cnt > 0; p++ ) {
00058               if ( IS_REWRITE_SUBMATCH_ESCAPE( p[ 0 ] ) ) {
00059                      /*
00060                       * '%' marks the beginning of a new map
00061                       */
00062                      if ( p[ 1 ] == '{' ) {
00063                             cnt++;
00064                      /*
00065                       * '%' followed by a digit may mark the beginning
00066                       * of an old map
00067                       */
00068                      } else if ( isdigit( (unsigned char) p[ 1 ] ) && p[ 2 ] == '{' ) {
00069                             cnt++;
00070                             p++;
00071                      }
00072 
00073                      if ( p[ 1 ] != '\0' ) {
00074                             p++;
00075                      }
00076 
00077               } else if ( p[ 0 ] == '}' ) {
00078                      cnt--;
00079               }
00080        }
00081        if ( cnt != 0 ) {
00082               return NULL;
00083        }
00084        *currpos = p;
00085        
00086        /*
00087         * Copy the map invocation
00088         */
00089        l = p - string - 1;
00090        s = calloc( sizeof( char ), l + 1 );
00091        if ( s == NULL ) {
00092               return NULL;
00093        }
00094        AC_MEMCPY( s, string, l );
00095        s[ l ] = 0;
00096 
00097        /*
00098         * Isolate the map name (except for variable deref)
00099         */
00100        switch ( s[ 0 ] ) {
00101        case REWRITE_OPERATOR_VARIABLE_GET:
00102        case REWRITE_OPERATOR_PARAM_GET:
00103               break;
00104 
00105        default:
00106               begin = strchr( s, '(' );
00107               if ( begin == NULL ) {
00108                      rc = -1;
00109                      goto cleanup;
00110               }
00111               begin[ 0 ] = '\0';
00112               begin++;
00113               break;
00114        }
00115 
00116        /*
00117         * Check for special map types
00118         */
00119        p = s;
00120        switch ( p[ 0 ] ) {
00121        case REWRITE_OPERATOR_SUBCONTEXT:
00122        case REWRITE_OPERATOR_COMMAND:
00123        case REWRITE_OPERATOR_VARIABLE_SET:
00124        case REWRITE_OPERATOR_VARIABLE_GET:
00125        case REWRITE_OPERATOR_PARAM_GET:
00126               p++;
00127               break;
00128        }
00129 
00130        /*
00131         * Variable set and get may be repeated to indicate session-wide
00132         * instead of operation-wide variables
00133         */
00134        switch ( p[ 0 ] ) {
00135         case REWRITE_OPERATOR_VARIABLE_SET:
00136        case REWRITE_OPERATOR_VARIABLE_GET:
00137               p++;
00138               break;
00139        }
00140 
00141        /*
00142         * Variable get token can be appended to variable set to mean store
00143         * AND rewrite
00144         */
00145        if ( p[ 0 ] == REWRITE_OPERATOR_VARIABLE_GET ) {
00146               p++;
00147        }
00148        
00149        /*
00150         * Check the syntax of the variable name
00151         */
00152        if ( !isalpha( (unsigned char) p[ 0 ] ) ) {
00153               rc = -1;
00154               goto cleanup;
00155        }
00156        for ( p++; p[ 0 ] != '\0'; p++ ) {
00157               if ( !isalnum( (unsigned char) p[ 0 ] ) ) {
00158                      rc = -1;
00159                      goto cleanup;
00160               }
00161        }
00162 
00163        /*
00164         * Isolate the argument of the map (except for variable deref)
00165         */
00166        switch ( s[ 0 ] ) {
00167        case REWRITE_OPERATOR_VARIABLE_GET:
00168        case REWRITE_OPERATOR_PARAM_GET:
00169               break;
00170 
00171        default:
00172               end = strrchr( begin, ')' );
00173               if ( end == NULL ) {
00174                      rc = -1;
00175                      goto cleanup;
00176               }
00177               end[ 0 ] = '\0';
00178 
00179               /*
00180                * Compile the substitution pattern of the map argument
00181                */
00182               subst = rewrite_subst_compile( info, begin );
00183               if ( subst == NULL ) {
00184                      rc = -1;
00185                      goto cleanup;
00186               }
00187               break;
00188        }
00189 
00190        /*
00191         * Create the map
00192         */
00193        map = calloc( sizeof( struct rewrite_map ), 1 );
00194        if ( map == NULL ) {
00195               rc = -1;
00196               goto cleanup;
00197        }
00198        memset( map, 0, sizeof( struct rewrite_map ) );
00199        
00200 #ifdef USE_REWRITE_LDAP_PVT_THREADS
00201         if ( ldap_pvt_thread_mutex_init( &map->lm_mutex ) ) {
00202               rc = -1;
00203               goto cleanup;
00204        }
00205        ++mtx;
00206 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
00207                      
00208        /*
00209         * No subst for variable deref
00210         */
00211        switch ( s[ 0 ] ) {
00212        case REWRITE_OPERATOR_VARIABLE_GET:
00213        case REWRITE_OPERATOR_PARAM_GET:
00214               break;
00215 
00216        default:
00217               map->lm_subst = subst;
00218               break;
00219        }
00220 
00221        /*
00222         * Parses special map types
00223         */
00224        switch ( s[ 0 ] ) {
00225        
00226        /*
00227         * Subcontext
00228         */
00229        case REWRITE_OPERATOR_SUBCONTEXT:         /* '>' */
00230 
00231               /*
00232                * Fetch the rewrite context
00233                * it MUST have been defined previously
00234                */
00235               map->lm_type = REWRITE_MAP_SUBCONTEXT;
00236               map->lm_name = strdup( s + 1 );
00237               if ( map->lm_name == NULL ) {
00238                      rc = -1;
00239                      goto cleanup;
00240               }
00241               map->lm_data = rewrite_context_find( info, s + 1 );
00242               if ( map->lm_data == NULL ) {
00243                      rc = -1;
00244                      goto cleanup;
00245               }
00246               break;
00247 
00248        /*
00249         * External command (not implemented yet)
00250         */
00251        case REWRITE_OPERATOR_COMMAND:            /* '|' */
00252               rc = -1;
00253               goto cleanup;
00254        
00255        /*
00256         * Variable set
00257         */
00258        case REWRITE_OPERATOR_VARIABLE_SET:       /* '&' */
00259               if ( s[ 1 ] == REWRITE_OPERATOR_VARIABLE_SET ) {
00260                      if ( s[ 2 ] == REWRITE_OPERATOR_VARIABLE_GET ) {
00261                             map->lm_type = REWRITE_MAP_SETW_SESN_VAR;
00262                             map->lm_name = strdup( s + 3 );
00263                      } else {
00264                             map->lm_type = REWRITE_MAP_SET_SESN_VAR;
00265                             map->lm_name = strdup( s + 2 );
00266                      }
00267               } else {
00268                      if ( s[ 1 ] == REWRITE_OPERATOR_VARIABLE_GET ) {
00269                             map->lm_type = REWRITE_MAP_SETW_OP_VAR;
00270                             map->lm_name = strdup( s + 2 );
00271                      } else {
00272                             map->lm_type = REWRITE_MAP_SET_OP_VAR;
00273                             map->lm_name = strdup( s + 1 );
00274                      }
00275               }
00276               if ( map->lm_name == NULL ) {
00277                      rc = -1;
00278                      goto cleanup;
00279               }
00280               break;
00281        
00282        /*
00283         * Variable dereference
00284         */
00285        case REWRITE_OPERATOR_VARIABLE_GET:       /* '*' */
00286               if ( s[ 1 ] == REWRITE_OPERATOR_VARIABLE_GET ) {
00287                      map->lm_type = REWRITE_MAP_GET_SESN_VAR;
00288                      map->lm_name = strdup( s + 2 );
00289               } else {
00290                      map->lm_type = REWRITE_MAP_GET_OP_VAR;
00291                      map->lm_name = strdup( s + 1 );
00292               }
00293               if ( map->lm_name == NULL ) {
00294                      rc = -1;
00295                      goto cleanup;
00296               }
00297               break;
00298        
00299        /*
00300         * Parameter
00301         */
00302        case REWRITE_OPERATOR_PARAM_GET:          /* '$' */
00303               map->lm_type = REWRITE_MAP_GET_PARAM;
00304               map->lm_name = strdup( s + 1 );
00305               if ( map->lm_name == NULL ) {
00306                      rc = -1;
00307                      goto cleanup;
00308               }
00309               break;
00310        
00311        /*
00312         * Built-in map
00313         */
00314        default:
00315               map->lm_type = REWRITE_MAP_BUILTIN;
00316               map->lm_name = strdup( s );
00317               if ( map->lm_name == NULL ) {
00318                      rc = -1;
00319                      goto cleanup;
00320               }
00321               map->lm_data = rewrite_builtin_map_find( info, s );
00322               if ( map->lm_data == NULL ) {
00323                      rc = -1;
00324                      goto cleanup;
00325               }
00326               break;
00327 
00328        }
00329 
00330 cleanup:
00331        free( s );
00332        if ( rc ) {
00333               if ( subst != NULL ) {
00334                      free( subst );
00335               }
00336               if ( map ) {
00337 #ifdef USE_REWRITE_LDAP_PVT_THREADS
00338                       if ( mtx ) {
00339                             ldap_pvt_thread_mutex_destroy( &map->lm_mutex );
00340                      }
00341 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
00342 
00343                      if ( map->lm_name ) {
00344                             free( map->lm_name );
00345                             map->lm_name = NULL;
00346                      }
00347                      free( map );
00348                      map = NULL;
00349               }
00350        }
00351 
00352        return map;
00353 }
00354 
00355 /*
00356  * Applies the new map type
00357  */
00358 int
00359 rewrite_map_apply(
00360               struct rewrite_info *info,
00361               struct rewrite_op *op,
00362               struct rewrite_map *map,
00363               struct berval *key,
00364               struct berval *val
00365 )
00366 {
00367        int rc = REWRITE_SUCCESS;
00368 
00369        assert( info != NULL );
00370        assert( op != NULL );
00371        assert( map != NULL );
00372        assert( key != NULL );
00373        assert( val != NULL );
00374 
00375        val->bv_val = NULL;
00376        val->bv_len = 0;
00377        
00378        switch ( map->lm_type ) {
00379        case REWRITE_MAP_SUBCONTEXT:
00380               rc = rewrite_context_apply( info, op, 
00381                             ( struct rewrite_context * )map->lm_data,
00382                             key->bv_val, &val->bv_val );
00383               if ( val->bv_val != NULL ) {
00384                      if ( val->bv_val == key->bv_val ) {
00385                             val->bv_len = key->bv_len;
00386                             key->bv_val = NULL;
00387                      } else {
00388                             val->bv_len = strlen( val->bv_val );
00389                      }
00390               }
00391               break;
00392 
00393        case REWRITE_MAP_SET_OP_VAR:
00394        case REWRITE_MAP_SETW_OP_VAR:
00395               rc = rewrite_var_set( &op->lo_vars, map->lm_name,
00396                             key->bv_val, 1 )
00397                      ? REWRITE_SUCCESS : REWRITE_ERR;
00398               if ( rc == REWRITE_SUCCESS ) {
00399                      if ( map->lm_type == REWRITE_MAP_SET_OP_VAR ) {
00400                             val->bv_val = strdup( "" );
00401                      } else {
00402                             val->bv_val = strdup( key->bv_val );
00403                             val->bv_len = key->bv_len;
00404                      }
00405                      if ( val->bv_val == NULL ) {
00406                             rc = REWRITE_ERR;
00407                      }
00408               }
00409               break;
00410        
00411        case REWRITE_MAP_GET_OP_VAR: {
00412               struct rewrite_var *var;
00413 
00414               var = rewrite_var_find( op->lo_vars, map->lm_name );
00415               if ( var == NULL ) {
00416                      rc = REWRITE_ERR;
00417               } else {
00418                      val->bv_val = strdup( var->lv_value.bv_val );
00419                      val->bv_len = var->lv_value.bv_len;
00420                      if ( val->bv_val == NULL ) {
00421                             rc = REWRITE_ERR;
00422                      }
00423               }
00424               break; 
00425        }
00426 
00427        case REWRITE_MAP_SET_SESN_VAR:
00428        case REWRITE_MAP_SETW_SESN_VAR:
00429               if ( op->lo_cookie == NULL ) {
00430                      rc = REWRITE_ERR;
00431                      break;
00432               }
00433               rc = rewrite_session_var_set( info, op->lo_cookie, 
00434                             map->lm_name, key->bv_val );
00435               if ( rc == REWRITE_SUCCESS ) {
00436                      if ( map->lm_type == REWRITE_MAP_SET_SESN_VAR ) {
00437                             val->bv_val = strdup( "" );
00438                      } else {
00439                             val->bv_val = strdup( key->bv_val );
00440                             val->bv_len = key->bv_len;
00441                      }
00442                      if ( val->bv_val == NULL ) {
00443                             rc = REWRITE_ERR;
00444                      }
00445               }
00446               break;
00447 
00448        case REWRITE_MAP_GET_SESN_VAR:
00449               rc = rewrite_session_var_get( info, op->lo_cookie,
00450                             map->lm_name, val );
00451               break;        
00452 
00453        case REWRITE_MAP_GET_PARAM:
00454               rc = rewrite_param_get( info, map->lm_name, val );
00455               break;
00456 
00457        case REWRITE_MAP_BUILTIN: {
00458               struct rewrite_builtin_map *bmap = map->lm_data;
00459 
00460               if ( bmap->lb_mapper && bmap->lb_mapper->rm_apply )
00461                      rc = bmap->lb_mapper->rm_apply( bmap->lb_private, key->bv_val,
00462                             val );
00463               else
00464                      rc = REWRITE_ERR;
00465                      break;
00466               break;
00467        }
00468 
00469        default:
00470               rc = REWRITE_ERR;
00471               break;
00472        }
00473 
00474        return rc;
00475 }
00476 
00477 void
00478 rewrite_builtin_map_free(
00479               void *tmp
00480 )
00481 {
00482        struct rewrite_builtin_map *map = ( struct rewrite_builtin_map * )tmp;
00483 
00484        assert( map != NULL );
00485 
00486        if ( map->lb_mapper && map->lb_mapper->rm_destroy )
00487               map->lb_mapper->rm_destroy( map->lb_private );
00488 
00489        free( map->lb_name );
00490        free( map );
00491 }
00492 
00493 int
00494 rewrite_map_destroy(
00495               struct rewrite_map **pmap
00496 )
00497 {
00498        struct rewrite_map *map;
00499        
00500        assert( pmap != NULL );
00501        assert( *pmap != NULL );
00502 
00503        map = *pmap;
00504 
00505 #ifdef USE_REWRITE_LDAP_PVT_THREADS
00506        ldap_pvt_thread_mutex_lock( &map->lm_mutex );
00507 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
00508 
00509        if ( map->lm_name ) {
00510               free( map->lm_name );
00511               map->lm_name = NULL;
00512        }
00513 
00514        if ( map->lm_subst ) {
00515               rewrite_subst_destroy( &map->lm_subst );
00516        }
00517 
00518 #ifdef USE_REWRITE_LDAP_PVT_THREADS
00519        ldap_pvt_thread_mutex_unlock( &map->lm_mutex );
00520        ldap_pvt_thread_mutex_destroy( &map->lm_mutex );
00521 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
00522 
00523        free( map );
00524        *pmap = NULL;
00525        
00526        return 0;
00527 }
00528 
00529 /* ldapmap.c */
00530 extern const rewrite_mapper rewrite_ldap_mapper;
00531 
00532 const rewrite_mapper *
00533 rewrite_mapper_find(
00534        const char *name
00535 )
00536 {
00537        int i;
00538 
00539        if ( !strcasecmp( name, "ldap" ))
00540               return &rewrite_ldap_mapper;
00541 
00542        for (i=0; i<num_mappers; i++)
00543               if ( !strcasecmp( name, mappers[i]->rm_name ))
00544                      return mappers[i];
00545        return NULL;
00546 }
00547 
00548 int
00549 rewrite_mapper_register(
00550        const rewrite_mapper *map
00551 )
00552 {
00553        if ( num_mappers % MAPPER_ALLOC == 0 ) {
00554               const rewrite_mapper **mnew;
00555               mnew = realloc( mappers, (num_mappers + MAPPER_ALLOC) *
00556                      sizeof( rewrite_mapper * ));
00557               if ( mnew )
00558                      mappers = mnew;
00559               else
00560                      return -1;
00561        }
00562        mappers[num_mappers++] = map;
00563        return 0;
00564 }
00565 
00566 int
00567 rewrite_mapper_unregister(
00568        const rewrite_mapper *map
00569 )
00570 {
00571        int i;
00572 
00573        for (i = 0; i<num_mappers; i++) {
00574               if ( mappers[i] == map ) {
00575                      num_mappers--;
00576                      mappers[i] = mappers[num_mappers];
00577                      mappers[num_mappers] = NULL;
00578                      return 0;
00579               }
00580        }
00581        /* not found */
00582        return -1;
00583 }