Sync usage with man page.
[netbsd-mini2440.git] / external / bsd / openldap / dist / libraries / librewrite / xmap.c
blob13e6ca9872f0949f8d0b7f7d2f62be9bb23bfcb8
1 /* $OpenLDAP: pkg/ldap/libraries/librewrite/xmap.c,v 1.12.2.3 2008/02/11 23:26:43 kurt Exp $ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 * Copyright 2000-2008 The OpenLDAP Foundation.
5 * All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted only as authorized by the OpenLDAP
9 * Public License.
11 * A copy of this license is available in the file LICENSE in the
12 * top-level directory of the distribution or, alternatively, at
13 * <http://www.OpenLDAP.org/license.html>.
15 /* ACKNOWLEDGEMENT:
16 * This work was initially developed by Pierangelo Masarati for
17 * inclusion in OpenLDAP Software.
20 #include <portable.h>
22 #include <stdio.h>
24 #ifdef HAVE_PWD_H
25 #include <pwd.h>
26 #endif
28 #define LDAP_DEPRECATED 1
29 #include "rewrite-int.h"
30 #include "rewrite-map.h"
33 * Global data
35 #ifdef USE_REWRITE_LDAP_PVT_THREADS
36 ldap_pvt_thread_mutex_t xpasswd_mutex;
37 static int xpasswd_mutex_init = 0;
38 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
41 * Map parsing
42 * NOTE: these are old-fashion maps; new maps will be parsed on separate
43 * config lines, and referred by name.
45 struct rewrite_map *
46 rewrite_xmap_parse(
47 struct rewrite_info *info,
48 const char *s,
49 const char **currpos
52 struct rewrite_map *map;
54 assert( info != NULL );
55 assert( s != NULL );
56 assert( currpos != NULL );
58 Debug( LDAP_DEBUG_ARGS, "rewrite_xmap_parse: %s\n%s%s",
59 s, "", "" );
61 *currpos = NULL;
63 map = calloc( sizeof( struct rewrite_map ), 1 );
64 if ( map == NULL ) {
65 Debug( LDAP_DEBUG_ANY, "rewrite_xmap_parse:"
66 " calloc failed\n%s%s%s", "", "", "" );
67 return NULL;
71 * Experimental passwd map:
72 * replaces the uid with the matching gecos from /etc/passwd file
74 if ( strncasecmp(s, "xpasswd", 7 ) == 0 ) {
75 map->lm_type = REWRITE_MAP_XPWDMAP;
76 map->lm_name = strdup( "xpasswd" );
78 assert( s[7] == '}' );
79 *currpos = s + 8;
81 #ifdef USE_REWRITE_LDAP_PVT_THREADS
82 if ( !xpasswd_mutex_init ) {
83 if ( ldap_pvt_thread_mutex_init( &xpasswd_mutex ) ) {
84 free( map );
85 return NULL;
88 ++xpasswd_mutex_init;
89 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
91 /* Don't really care if fails */
92 return map;
95 * Experimental file map:
96 * looks up key in a `key value' ascii file
98 } else if ( strncasecmp( s, "xfile", 5 ) == 0 ) {
99 char *filename;
100 const char *p;
101 int l;
102 int c = 5;
104 map->lm_type = REWRITE_MAP_XFILEMAP;
106 if ( s[ c ] != '(' ) {
107 free( map );
108 return NULL;
111 /* Must start with '/' for security concerns */
112 c++;
113 if ( s[ c ] != '/' ) {
114 free( map );
115 return NULL;
118 for ( p = s + c; p[ 0 ] != '\0' && p[ 0 ] != ')'; p++ );
119 if ( p[ 0 ] != ')' ) {
120 free( map );
121 return NULL;
124 l = p - s - c;
125 filename = calloc( sizeof( char ), l + 1 );
126 AC_MEMCPY( filename, s + c, l );
127 filename[ l ] = '\0';
129 map->lm_args = ( void * )fopen( filename, "r" );
130 free( filename );
132 if ( map->lm_args == NULL ) {
133 free( map );
134 return NULL;
137 *currpos = p + 1;
139 #ifdef USE_REWRITE_LDAP_PVT_THREADS
140 if ( ldap_pvt_thread_mutex_init( &map->lm_mutex ) ) {
141 fclose( ( FILE * )map->lm_args );
142 free( map );
143 return NULL;
145 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
147 return map;
150 * Experimental ldap map:
151 * looks up key on the fly (not implemented!)
153 } else if ( strncasecmp(s, "xldap", 5 ) == 0 ) {
154 char *p;
155 char *url;
156 int l, rc;
157 int c = 5;
158 LDAPURLDesc *lud;
160 if ( s[ c ] != '(' ) {
161 free( map );
162 return NULL;
164 c++;
166 p = strchr( s, '}' );
167 if ( p == NULL ) {
168 free( map );
169 return NULL;
171 p--;
173 *currpos = p + 2;
176 * Add two bytes for urlencoding of '%s'
178 l = p - s - c;
179 url = calloc( sizeof( char ), l + 3 );
180 AC_MEMCPY( url, s + c, l );
181 url[ l ] = '\0';
184 * Urlencodes the '%s' for ldap_url_parse
186 p = strchr( url, '%' );
187 if ( p != NULL ) {
188 AC_MEMCPY( p + 3, p + 1, strlen( p + 1 ) + 1 );
189 p[ 1 ] = '2';
190 p[ 2 ] = '5';
193 rc = ldap_url_parse( url, &lud );
194 free( url );
196 if ( rc != LDAP_SUCCESS ) {
197 free( map );
198 return NULL;
200 assert( lud != NULL );
202 map->lm_args = ( void * )lud;
203 map->lm_type = REWRITE_MAP_XLDAPMAP;
205 #ifdef USE_REWRITE_LDAP_PVT_THREADS
206 if ( ldap_pvt_thread_mutex_init( &map->lm_mutex ) ) {
207 ldap_free_urldesc( lud );
208 free( map );
209 return NULL;
211 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
213 return map;
215 /* Unhandled map */
218 free( map );
219 return NULL;
223 * Map key -> value resolution
224 * NOTE: these are old-fashion maps; new maps will be parsed on separate
225 * config lines, and referred by name.
228 rewrite_xmap_apply(
229 struct rewrite_info *info,
230 struct rewrite_op *op,
231 struct rewrite_map *map,
232 struct berval *key,
233 struct berval *val
236 int rc = REWRITE_SUCCESS;
238 assert( info != NULL );
239 assert( op != NULL );
240 assert( map != NULL );
241 assert( key != NULL );
242 assert( val != NULL );
244 val->bv_val = NULL;
245 val->bv_len = 0;
247 switch ( map->lm_type ) {
248 #ifdef HAVE_GETPWNAM
249 case REWRITE_MAP_XPWDMAP: {
250 struct passwd *pwd;
252 #ifdef USE_REWRITE_LDAP_PVT_THREADS
253 ldap_pvt_thread_mutex_lock( &xpasswd_mutex );
254 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
256 pwd = getpwnam( key->bv_val );
257 if ( pwd == NULL ) {
259 #ifdef USE_REWRITE_LDAP_PVT_THREADS
260 ldap_pvt_thread_mutex_unlock( &xpasswd_mutex );
261 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
263 rc = LDAP_NO_SUCH_OBJECT;
264 break;
267 #ifdef HAVE_STRUCT_PASSWD_PW_GECOS
268 if ( pwd->pw_gecos != NULL && pwd->pw_gecos[0] != '\0' ) {
269 int l = strlen( pwd->pw_gecos );
271 val->bv_val = strdup( pwd->pw_gecos );
272 if ( val->bv_val == NULL ) {
274 #ifdef USE_REWRITE_LDAP_PVT_THREADS
275 ldap_pvt_thread_mutex_unlock( &xpasswd_mutex );
276 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
278 rc = REWRITE_ERR;
279 break;
281 val->bv_len = l;
282 } else
283 #endif /* HAVE_STRUCT_PASSWD_PW_GECOS */
285 val->bv_val = strdup( key->bv_val );
286 val->bv_len = key->bv_len;
289 #ifdef USE_REWRITE_LDAP_PVT_THREADS
290 ldap_pvt_thread_mutex_unlock( &xpasswd_mutex );
291 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
293 break;
295 #endif /* HAVE_GETPWNAM*/
297 case REWRITE_MAP_XFILEMAP: {
298 char buf[1024];
300 if ( map->lm_args == NULL ) {
301 rc = REWRITE_ERR;
302 break;
305 #ifdef USE_REWRITE_LDAP_PVT_THREADS
306 ldap_pvt_thread_mutex_lock( &map->lm_mutex );
307 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
309 rewind( ( FILE * )map->lm_args );
311 while ( fgets( buf, sizeof( buf ), ( FILE * )map->lm_args ) ) {
312 char *p;
313 int blen;
315 blen = strlen( buf );
316 if ( buf[ blen - 1 ] == '\n' ) {
317 buf[ blen - 1 ] = '\0';
320 p = strtok( buf, " " );
321 if ( p == NULL ) {
322 #ifdef USE_REWRITE_LDAP_PVT_THREADS
323 ldap_pvt_thread_mutex_unlock( &map->lm_mutex );
324 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
325 rc = REWRITE_ERR;
326 goto rc_return;
328 if ( strcasecmp( p, key->bv_val ) == 0
329 && ( p = strtok( NULL, "" ) ) ) {
330 val->bv_val = strdup( p );
331 if ( val->bv_val == NULL ) {
332 return REWRITE_ERR;
335 val->bv_len = strlen( p );
337 #ifdef USE_REWRITE_LDAP_PVT_THREADS
338 ldap_pvt_thread_mutex_unlock( &map->lm_mutex );
339 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
341 goto rc_return;
345 #ifdef USE_REWRITE_LDAP_PVT_THREADS
346 ldap_pvt_thread_mutex_unlock( &map->lm_mutex );
347 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
349 rc = REWRITE_ERR;
351 break;
354 case REWRITE_MAP_XLDAPMAP: {
355 LDAP *ld;
356 char filter[1024];
357 LDAPMessage *res = NULL, *entry;
358 LDAPURLDesc *lud = ( LDAPURLDesc * )map->lm_args;
359 int attrsonly = 0;
360 char **values;
362 assert( lud != NULL );
365 * No mutex because there is no write on the map data
368 ld = ldap_init( lud->lud_host, lud->lud_port );
369 if ( ld == NULL ) {
370 rc = REWRITE_ERR;
371 goto rc_return;
374 snprintf( filter, sizeof( filter ), lud->lud_filter,
375 key->bv_val );
377 if ( strcasecmp( lud->lud_attrs[ 0 ], "dn" ) == 0 ) {
378 attrsonly = 1;
380 rc = ldap_search_s( ld, lud->lud_dn, lud->lud_scope,
381 filter, lud->lud_attrs, attrsonly, &res );
382 if ( rc != LDAP_SUCCESS ) {
383 ldap_unbind( ld );
384 rc = REWRITE_ERR;
385 goto rc_return;
388 if ( ldap_count_entries( ld, res ) != 1 ) {
389 ldap_unbind( ld );
390 rc = REWRITE_ERR;
391 goto rc_return;
394 entry = ldap_first_entry( ld, res );
395 if ( entry == NULL ) {
396 ldap_msgfree( res );
397 ldap_unbind( ld );
398 rc = REWRITE_ERR;
399 goto rc_return;
401 if ( attrsonly == 1 ) {
402 val->bv_val = ldap_get_dn( ld, entry );
403 if ( val->bv_val == NULL ) {
404 ldap_msgfree( res );
405 ldap_unbind( ld );
406 rc = REWRITE_ERR;
407 goto rc_return;
409 } else {
410 values = ldap_get_values( ld, entry,
411 lud->lud_attrs[0] );
412 if ( values == NULL ) {
413 ldap_msgfree( res );
414 ldap_unbind( ld );
415 rc = REWRITE_ERR;
416 goto rc_return;
418 val->bv_val = strdup( values[ 0 ] );
419 ldap_value_free( values );
421 val->bv_len = strlen( val->bv_val );
423 ldap_msgfree( res );
424 ldap_unbind( ld );
426 rc = REWRITE_SUCCESS;
430 rc_return:;
431 return rc;
435 rewrite_xmap_destroy(
436 struct rewrite_map **pmap
439 struct rewrite_map *map;
441 assert( pmap != NULL );
442 assert( *pmap != NULL );
444 map = *pmap;
446 switch ( map->lm_type ) {
447 case REWRITE_MAP_XPWDMAP:
448 #ifdef USE_REWRITE_LDAP_PVT_THREADS
449 --xpasswd_mutex_init;
450 if ( !xpasswd_mutex_init ) {
451 ldap_pvt_thread_mutex_destroy( &xpasswd_mutex );
453 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
455 break;
457 case REWRITE_MAP_XFILEMAP:
458 #ifdef USE_REWRITE_LDAP_PVT_THREADS
459 ldap_pvt_thread_mutex_lock( &map->lm_mutex );
460 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
462 if ( map->lm_args ) {
463 fclose( ( FILE * )map->lm_args );
464 map->lm_args = NULL;
467 #ifdef USE_REWRITE_LDAP_PVT_THREADS
468 ldap_pvt_thread_mutex_unlock( &map->lm_mutex );
469 ldap_pvt_thread_mutex_destroy( &map->lm_mutex );
470 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
471 break;
473 case REWRITE_MAP_XLDAPMAP:
474 #ifdef USE_REWRITE_LDAP_PVT_THREADS
475 ldap_pvt_thread_mutex_lock( &map->lm_mutex );
476 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
478 if ( map->lm_args ) {
479 ldap_free_urldesc( ( LDAPURLDesc * )map->lm_args );
480 map->lm_args = NULL;
483 #ifdef USE_REWRITE_LDAP_PVT_THREADS
484 ldap_pvt_thread_mutex_unlock( &map->lm_mutex );
485 ldap_pvt_thread_mutex_destroy( &map->lm_mutex );
486 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
487 break;
489 default:
490 break;
494 free( map->lm_name );
495 free( map );
496 *pmap = NULL;
498 return 0;