Back to index

openldap  2.4.31
ldapmap.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 #define LDAP_DEPRECATED 1
00023 #include "rewrite-int.h"
00024 #include "rewrite-map.h"
00025 
00026 typedef enum {
00027        MAP_LDAP_UNKNOWN,
00028        MAP_LDAP_EVERYTIME,
00029        MAP_LDAP_NOW,
00030        MAP_LDAP_LATER
00031 } bindwhen_t;
00032 
00033 /*
00034  * LDAP map data structure
00035  */
00036 struct ldap_map_data {
00037        char                           *lm_url;
00038        LDAPURLDesc                    *lm_lud;
00039        int                         lm_version;
00040        char                           *lm_binddn;
00041        struct berval               lm_cred;
00042 
00043        bindwhen_t                  lm_when;
00044 
00045        LDAP                           *lm_ld;
00046 
00047        int                             lm_wantdn;
00048        char                        *lm_attrs[ 2 ];
00049 
00050 #ifdef USE_REWRITE_LDAP_PVT_THREADS
00051        ldap_pvt_thread_mutex_t         lm_mutex;
00052 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
00053 };
00054 
00055 static void
00056 map_ldap_free(
00057               struct ldap_map_data *data
00058 )
00059 {
00060        assert( data != NULL );
00061 
00062        if ( data->lm_url != NULL ) {
00063               free( data->lm_url );
00064        }
00065 
00066        if ( data->lm_lud != NULL ) {
00067               ldap_free_urldesc( data->lm_lud );
00068        }
00069 
00070        if ( data->lm_binddn != NULL ) {
00071               free( data->lm_binddn );
00072        }
00073 
00074        if ( data->lm_cred.bv_val != NULL ) {
00075               memset( data->lm_cred.bv_val, 0, data->lm_cred.bv_len );
00076               free( data->lm_cred.bv_val );
00077               data->lm_cred.bv_val = NULL;
00078               data->lm_cred.bv_len = 0;
00079        }
00080 
00081        if ( data->lm_when != MAP_LDAP_EVERYTIME && data->lm_ld != NULL ) {
00082               ldap_unbind_ext( data->lm_ld, NULL, NULL );
00083        }
00084 
00085        free( data );
00086 }
00087 
00088 static void *
00089 map_ldap_parse(
00090               const char *fname,
00091               int lineno,
00092               int argc,
00093               char **argv
00094 )
00095 {
00096        struct ldap_map_data *data;
00097        char *p, *uri;
00098 
00099        assert( fname != NULL );
00100        assert( argv != NULL );
00101 
00102        data = calloc( sizeof( struct ldap_map_data ), 1 );
00103        if ( data == NULL ) {
00104               return NULL;
00105        }
00106 
00107        if ( argc < 1 ) {
00108               Debug( LDAP_DEBUG_ANY,
00109                             "[%s:%d] ldap map needs URI\n%s",
00110                             fname, lineno, "" );
00111               free( data );
00112               return NULL;
00113        }
00114 
00115        uri = argv[ 0 ];
00116        if ( strncasecmp( uri, "uri=", STRLENOF( "uri=" ) ) == 0 ) {
00117               uri += STRLENOF( "uri=" );
00118        }
00119 
00120        data->lm_url = strdup( uri );
00121        if ( data->lm_url == NULL ) {
00122               map_ldap_free( data );
00123               return NULL;
00124        }
00125        
00126        if ( ldap_url_parse( uri, &data->lm_lud ) != REWRITE_SUCCESS ) {
00127               Debug( LDAP_DEBUG_ANY,
00128                             "[%s:%d] illegal URI '%s'\n",
00129                             fname, lineno, argv[ 0 ] );
00130               map_ldap_free( data );
00131               return NULL;
00132        }
00133 
00134        /* trim everything after [host][:port] */
00135        p = strchr( data->lm_url, '/' );
00136        assert( p[ 1 ] == '/' );
00137        if ( ( p = strchr( p + 2, '/' ) ) != NULL ) {
00138               p[ 0 ] = '\0';
00139        }
00140 
00141        if ( data->lm_lud->lud_attrs == NULL ) {
00142               data->lm_attrs[ 0 ] = LDAP_NO_ATTRS;
00143               data->lm_wantdn = 1;
00144 
00145        } else {
00146               if ( data->lm_lud->lud_attrs[ 1 ] != NULL ) {
00147                      Debug( LDAP_DEBUG_ANY,
00148                             "[%s:%d] only one attribute allowed in URI\n",
00149                             fname, lineno, 0 );
00150                      map_ldap_free( data );
00151                      return NULL;
00152               }
00153 
00154               if ( strcasecmp( data->lm_lud->lud_attrs[ 0 ], "dn" ) == 0
00155                      || strcasecmp( data->lm_lud->lud_attrs[ 0 ], "entryDN" ) == 0 )
00156               {
00157                      ldap_memfree( data->lm_lud->lud_attrs[ 0 ] );
00158                      ldap_memfree( data->lm_lud->lud_attrs );
00159                      data->lm_lud->lud_attrs = NULL;
00160                      data->lm_attrs[ 0 ] = LDAP_NO_ATTRS;
00161                      data->lm_wantdn = 1;
00162 
00163               } else {
00164                      data->lm_attrs[ 0 ] = data->lm_lud->lud_attrs[ 0 ];
00165               }
00166        }
00167 
00168        data->lm_attrs[ 1 ] = NULL;
00169 
00170        /* safe defaults */
00171        data->lm_version = LDAP_VERSION3;
00172 
00173        for ( argc--, argv++; argc > 0; argc--, argv++ ) {
00174               if ( strncasecmp( argv[ 0 ], "binddn=", STRLENOF( "binddn=" ) ) == 0 ) {
00175                      char *p = argv[ 0 ] + STRLENOF( "binddn=" );
00176                      int l;
00177 
00178                      if ( p[ 0 ] == '\"' || p [ 0 ] == '\'' ) {
00179                             l = strlen( p ) - 2;
00180                             p++;
00181                             if ( p[ l ] != p[ 0 ] ) {
00182                                    map_ldap_free( data );
00183                                    return NULL;
00184                             }
00185                      } else {
00186                             l = strlen( p );
00187                      }
00188                      
00189                      data->lm_binddn = strdup( p );                   
00190                      if ( data->lm_binddn == NULL ) {
00191                             map_ldap_free( data );
00192                             return NULL;
00193                      }
00194 
00195                      if ( data->lm_binddn[ l ] == '\"' 
00196                                    || data->lm_binddn[ l ] == '\'' ) {
00197                             data->lm_binddn[ l ] = '\0';
00198                      }
00199 
00200                      /* deprecated */
00201               } else if ( strncasecmp( argv[ 0 ], "bindpw=", STRLENOF( "bindpw=" ) ) == 0 ) {
00202                      ber_str2bv( argv[ 0 ] + STRLENOF( "bindpw=" ), 0, 1, &data->lm_cred );
00203                      if ( data->lm_cred.bv_val == NULL ) {
00204                             map_ldap_free( data );
00205                             return NULL;
00206                      }
00207 
00208               } else if ( strncasecmp( argv[ 0 ], "credentials=", STRLENOF( "credentials=" ) ) == 0 ) {
00209                      ber_str2bv( argv[ 0 ] + STRLENOF( "credentials=" ), 0, 1, &data->lm_cred );
00210                      if ( data->lm_cred.bv_val == NULL ) {
00211                             map_ldap_free( data );
00212                             return NULL;
00213                      }
00214 
00215               } else if ( strncasecmp( argv[ 0 ], "bindwhen=", STRLENOF( "bindwhen=" ) ) == 0 ) {
00216                      char *p = argv[ 0 ] + STRLENOF( "bindwhen=" );
00217 
00218                      if ( strcasecmp( p, "now" ) == 0 ) {
00219                             int rc;
00220                             
00221                             data->lm_when = MAP_LDAP_NOW;
00222                             
00223                             /*
00224                              * Init LDAP handler ...
00225                              */
00226                             rc = ldap_initialize( &data->lm_ld, data->lm_url );
00227                             if ( rc != LDAP_SUCCESS ) {
00228                                    map_ldap_free( data );
00229                                    return NULL;
00230                             }
00231 
00232                             ldap_set_option( data->lm_ld,
00233                                    LDAP_OPT_PROTOCOL_VERSION,
00234                                    (void *)&data->lm_version );
00235 
00236 #ifdef USE_REWRITE_LDAP_PVT_THREADS
00237                             ldap_pvt_thread_mutex_init( &data->lm_mutex );
00238 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
00239 
00240                      } else if ( strcasecmp( p, "later" ) == 0 ) {
00241                             data->lm_when = MAP_LDAP_LATER;
00242 
00243 #ifdef USE_REWRITE_LDAP_PVT_THREADS
00244                             ldap_pvt_thread_mutex_init( &data->lm_mutex );
00245 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
00246 
00247                      } else if ( strcasecmp( p, "everytime" ) == 0 ) {
00248                             data->lm_when = MAP_LDAP_EVERYTIME;
00249                      } else {
00250                             /* ignore ... */
00251                      }
00252 
00253               } else if ( strncasecmp( argv[ 0 ], "version=", STRLENOF( "version=" ) ) == 0 ) {
00254                      if ( lutil_atoi( &data->lm_version, argv[ 0 ] + STRLENOF( "version=" ) ) ) {
00255                             map_ldap_free( data );
00256                             return NULL;
00257                      }
00258 
00259                      switch ( data->lm_version ) {
00260                      case LDAP_VERSION2:
00261                      case LDAP_VERSION3:
00262                             break;
00263 
00264                      default:
00265                             Debug( LDAP_DEBUG_ANY,
00266                                    "[%s:%d] unknown version %s\n",
00267                                    fname, lineno, p );
00268                             map_ldap_free( data );
00269                             return NULL;
00270                      }
00271 
00272               } else {
00273                      Debug( LDAP_DEBUG_ANY,
00274                             "[%s:%d] unknown option %s (ignored)\n",
00275                             fname, lineno, argv[0] );
00276               }
00277        }
00278 
00279        if ( data->lm_when == MAP_LDAP_UNKNOWN ) {
00280               data->lm_when = MAP_LDAP_EVERYTIME;
00281        }
00282 
00283        return ( void * )data;
00284 }
00285 
00286 static int
00287 map_ldap_apply(
00288               void *private,
00289               const char *filter,
00290               struct berval *val
00291 
00292 )
00293 {
00294        LDAP *ld;
00295        LDAPMessage *res = NULL, *entry;
00296        int rc;
00297        struct ldap_map_data *data = private;
00298        LDAPURLDesc *lud = data->lm_lud;
00299        
00300        int first_try = 1, set_version = 0;
00301 
00302        assert( private != NULL );
00303        assert( filter != NULL );
00304        assert( val != NULL );
00305 
00306        val->bv_val = NULL;
00307        val->bv_len = 0;
00308 
00309        if ( data->lm_when == MAP_LDAP_EVERYTIME ) {
00310               rc = ldap_initialize( &ld, data->lm_url );
00311               set_version = 1;
00312 
00313        } else {
00314 #ifdef USE_REWRITE_LDAP_PVT_THREADS
00315               ldap_pvt_thread_mutex_lock( &data->lm_mutex );
00316 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
00317 
00318               rc = LDAP_SUCCESS;
00319 
00320               if ( data->lm_when == MAP_LDAP_LATER && data->lm_ld == NULL ) {
00321                      rc = ldap_initialize( &data->lm_ld, data->lm_url );
00322                      set_version = 1;
00323               }
00324               
00325               ld = data->lm_ld;
00326        }
00327 
00328        if ( rc != LDAP_SUCCESS ) {
00329               rc = REWRITE_ERR;
00330               goto rc_return;
00331        }
00332 
00333 do_bind:;
00334        if ( set_version ) {
00335               ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION,
00336                      (void *)&data->lm_version );
00337               set_version = 0;
00338        }
00339 
00340        if ( data->lm_binddn != NULL ) {
00341               rc = ldap_sasl_bind_s( ld, data->lm_binddn,
00342                      LDAP_SASL_SIMPLE, &data->lm_cred,
00343                      NULL, NULL, NULL );
00344               if ( rc == LDAP_SERVER_DOWN && first_try ) {
00345                      first_try = 0;
00346                      if ( ldap_initialize( &ld, data->lm_url ) != LDAP_SUCCESS ) {
00347                             rc = REWRITE_ERR;
00348                             goto rc_return;
00349                      }
00350                      set_version = 1;
00351                      goto do_bind;
00352 
00353               } else if ( rc != REWRITE_SUCCESS ) {
00354                      rc = REWRITE_ERR;
00355                      goto rc_return;
00356               }
00357        }
00358 
00359        rc = ldap_search_ext_s( ld, lud->lud_dn, lud->lud_scope, ( char * )filter,
00360                      data->lm_attrs, 0, NULL, NULL, NULL, 1, &res );
00361        if ( rc == LDAP_SERVER_DOWN && first_try ) {
00362               first_try = 0;
00363                 if ( ldap_initialize( &ld, data->lm_url ) != LDAP_SUCCESS ) {
00364                      rc = REWRITE_ERR;
00365                      goto rc_return;
00366               }
00367               set_version = 1;
00368               goto do_bind;
00369 
00370        } else if ( rc != LDAP_SUCCESS ) {
00371               rc = REWRITE_ERR;
00372               goto rc_return;
00373        }
00374 
00375        if ( ldap_count_entries( ld, res ) != 1 ) {
00376               ldap_msgfree( res );
00377               rc = REWRITE_ERR;
00378               goto rc_return;
00379        }
00380 
00381        entry = ldap_first_entry( ld, res );
00382        assert( entry != NULL );
00383 
00384        if ( data->lm_wantdn == 1 ) {
00385               /*
00386                * dn is newly allocated, so there's no need to strdup it
00387                */
00388               val->bv_val = ldap_get_dn( ld, entry );
00389               val->bv_len = strlen( val->bv_val );
00390 
00391        } else {
00392               struct berval **values;
00393 
00394               values = ldap_get_values_len( ld, entry, data->lm_attrs[ 0 ] );
00395               if ( values != NULL ) {
00396                      if ( values[ 0 ] != NULL && values[ 0 ]->bv_val != NULL ) {
00397 #if 0
00398                             /* NOTE: in principle, multiple values
00399                              * should not be acceptable according
00400                              * to the current API; ignore by now */
00401                             if ( values[ 1 ] != NULL ) {
00402                                    /* error */                        
00403                             }
00404 #endif
00405                             ber_dupbv( val, values[ 0 ] );
00406                      }
00407                      ldap_value_free_len( values );
00408               }
00409        }
00410        
00411        ldap_msgfree( res );
00412 
00413        if ( val->bv_val == NULL ) {
00414               rc = REWRITE_ERR;
00415               goto rc_return;
00416        }
00417 
00418 rc_return:;
00419        if ( data->lm_when == MAP_LDAP_EVERYTIME ) {
00420               if ( ld != NULL ) {
00421                      ldap_unbind_ext( ld, NULL, NULL );
00422               }
00423 
00424        } else {
00425               data->lm_ld = ld;
00426 #ifdef USE_REWRITE_LDAP_PVT_THREADS
00427               ldap_pvt_thread_mutex_unlock( &data->lm_mutex );
00428 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
00429        }
00430        
00431        return rc;
00432 }
00433 
00434 static int
00435 map_ldap_destroy(
00436               void *private
00437 )
00438 {
00439        struct ldap_map_data *data = private;
00440 
00441        assert( private != NULL );
00442        
00443        map_ldap_free( data );
00444 
00445        return 0;
00446 }
00447 
00448 const rewrite_mapper rewrite_ldap_mapper = {
00449        "ldap",
00450        map_ldap_parse,
00451        map_ldap_apply,
00452        map_ldap_destroy
00453 };
00454