Commit a3deda80 authored by Pierangelo Masarati's avatar Pierangelo Masarati
Browse files

fix a number of mem leaks; add destroy code; HEADS-UP: API change in rewrite_info_delete()

parent e6174878
......@@ -96,7 +96,7 @@ rewrite_info_init(
*/
LDAP_REWRITE_F (int)
rewrite_info_delete(
struct rewrite_info *info
struct rewrite_info **info
);
......
......@@ -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
......
......@@ -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 ] : "" ) );
/*
......
......@@ -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;
}
......@@ -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;
}
......
......@@ -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 */