Back to index

openldap  2.4.31
xmap.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 #define LDAP_DEPRECATED 1
00029 #include "rewrite-int.h"
00030 #include "rewrite-map.h"
00031 
00032 /*
00033  * Global data
00034  */
00035 #ifdef USE_REWRITE_LDAP_PVT_THREADS
00036 ldap_pvt_thread_mutex_t xpasswd_mutex;
00037 static int xpasswd_mutex_init = 0;
00038 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
00039 
00040 /*
00041  * Map parsing
00042  * NOTE: these are old-fashion maps; new maps will be parsed on separate
00043  * config lines, and referred by name.
00044  */
00045 struct rewrite_map *
00046 rewrite_xmap_parse(
00047               struct rewrite_info *info,
00048               const char *s,
00049               const char **currpos
00050 )
00051 {
00052        struct rewrite_map *map;
00053 
00054        assert( info != NULL );
00055        assert( s != NULL );
00056        assert( currpos != NULL );
00057 
00058        Debug( LDAP_DEBUG_ARGS, "rewrite_xmap_parse: %s\n%s%s",
00059                      s, "", "" );
00060 
00061        *currpos = NULL;
00062 
00063        map = calloc( sizeof( struct rewrite_map ), 1 );
00064        if ( map == NULL ) {
00065               Debug( LDAP_DEBUG_ANY, "rewrite_xmap_parse:"
00066                             " calloc failed\n%s%s%s", "", "", "" );
00067               return NULL;
00068        }
00069 
00070        /*
00071         * Experimental passwd map:
00072         * replaces the uid with the matching gecos from /etc/passwd file 
00073         */
00074        if ( strncasecmp(s, "xpasswd", 7 ) == 0 ) {
00075               map->lm_type = REWRITE_MAP_XPWDMAP;
00076               map->lm_name = strdup( "xpasswd" );
00077               if ( map->lm_name == NULL ) {
00078                      free( map );
00079                      return NULL;
00080               }
00081 
00082               assert( s[7] == '}' );
00083               *currpos = s + 8;
00084 
00085 #ifdef USE_REWRITE_LDAP_PVT_THREADS
00086               if ( !xpasswd_mutex_init ) {
00087                      if ( ldap_pvt_thread_mutex_init( &xpasswd_mutex ) ) {
00088                             free( map );
00089                             return NULL;
00090                      }
00091               }
00092               ++xpasswd_mutex_init;
00093 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
00094 
00095               /* Don't really care if fails */
00096               return map;
00097        
00098        /*
00099         * Experimental file map:
00100         * looks up key in a `key value' ascii file
00101         */
00102        } else if ( strncasecmp( s, "xfile", 5 ) == 0 ) {
00103               char *filename;
00104               const char *p;
00105               int l;
00106               int c = 5;
00107               
00108               map->lm_type = REWRITE_MAP_XFILEMAP;
00109               
00110               if ( s[ c ] != '(' ) {
00111                      free( map );
00112                      return NULL;
00113               }
00114 
00115               /* Must start with '/' for security concerns */
00116               c++;
00117               if ( s[ c ] != '/' ) {
00118                      free( map );
00119                      return NULL;
00120               }
00121 
00122               for ( p = s + c; p[ 0 ] != '\0' && p[ 0 ] != ')'; p++ );
00123               if ( p[ 0 ] != ')' ) {
00124                      free( map );
00125                      return NULL;
00126               }
00127 
00128               l = p - s - c;
00129               filename = calloc( sizeof( char ), l + 1 );
00130               if ( filename == NULL ) {
00131                      free( map );
00132                      return NULL;
00133               }
00134               AC_MEMCPY( filename, s + c, l );
00135               filename[ l ] = '\0';
00136               
00137               map->lm_args = ( void * )fopen( filename, "r" );
00138               free( filename );
00139 
00140               if ( map->lm_args == NULL ) {
00141                      free( map );
00142                      return NULL;
00143               }
00144 
00145               *currpos = p + 1;
00146 
00147 #ifdef USE_REWRITE_LDAP_PVT_THREADS
00148                 if ( ldap_pvt_thread_mutex_init( &map->lm_mutex ) ) {
00149                      fclose( ( FILE * )map->lm_args );
00150                      free( map );
00151                      return NULL;
00152               }
00153 #endif /* USE_REWRITE_LDAP_PVT_THREADS */ 
00154               
00155               return map;
00156 
00157        /*
00158          * Experimental ldap map:
00159          * looks up key on the fly (not implemented!)
00160          */
00161         } else if ( strncasecmp(s, "xldap", 5 ) == 0 ) {
00162               char *p;
00163               char *url;
00164               int l, rc;
00165               int c = 5;
00166               LDAPURLDesc *lud;
00167 
00168               if ( s[ c ] != '(' ) {
00169                      free( map );
00170                      return NULL;
00171               }
00172               c++;
00173               
00174               p = strchr( s, '}' );
00175               if ( p == NULL ) {
00176                      free( map );
00177                      return NULL;
00178               }
00179               p--;
00180 
00181               *currpos = p + 2;
00182        
00183               /*
00184                * Add two bytes for urlencoding of '%s'
00185                */
00186               l = p - s - c;
00187               url = calloc( sizeof( char ), l + 3 );
00188               if ( url == NULL ) {
00189                      free( map );
00190                      return NULL;
00191               }
00192               AC_MEMCPY( url, s + c, l );
00193               url[ l ] = '\0';
00194 
00195               /*
00196                * Urlencodes the '%s' for ldap_url_parse
00197                */
00198               p = strchr( url, '%' );
00199               if ( p != NULL ) {
00200                      AC_MEMCPY( p + 3, p + 1, strlen( p + 1 ) + 1 );
00201                      p[ 1 ] = '2';
00202                      p[ 2 ] = '5';
00203               }
00204 
00205               rc =  ldap_url_parse( url, &lud );
00206               free( url );
00207 
00208               if ( rc != LDAP_SUCCESS ) {
00209                      free( map );
00210                      return NULL;
00211               }
00212               assert( lud != NULL );
00213 
00214               map->lm_args = ( void * )lud;
00215               map->lm_type = REWRITE_MAP_XLDAPMAP;
00216 
00217 #ifdef USE_REWRITE_LDAP_PVT_THREADS
00218                 if ( ldap_pvt_thread_mutex_init( &map->lm_mutex ) ) {
00219                      ldap_free_urldesc( lud );
00220                      free( map );
00221                      return NULL;
00222               }
00223 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
00224 
00225               return map;
00226        
00227        /* Unhandled map */
00228        }
00229 
00230        free( map );
00231        return NULL;
00232 }
00233 
00234 /*
00235  * Map key -> value resolution
00236  * NOTE: these are old-fashion maps; new maps will be parsed on separate
00237  * config lines, and referred by name.
00238  */
00239 int
00240 rewrite_xmap_apply(
00241               struct rewrite_info *info,
00242               struct rewrite_op *op,
00243               struct rewrite_map *map,
00244               struct berval *key,
00245               struct berval *val
00246 )
00247 {
00248        int rc = REWRITE_SUCCESS;
00249        
00250        assert( info != NULL );
00251        assert( op != NULL );
00252        assert( map != NULL );
00253        assert( key != NULL );
00254        assert( val != NULL );
00255        
00256        val->bv_val = NULL;
00257        val->bv_len = 0;
00258        
00259        switch ( map->lm_type ) {
00260 #ifdef HAVE_GETPWNAM
00261        case REWRITE_MAP_XPWDMAP: {
00262               struct passwd *pwd;
00263 
00264 #ifdef USE_REWRITE_LDAP_PVT_THREADS
00265               ldap_pvt_thread_mutex_lock( &xpasswd_mutex );
00266 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
00267               
00268               pwd = getpwnam( key->bv_val );
00269               if ( pwd == NULL ) {
00270 
00271 #ifdef USE_REWRITE_LDAP_PVT_THREADS
00272                      ldap_pvt_thread_mutex_unlock( &xpasswd_mutex );
00273 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
00274 
00275                      rc = LDAP_NO_SUCH_OBJECT;
00276                      break;
00277               }
00278 
00279 #ifdef HAVE_STRUCT_PASSWD_PW_GECOS
00280               if ( pwd->pw_gecos != NULL && pwd->pw_gecos[0] != '\0' ) {
00281                      int l = strlen( pwd->pw_gecos );
00282                      
00283                      val->bv_val = strdup( pwd->pw_gecos );
00284                      val->bv_len = l;
00285               } else
00286 #endif /* HAVE_STRUCT_PASSWD_PW_GECOS */
00287               {
00288                      val->bv_val = strdup( key->bv_val );
00289                      val->bv_len = key->bv_len;
00290               }
00291 
00292 #ifdef USE_REWRITE_LDAP_PVT_THREADS
00293               ldap_pvt_thread_mutex_unlock( &xpasswd_mutex );
00294 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
00295 
00296               if ( val->bv_val == NULL ) {
00297                      rc = REWRITE_ERR;
00298               }
00299               break;
00300        }
00301 #endif /* HAVE_GETPWNAM*/
00302        
00303        case REWRITE_MAP_XFILEMAP: {
00304               char buf[1024];
00305               
00306               if ( map->lm_args == NULL ) {
00307                      rc = REWRITE_ERR;
00308                      break;
00309               }
00310               
00311 #ifdef USE_REWRITE_LDAP_PVT_THREADS
00312               ldap_pvt_thread_mutex_lock( &map->lm_mutex );
00313 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
00314 
00315               rewind( ( FILE * )map->lm_args );
00316               
00317               while ( fgets( buf, sizeof( buf ), ( FILE * )map->lm_args ) ) {
00318                      char *p;
00319                      int blen;
00320                      
00321                      blen = strlen( buf );
00322                      if ( buf[ blen - 1 ] == '\n' ) {
00323                             buf[ blen - 1 ] = '\0';
00324                      }
00325                      
00326                      p = strtok( buf, " " );
00327                      if ( p == NULL ) {
00328 #ifdef USE_REWRITE_LDAP_PVT_THREADS
00329                             ldap_pvt_thread_mutex_unlock( &map->lm_mutex );
00330 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
00331                             rc = REWRITE_ERR;
00332                             goto rc_return;
00333                      }
00334                      if ( strcasecmp( p, key->bv_val ) == 0 
00335                                    && ( p = strtok( NULL, "" ) ) ) {
00336                             val->bv_val = strdup( p );
00337                             if ( val->bv_val == NULL ) {
00338                                    return REWRITE_ERR;
00339                             }
00340 
00341                             val->bv_len = strlen( p );
00342                             
00343 #ifdef USE_REWRITE_LDAP_PVT_THREADS
00344                             ldap_pvt_thread_mutex_unlock( &map->lm_mutex );
00345 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
00346                             
00347                             goto rc_return;
00348                      }
00349               }
00350 
00351 #ifdef USE_REWRITE_LDAP_PVT_THREADS
00352               ldap_pvt_thread_mutex_unlock( &map->lm_mutex );
00353 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
00354 
00355               rc = REWRITE_ERR;
00356               
00357               break;
00358        }
00359 
00360        case REWRITE_MAP_XLDAPMAP: {
00361               LDAP *ld;
00362               char filter[1024];
00363               LDAPMessage *res = NULL, *entry;
00364               LDAPURLDesc *lud = ( LDAPURLDesc * )map->lm_args;
00365               int attrsonly = 0;
00366               char **values;
00367 
00368               assert( lud != NULL );
00369 
00370               /*
00371                * No mutex because there is no write on the map data
00372                */
00373               
00374               ld = ldap_init( lud->lud_host, lud->lud_port );
00375               if ( ld == NULL ) {
00376                      rc = REWRITE_ERR;
00377                      goto rc_return;
00378               }
00379 
00380               snprintf( filter, sizeof( filter ), lud->lud_filter,
00381                             key->bv_val );
00382 
00383               if ( strcasecmp( lud->lud_attrs[ 0 ], "dn" ) == 0 ) {
00384                      attrsonly = 1;
00385               }
00386               rc = ldap_search_s( ld, lud->lud_dn, lud->lud_scope,
00387                             filter, lud->lud_attrs, attrsonly, &res );
00388               if ( rc != LDAP_SUCCESS ) {
00389                      ldap_unbind( ld );
00390                      rc = REWRITE_ERR;
00391                      goto rc_return;
00392               }
00393 
00394               if ( ldap_count_entries( ld, res ) != 1 ) {
00395                      ldap_unbind( ld );
00396                      rc = REWRITE_ERR;
00397                      goto rc_return;
00398               }
00399 
00400               entry = ldap_first_entry( ld, res );
00401               if ( entry == NULL ) {
00402                      ldap_msgfree( res );
00403                      ldap_unbind( ld );
00404                      rc = REWRITE_ERR;
00405                      goto rc_return;
00406               }
00407               if ( attrsonly == 1 ) {
00408                      val->bv_val = ldap_get_dn( ld, entry );
00409 
00410               } else {
00411                      values = ldap_get_values( ld, entry,
00412                                    lud->lud_attrs[0] );
00413                      if ( values != NULL ) {
00414                             val->bv_val = strdup( values[ 0 ] );
00415                             ldap_value_free( values );
00416                      }
00417               }
00418 
00419               ldap_msgfree( res );
00420               ldap_unbind( ld );
00421               
00422               if ( val->bv_val == NULL ) {
00423                      rc = REWRITE_ERR;
00424                      goto rc_return;
00425               }
00426               val->bv_len = strlen( val->bv_val );
00427 
00428               rc = REWRITE_SUCCESS;
00429        } break;
00430        }
00431 
00432 rc_return:;
00433        return rc;
00434 }
00435 
00436 int
00437 rewrite_xmap_destroy(
00438               struct rewrite_map **pmap
00439 )
00440 {
00441        struct rewrite_map *map;
00442 
00443        assert( pmap != NULL );
00444        assert( *pmap != NULL );
00445 
00446        map = *pmap;
00447 
00448        switch ( map->lm_type ) {
00449        case REWRITE_MAP_XPWDMAP:
00450 #ifdef USE_REWRITE_LDAP_PVT_THREADS
00451               --xpasswd_mutex_init;
00452               if ( !xpasswd_mutex_init ) {
00453                      ldap_pvt_thread_mutex_destroy( &xpasswd_mutex );
00454               }
00455 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
00456 
00457               break;
00458 
00459        case REWRITE_MAP_XFILEMAP:
00460 #ifdef USE_REWRITE_LDAP_PVT_THREADS
00461               ldap_pvt_thread_mutex_lock( &map->lm_mutex );
00462 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
00463 
00464               if ( map->lm_args ) {
00465                      fclose( ( FILE * )map->lm_args );
00466                      map->lm_args = NULL;
00467               }
00468 
00469 #ifdef USE_REWRITE_LDAP_PVT_THREADS
00470               ldap_pvt_thread_mutex_unlock( &map->lm_mutex );
00471               ldap_pvt_thread_mutex_destroy( &map->lm_mutex );
00472 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
00473               break;
00474 
00475        case REWRITE_MAP_XLDAPMAP:
00476 #ifdef USE_REWRITE_LDAP_PVT_THREADS
00477               ldap_pvt_thread_mutex_lock( &map->lm_mutex );
00478 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
00479 
00480               if ( map->lm_args ) {
00481                      ldap_free_urldesc( ( LDAPURLDesc * )map->lm_args );
00482                      map->lm_args = NULL;
00483               }
00484 
00485 #ifdef USE_REWRITE_LDAP_PVT_THREADS
00486               ldap_pvt_thread_mutex_unlock( &map->lm_mutex );
00487               ldap_pvt_thread_mutex_destroy( &map->lm_mutex );
00488 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
00489               break;
00490 
00491        default:
00492               break;
00493 
00494        }
00495 
00496        free( map->lm_name );
00497        free( map );
00498        *pmap = NULL;
00499 
00500        return 0;
00501 }
00502