xref: /netbsd-src/external/bsd/openldap/dist/libraries/librewrite/xmap.c (revision 549b59ed3ccf0d36d3097190a0db27b770f3a839)
1*549b59edSchristos /*	$NetBSD: xmap.c,v 1.3 2021/08/14 16:14:58 christos Exp $	*/
24e6df137Slukem 
3d11b170bStron /* $OpenLDAP$ */
42de962bdSlukem /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
52de962bdSlukem  *
6*549b59edSchristos  * Copyright 2000-2021 The OpenLDAP Foundation.
72de962bdSlukem  * All rights reserved.
82de962bdSlukem  *
92de962bdSlukem  * Redistribution and use in source and binary forms, with or without
102de962bdSlukem  * modification, are permitted only as authorized by the OpenLDAP
112de962bdSlukem  * Public License.
122de962bdSlukem  *
132de962bdSlukem  * A copy of this license is available in the file LICENSE in the
142de962bdSlukem  * top-level directory of the distribution or, alternatively, at
152de962bdSlukem  * <http://www.OpenLDAP.org/license.html>.
162de962bdSlukem  */
172de962bdSlukem /* ACKNOWLEDGEMENT:
182de962bdSlukem  * This work was initially developed by Pierangelo Masarati for
192de962bdSlukem  * inclusion in OpenLDAP Software.
202de962bdSlukem  */
212de962bdSlukem 
222de962bdSlukem #include <portable.h>
232de962bdSlukem 
242de962bdSlukem #include <stdio.h>
252de962bdSlukem 
262de962bdSlukem #ifdef HAVE_PWD_H
272de962bdSlukem #include <pwd.h>
282de962bdSlukem #endif
292de962bdSlukem 
302de962bdSlukem #define LDAP_DEPRECATED 1
312de962bdSlukem #include "rewrite-int.h"
322de962bdSlukem #include "rewrite-map.h"
332de962bdSlukem 
342de962bdSlukem /*
352de962bdSlukem  * Global data
362de962bdSlukem  */
372de962bdSlukem #ifdef USE_REWRITE_LDAP_PVT_THREADS
382de962bdSlukem ldap_pvt_thread_mutex_t xpasswd_mutex;
392de962bdSlukem static int xpasswd_mutex_init = 0;
402de962bdSlukem #endif /* USE_REWRITE_LDAP_PVT_THREADS */
412de962bdSlukem 
422de962bdSlukem /*
432de962bdSlukem  * Map parsing
442de962bdSlukem  * NOTE: these are old-fashion maps; new maps will be parsed on separate
452de962bdSlukem  * config lines, and referred by name.
462de962bdSlukem  */
472de962bdSlukem struct rewrite_map *
rewrite_xmap_parse(struct rewrite_info * info,const char * s,const char ** currpos)482de962bdSlukem rewrite_xmap_parse(
492de962bdSlukem 		struct rewrite_info *info,
502de962bdSlukem 		const char *s,
512de962bdSlukem 		const char **currpos
522de962bdSlukem )
532de962bdSlukem {
542de962bdSlukem 	struct rewrite_map *map;
552de962bdSlukem 
562de962bdSlukem 	assert( info != NULL );
572de962bdSlukem 	assert( s != NULL );
582de962bdSlukem 	assert( currpos != NULL );
592de962bdSlukem 
60*549b59edSchristos 	Debug( LDAP_DEBUG_ARGS, "rewrite_xmap_parse: %s\n",
61*549b59edSchristos 			s );
622de962bdSlukem 
632de962bdSlukem 	*currpos = NULL;
642de962bdSlukem 
652de962bdSlukem 	map = calloc( sizeof( struct rewrite_map ), 1 );
662de962bdSlukem 	if ( map == NULL ) {
672de962bdSlukem 		Debug( LDAP_DEBUG_ANY, "rewrite_xmap_parse:"
68*549b59edSchristos 				" calloc failed\n" );
692de962bdSlukem 		return NULL;
702de962bdSlukem 	}
712de962bdSlukem 
722de962bdSlukem 	/*
732de962bdSlukem 	 * Experimental passwd map:
742de962bdSlukem 	 * replaces the uid with the matching gecos from /etc/passwd file
752de962bdSlukem 	 */
762de962bdSlukem 	if ( strncasecmp(s, "xpasswd", 7 ) == 0 ) {
772de962bdSlukem 		map->lm_type = REWRITE_MAP_XPWDMAP;
782de962bdSlukem 		map->lm_name = strdup( "xpasswd" );
794e6df137Slukem 		if ( map->lm_name == NULL ) {
804e6df137Slukem 			free( map );
814e6df137Slukem 			return NULL;
824e6df137Slukem 		}
832de962bdSlukem 
842de962bdSlukem 		assert( s[7] == '}' );
852de962bdSlukem 		*currpos = s + 8;
862de962bdSlukem 
872de962bdSlukem #ifdef USE_REWRITE_LDAP_PVT_THREADS
882de962bdSlukem 		if ( !xpasswd_mutex_init ) {
892de962bdSlukem 			if ( ldap_pvt_thread_mutex_init( &xpasswd_mutex ) ) {
902de962bdSlukem 				free( map );
912de962bdSlukem 				return NULL;
922de962bdSlukem 			}
932de962bdSlukem 		}
942de962bdSlukem 		++xpasswd_mutex_init;
952de962bdSlukem #endif /* USE_REWRITE_LDAP_PVT_THREADS */
962de962bdSlukem 
972de962bdSlukem 		/* Don't really care if fails */
982de962bdSlukem 		return map;
992de962bdSlukem 
1002de962bdSlukem 	/*
1012de962bdSlukem 	 * Experimental file map:
1022de962bdSlukem 	 * looks up key in a `key value' ascii file
1032de962bdSlukem 	 */
1042de962bdSlukem 	} else if ( strncasecmp( s, "xfile", 5 ) == 0 ) {
1052de962bdSlukem 		char *filename;
1062de962bdSlukem 		const char *p;
1072de962bdSlukem 		int l;
1082de962bdSlukem 		int c = 5;
1092de962bdSlukem 
1102de962bdSlukem 		map->lm_type = REWRITE_MAP_XFILEMAP;
1112de962bdSlukem 
1122de962bdSlukem 		if ( s[ c ] != '(' ) {
1132de962bdSlukem 			free( map );
1142de962bdSlukem 			return NULL;
1152de962bdSlukem 		}
1162de962bdSlukem 
1172de962bdSlukem 		/* Must start with '/' for security concerns */
1182de962bdSlukem 		c++;
1192de962bdSlukem 		if ( s[ c ] != '/' ) {
1202de962bdSlukem 			free( map );
1212de962bdSlukem 			return NULL;
1222de962bdSlukem 		}
1232de962bdSlukem 
1242de962bdSlukem 		for ( p = s + c; p[ 0 ] != '\0' && p[ 0 ] != ')'; p++ );
1252de962bdSlukem 		if ( p[ 0 ] != ')' ) {
1262de962bdSlukem 			free( map );
1272de962bdSlukem 			return NULL;
1282de962bdSlukem 		}
1292de962bdSlukem 
1302de962bdSlukem 		l = p - s - c;
1312de962bdSlukem 		filename = calloc( sizeof( char ), l + 1 );
1324e6df137Slukem 		if ( filename == NULL ) {
1334e6df137Slukem 			free( map );
1344e6df137Slukem 			return NULL;
1354e6df137Slukem 		}
1362de962bdSlukem 		AC_MEMCPY( filename, s + c, l );
1372de962bdSlukem 		filename[ l ] = '\0';
1382de962bdSlukem 
1392de962bdSlukem 		map->lm_args = ( void * )fopen( filename, "r" );
1402de962bdSlukem 		free( filename );
1412de962bdSlukem 
1422de962bdSlukem 		if ( map->lm_args == NULL ) {
1432de962bdSlukem 			free( map );
1442de962bdSlukem 			return NULL;
1452de962bdSlukem 		}
1462de962bdSlukem 
1472de962bdSlukem 		*currpos = p + 1;
1482de962bdSlukem 
1492de962bdSlukem #ifdef USE_REWRITE_LDAP_PVT_THREADS
1502de962bdSlukem                 if ( ldap_pvt_thread_mutex_init( &map->lm_mutex ) ) {
1512de962bdSlukem 			fclose( ( FILE * )map->lm_args );
1522de962bdSlukem 			free( map );
1532de962bdSlukem 			return NULL;
1542de962bdSlukem 		}
1552de962bdSlukem #endif /* USE_REWRITE_LDAP_PVT_THREADS */
1562de962bdSlukem 
1572de962bdSlukem 		return map;
1582de962bdSlukem 
1592de962bdSlukem 	/*
1602de962bdSlukem          * Experimental ldap map:
1612de962bdSlukem          * looks up key on the fly (not implemented!)
1622de962bdSlukem          */
1632de962bdSlukem         } else if ( strncasecmp(s, "xldap", 5 ) == 0 ) {
1642de962bdSlukem 		char *p;
1652de962bdSlukem 		char *url;
1662de962bdSlukem 		int l, rc;
1672de962bdSlukem 		int c = 5;
1682de962bdSlukem 		LDAPURLDesc *lud;
1692de962bdSlukem 
1702de962bdSlukem 		if ( s[ c ] != '(' ) {
1712de962bdSlukem 			free( map );
1722de962bdSlukem 			return NULL;
1732de962bdSlukem 		}
1742de962bdSlukem 		c++;
1752de962bdSlukem 
1762de962bdSlukem 		p = strchr( s, '}' );
1772de962bdSlukem 		if ( p == NULL ) {
1782de962bdSlukem 			free( map );
1792de962bdSlukem 			return NULL;
1802de962bdSlukem 		}
1812de962bdSlukem 		p--;
1822de962bdSlukem 
1832de962bdSlukem 		*currpos = p + 2;
1842de962bdSlukem 
1852de962bdSlukem 		/*
1862de962bdSlukem 		 * Add two bytes for urlencoding of '%s'
1872de962bdSlukem 		 */
1882de962bdSlukem 		l = p - s - c;
1892de962bdSlukem 		url = calloc( sizeof( char ), l + 3 );
1904e6df137Slukem 		if ( url == NULL ) {
1914e6df137Slukem 			free( map );
1924e6df137Slukem 			return NULL;
1934e6df137Slukem 		}
1942de962bdSlukem 		AC_MEMCPY( url, s + c, l );
1952de962bdSlukem 		url[ l ] = '\0';
1962de962bdSlukem 
1972de962bdSlukem 		/*
1982de962bdSlukem 		 * Urlencodes the '%s' for ldap_url_parse
1992de962bdSlukem 		 */
2002de962bdSlukem 		p = strchr( url, '%' );
2012de962bdSlukem 		if ( p != NULL ) {
2022de962bdSlukem 			AC_MEMCPY( p + 3, p + 1, strlen( p + 1 ) + 1 );
2032de962bdSlukem 			p[ 1 ] = '2';
2042de962bdSlukem 			p[ 2 ] = '5';
2052de962bdSlukem 		}
2062de962bdSlukem 
2072de962bdSlukem 		rc =  ldap_url_parse( url, &lud );
2082de962bdSlukem 		free( url );
2092de962bdSlukem 
2102de962bdSlukem 		if ( rc != LDAP_SUCCESS ) {
2112de962bdSlukem 			free( map );
2122de962bdSlukem 			return NULL;
2132de962bdSlukem 		}
2142de962bdSlukem 		assert( lud != NULL );
2152de962bdSlukem 
2162de962bdSlukem 		map->lm_args = ( void * )lud;
2172de962bdSlukem 		map->lm_type = REWRITE_MAP_XLDAPMAP;
2182de962bdSlukem 
2192de962bdSlukem #ifdef USE_REWRITE_LDAP_PVT_THREADS
2202de962bdSlukem                 if ( ldap_pvt_thread_mutex_init( &map->lm_mutex ) ) {
2212de962bdSlukem 			ldap_free_urldesc( lud );
2222de962bdSlukem 			free( map );
2232de962bdSlukem 			return NULL;
2242de962bdSlukem 		}
2252de962bdSlukem #endif /* USE_REWRITE_LDAP_PVT_THREADS */
2262de962bdSlukem 
2272de962bdSlukem 		return map;
2282de962bdSlukem 
2292de962bdSlukem 	/* Unhandled map */
2302de962bdSlukem 	}
2312de962bdSlukem 
2322de962bdSlukem 	free( map );
2332de962bdSlukem 	return NULL;
2342de962bdSlukem }
2352de962bdSlukem 
2362de962bdSlukem /*
2372de962bdSlukem  * Map key -> value resolution
2382de962bdSlukem  * NOTE: these are old-fashion maps; new maps will be parsed on separate
2392de962bdSlukem  * config lines, and referred by name.
2402de962bdSlukem  */
2412de962bdSlukem int
rewrite_xmap_apply(struct rewrite_info * info,struct rewrite_op * op,struct rewrite_map * map,struct berval * key,struct berval * val)2422de962bdSlukem rewrite_xmap_apply(
2432de962bdSlukem 		struct rewrite_info *info,
2442de962bdSlukem 		struct rewrite_op *op,
2452de962bdSlukem 		struct rewrite_map *map,
2462de962bdSlukem 		struct berval *key,
2472de962bdSlukem 		struct berval *val
2482de962bdSlukem )
2492de962bdSlukem {
2502de962bdSlukem 	int rc = REWRITE_SUCCESS;
2512de962bdSlukem 
2522de962bdSlukem 	assert( info != NULL );
2532de962bdSlukem 	assert( op != NULL );
2542de962bdSlukem 	assert( map != NULL );
2552de962bdSlukem 	assert( key != NULL );
2562de962bdSlukem 	assert( val != NULL );
2572de962bdSlukem 
2582de962bdSlukem 	val->bv_val = NULL;
2592de962bdSlukem 	val->bv_len = 0;
2602de962bdSlukem 
2612de962bdSlukem 	switch ( map->lm_type ) {
2622de962bdSlukem #ifdef HAVE_GETPWNAM
2632de962bdSlukem 	case REWRITE_MAP_XPWDMAP: {
2642de962bdSlukem 		struct passwd *pwd;
2652de962bdSlukem 
2662de962bdSlukem #ifdef USE_REWRITE_LDAP_PVT_THREADS
2672de962bdSlukem 		ldap_pvt_thread_mutex_lock( &xpasswd_mutex );
2682de962bdSlukem #endif /* USE_REWRITE_LDAP_PVT_THREADS */
2692de962bdSlukem 
2702de962bdSlukem 		pwd = getpwnam( key->bv_val );
2712de962bdSlukem 		if ( pwd == NULL ) {
2722de962bdSlukem 
2732de962bdSlukem #ifdef USE_REWRITE_LDAP_PVT_THREADS
2742de962bdSlukem 			ldap_pvt_thread_mutex_unlock( &xpasswd_mutex );
2752de962bdSlukem #endif /* USE_REWRITE_LDAP_PVT_THREADS */
2762de962bdSlukem 
2772de962bdSlukem 			rc = LDAP_NO_SUCH_OBJECT;
2782de962bdSlukem 			break;
2792de962bdSlukem 		}
2802de962bdSlukem 
2812de962bdSlukem #ifdef HAVE_STRUCT_PASSWD_PW_GECOS
2822de962bdSlukem 		if ( pwd->pw_gecos != NULL && pwd->pw_gecos[0] != '\0' ) {
2832de962bdSlukem 			int l = strlen( pwd->pw_gecos );
2842de962bdSlukem 
2852de962bdSlukem 			val->bv_val = strdup( pwd->pw_gecos );
2862de962bdSlukem 			val->bv_len = l;
2872de962bdSlukem 		} else
2882de962bdSlukem #endif /* HAVE_STRUCT_PASSWD_PW_GECOS */
2892de962bdSlukem 		{
2902de962bdSlukem 			val->bv_val = strdup( key->bv_val );
2912de962bdSlukem 			val->bv_len = key->bv_len;
2922de962bdSlukem 		}
2932de962bdSlukem 
2942de962bdSlukem #ifdef USE_REWRITE_LDAP_PVT_THREADS
2952de962bdSlukem 		ldap_pvt_thread_mutex_unlock( &xpasswd_mutex );
2962de962bdSlukem #endif /* USE_REWRITE_LDAP_PVT_THREADS */
2972de962bdSlukem 
2984e6df137Slukem 		if ( val->bv_val == NULL ) {
2994e6df137Slukem 			rc = REWRITE_ERR;
3004e6df137Slukem 		}
3012de962bdSlukem 		break;
3022de962bdSlukem 	}
3032de962bdSlukem #endif /* HAVE_GETPWNAM*/
3042de962bdSlukem 
3052de962bdSlukem 	case REWRITE_MAP_XFILEMAP: {
3062de962bdSlukem 		char buf[1024];
3072de962bdSlukem 
3082de962bdSlukem 		if ( map->lm_args == NULL ) {
3092de962bdSlukem 			rc = REWRITE_ERR;
3102de962bdSlukem 			break;
3112de962bdSlukem 		}
3122de962bdSlukem 
3132de962bdSlukem #ifdef USE_REWRITE_LDAP_PVT_THREADS
3142de962bdSlukem 		ldap_pvt_thread_mutex_lock( &map->lm_mutex );
3152de962bdSlukem #endif /* USE_REWRITE_LDAP_PVT_THREADS */
3162de962bdSlukem 
3172de962bdSlukem 		rewind( ( FILE * )map->lm_args );
3182de962bdSlukem 
3192de962bdSlukem 		while ( fgets( buf, sizeof( buf ), ( FILE * )map->lm_args ) ) {
3202de962bdSlukem 			char *p;
3212de962bdSlukem 			int blen;
3222de962bdSlukem 
3232de962bdSlukem 			blen = strlen( buf );
3242de962bdSlukem 			if ( buf[ blen - 1 ] == '\n' ) {
3252de962bdSlukem 				buf[ blen - 1 ] = '\0';
3262de962bdSlukem 			}
3272de962bdSlukem 
3282de962bdSlukem 			p = strtok( buf, " " );
3292de962bdSlukem 			if ( p == NULL ) {
3302de962bdSlukem #ifdef USE_REWRITE_LDAP_PVT_THREADS
3312de962bdSlukem 				ldap_pvt_thread_mutex_unlock( &map->lm_mutex );
3322de962bdSlukem #endif /* USE_REWRITE_LDAP_PVT_THREADS */
3332de962bdSlukem 				rc = REWRITE_ERR;
3342de962bdSlukem 				goto rc_return;
3352de962bdSlukem 			}
3362de962bdSlukem 			if ( strcasecmp( p, key->bv_val ) == 0
3372de962bdSlukem 					&& ( p = strtok( NULL, "" ) ) ) {
3382de962bdSlukem 				val->bv_val = strdup( p );
3392de962bdSlukem 				if ( val->bv_val == NULL ) {
340376af7d7Schristos #ifdef USE_REWRITE_LDAP_PVT_THREADS
341376af7d7Schristos 					ldap_pvt_thread_mutex_unlock( &map->lm_mutex );
342376af7d7Schristos #endif /* USE_REWRITE_LDAP_PVT_THREADS */
343376af7d7Schristos 					rc = REWRITE_ERR;
344376af7d7Schristos 					goto rc_return;
3452de962bdSlukem 				}
3462de962bdSlukem 
3472de962bdSlukem 				val->bv_len = strlen( p );
3482de962bdSlukem 
3492de962bdSlukem #ifdef USE_REWRITE_LDAP_PVT_THREADS
3502de962bdSlukem 				ldap_pvt_thread_mutex_unlock( &map->lm_mutex );
3512de962bdSlukem #endif /* USE_REWRITE_LDAP_PVT_THREADS */
3522de962bdSlukem 
3532de962bdSlukem 				goto rc_return;
3542de962bdSlukem 			}
3552de962bdSlukem 		}
3562de962bdSlukem 
3572de962bdSlukem #ifdef USE_REWRITE_LDAP_PVT_THREADS
3582de962bdSlukem 		ldap_pvt_thread_mutex_unlock( &map->lm_mutex );
3592de962bdSlukem #endif /* USE_REWRITE_LDAP_PVT_THREADS */
3602de962bdSlukem 
3612de962bdSlukem 		rc = REWRITE_ERR;
3622de962bdSlukem 
3632de962bdSlukem 		break;
3642de962bdSlukem 	}
3652de962bdSlukem 
3662de962bdSlukem 	case REWRITE_MAP_XLDAPMAP: {
3672de962bdSlukem 		LDAP *ld;
3682de962bdSlukem 		char filter[1024];
3692de962bdSlukem 		LDAPMessage *res = NULL, *entry;
3702de962bdSlukem 		LDAPURLDesc *lud = ( LDAPURLDesc * )map->lm_args;
3712de962bdSlukem 		int attrsonly = 0;
3722de962bdSlukem 		char **values;
3732de962bdSlukem 
3742de962bdSlukem 		assert( lud != NULL );
3752de962bdSlukem 
3762de962bdSlukem 		/*
3772de962bdSlukem 		 * No mutex because there is no write on the map data
3782de962bdSlukem 		 */
3792de962bdSlukem 
3802de962bdSlukem 		ld = ldap_init( lud->lud_host, lud->lud_port );
3812de962bdSlukem 		if ( ld == NULL ) {
3822de962bdSlukem 			rc = REWRITE_ERR;
3832de962bdSlukem 			goto rc_return;
3842de962bdSlukem 		}
3852de962bdSlukem 
3862de962bdSlukem 		snprintf( filter, sizeof( filter ), lud->lud_filter,
3872de962bdSlukem 				key->bv_val );
3882de962bdSlukem 
3892de962bdSlukem 		if ( strcasecmp( lud->lud_attrs[ 0 ], "dn" ) == 0 ) {
3902de962bdSlukem 			attrsonly = 1;
3912de962bdSlukem 		}
3922de962bdSlukem 		rc = ldap_search_s( ld, lud->lud_dn, lud->lud_scope,
3932de962bdSlukem 				filter, lud->lud_attrs, attrsonly, &res );
3942de962bdSlukem 		if ( rc != LDAP_SUCCESS ) {
3952de962bdSlukem 			ldap_unbind( ld );
3962de962bdSlukem 			rc = REWRITE_ERR;
3972de962bdSlukem 			goto rc_return;
3982de962bdSlukem 		}
3992de962bdSlukem 
4002de962bdSlukem 		if ( ldap_count_entries( ld, res ) != 1 ) {
4012de962bdSlukem 			ldap_unbind( ld );
4022de962bdSlukem 			rc = REWRITE_ERR;
4032de962bdSlukem 			goto rc_return;
4042de962bdSlukem 		}
4052de962bdSlukem 
4062de962bdSlukem 		entry = ldap_first_entry( ld, res );
4072de962bdSlukem 		if ( entry == NULL ) {
4082de962bdSlukem 			ldap_msgfree( res );
4092de962bdSlukem 			ldap_unbind( ld );
4102de962bdSlukem 			rc = REWRITE_ERR;
4112de962bdSlukem 			goto rc_return;
4122de962bdSlukem 		}
4132de962bdSlukem 		if ( attrsonly == 1 ) {
4142de962bdSlukem 			val->bv_val = ldap_get_dn( ld, entry );
4154e6df137Slukem 
4162de962bdSlukem 		} else {
4172de962bdSlukem 			values = ldap_get_values( ld, entry,
4182de962bdSlukem 					lud->lud_attrs[0] );
4194e6df137Slukem 			if ( values != NULL ) {
4202de962bdSlukem 				val->bv_val = strdup( values[ 0 ] );
4212de962bdSlukem 				ldap_value_free( values );
4222de962bdSlukem 			}
4234e6df137Slukem 		}
4242de962bdSlukem 
4252de962bdSlukem 		ldap_msgfree( res );
4262de962bdSlukem 		ldap_unbind( ld );
4272de962bdSlukem 
4284e6df137Slukem 		if ( val->bv_val == NULL ) {
4294e6df137Slukem 			rc = REWRITE_ERR;
4304e6df137Slukem 			goto rc_return;
4312de962bdSlukem 		}
4324e6df137Slukem 		val->bv_len = strlen( val->bv_val );
4334e6df137Slukem 
4344e6df137Slukem 		rc = REWRITE_SUCCESS;
4354e6df137Slukem 	} break;
4362de962bdSlukem 	}
4372de962bdSlukem 
4382de962bdSlukem rc_return:;
4392de962bdSlukem 	return rc;
4402de962bdSlukem }
4412de962bdSlukem 
4422de962bdSlukem int
rewrite_xmap_destroy(struct rewrite_map ** pmap)4432de962bdSlukem rewrite_xmap_destroy(
4442de962bdSlukem 		struct rewrite_map **pmap
4452de962bdSlukem )
4462de962bdSlukem {
4472de962bdSlukem 	struct rewrite_map *map;
4482de962bdSlukem 
4492de962bdSlukem 	assert( pmap != NULL );
4502de962bdSlukem 	assert( *pmap != NULL );
4512de962bdSlukem 
4522de962bdSlukem 	map = *pmap;
4532de962bdSlukem 
4542de962bdSlukem 	switch ( map->lm_type ) {
4552de962bdSlukem 	case REWRITE_MAP_XPWDMAP:
4562de962bdSlukem #ifdef USE_REWRITE_LDAP_PVT_THREADS
4572de962bdSlukem 		--xpasswd_mutex_init;
4582de962bdSlukem 		if ( !xpasswd_mutex_init ) {
4592de962bdSlukem 			ldap_pvt_thread_mutex_destroy( &xpasswd_mutex );
4602de962bdSlukem 		}
4612de962bdSlukem #endif /* USE_REWRITE_LDAP_PVT_THREADS */
4622de962bdSlukem 
4632de962bdSlukem 		break;
4642de962bdSlukem 
4652de962bdSlukem 	case REWRITE_MAP_XFILEMAP:
4662de962bdSlukem #ifdef USE_REWRITE_LDAP_PVT_THREADS
4672de962bdSlukem 		ldap_pvt_thread_mutex_lock( &map->lm_mutex );
4682de962bdSlukem #endif /* USE_REWRITE_LDAP_PVT_THREADS */
4692de962bdSlukem 
4702de962bdSlukem 		if ( map->lm_args ) {
4712de962bdSlukem 			fclose( ( FILE * )map->lm_args );
4722de962bdSlukem 			map->lm_args = NULL;
4732de962bdSlukem 		}
4742de962bdSlukem 
4752de962bdSlukem #ifdef USE_REWRITE_LDAP_PVT_THREADS
4762de962bdSlukem 		ldap_pvt_thread_mutex_unlock( &map->lm_mutex );
4772de962bdSlukem 		ldap_pvt_thread_mutex_destroy( &map->lm_mutex );
4782de962bdSlukem #endif /* USE_REWRITE_LDAP_PVT_THREADS */
4792de962bdSlukem 		break;
4802de962bdSlukem 
4812de962bdSlukem 	case REWRITE_MAP_XLDAPMAP:
4822de962bdSlukem #ifdef USE_REWRITE_LDAP_PVT_THREADS
4832de962bdSlukem 		ldap_pvt_thread_mutex_lock( &map->lm_mutex );
4842de962bdSlukem #endif /* USE_REWRITE_LDAP_PVT_THREADS */
4852de962bdSlukem 
4862de962bdSlukem 		if ( map->lm_args ) {
4872de962bdSlukem 			ldap_free_urldesc( ( LDAPURLDesc * )map->lm_args );
4882de962bdSlukem 			map->lm_args = NULL;
4892de962bdSlukem 		}
4902de962bdSlukem 
4912de962bdSlukem #ifdef USE_REWRITE_LDAP_PVT_THREADS
4922de962bdSlukem 		ldap_pvt_thread_mutex_unlock( &map->lm_mutex );
4932de962bdSlukem 		ldap_pvt_thread_mutex_destroy( &map->lm_mutex );
4942de962bdSlukem #endif /* USE_REWRITE_LDAP_PVT_THREADS */
4952de962bdSlukem 		break;
4962de962bdSlukem 
4972de962bdSlukem 	default:
4982de962bdSlukem 		break;
4992de962bdSlukem 
5002de962bdSlukem 	}
5012de962bdSlukem 
5022de962bdSlukem 	free( map->lm_name );
5032de962bdSlukem 	free( map );
5042de962bdSlukem 	*pmap = NULL;
5052de962bdSlukem 
5062de962bdSlukem 	return 0;
5072de962bdSlukem }
5082de962bdSlukem 
509