From a3deda802658cd20188b3c5c3a127ccc122436dc Mon Sep 17 00:00:00 2001 From: Pierangelo Masarati Date: Fri, 14 Nov 2003 18:39:18 +0000 Subject: [PATCH] fix a number of mem leaks; add destroy code; HEADS-UP: API change in rewrite_info_delete() --- include/rewrite.h | 2 +- libraries/librewrite/Makefile.in | 4 +- libraries/librewrite/config.c | 20 +- libraries/librewrite/context.c | 47 +++ libraries/librewrite/info.c | 26 +- libraries/librewrite/map.c | 507 +++++------------------------ libraries/librewrite/params.c | 12 +- libraries/librewrite/rewrite-int.h | 35 +- libraries/librewrite/rewrite.c | 10 +- libraries/librewrite/rule.c | 62 +++- libraries/librewrite/session.c | 26 +- libraries/librewrite/subst.c | 210 +++++++----- libraries/librewrite/var.c | 20 +- libraries/librewrite/xmap.c | 502 ++++++++++++++++++++++++++++ servers/slapd/back-ldap/init.c | 2 +- servers/slapd/back-meta/init.c | 6 +- 16 files changed, 924 insertions(+), 567 deletions(-) create mode 100644 libraries/librewrite/xmap.c diff --git a/include/rewrite.h b/include/rewrite.h index 08398420c0..fdf7c1f4df 100644 --- a/include/rewrite.h +++ b/include/rewrite.h @@ -96,7 +96,7 @@ rewrite_info_init( */ LDAP_REWRITE_F (int) rewrite_info_delete( - struct rewrite_info *info + struct rewrite_info **info ); diff --git a/libraries/librewrite/Makefile.in b/libraries/librewrite/Makefile.in index f2e4cdfa6a..b8a487192f 100644 --- a/libraries/librewrite/Makefile.in +++ b/libraries/librewrite/Makefile.in @@ -8,11 +8,11 @@ ## SRCS = config.c context.c info.c ldapmap.c map.c params.c rule.c \ - session.c subst.c var.c \ + session.c subst.c var.c xmap.c \ parse.c rewrite.c XSRCS = version.c OBJS = config.o context.o info.o ldapmap.o map.o params.o rule.o \ - session.o subst.o var.o + session.o subst.o var.o xmap.o LDAP_INCDIR= ../../include LDAP_LIBDIR= ../../libraries diff --git a/libraries/librewrite/config.c b/libraries/librewrite/config.c index 556fd30947..baf88d40a7 100644 --- a/libraries/librewrite/config.c +++ b/libraries/librewrite/config.c @@ -123,12 +123,12 @@ rewrite_parse( * Checks for existence (lots of contexts should be * available by default ...) */ - __curr_context = rewrite_context_find( info, argv[ 1 ] ); - if ( __curr_context == NULL ) { - __curr_context = rewrite_context_create( info, + rewrite_int_curr_context = rewrite_context_find( info, argv[ 1 ] ); + if ( rewrite_int_curr_context == NULL ) { + rewrite_int_curr_context = rewrite_context_create( info, argv[ 1 ] ); } - if ( __curr_context == NULL ) { + if ( rewrite_int_curr_context == NULL ) { return -1; } @@ -173,8 +173,8 @@ rewrite_parse( return -1; } - __curr_context->lc_alias = aliased; - __curr_context = aliased; + rewrite_int_curr_context->lc_alias = aliased; + rewrite_int_curr_context = aliased; } else { Debug( LDAP_DEBUG_ANY, "[%s:%d] extra fields" @@ -202,22 +202,22 @@ rewrite_parse( fname, lineno, "" ); } - if ( __curr_context == NULL ) { + if ( rewrite_int_curr_context == NULL ) { Debug( LDAP_DEBUG_ANY, "[%s:%d] rewriteRule outside a" " context; will add to default\n%s", fname, lineno, "" ); - __curr_context = rewrite_context_find( info, + rewrite_int_curr_context = rewrite_context_find( info, REWRITE_DEFAULT_CONTEXT ); /* * Default context MUST exist in a properly initialized * struct rewrite_info */ - assert( __curr_context != NULL ); + assert( rewrite_int_curr_context != NULL ); } - rc = rewrite_rule_compile( info, __curr_context, argv[ 1 ], + rc = rewrite_rule_compile( info, rewrite_int_curr_context, argv[ 1 ], argv[ 2 ], ( argc == 4 ? argv[ 3 ] : "" ) ); /* diff --git a/libraries/librewrite/context.c b/libraries/librewrite/context.c index 115cca6f1e..4758c8fff7 100644 --- a/libraries/librewrite/context.c +++ b/libraries/librewrite/context.c @@ -144,6 +144,7 @@ rewrite_context_create( free( context ); return NULL; } + memset( context->lc_rule, 0, sizeof( struct rewrite_rule ) ); /* * Add context to tree @@ -413,3 +414,49 @@ rc_end_of_context:; return return_code; } +void +rewrite_context_free( + void *tmp +) +{ + struct rewrite_context *context = (struct rewrite_context *)tmp; + + assert( tmp ); + + rewrite_context_destroy( &context ); +} + +int +rewrite_context_destroy( + struct rewrite_context **pcontext +) +{ + struct rewrite_context *context; + struct rewrite_rule *r; + + assert( pcontext ); + assert( *pcontext ); + + context = *pcontext; + + assert( context->lc_rule ); + + for ( r = context->lc_rule->lr_next; r; ) { + struct rewrite_rule *cr = r; + + r = r->lr_next; + rewrite_rule_destroy( &cr ); + } + + free( context->lc_rule ); + context->lc_rule = NULL; + + assert( context->lc_name ); + free( context->lc_name ); + context->lc_name = NULL; + + free( context ); + *pcontext = NULL; + + return 0; +} diff --git a/libraries/librewrite/info.c b/libraries/librewrite/info.c index 6a89f3ce43..aeb43d6ee6 100644 --- a/libraries/librewrite/info.c +++ b/libraries/librewrite/info.c @@ -35,7 +35,7 @@ * rewrite_parse; it can be altered only by a * rewriteContext config line or by a change in info. */ -struct rewrite_context *__curr_context = NULL; +struct rewrite_context *rewrite_int_curr_context = NULL; /* * Inits the info @@ -63,7 +63,7 @@ rewrite_info_init( /* * Resets the running context for parsing ... */ - __curr_context = NULL; + rewrite_int_curr_context = NULL; info = calloc( sizeof( struct rewrite_info ), 1 ); if ( info == NULL ) { @@ -102,20 +102,36 @@ rewrite_info_init( */ int rewrite_info_delete( - struct rewrite_info *info + struct rewrite_info **pinfo ) { - assert( info != NULL ); + struct rewrite_info *info; + + assert( pinfo != NULL ); + assert( *pinfo != NULL ); + + info = *pinfo; + if ( info->li_context ) { + avl_free( info->li_context, rewrite_context_free ); + } + info->li_context = NULL; + rewrite_session_destroy( info ); +#ifdef USE_REWRITE_LDAP_PVT_THREADS + ldap_pvt_thread_rdwr_destroy( &info->li_cookies_mutex ); +#endif /* USE_REWRITE_LDAP_PVT_THREADS */ + rewrite_param_destroy( info ); #ifdef USE_REWRITE_LDAP_PVT_THREADS - ldap_pvt_thread_rdwr_destroy( &info->li_cookies_mutex ); ldap_pvt_thread_rdwr_destroy( &info->li_params_mutex ); #endif /* USE_REWRITE_LDAP_PVT_THREADS */ + free( info ); + *pinfo = NULL; + return REWRITE_SUCCESS; } diff --git a/libraries/librewrite/map.c b/libraries/librewrite/map.c index 7ddd0d99dd..c7acbc31eb 100644 --- a/libraries/librewrite/map.c +++ b/libraries/librewrite/map.c @@ -33,195 +33,6 @@ #include "rewrite-int.h" #include "rewrite-map.h" -/* - * Global data - */ -#ifdef USE_REWRITE_LDAP_PVT_THREADS -ldap_pvt_thread_mutex_t xpasswd_mutex; -static int xpasswd_mutex_init = 0; -#endif /* USE_REWRITE_LDAP_PVT_THREADS */ - -/* - * Map parsing - * NOTE: these are old-fashion maps; new maps will be parsed on separate - * config lines, and referred by name. - */ -struct rewrite_map * -rewrite_xmap_parse( - struct rewrite_info *info, - const char *s, - const char **currpos -) -{ - struct rewrite_map *map; - - assert( info != NULL ); - assert( s != NULL ); - assert( currpos != NULL ); - - Debug( LDAP_DEBUG_ARGS, "rewrite_xmap_parse: %s\n%s%s", - s, "", "" ); - - *currpos = NULL; - - map = calloc( sizeof( struct rewrite_map ), 1 ); - if ( map == NULL ) { - Debug( LDAP_DEBUG_ANY, "rewrite_xmap_parse:" - " calloc failed\n%s%s%s", "", "", "" ); - return NULL; - } - - /* - * Experimental passwd map: - * replaces the uid with the matching gecos from /etc/passwd file - */ - if ( strncasecmp(s, "xpasswd", 7 ) == 0 ) { - map->lm_type = REWRITE_MAP_XPWDMAP; - map->lm_name = strdup( "xpasswd" ); - - assert( s[7] == '}' ); - *currpos = s + 8; - -#ifdef USE_REWRITE_LDAP_PVT_THREADS - if ( !xpasswd_mutex_init ) { - xpasswd_mutex_init = 1; - if ( ldap_pvt_thread_mutex_init( &xpasswd_mutex ) ) { - free( map ); - return NULL; - } - } -#endif /* USE_REWRITE_LDAP_PVT_THREADS */ - - /* Don't really care if fails */ - return map; - - /* - * Experimental file map: - * looks up key in a `key value' ascii file - */ - } else if ( strncasecmp(s, "xfile", 5 ) == 0 ) { - char *filename; - const char *p; - int l; - int c = 5; - - map->lm_type = REWRITE_MAP_XFILEMAP; - - if ( s[ c ] != '(' ) { - free( map ); - return NULL; - } - - /* Must start with '/' for security concerns */ - c++; - if ( s[ c ] != '/' ) { - free( map ); - return NULL; - } - - for ( p = s + c; p[ 0 ] != '\0' && p[ 0 ] != ')'; p++ ); - if ( p[ 0 ] != ')' ) { - free( map ); - return NULL; - } - - l = p - s - c; - filename = calloc( sizeof( char ), l + 1 ); - AC_MEMCPY( filename, s + c, l ); - filename[ l ] = '\0'; - - map->lm_args = ( void * )fopen( filename, "r" ); - free( filename ); - - if ( map->lm_args == NULL ) { - free( map ); - return NULL; - } - - *currpos = p + 1; - -#ifdef USE_REWRITE_LDAP_PVT_THREADS - if ( ldap_pvt_thread_mutex_init( &map->lm_mutex ) ) { - fclose( ( FILE * )map->lm_args ); - free( map ); - return NULL; - } -#endif /* USE_REWRITE_LDAP_PVT_THREADS */ - - return map; - - /* - * Experimental ldap map: - * looks up key on the fly (not implemented!) - */ - } else if ( strncasecmp(s, "xldap", 5 ) == 0 ) { - char *p; - char *url; - int l, rc; - int c = 5; - LDAPURLDesc *lud; - - if ( s[ c ] != '(' ) { - free( map ); - return NULL; - } - c++; - - p = strchr( s, '}' ); - if ( p == NULL ) { - free( map ); - return NULL; - } - p--; - - *currpos = p + 2; - - /* - * Add two bytes for urlencoding of '%s' - */ - l = p - s - c; - url = calloc( sizeof( char ), l + 3 ); - AC_MEMCPY( url, s + c, l ); - url[ l ] = '\0'; - - /* - * Urlencodes the '%s' for ldap_url_parse - */ - p = strchr( url, '%' ); - if ( p != NULL ) { - AC_MEMCPY( p + 3, p + 1, strlen( p + 1 ) + 1 ); - p[ 1 ] = '2'; - p[ 2 ] = '5'; - } - - rc = ldap_url_parse( url, &lud ); - free( url ); - - if ( rc != LDAP_SUCCESS ) { - free( map ); - return NULL; - } - assert( lud != NULL ); - - map->lm_args = ( void * )lud; - map->lm_type = REWRITE_MAP_XLDAPMAP; - -#ifdef USE_REWRITE_LDAP_PVT_THREADS - if ( ldap_pvt_thread_mutex_init( &map->lm_mutex ) ) { - ldap_free_urldesc( lud ); - free( map ); - return NULL; - } -#endif /* USE_REWRITE_LDAP_PVT_THREADS */ - - return map; - - /* Unhandled map */ - } - - return NULL; -} - struct rewrite_map * rewrite_map_parse( struct rewrite_info *info, @@ -233,7 +44,7 @@ rewrite_map_parse( struct rewrite_subst *subst = NULL; char *s, *begin = NULL, *end; const char *p; - int l, cnt; + int l, cnt, mtx = 0, rc = 0; assert( info != NULL ); assert( string != NULL ); @@ -259,8 +70,11 @@ rewrite_map_parse( cnt++; p++; } - if ( p[ 1 ] != '\0' ) + + if ( p[ 1 ] != '\0' ) { p++; + } + } else if ( p[ 0 ] == '}' ) { cnt--; } @@ -285,11 +99,12 @@ rewrite_map_parse( case REWRITE_OPERATOR_VARIABLE_GET: case REWRITE_OPERATOR_PARAM_GET: break; + default: begin = strchr( s, '(' ); if ( begin == NULL ) { - free( s ); - return NULL; + rc = -1; + goto cleanup; } begin[ 0 ] = '\0'; begin++; @@ -333,13 +148,13 @@ rewrite_map_parse( * Check the syntax of the variable name */ if ( !isalpha( (unsigned char) p[ 0 ] ) ) { - free( s ); - return NULL; + rc = -1; + goto cleanup; } for ( p++; p[ 0 ] != '\0'; p++ ) { if ( !isalnum( (unsigned char) p[ 0 ] ) ) { - free( s ); - return NULL; + rc = -1; + goto cleanup; } } @@ -350,11 +165,12 @@ rewrite_map_parse( case REWRITE_OPERATOR_VARIABLE_GET: case REWRITE_OPERATOR_PARAM_GET: break; + default: end = strrchr( begin, ')' ); if ( end == NULL ) { - free( s ); - return NULL; + rc = -1; + goto cleanup; } end[ 0 ] = '\0'; @@ -363,8 +179,8 @@ rewrite_map_parse( */ subst = rewrite_subst_compile( info, begin ); if ( subst == NULL ) { - free( s ); - return NULL; + rc = -1; + goto cleanup; } break; } @@ -374,22 +190,17 @@ rewrite_map_parse( */ map = calloc( sizeof( struct rewrite_map ), 1 ); if ( map == NULL ) { - if ( subst != NULL ) { - free( subst ); - } - free( s ); - return NULL; + rc = -1; + goto cleanup; } + memset( map, 0, sizeof( struct rewrite_map ) ); #ifdef USE_REWRITE_LDAP_PVT_THREADS if ( ldap_pvt_thread_mutex_init( &map->lm_mutex ) ) { - if ( subst != NULL ) { - free( subst ); - } - free( s ); - free( map ); - return NULL; + rc = -1; + goto cleanup; } + ++mtx; #endif /* USE_REWRITE_LDAP_PVT_THREADS */ /* @@ -399,6 +210,7 @@ rewrite_map_parse( case REWRITE_OPERATOR_VARIABLE_GET: case REWRITE_OPERATOR_PARAM_GET: break; + default: map->lm_subst = subst; break; @@ -422,19 +234,17 @@ rewrite_map_parse( map->lm_name = strdup( s + 1 ); map->lm_data = rewrite_context_find( info, s + 1 ); if ( map->lm_data == NULL ) { - free( s ); - free( map ); - return NULL; + rc = -1; + goto cleanup; } break; /* - * External command + * External command (not implemented yet) */ case REWRITE_OPERATOR_COMMAND: /* '|' */ - free( map ); - map = NULL; - break; + rc = -1; + goto cleanup; /* * Variable set @@ -488,226 +298,36 @@ rewrite_map_parse( map->lm_name = strdup( s ); map->lm_data = rewrite_builtin_map_find( info, s ); if ( map->lm_data == NULL ) { - return NULL; + rc = -1; + goto cleanup; } break; } - - free( s ); - return map; -} -/* - * Map key -> value resolution - * NOTE: these are old-fashion maps; new maps will be parsed on separate - * config lines, and referred by name. - */ -int -rewrite_xmap_apply( - struct rewrite_info *info, - struct rewrite_op *op, - struct rewrite_map *map, - struct berval *key, - struct berval *val -) -{ - int rc = REWRITE_SUCCESS; - - assert( info != NULL ); - assert( op != NULL ); - assert( map != NULL ); - assert( key != NULL ); - assert( val != NULL ); - - val->bv_val = NULL; - val->bv_len = 0; - - switch ( map->lm_type ) { -#ifdef HAVE_GETPWNAM - case REWRITE_MAP_XPWDMAP: { - struct passwd *pwd; - -#ifdef USE_REWRITE_LDAP_PVT_THREADS - ldap_pvt_thread_mutex_lock( &xpasswd_mutex ); -#endif /* USE_REWRITE_LDAP_PVT_THREADS */ - - pwd = getpwnam( key->bv_val ); - if ( pwd == NULL ) { - -#ifdef USE_REWRITE_LDAP_PVT_THREADS - ldap_pvt_thread_mutex_unlock( &xpasswd_mutex ); -#endif /* USE_REWRITE_LDAP_PVT_THREADS */ - - rc = REWRITE_NO_SUCH_OBJECT; - break; +cleanup: + free( s ); + if ( rc ) { + if ( subst != NULL ) { + free( subst ); } - -#ifdef HAVE_PW_GECOS - if ( pwd->pw_gecos != NULL && pwd->pw_gecos[0] != '\0' ) { - int l = strlen( pwd->pw_gecos ); - - val->bv_val = strdup( pwd->pw_gecos ); - if ( val->bv_val == NULL ) { - + if ( map ) { #ifdef USE_REWRITE_LDAP_PVT_THREADS - ldap_pvt_thread_mutex_unlock( &xpasswd_mutex ); -#endif /* USE_REWRITE_LDAP_PVT_THREADS */ - - rc = REWRITE_ERR; - break; + if ( mtx ) { + ldap_pvt_thread_mutex_destroy( &map->lm_mutex ); } - val->bv_len = l; - } else -#endif /* HAVE_PW_GECOS */ - { - val->bv_val = strdup( key->bv_val ); - val->bv_len = key->bv_len; - } - -#ifdef USE_REWRITE_LDAP_PVT_THREADS - ldap_pvt_thread_mutex_unlock( &xpasswd_mutex ); -#endif /* USE_REWRITE_LDAP_PVT_THREADS */ - - break; - } -#endif /* HAVE_GETPWNAM*/ - - case REWRITE_MAP_XFILEMAP: { - char buf[1024]; - - if ( map->lm_args == NULL ) { - rc = REWRITE_ERR; - break; - } - -#ifdef USE_REWRITE_LDAP_PVT_THREADS - ldap_pvt_thread_mutex_lock( &map->lm_mutex ); #endif /* USE_REWRITE_LDAP_PVT_THREADS */ - rewind( ( FILE * )map->lm_args ); - - while ( fgets( buf, sizeof( buf ), ( FILE * )map->lm_args ) ) { - char *p; - int blen; - - blen = strlen( buf ); - if ( buf[ blen - 1 ] == '\n' ) { - buf[ blen - 1 ] = '\0'; - } - - p = strtok( buf, " " ); - if ( p == NULL ) { -#ifdef USE_REWRITE_LDAP_PVT_THREADS - ldap_pvt_thread_mutex_unlock( &map->lm_mutex ); -#endif /* USE_REWRITE_LDAP_PVT_THREADS */ - rc = REWRITE_ERR; - goto rc_return; - } - if ( strcasecmp( p, key->bv_val ) == 0 - && ( p = strtok( NULL, "" ) ) ) { - val->bv_val = strdup( p ); - if ( val->bv_val == NULL ) { - return REWRITE_ERR; - } - - val->bv_len = strlen( p ); - -#ifdef USE_REWRITE_LDAP_PVT_THREADS - ldap_pvt_thread_mutex_unlock( &map->lm_mutex ); -#endif /* USE_REWRITE_LDAP_PVT_THREADS */ - - goto rc_return; + if ( map->lm_name ) { + free( map->lm_name ); + map->lm_name = NULL; } + free( map ); + map = NULL; } - -#ifdef USE_REWRITE_LDAP_PVT_THREADS - ldap_pvt_thread_mutex_unlock( &map->lm_mutex ); -#endif /* USE_REWRITE_LDAP_PVT_THREADS */ - - rc = REWRITE_ERR; - - break; - } - - case REWRITE_MAP_XLDAPMAP: { - LDAP *ld; - char filter[1024]; - LDAPMessage *res = NULL, *entry; - LDAPURLDesc *lud = ( LDAPURLDesc * )map->lm_args; - int attrsonly = 0; - char **values; - - assert( lud != NULL ); - - /* - * No mutex because there is no write on the map data - */ - - ld = ldap_init( lud->lud_host, lud->lud_port ); - if ( ld == NULL ) { - rc = REWRITE_ERR; - goto rc_return; - } - - snprintf( filter, sizeof( filter ), lud->lud_filter, - key->bv_val ); - - if ( strcasecmp( lud->lud_attrs[ 0 ], "dn" ) == 0 ) { - attrsonly = 1; - } - rc = ldap_search_s( ld, lud->lud_dn, lud->lud_scope, - filter, lud->lud_attrs, attrsonly, &res ); - if ( rc != LDAP_SUCCESS ) { - ldap_unbind( ld ); - rc = REWRITE_ERR; - goto rc_return; - } - - if ( ldap_count_entries( ld, res ) != 1 ) { - ldap_unbind( ld ); - rc = REWRITE_ERR; - goto rc_return; - } - - entry = ldap_first_entry( ld, res ); - if ( entry == NULL ) { - ldap_msgfree( res ); - ldap_unbind( ld ); - rc = REWRITE_ERR; - goto rc_return; - } - if ( attrsonly == 1 ) { - val->bv_val = ldap_get_dn( ld, entry ); - if ( val->bv_val == NULL ) { - ldap_msgfree( res ); - ldap_unbind( ld ); - rc = REWRITE_ERR; - goto rc_return; - } - } else { - values = ldap_get_values( ld, entry, - lud->lud_attrs[0] ); - if ( values == NULL ) { - ldap_msgfree( res ); - ldap_unbind( ld ); - rc = REWRITE_ERR; - goto rc_return; - } - val->bv_val = strdup( values[ 0 ] ); - ldap_value_free( values ); - } - val->bv_len = strlen( val->bv_val ); - - ldap_msgfree( res ); - ldap_unbind( ld ); - - rc = REWRITE_SUCCESS; - } } -rc_return:; - return rc; + return map; } /* @@ -796,6 +416,7 @@ rewrite_map_apply( case REWRITE_MAP_BUILTIN: { struct rewrite_builtin_map *bmap = map->lm_data; + switch ( bmap->lb_type ) { case REWRITE_BUILTIN_MAP_LDAP: rc = map_ldap_apply( bmap, key->bv_val, val ); @@ -815,3 +436,39 @@ rewrite_map_apply( return rc; } +int +rewrite_map_destroy( + struct rewrite_map **pmap +) +{ + struct rewrite_map *map; + + assert( pmap ); + assert( *pmap ); + + map = *pmap; + +#ifdef USE_REWRITE_LDAP_PVT_THREADS + ldap_pvt_thread_mutex_lock( &map->lm_mutex ); +#endif /* USE_REWRITE_LDAP_PVT_THREADS */ + + if ( map->lm_name ) { + free( map->lm_name ); + map->lm_name = NULL; + } + + if ( map->lm_subst ) { + rewrite_subst_destroy( &map->lm_subst ); + } + +#ifdef USE_REWRITE_LDAP_PVT_THREADS + ldap_pvt_thread_mutex_unlock( &map->lm_mutex ); + ldap_pvt_thread_mutex_destroy( &map->lm_mutex ); +#endif /* USE_REWRITE_LDAP_PVT_THREADS */ + + free( map ); + *pmap = NULL; + + return 0; +} + diff --git a/libraries/librewrite/params.c b/libraries/librewrite/params.c index 07daa0aabd..d86f3c32a2 100644 --- a/libraries/librewrite/params.c +++ b/libraries/librewrite/params.c @@ -112,6 +112,16 @@ rewrite_param_get( return REWRITE_SUCCESS; } +static void +rewrite_param_free( + void *tmp +) +{ + char *value = ( char * )tmp; + + free( value ); +} + /* * Destroys the parameter tree */ @@ -128,7 +138,7 @@ rewrite_param_destroy( ldap_pvt_thread_rdwr_wlock( &info->li_params_mutex ); #endif /* USE_REWRITE_LDAP_PVT_THREADS */ - count = avl_free( info->li_params, NULL ); + count = avl_free( info->li_params, rewrite_param_free ); info->li_params = NULL; #ifdef USE_REWRITE_LDAP_PVT_THREADS diff --git a/libraries/librewrite/rewrite-int.h b/libraries/librewrite/rewrite-int.h index b8bc161a54..c30e617b2f 100644 --- a/libraries/librewrite/rewrite-int.h +++ b/libraries/librewrite/rewrite-int.h @@ -189,10 +189,10 @@ struct rewrite_submatch { */ struct rewrite_subst { size_t lt_subs_len; - struct berval **lt_subs; + struct berval *lt_subs; int lt_num_submatch; - struct rewrite_submatch **lt_submatch; + struct rewrite_submatch *lt_submatch; }; /* @@ -315,7 +315,7 @@ struct rewrite_info { * PRIVATE * ***********/ -LDAP_REWRITE_V (struct rewrite_context*) __curr_context; +LDAP_REWRITE_V (struct rewrite_context*) rewrite_int_curr_context; /* * Maps @@ -359,6 +359,15 @@ rewrite_xmap_apply( struct berval *val ); +LDAP_REWRITE_F (int) +rewrite_map_destroy( + struct rewrite_map **map +); + +LDAP_REWRITE_F (int) +rewrite_xmap_destroy( + struct rewrite_map **map +); /* * Submatch substitution @@ -387,6 +396,11 @@ rewrite_subst_apply( struct berval *val ); +LDAP_REWRITE_F (int) +rewrite_subst_destroy( + struct rewrite_subst **subst +); + /* * Rules @@ -422,6 +436,11 @@ rewrite_rule_apply( char **result ); +LDAP_REWRITE_F (int) +rewrite_rule_destroy( + struct rewrite_rule **rule +); + /* * Sessions */ @@ -555,5 +574,15 @@ rewrite_context_apply( char **result ); +LDAP_REWRITE_F (int) +rewrite_context_destroy( + struct rewrite_context **context +); + +LDAP_REWRITE_F (void) +rewrite_context_free( + void *tmp +); + #endif /* REWRITE_INT_H */ diff --git a/libraries/librewrite/rewrite.c b/libraries/librewrite/rewrite.c index ac301b7a51..b40ca26ce8 100644 --- a/libraries/librewrite/rewrite.c +++ b/libraries/librewrite/rewrite.c @@ -52,7 +52,7 @@ apply( int rc; void *cookie = &info; - info = rewrite_info_init(REWRITE_MODE_ERR); + info = rewrite_info_init( REWRITE_MODE_ERR ); if ( rewrite_read( fin, info ) != 0 ) { exit( EXIT_FAILURE ); @@ -84,8 +84,12 @@ apply( string = result; } + free( string ); + rewrite_session_delete( info, cookie ); + rewrite_info_delete( &info ); + return result; } @@ -139,6 +143,10 @@ main( int argc, char *argv[] ) apply( ( fin ? fin : stdin ), rewriteContext, argv[ optind ] ); + if ( fin ) { + fclose( fin ); + } + return 0; } diff --git a/libraries/librewrite/rule.c b/libraries/librewrite/rule.c index c8a1c07a14..c812cf3fa9 100644 --- a/libraries/librewrite/rule.c +++ b/libraries/librewrite/rule.c @@ -336,7 +336,8 @@ rewrite_rule_apply( int rc = REWRITE_SUCCESS; char *string; - struct berval val; + int strcnt = 0; + struct berval val = { 0, NULL }; assert( info != NULL ); assert( op != NULL ); @@ -346,10 +347,7 @@ rewrite_rule_apply( *result = NULL; - string = strdup( arg ); - if ( string == NULL ) { - return REWRITE_REGEXEC_ERR; - } + string = (char *)arg; /* * In case recursive match is required (default) @@ -357,13 +355,14 @@ rewrite_rule_apply( recurse:; Debug( LDAP_DEBUG_TRACE, "==> rewrite_rule_apply" - " rule='%s' string='%s'\n%s", - rule->lr_pattern, string, "" ); + " rule='%s' string='%s'\n", + rule->lr_pattern, string, 0 ); op->lo_num_passes++; if ( regexec( &rule->lr_regex, string, nmatch, match, 0 ) != 0 ) { - if ( *result == NULL ) { + if ( *result == NULL && strcnt > 0 ) { free( string ); + string = NULL; } /* @@ -376,7 +375,11 @@ recurse:; match, &val ); *result = val.bv_val; - free( string ); + val.bv_val = NULL; + if ( strcnt > 0 ) { + free( string ); + string = NULL; + } if ( rc != REWRITE_REGEXEC_OK ) { return rc; @@ -385,9 +388,50 @@ recurse:; if ( ( rule->lr_mode & REWRITE_RECURSE ) == REWRITE_RECURSE && op->lo_num_passes <= info->li_max_passes ) { string = *result; + strcnt++; + goto recurse; } return REWRITE_REGEXEC_OK; } +int +rewrite_rule_destroy( + struct rewrite_rule **prule + ) +{ + struct rewrite_rule *rule; + + assert( prule ); + assert( *prule ); + + rule = *prule; + + if ( rule->lr_pattern ) { + free( rule->lr_pattern ); + rule->lr_pattern = NULL; + } + + if ( rule->lr_subststring ) { + free( rule->lr_subststring ); + rule->lr_subststring = NULL; + } + + if ( rule->lr_flagstring ) { + free( rule->lr_flagstring ); + rule->lr_flagstring = NULL; + } + + if ( rule->lr_subst ) { + rewrite_subst_destroy( &rule->lr_subst ); + } + + regfree( &rule->lr_regex ); + + free( rule ); + *prule = NULL; + + return 0; +} + diff --git a/libraries/librewrite/session.c b/libraries/librewrite/session.c index a0c2808aed..20ab8fdde8 100644 --- a/libraries/librewrite/session.c +++ b/libraries/librewrite/session.c @@ -317,25 +317,27 @@ rewrite_session_delete( session = rewrite_session_find( info, cookie ); - if ( session != NULL ) { - if ( --session->ls_count > 0 ) { - rewrite_session_return( info, session ); - return REWRITE_SUCCESS; - } + if ( session == NULL ) { + return REWRITE_SUCCESS; + } + + if ( --session->ls_count > 0 ) { + rewrite_session_return( info, session ); + return REWRITE_SUCCESS; + } #ifdef USE_REWRITE_LDAP_PVT_THREADS - ldap_pvt_thread_rdwr_wlock( &session->ls_vars_mutex ); + ldap_pvt_thread_rdwr_wlock( &session->ls_vars_mutex ); #endif /* USE_REWRITE_LDAP_PVT_THREADS */ - rewrite_var_delete( session->ls_vars ); + rewrite_var_delete( session->ls_vars ); #ifdef USE_REWRITE_LDAP_PVT_THREADS - ldap_pvt_thread_rdwr_wunlock( &session->ls_vars_mutex ); - ldap_pvt_thread_mutex_unlock( &session->ls_mutex ); - ldap_pvt_thread_rdwr_destroy( &session->ls_vars_mutex ); - ldap_pvt_thread_mutex_destroy( &session->ls_mutex ); + ldap_pvt_thread_rdwr_wunlock( &session->ls_vars_mutex ); + ldap_pvt_thread_rdwr_destroy( &session->ls_vars_mutex ); + ldap_pvt_thread_mutex_unlock( &session->ls_mutex ); + ldap_pvt_thread_mutex_destroy( &session->ls_mutex ); #endif /* USE_REWRITE_LDAP_PVT_THREADS */ - } #ifdef USE_REWRITE_LDAP_PVT_THREADS ldap_pvt_thread_rdwr_wlock( &info->li_cookies_mutex ); diff --git a/libraries/librewrite/subst.c b/libraries/librewrite/subst.c index a6d9fdbabf..6aafac5118 100644 --- a/libraries/librewrite/subst.c +++ b/libraries/librewrite/subst.c @@ -36,8 +36,8 @@ rewrite_subst_compile( ) { size_t subs_len; - struct berval **subs = NULL, **tmps; - struct rewrite_submatch **submatch = NULL; + struct berval *subs = NULL, *tmps; + struct rewrite_submatch *submatch = NULL; struct rewrite_subst *s = NULL; @@ -58,21 +58,20 @@ rewrite_subst_compile( if ( p[ 0 ] != REWRITE_SUBMATCH_ESCAPE ) { continue; } + if ( p[ 1 ] == REWRITE_SUBMATCH_ESCAPE ) { - AC_MEMCPY((char *)p, p + 1, strlen( p ) ); + /* Pull &p[1] over p, including the trailing '\0' */ + AC_MEMCPY((char *)p, &p[ 1 ], strlen( p ) ); continue; } - nsub++; - - tmps = (struct berval **)realloc( subs, - sizeof( struct berval * )*( nsub + 1 ) ); + tmps = (struct berval *)realloc( subs, + sizeof( struct berval )*( nsub + 1 ) ); if ( tmps == NULL ) { - /* cleanup */ + /* FIXME: cleanup */ return NULL; } subs = tmps; - subs[ nsub ] = NULL; /* * I think an `if l > 0' at runtime is better outside than @@ -81,21 +80,16 @@ rewrite_subst_compile( l = p - begin; if ( l > 0 ) { subs_len += l; - subs[ nsub - 1 ] = - calloc( sizeof( struct berval ), 1 ); - if ( subs[ nsub - 1 ] == NULL ) { - /* cleanup */ + subs[ nsub ].bv_len = l; + subs[ nsub ].bv_val = malloc( l + 1 ); + if ( subs[ nsub ].bv_val == NULL ) { return NULL; } - subs[ nsub - 1 ]->bv_len = l; - subs[ nsub - 1 ]->bv_val = malloc( l + 1 ); - if ( subs[ nsub - 1 ]->bv_val == NULL ) { - return NULL; - } - AC_MEMCPY( subs[ nsub - 1 ]->bv_val, begin, l ); - subs[ nsub - 1 ]->bv_val[ l ] = '\0'; + AC_MEMCPY( subs[ nsub ].bv_val, begin, l ); + subs[ nsub ].bv_val[ l ] = '\0'; } else { - subs[ nsub - 1 ] = NULL; + subs[ nsub ].bv_val = NULL; + subs[ nsub ].bv_len = 0; } /* @@ -103,40 +97,32 @@ rewrite_subst_compile( */ if ( isdigit( (unsigned char) p[ 1 ] ) ) { int d = p[ 1 ] - '0'; - struct rewrite_submatch **tmpsm; + struct rewrite_submatch *tmpsm; /* * Add a new value substitution scheme */ tmpsm = realloc( submatch, - sizeof( struct rewrite_submatch * )*( nsub + 1 ) ); + sizeof( struct rewrite_submatch )*( nsub + 1 ) ); if ( tmpsm == NULL ) { /* cleanup */ return NULL; } submatch = tmpsm; - submatch[ nsub ] = NULL; - - submatch[ nsub - 1 ] = - calloc( sizeof( struct rewrite_submatch ), 1 ); - if ( submatch[ nsub - 1 ] == NULL ) { - /* cleanup */ - return NULL; - } - submatch[ nsub - 1 ]->ls_submatch = d; + submatch[ nsub ].ls_submatch = d; /* * If there is no argument, use default * (substitute substring as is) */ if ( p[ 2 ] != '{' ) { - submatch[ nsub - 1 ]->ls_type = + submatch[ nsub ].ls_type = REWRITE_SUBMATCH_ASIS; begin = ++p + 1; } else { struct rewrite_map *map; - submatch[ nsub - 1 ]->ls_type = + submatch[ nsub ].ls_type = REWRITE_SUBMATCH_XMAP; map = rewrite_xmap_parse( info, @@ -147,7 +133,7 @@ rewrite_subst_compile( } p = begin - 1; - submatch[ nsub - 1 ]->ls_map = map; + submatch[ nsub ].ls_map = map; } /* @@ -155,7 +141,7 @@ rewrite_subst_compile( */ } else if ( p[ 1 ] == '{' ) { struct rewrite_map *map; - struct rewrite_submatch **tmpsm; + struct rewrite_submatch *tmpsm; map = rewrite_map_parse( info, p + 2, &begin ); if ( map == NULL ) { @@ -168,31 +154,25 @@ rewrite_subst_compile( * Add a new value substitution scheme */ tmpsm = realloc( submatch, - sizeof( struct rewrite_submatch * )*( nsub + 1 ) ); + sizeof( struct rewrite_submatch )*( nsub + 1 ) ); if ( tmpsm == NULL ) { /* cleanup */ return NULL; } submatch = tmpsm; - submatch[ nsub ] = NULL; - submatch[ nsub - 1 ] = - calloc( sizeof( struct rewrite_submatch ), 1 ); - if ( submatch[ nsub - 1 ] == NULL ) { - /* cleanup */ - return NULL; - } - - submatch[ nsub - 1 ]->ls_type = + submatch[ nsub ].ls_type = REWRITE_SUBMATCH_MAP_W_ARG; - submatch[ nsub - 1 ]->ls_map = map; + submatch[ nsub ].ls_map = map; } + + nsub++; } /* * Last part of string */ - tmps = realloc( subs, sizeof( struct berval *)*( nsub + 2 ) ); + tmps = realloc( subs, sizeof( struct berval )*( nsub + 1 ) ); if ( tmps == NULL ) { /* * XXX need to free the value subst stuff! @@ -202,17 +182,16 @@ rewrite_subst_compile( } subs = tmps; - subs[ nsub + 1 ] = NULL; l = p - begin; if ( l > 0 ) { - subs[ nsub ] = calloc( sizeof( struct berval ), 1 ); subs_len += l; - subs[ nsub ]->bv_len = l; - subs[ nsub ]->bv_val = malloc( l + 1 ); - AC_MEMCPY( subs[ nsub ]->bv_val, begin, l ); - subs[ nsub ]->bv_val[ l ] = '\0'; + subs[ nsub ].bv_len = l; + subs[ nsub ].bv_val = malloc( l + 1 ); + AC_MEMCPY( subs[ nsub ].bv_val, begin, l ); + subs[ nsub ].bv_val[ l ] = '\0'; } else { - subs[ nsub ] = NULL; + subs[ nsub ].bv_val = NULL; + subs[ nsub ].bv_len = 0; } s = calloc( sizeof( struct rewrite_subst ), 1 ); @@ -241,8 +220,8 @@ submatch_copy( struct berval *val ) { - int c, l; - const char *s; + int c, l; + const char *s; assert( submatch != NULL ); assert( submatch->ls_type == REWRITE_SUBMATCH_ASIS @@ -250,12 +229,12 @@ submatch_copy( assert( string != NULL ); assert( match != NULL ); assert( val != NULL ); + assert( val->bv_val == NULL ); c = submatch->ls_submatch; s = string + match[ c ].rm_so; l = match[ c ].rm_eo - match[ c ].rm_so; - val->bv_val = NULL; val->bv_len = l; val->bv_val = calloc( sizeof( char ), l + 1 ); if ( val->bv_val == NULL ) { @@ -284,7 +263,7 @@ rewrite_subst_apply( { struct berval *submatch = NULL; char *res = NULL; - int n, l, cl; + int n = 0, l, cl; int rc = REWRITE_REGEXEC_OK; assert( info != NULL ); @@ -294,6 +273,8 @@ rewrite_subst_apply( assert( match != NULL ); assert( val != NULL ); + assert( val->bv_val == NULL ); + val->bv_val = NULL; val->bv_len = 0; @@ -312,58 +293,59 @@ rewrite_subst_apply( * Resolve submatches (simple subst, map expansion and so). */ for ( n = 0, l = 0; n < subst->lt_num_submatch; n++ ) { - struct berval key; - int rc; + struct berval key = { 0, NULL }; + + submatch[ n ].bv_val = NULL; /* * Get key */ - switch( subst->lt_submatch[ n ]->ls_type ) { + switch ( subst->lt_submatch[ n ].ls_type ) { case REWRITE_SUBMATCH_ASIS: case REWRITE_SUBMATCH_XMAP: - rc = submatch_copy( subst->lt_submatch[ n ], + rc = submatch_copy( &subst->lt_submatch[ n ], string, match, &key ); if ( rc != REWRITE_SUCCESS ) { - free( submatch ); - return REWRITE_REGEXEC_ERR; + rc = REWRITE_REGEXEC_ERR; + goto cleanup; } break; case REWRITE_SUBMATCH_MAP_W_ARG: - switch ( subst->lt_submatch[ n ]->ls_map->lm_type ) { + switch ( subst->lt_submatch[ n ].ls_map->lm_type ) { case REWRITE_MAP_GET_OP_VAR: case REWRITE_MAP_GET_SESN_VAR: case REWRITE_MAP_GET_PARAM: rc = REWRITE_SUCCESS; break; + default: rc = rewrite_subst_apply( info, op, - subst->lt_submatch[ n ]->ls_map->lm_subst, + subst->lt_submatch[ n ].ls_map->lm_subst, string, match, &key); } if ( rc != REWRITE_SUCCESS ) { - free( submatch ); - return REWRITE_REGEXEC_ERR; + rc = REWRITE_REGEXEC_ERR; + goto cleanup; } break; default: - Debug( LDAP_DEBUG_ANY, "Not Implemented\n%s%s%s", - "", "", "" ); + Debug( LDAP_DEBUG_ANY, "Not Implemented\n", 0, 0, 0 ); rc = REWRITE_ERR; break; } if ( rc != REWRITE_SUCCESS ) { - free( submatch ); - return REWRITE_REGEXEC_ERR; + rc = REWRITE_REGEXEC_ERR; + goto cleanup; } /* * Resolve key */ - switch ( subst->lt_submatch[ n ]->ls_type ) { + switch ( subst->lt_submatch[ n ].ls_type ) { case REWRITE_SUBMATCH_ASIS: submatch[ n ] = key; rc = REWRITE_SUCCESS; @@ -371,16 +353,16 @@ rewrite_subst_apply( case REWRITE_SUBMATCH_XMAP: rc = rewrite_xmap_apply( info, op, - subst->lt_submatch[ n ]->ls_map, + subst->lt_submatch[ n ].ls_map, &key, &submatch[ n ] ); break; case REWRITE_SUBMATCH_MAP_W_ARG: rc = rewrite_map_apply( info, op, - subst->lt_submatch[ n ]->ls_map, + subst->lt_submatch[ n ].ls_map, &key, &submatch[ n ] ); break; - + default: /* * When implemented, this might return the @@ -393,8 +375,7 @@ rewrite_subst_apply( } if ( rc != REWRITE_SUCCESS ) { - free( submatch ); - return REWRITE_REGEXEC_ERR; + rc = REWRITE_REGEXEC_ERR; } /* @@ -418,19 +399,18 @@ rewrite_subst_apply( * Apply submatches (possibly resolved thru maps */ for ( n = 0, cl = 0; n < subst->lt_num_submatch; n++ ) { - if ( subst->lt_subs[ n ] != NULL ) { - AC_MEMCPY( res + cl, subst->lt_subs[ n ]->bv_val, - subst->lt_subs[ n ]->bv_len ); - cl += subst->lt_subs[ n ]->bv_len; + if ( subst->lt_subs[ n ].bv_val != NULL ) { + AC_MEMCPY( res + cl, subst->lt_subs[ n ].bv_val, + subst->lt_subs[ n ].bv_len ); + cl += subst->lt_subs[ n ].bv_len; } AC_MEMCPY( res + cl, submatch[ n ].bv_val, submatch[ n ].bv_len ); cl += submatch[ n ].bv_len; - free( submatch[ n ].bv_val ); } - if ( subst->lt_subs[ n ] != NULL ) { - AC_MEMCPY( res + cl, subst->lt_subs[ n ]->bv_val, - subst->lt_subs[ n ]->bv_len ); + if ( subst->lt_subs[ n ].bv_val != NULL ) { + AC_MEMCPY( res + cl, subst->lt_subs[ n ].bv_val, + subst->lt_subs[ n ].bv_len ); } val->bv_val = res; @@ -438,9 +418,65 @@ rewrite_subst_apply( cleanup:; if ( submatch ) { + for ( ; --n >= 0; ) { + if ( submatch[ n ].bv_val ) { + free( submatch[ n ].bv_val ); + } + } free( submatch ); } return rc; } +/* + * frees data + */ +int +rewrite_subst_destroy( + struct rewrite_subst **psubst +) +{ + int n; + struct rewrite_subst *subst; + + assert( psubst ); + assert( *psubst ); + + subst = *psubst; + + for ( n = 0; n < subst->lt_num_submatch; n++ ) { + if ( subst->lt_subs[ n ].bv_val ) { + free( subst->lt_subs[ n ].bv_val ); + subst->lt_subs[ n ].bv_val = NULL; + } + + switch ( subst->lt_submatch[ n ].ls_type ) { + case REWRITE_SUBMATCH_ASIS: + break; + + case REWRITE_SUBMATCH_XMAP: + rewrite_xmap_destroy( &subst->lt_submatch[ n ].ls_map ); + break; + + case REWRITE_SUBMATCH_MAP_W_ARG: + rewrite_map_destroy( &subst->lt_submatch[ n ].ls_map ); + break; + + default: + break; + } + } + + /* last one */ + if ( subst->lt_subs[ n ].bv_val ) { + free( subst->lt_subs[ n ].bv_val ); + subst->lt_subs[ n ].bv_val = NULL; + } + + free( subst ); + *psubst = NULL; + + return 0; +} + diff --git a/libraries/librewrite/var.c b/libraries/librewrite/var.c index 941e54b426..e701655a86 100644 --- a/libraries/librewrite/var.c +++ b/libraries/librewrite/var.c @@ -109,25 +109,31 @@ rewrite_var_insert( if ( var == NULL ) { return NULL; } + memset( var, 0, sizeof( struct rewrite_var ) ); var->lv_name = ( char * )strdup( name ); if ( var->lv_name == NULL ) { - free( var ); - return NULL; + rc = -1; + goto cleanup; } var->lv_value.bv_val = strdup( value ); if ( var->lv_value.bv_val == NULL ) { - free( var ); - free( var->lv_name ); - return NULL; + rc = -1; + goto cleanup; } var->lv_value.bv_len = strlen( value ); rc = avl_insert( tree, ( caddr_t )var, rewrite_var_cmp, rewrite_var_dup ); if ( rc != 0 ) { - free( var ); + rc = -1; + goto cleanup; + } + +cleanup:; + if ( rc != 0 ) { free( var->lv_name ); free( var->lv_value.bv_val ); - return NULL; + free( var ); + var = NULL; } return var; diff --git a/libraries/librewrite/xmap.c b/libraries/librewrite/xmap.c new file mode 100644 index 0000000000..195bee0be7 --- /dev/null +++ b/libraries/librewrite/xmap.c @@ -0,0 +1,502 @@ +/****************************************************************************** + * + * Copyright (C) 2000 Pierangelo Masarati, + * All rights reserved. + * + * Permission is granted to anyone to use this software for any purpose + * on any computer system, and to alter it and redistribute it, subject + * to the following restrictions: + * + * 1. The author is not responsible for the consequences of use of this + * software, no matter how awful, even if they arise from flaws in it. + * + * 2. The origin of this software must not be misrepresented, either by + * explicit claim or by omission. Since few users ever read sources, + * credits should appear in the documentation. + * + * 3. Altered versions must be plainly marked as such, and must not be + * misrepresented as being the original software. Since few users + * ever read sources, credits should appear in the documentation. + * + * 4. This notice may not be removed or altered. + * + ******************************************************************************/ + +#include + +#include + +#ifdef HAVE_PWD_H +#include +#endif + +#include "rewrite-int.h" +#include "rewrite-map.h" + +/* + * Global data + */ +#ifdef USE_REWRITE_LDAP_PVT_THREADS +ldap_pvt_thread_mutex_t xpasswd_mutex; +static int xpasswd_mutex_init = 0; +#endif /* USE_REWRITE_LDAP_PVT_THREADS */ + +/* + * Map parsing + * NOTE: these are old-fashion maps; new maps will be parsed on separate + * config lines, and referred by name. + */ +struct rewrite_map * +rewrite_xmap_parse( + struct rewrite_info *info, + const char *s, + const char **currpos +) +{ + struct rewrite_map *map; + + assert( info != NULL ); + assert( s != NULL ); + assert( currpos != NULL ); + + Debug( LDAP_DEBUG_ARGS, "rewrite_xmap_parse: %s\n%s%s", + s, "", "" ); + + *currpos = NULL; + + map = calloc( sizeof( struct rewrite_map ), 1 ); + if ( map == NULL ) { + Debug( LDAP_DEBUG_ANY, "rewrite_xmap_parse:" + " calloc failed\n%s%s%s", "", "", "" ); + return NULL; + } + + /* + * Experimental passwd map: + * replaces the uid with the matching gecos from /etc/passwd file + */ + if ( strncasecmp(s, "xpasswd", 7 ) == 0 ) { + map->lm_type = REWRITE_MAP_XPWDMAP; + map->lm_name = strdup( "xpasswd" ); + + assert( s[7] == '}' ); + *currpos = s + 8; + +#ifdef USE_REWRITE_LDAP_PVT_THREADS + if ( !xpasswd_mutex_init ) { + if ( ldap_pvt_thread_mutex_init( &xpasswd_mutex ) ) { + free( map ); + return NULL; + } + } + ++xpasswd_mutex_init; +#endif /* USE_REWRITE_LDAP_PVT_THREADS */ + + /* Don't really care if fails */ + return map; + + /* + * Experimental file map: + * looks up key in a `key value' ascii file + */ + } else if ( strncasecmp(s, "xfile", 5 ) == 0 ) { + char *filename; + const char *p; + int l; + int c = 5; + + map->lm_type = REWRITE_MAP_XFILEMAP; + + if ( s[ c ] != '(' ) { + free( map ); + return NULL; + } + + /* Must start with '/' for security concerns */ + c++; + if ( s[ c ] != '/' ) { + free( map ); + return NULL; + } + + for ( p = s + c; p[ 0 ] != '\0' && p[ 0 ] != ')'; p++ ); + if ( p[ 0 ] != ')' ) { + free( map ); + return NULL; + } + + l = p - s - c; + filename = calloc( sizeof( char ), l + 1 ); + AC_MEMCPY( filename, s + c, l ); + filename[ l ] = '\0'; + + map->lm_args = ( void * )fopen( filename, "r" ); + free( filename ); + + if ( map->lm_args == NULL ) { + free( map ); + return NULL; + } + + *currpos = p + 1; + +#ifdef USE_REWRITE_LDAP_PVT_THREADS + if ( ldap_pvt_thread_mutex_init( &map->lm_mutex ) ) { + fclose( ( FILE * )map->lm_args ); + free( map ); + return NULL; + } +#endif /* USE_REWRITE_LDAP_PVT_THREADS */ + + return map; + + /* + * Experimental ldap map: + * looks up key on the fly (not implemented!) + */ + } else if ( strncasecmp(s, "xldap", 5 ) == 0 ) { + char *p; + char *url; + int l, rc; + int c = 5; + LDAPURLDesc *lud; + + if ( s[ c ] != '(' ) { + free( map ); + return NULL; + } + c++; + + p = strchr( s, '}' ); + if ( p == NULL ) { + free( map ); + return NULL; + } + p--; + + *currpos = p + 2; + + /* + * Add two bytes for urlencoding of '%s' + */ + l = p - s - c; + url = calloc( sizeof( char ), l + 3 ); + AC_MEMCPY( url, s + c, l ); + url[ l ] = '\0'; + + /* + * Urlencodes the '%s' for ldap_url_parse + */ + p = strchr( url, '%' ); + if ( p != NULL ) { + AC_MEMCPY( p + 3, p + 1, strlen( p + 1 ) + 1 ); + p[ 1 ] = '2'; + p[ 2 ] = '5'; + } + + rc = ldap_url_parse( url, &lud ); + free( url ); + + if ( rc != LDAP_SUCCESS ) { + free( map ); + return NULL; + } + assert( lud != NULL ); + + map->lm_args = ( void * )lud; + map->lm_type = REWRITE_MAP_XLDAPMAP; + +#ifdef USE_REWRITE_LDAP_PVT_THREADS + if ( ldap_pvt_thread_mutex_init( &map->lm_mutex ) ) { + ldap_free_urldesc( lud ); + free( map ); + return NULL; + } +#endif /* USE_REWRITE_LDAP_PVT_THREADS */ + + return map; + + /* Unhandled map */ + } + + return NULL; +} + +/* + * Map key -> value resolution + * NOTE: these are old-fashion maps; new maps will be parsed on separate + * config lines, and referred by name. + */ +int +rewrite_xmap_apply( + struct rewrite_info *info, + struct rewrite_op *op, + struct rewrite_map *map, + struct berval *key, + struct berval *val +) +{ + int rc = REWRITE_SUCCESS; + + assert( info != NULL ); + assert( op != NULL ); + assert( map != NULL ); + assert( key != NULL ); + assert( val != NULL ); + + val->bv_val = NULL; + val->bv_len = 0; + + switch ( map->lm_type ) { +#ifdef HAVE_GETPWNAM + case REWRITE_MAP_XPWDMAP: { + struct passwd *pwd; + +#ifdef USE_REWRITE_LDAP_PVT_THREADS + ldap_pvt_thread_mutex_lock( &xpasswd_mutex ); +#endif /* USE_REWRITE_LDAP_PVT_THREADS */ + + pwd = getpwnam( key->bv_val ); + if ( pwd == NULL ) { + +#ifdef USE_REWRITE_LDAP_PVT_THREADS + ldap_pvt_thread_mutex_unlock( &xpasswd_mutex ); +#endif /* USE_REWRITE_LDAP_PVT_THREADS */ + + rc = REWRITE_NO_SUCH_OBJECT; + break; + } + +#ifdef HAVE_PW_GECOS + if ( pwd->pw_gecos != NULL && pwd->pw_gecos[0] != '\0' ) { + int l = strlen( pwd->pw_gecos ); + + val->bv_val = strdup( pwd->pw_gecos ); + if ( val->bv_val == NULL ) { + +#ifdef USE_REWRITE_LDAP_PVT_THREADS + ldap_pvt_thread_mutex_unlock( &xpasswd_mutex ); +#endif /* USE_REWRITE_LDAP_PVT_THREADS */ + + rc = REWRITE_ERR; + break; + } + val->bv_len = l; + } else +#endif /* HAVE_PW_GECOS */ + { + val->bv_val = strdup( key->bv_val ); + val->bv_len = key->bv_len; + } + +#ifdef USE_REWRITE_LDAP_PVT_THREADS + ldap_pvt_thread_mutex_unlock( &xpasswd_mutex ); +#endif /* USE_REWRITE_LDAP_PVT_THREADS */ + + break; + } +#endif /* HAVE_GETPWNAM*/ + + case REWRITE_MAP_XFILEMAP: { + char buf[1024]; + + if ( map->lm_args == NULL ) { + rc = REWRITE_ERR; + break; + } + +#ifdef USE_REWRITE_LDAP_PVT_THREADS + ldap_pvt_thread_mutex_lock( &map->lm_mutex ); +#endif /* USE_REWRITE_LDAP_PVT_THREADS */ + + rewind( ( FILE * )map->lm_args ); + + while ( fgets( buf, sizeof( buf ), ( FILE * )map->lm_args ) ) { + char *p; + int blen; + + blen = strlen( buf ); + if ( buf[ blen - 1 ] == '\n' ) { + buf[ blen - 1 ] = '\0'; + } + + p = strtok( buf, " " ); + if ( p == NULL ) { +#ifdef USE_REWRITE_LDAP_PVT_THREADS + ldap_pvt_thread_mutex_unlock( &map->lm_mutex ); +#endif /* USE_REWRITE_LDAP_PVT_THREADS */ + rc = REWRITE_ERR; + goto rc_return; + } + if ( strcasecmp( p, key->bv_val ) == 0 + && ( p = strtok( NULL, "" ) ) ) { + val->bv_val = strdup( p ); + if ( val->bv_val == NULL ) { + return REWRITE_ERR; + } + + val->bv_len = strlen( p ); + +#ifdef USE_REWRITE_LDAP_PVT_THREADS + ldap_pvt_thread_mutex_unlock( &map->lm_mutex ); +#endif /* USE_REWRITE_LDAP_PVT_THREADS */ + + goto rc_return; + } + } + +#ifdef USE_REWRITE_LDAP_PVT_THREADS + ldap_pvt_thread_mutex_unlock( &map->lm_mutex ); +#endif /* USE_REWRITE_LDAP_PVT_THREADS */ + + rc = REWRITE_ERR; + + break; + } + + case REWRITE_MAP_XLDAPMAP: { + LDAP *ld; + char filter[1024]; + LDAPMessage *res = NULL, *entry; + LDAPURLDesc *lud = ( LDAPURLDesc * )map->lm_args; + int attrsonly = 0; + char **values; + + assert( lud != NULL ); + + /* + * No mutex because there is no write on the map data + */ + + ld = ldap_init( lud->lud_host, lud->lud_port ); + if ( ld == NULL ) { + rc = REWRITE_ERR; + goto rc_return; + } + + snprintf( filter, sizeof( filter ), lud->lud_filter, + key->bv_val ); + + if ( strcasecmp( lud->lud_attrs[ 0 ], "dn" ) == 0 ) { + attrsonly = 1; + } + rc = ldap_search_s( ld, lud->lud_dn, lud->lud_scope, + filter, lud->lud_attrs, attrsonly, &res ); + if ( rc != LDAP_SUCCESS ) { + ldap_unbind( ld ); + rc = REWRITE_ERR; + goto rc_return; + } + + if ( ldap_count_entries( ld, res ) != 1 ) { + ldap_unbind( ld ); + rc = REWRITE_ERR; + goto rc_return; + } + + entry = ldap_first_entry( ld, res ); + if ( entry == NULL ) { + ldap_msgfree( res ); + ldap_unbind( ld ); + rc = REWRITE_ERR; + goto rc_return; + } + if ( attrsonly == 1 ) { + val->bv_val = ldap_get_dn( ld, entry ); + if ( val->bv_val == NULL ) { + ldap_msgfree( res ); + ldap_unbind( ld ); + rc = REWRITE_ERR; + goto rc_return; + } + } else { + values = ldap_get_values( ld, entry, + lud->lud_attrs[0] ); + if ( values == NULL ) { + ldap_msgfree( res ); + ldap_unbind( ld ); + rc = REWRITE_ERR; + goto rc_return; + } + val->bv_val = strdup( values[ 0 ] ); + ldap_value_free( values ); + } + val->bv_len = strlen( val->bv_val ); + + ldap_msgfree( res ); + ldap_unbind( ld ); + + rc = REWRITE_SUCCESS; + } + } + +rc_return:; + return rc; +} + +int +rewrite_xmap_destroy( + struct rewrite_map **pmap +) +{ + struct rewrite_map *map; + + assert( pmap ); + assert( *pmap ); + + map = *pmap; + + switch ( map->lm_type ) { + case REWRITE_MAP_XPWDMAP: +#ifdef USE_REWRITE_LDAP_PVT_THREADS + --xpasswd_mutex_init; + if ( !xpasswd_mutex_init ) { + ldap_pvt_thread_mutex_destroy( &xpasswd_mutex ); + } +#endif /* USE_REWRITE_LDAP_PVT_THREADS */ + + break; + + case REWRITE_MAP_XFILEMAP: +#ifdef USE_REWRITE_LDAP_PVT_THREADS + ldap_pvt_thread_mutex_lock( &map->lm_mutex ); +#endif /* USE_REWRITE_LDAP_PVT_THREADS */ + + if ( map->lm_args ) { + fclose( ( FILE * )map->lm_args ); + map->lm_args = NULL; + } + +#ifdef USE_REWRITE_LDAP_PVT_THREADS + ldap_pvt_thread_mutex_unlock( &map->lm_mutex ); + ldap_pvt_thread_mutex_destroy( &map->lm_mutex ); +#endif /* USE_REWRITE_LDAP_PVT_THREADS */ + break; + + case REWRITE_MAP_XLDAPMAP: +#ifdef USE_REWRITE_LDAP_PVT_THREADS + ldap_pvt_thread_mutex_lock( &map->lm_mutex ); +#endif /* USE_REWRITE_LDAP_PVT_THREADS */ + + if ( map->lm_args ) { + ldap_free_urldesc( ( LDAPURLDesc * )map->lm_args ); + map->lm_args = NULL; + } + +#ifdef USE_REWRITE_LDAP_PVT_THREADS + ldap_pvt_thread_mutex_unlock( &map->lm_mutex ); + ldap_pvt_thread_mutex_destroy( &map->lm_mutex ); +#endif /* USE_REWRITE_LDAP_PVT_THREADS */ + break; + + default: + break; + + } + + free( map ); + *pmap = NULL; + + return 0; +} + diff --git a/servers/slapd/back-ldap/init.c b/servers/slapd/back-ldap/init.c index fb3d8d676d..327ffc7f4e 100644 --- a/servers/slapd/back-ldap/init.c +++ b/servers/slapd/back-ldap/init.c @@ -198,7 +198,7 @@ ldap_back_db_destroy( } #ifdef ENABLE_REWRITE if (li->rwmap.rwm_rw) { - rewrite_info_delete( li->rwmap.rwm_rw ); + rewrite_info_delete( &li->rwmap.rwm_rw ); } #else /* !ENABLE_REWRITE */ if (li->rwmap.rwm_suffix_massage) { diff --git a/servers/slapd/back-meta/init.c b/servers/slapd/back-meta/init.c index 3f8009a185..c4ac607e38 100644 --- a/servers/slapd/back-meta/init.c +++ b/servers/slapd/back-meta/init.c @@ -147,13 +147,13 @@ meta_back_db_init( cm = (cache_manager *)ch_malloc(sizeof(cache_manager)); if ( cm == NULL ) { - rewrite_info_delete( rwinfo ); + rewrite_info_delete( &rwinfo ); return -1; } qm = (query_manager*)ch_malloc(sizeof(query_manager)); if ( qm == NULL ) { - rewrite_info_delete( rwinfo ); + rewrite_info_delete( &rwinfo ); ch_free( cm ); return -1; } @@ -259,7 +259,7 @@ target_free( free( lt->pseudorootpw.bv_val ); } if ( lt->rwmap.rwm_rw ) { - rewrite_info_delete( lt->rwmap.rwm_rw ); + rewrite_info_delete( <->rwmap.rwm_rw ); } avl_free( lt->rwmap.rwm_oc.remap, NULL ); avl_free( lt->rwmap.rwm_oc.map, mapping_free ); -- 2.39.5