Back to index

openldap  2.4.31
rwmconf.c
Go to the documentation of this file.
00001 /* rwmconf.c - rewrite/map configuration file routines */
00002 /* $OpenLDAP$ */
00003 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
00004  *
00005  * Copyright 1999-2012 The OpenLDAP Foundation.
00006  * Portions Copyright 1999-2003 Howard Chu.
00007  * Portions Copyright 2000-2003 Pierangelo Masarati.
00008  * All rights reserved.
00009  *
00010  * Redistribution and use in source and binary forms, with or without
00011  * modification, are permitted only as authorized by the OpenLDAP
00012  * Public License.
00013  *
00014  * A copy of this license is available in the file LICENSE in the
00015  * top-level directory of the distribution or, alternatively, at
00016  * <http://www.OpenLDAP.org/license.html>.
00017  */
00018 /* ACKNOWLEDGEMENTS:
00019  * This work was initially developed by the Howard Chu for inclusion
00020  * in OpenLDAP Software and subsequently enhanced by Pierangelo
00021  * Masarati.
00022  */
00023 
00024 #include "portable.h"
00025 
00026 #ifdef SLAPD_OVER_RWM
00027 
00028 #include <stdio.h>
00029 
00030 #include <ac/string.h>
00031 #include <ac/socket.h>
00032 
00033 #include "slap.h"
00034 #include "rwm.h"
00035 #include "lutil.h"
00036 
00037 int
00038 rwm_map_config(
00039               struct ldapmap       *oc_map,
00040               struct ldapmap       *at_map,
00041               const char    *fname,
00042               int           lineno,
00043               int           argc,
00044               char          **argv )
00045 {
00046        struct ldapmap              *map;
00047        struct ldapmapping   *mapping;
00048        char                 *src, *dst;
00049        int                  is_oc = 0;
00050        int                  rc = 0;
00051 
00052        if ( argc < 3 || argc > 4 ) {
00053               Debug( LDAP_DEBUG_ANY,
00054        "%s: line %d: syntax is \"map {objectclass | attribute} [<local> | *] {<foreign> | *}\"\n",
00055                      fname, lineno, 0 );
00056               return 1;
00057        }
00058 
00059        if ( strcasecmp( argv[1], "objectclass" ) == 0 ) {
00060               map = oc_map;
00061               is_oc = 1;
00062 
00063        } else if ( strcasecmp( argv[1], "attribute" ) == 0 ) {
00064               map = at_map;
00065 
00066        } else {
00067               Debug( LDAP_DEBUG_ANY, "%s: line %d: syntax is "
00068                      "\"map {objectclass | attribute} [<local> | *] "
00069                      "{<foreign> | *}\"\n",
00070                      fname, lineno, 0 );
00071               return 1;
00072        }
00073 
00074        if ( !is_oc && map->map == NULL ) {
00075               /* only init if required */
00076               if ( rwm_map_init( map, &mapping ) != LDAP_SUCCESS ) {
00077                      return 1;
00078               }
00079        }
00080 
00081        if ( strcmp( argv[2], "*" ) == 0 ) {
00082               if ( argc < 4 || strcmp( argv[3], "*" ) == 0 ) {
00083                      map->drop_missing = ( argc < 4 );
00084                      goto success_return;
00085               }
00086               src = dst = argv[3];
00087 
00088        } else if ( argc < 4 ) {
00089               src = "";
00090               dst = argv[2];
00091 
00092        } else {
00093               src = argv[2];
00094               dst = ( strcmp( argv[3], "*" ) == 0 ? src : argv[3] );
00095        }
00096 
00097        if ( ( map == at_map )
00098                      && ( strcasecmp( src, "objectclass" ) == 0
00099                      || strcasecmp( dst, "objectclass" ) == 0 ) )
00100        {
00101               Debug( LDAP_DEBUG_ANY,
00102                      "%s: line %d: objectclass attribute cannot be mapped\n",
00103                      fname, lineno, 0 );
00104               return 1;
00105        }
00106 
00107        mapping = (struct ldapmapping *)ch_calloc( 2,
00108               sizeof(struct ldapmapping) );
00109        if ( mapping == NULL ) {
00110               Debug( LDAP_DEBUG_ANY,
00111                      "%s: line %d: out of memory\n",
00112                      fname, lineno, 0 );
00113               return 1;
00114        }
00115        ber_str2bv( src, 0, 1, &mapping[0].m_src );
00116        ber_str2bv( dst, 0, 1, &mapping[0].m_dst );
00117        mapping[1].m_src = mapping[0].m_dst;
00118        mapping[1].m_dst = mapping[0].m_src;
00119 
00120        mapping[0].m_flags = RWMMAP_F_NONE;
00121        mapping[1].m_flags = RWMMAP_F_NONE;
00122 
00123        /*
00124         * schema check
00125         */
00126        if ( is_oc ) {
00127               if ( src[0] != '\0' ) {
00128                      mapping[0].m_src_oc = oc_bvfind( &mapping[0].m_src );
00129                      if ( mapping[0].m_src_oc == NULL ) {
00130                             Debug( LDAP_DEBUG_ANY,
00131        "%s: line %d: warning, source objectClass '%s' "
00132        "should be defined in schema\n",
00133                                    fname, lineno, src );
00134 
00135                             /*
00136                              * FIXME: this should become an err
00137                              */
00138                             mapping[0].m_src_oc = ch_malloc( sizeof( ObjectClass ) );
00139                             memset( mapping[0].m_src_oc, 0, sizeof( ObjectClass ) );
00140                             mapping[0].m_src_oc->soc_cname = mapping[0].m_src;
00141                             mapping[0].m_flags |= RWMMAP_F_FREE_SRC;
00142                      }
00143                      mapping[1].m_dst_oc = mapping[0].m_src_oc;
00144               }
00145 
00146               mapping[0].m_dst_oc = oc_bvfind( &mapping[0].m_dst );
00147               if ( mapping[0].m_dst_oc == NULL ) {
00148                      Debug( LDAP_DEBUG_ANY,
00149        "%s: line %d: warning, destination objectClass '%s' "
00150        "is not defined in schema\n",
00151                             fname, lineno, dst );
00152 
00153                      mapping[0].m_dst_oc = oc_bvfind_undef( &mapping[0].m_dst );
00154                      if ( mapping[0].m_dst_oc == NULL ) {
00155                             Debug( LDAP_DEBUG_ANY, "%s: line %d: unable to mimic destination objectClass '%s'\n",
00156                                    fname, lineno, dst );
00157                             goto error_return;
00158                      }
00159               }
00160               mapping[1].m_src_oc = mapping[0].m_dst_oc;
00161 
00162               mapping[0].m_flags |= RWMMAP_F_IS_OC;
00163               mapping[1].m_flags |= RWMMAP_F_IS_OC;
00164 
00165        } else {
00166               int                  rc;
00167               const char           *text = NULL;
00168 
00169               if ( src[0] != '\0' ) {
00170                      rc = slap_bv2ad( &mapping[0].m_src,
00171                                    &mapping[0].m_src_ad, &text );
00172                      if ( rc != LDAP_SUCCESS ) {
00173                             Debug( LDAP_DEBUG_ANY,
00174        "%s: line %d: warning, source attributeType '%s' "
00175        "should be defined in schema\n",
00176                                    fname, lineno, src );
00177 
00178                             /*
00179                              * we create a fake "proxied" ad 
00180                              * and add it here.
00181                              */
00182 
00183                             rc = slap_bv2undef_ad( &mapping[0].m_src,
00184                                           &mapping[0].m_src_ad, &text,
00185                                           SLAP_AD_PROXIED );
00186                             if ( rc != LDAP_SUCCESS ) {
00187                                    char prefix[1024];
00188                                    snprintf( prefix, sizeof(prefix),
00189        "%s: line %d: source attributeType '%s': %d",
00190                                           fname, lineno, src, rc );
00191                                    Debug( LDAP_DEBUG_ANY, "%s (%s)\n",
00192                                           prefix, text ? text : "null", 0 );
00193                                    goto error_return;
00194                             }
00195 
00196                      }
00197                      mapping[1].m_dst_ad = mapping[0].m_src_ad;
00198               }
00199 
00200               rc = slap_bv2ad( &mapping[0].m_dst, &mapping[0].m_dst_ad, &text );
00201               if ( rc != LDAP_SUCCESS ) {
00202                      Debug( LDAP_DEBUG_ANY,
00203        "%s: line %d: warning, destination attributeType '%s' "
00204        "is not defined in schema\n",
00205                             fname, lineno, dst );
00206 
00207                      rc = slap_bv2undef_ad( &mapping[0].m_dst,
00208                                    &mapping[0].m_dst_ad, &text,
00209                                    SLAP_AD_PROXIED );
00210                      if ( rc != LDAP_SUCCESS ) {
00211                             char prefix[1024];
00212                             snprintf( prefix, sizeof(prefix), 
00213        "%s: line %d: destination attributeType '%s': %d",
00214                                    fname, lineno, dst, rc );
00215                             Debug( LDAP_DEBUG_ANY, "%s (%s)\n",
00216                                    prefix, text ? text : "null", 0 );
00217                             goto error_return;
00218                      }
00219               }
00220               mapping[1].m_src_ad = mapping[0].m_dst_ad;
00221        }
00222 
00223        if ( ( src[0] != '\0' && avl_find( map->map, (caddr_t)mapping, rwm_mapping_cmp ) != NULL)
00224                      || avl_find( map->remap, (caddr_t)&mapping[1], rwm_mapping_cmp ) != NULL)
00225        {
00226               Debug( LDAP_DEBUG_ANY,
00227                      "%s: line %d: duplicate mapping found.\n",
00228                      fname, lineno, 0 );
00229               /* FIXME: free stuff */
00230               goto error_return;
00231        }
00232 
00233        if ( src[0] != '\0' ) {
00234               avl_insert( &map->map, (caddr_t)&mapping[0],
00235                                    rwm_mapping_cmp, rwm_mapping_dup );
00236        }
00237        avl_insert( &map->remap, (caddr_t)&mapping[1],
00238                             rwm_mapping_cmp, rwm_mapping_dup );
00239 
00240 success_return:;
00241        return rc;
00242 
00243 error_return:;
00244        if ( mapping ) {
00245               rwm_mapping_free( mapping );
00246        }
00247 
00248        return 1;
00249 }
00250 
00251 static char *
00252 rwm_suffix_massage_regexize( const char *s )
00253 {
00254        char *res, *ptr;
00255        const char *p, *r;
00256        int i;
00257 
00258        if ( s[0] == '\0' ) {
00259               return ch_strdup( "^(.+)$" );
00260        }
00261 
00262        for ( i = 0, p = s; 
00263                      ( r = strchr( p, ',' ) ) != NULL; 
00264                      p = r + 1, i++ )
00265               ;
00266 
00267        res = ch_calloc( sizeof( char ), strlen( s )
00268                      + STRLENOF( "((.+),)?" )
00269                      + STRLENOF( "[ ]?" ) * i
00270                      + STRLENOF( "$" ) + 1 );
00271 
00272        ptr = lutil_strcopy( res, "((.+),)?" );
00273        for ( i = 0, p = s;
00274                      ( r = strchr( p, ',' ) ) != NULL;
00275                      p = r + 1 , i++ ) {
00276               ptr = lutil_strncopy( ptr, p, r - p + 1 );
00277               ptr = lutil_strcopy( ptr, "[ ]?" );
00278 
00279               if ( r[ 1 ] == ' ' ) {
00280                      r++;
00281               }
00282        }
00283        ptr = lutil_strcopy( ptr, p );
00284        ptr[0] = '$';
00285        ptr[1] = '\0';
00286 
00287        return res;
00288 }
00289 
00290 static char *
00291 rwm_suffix_massage_patternize( const char *s, const char *p )
00292 {
00293        ber_len_t     len;
00294        char          *res, *ptr;
00295 
00296        len = strlen( p );
00297 
00298        if ( s[ 0 ] == '\0' ) {
00299               len++;
00300        }
00301 
00302        res = ch_calloc( sizeof( char ), len + STRLENOF( "%1" ) + 1 );
00303        if ( res == NULL ) {
00304               return NULL;
00305        }
00306 
00307        ptr = lutil_strcopy( res, ( p[0] == '\0' ? "%2" : "%1" ) );
00308        if ( s[ 0 ] == '\0' ) {
00309               ptr[ 0 ] = ',';
00310               ptr++;
00311        }
00312        lutil_strcopy( ptr, p );
00313 
00314        return res;
00315 }
00316 
00317 int
00318 rwm_suffix_massage_config( 
00319               struct rewrite_info *info,
00320               struct berval *pvnc,
00321               struct berval *nvnc,
00322               struct berval *prnc,
00323               struct berval *nrnc
00324 )
00325 {
00326        char *rargv[ 5 ];
00327        int line = 0;
00328 
00329        rargv[ 0 ] = "rewriteEngine";
00330        rargv[ 1 ] = "on";
00331        rargv[ 2 ] = NULL;
00332        rewrite_parse( info, "<suffix massage>", ++line, 2, rargv );
00333 
00334        rargv[ 0 ] = "rewriteContext";
00335        rargv[ 1 ] = "default";
00336        rargv[ 2 ] = NULL;
00337        rewrite_parse( info, "<suffix massage>", ++line, 2, rargv );
00338 
00339        rargv[ 0 ] = "rewriteRule";
00340        rargv[ 1 ] = rwm_suffix_massage_regexize( pvnc->bv_val );
00341        rargv[ 2 ] = rwm_suffix_massage_patternize( pvnc->bv_val, prnc->bv_val );
00342        rargv[ 3 ] = ":";
00343        rargv[ 4 ] = NULL;
00344        rewrite_parse( info, "<suffix massage>", ++line, 4, rargv );
00345        ch_free( rargv[ 1 ] );
00346        ch_free( rargv[ 2 ] );
00347        
00348        if ( BER_BVISEMPTY( pvnc ) ) {
00349               rargv[ 0 ] = "rewriteRule";
00350               rargv[ 1 ] = "^$";
00351               rargv[ 2 ] = prnc->bv_val;
00352               rargv[ 3 ] = ":";
00353               rargv[ 4 ] = NULL;
00354               rewrite_parse( info, "<suffix massage>", ++line, 4, rargv );
00355        }
00356 
00357        rargv[ 0 ] = "rewriteContext";
00358        rargv[ 1 ] = "searchEntryDN";
00359        rargv[ 2 ] = NULL;
00360        rewrite_parse( info, "<suffix massage>", ++line, 2, rargv );
00361        
00362        rargv[ 0 ] = "rewriteRule";
00363        rargv[ 1 ] = rwm_suffix_massage_regexize( prnc->bv_val );
00364        rargv[ 2 ] = rwm_suffix_massage_patternize( prnc->bv_val, pvnc->bv_val );
00365        rargv[ 3 ] = ":";
00366        rargv[ 4 ] = NULL;
00367        rewrite_parse( info, "<suffix massage>", ++line, 4, rargv );
00368        ch_free( rargv[ 1 ] );
00369        ch_free( rargv[ 2 ] );
00370 
00371        if ( BER_BVISEMPTY( prnc ) ) {
00372               rargv[ 0 ] = "rewriteRule";
00373               rargv[ 1 ] = "^$";
00374               rargv[ 2 ] = pvnc->bv_val;
00375               rargv[ 3 ] = ":";
00376               rargv[ 4 ] = NULL;
00377               rewrite_parse( info, "<suffix massage>", ++line, 4, rargv );
00378        }
00379 
00380        rargv[ 0 ] = "rewriteContext";
00381        rargv[ 1 ] = "matchedDN";
00382        rargv[ 2 ] = "alias";
00383        rargv[ 3 ] = "searchEntryDN";
00384        rargv[ 4 ] = NULL;
00385        rewrite_parse( info, "<suffix massage>", ++line, 4, rargv );
00386 
00387 #ifdef RWM_REFERRAL_REWRITE
00388        /* FIXME: we don't want this on by default, do we? */
00389        rargv[ 0 ] = "rewriteContext";
00390        rargv[ 1 ] = "referralDN";
00391        rargv[ 2 ] = "alias";
00392        rargv[ 3 ] = "searchEntryDN";
00393        rargv[ 4 ] = NULL;
00394        rewrite_parse( info, "<suffix massage>", ++line, 4, rargv );
00395 #else /* ! RWM_REFERRAL_REWRITE */
00396        rargv[ 0 ] = "rewriteContext";
00397        rargv[ 1 ] = "referralAttrDN";
00398        rargv[ 2 ] = NULL;
00399        rewrite_parse( info, "<suffix massage>", ++line, 2, rargv );
00400 
00401        rargv[ 0 ] = "rewriteContext";
00402        rargv[ 1 ] = "referralDN";
00403        rargv[ 2 ] = NULL;
00404        rewrite_parse( info, "<suffix massage>", ++line, 2, rargv );
00405 #endif /* ! RWM_REFERRAL_REWRITE */
00406 
00407        rargv[ 0 ] = "rewriteContext";
00408        rargv[ 1 ] = "searchAttrDN";
00409        rargv[ 2 ] = "alias";
00410        rargv[ 3 ] = "searchEntryDN";
00411        rargv[ 4 ] = NULL;
00412        rewrite_parse( info, "<suffix massage>", ++line, 4, rargv );
00413 
00414        return 0;
00415 }
00416 
00417 #endif /* SLAPD_OVER_RWM */