]> git.sur5r.net Git - openldap/blob - libraries/librewrite/xmap.c
more memleaks fixed; some cleanup
[openldap] / libraries / librewrite / xmap.c
1 /******************************************************************************
2  *
3  * Copyright (C) 2000 Pierangelo Masarati, <ando@sys-net.it>
4  * All rights reserved.
5  *
6  * Permission is granted to anyone to use this software for any purpose
7  * on any computer system, and to alter it and redistribute it, subject
8  * to the following restrictions:
9  *
10  * 1. The author is not responsible for the consequences of use of this
11  * software, no matter how awful, even if they arise from flaws in it.
12  *
13  * 2. The origin of this software must not be misrepresented, either by
14  * explicit claim or by omission.  Since few users ever read sources,
15  * credits should appear in the documentation.
16  *
17  * 3. Altered versions must be plainly marked as such, and must not be
18  * misrepresented as being the original software.  Since few users
19  * ever read sources, credits should appear in the documentation.
20  * 
21  * 4. This notice may not be removed or altered.
22  *
23  ******************************************************************************/
24
25 #include <portable.h>
26
27 #include <stdio.h>
28
29 #ifdef HAVE_PWD_H
30 #include <pwd.h>
31 #endif
32
33 #include "rewrite-int.h"
34 #include "rewrite-map.h"
35
36 /*
37  * Global data
38  */
39 #ifdef USE_REWRITE_LDAP_PVT_THREADS
40 ldap_pvt_thread_mutex_t xpasswd_mutex;
41 static int xpasswd_mutex_init = 0;
42 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
43
44 /*
45  * Map parsing
46  * NOTE: these are old-fashion maps; new maps will be parsed on separate
47  * config lines, and referred by name.
48  */
49 struct rewrite_map *
50 rewrite_xmap_parse(
51                 struct rewrite_info *info,
52                 const char *s,
53                 const char **currpos
54 )
55 {
56         struct rewrite_map *map;
57
58         assert( info != NULL );
59         assert( s != NULL );
60         assert( currpos != NULL );
61
62         Debug( LDAP_DEBUG_ARGS, "rewrite_xmap_parse: %s\n%s%s",
63                         s, "", "" );
64
65         *currpos = NULL;
66
67         map = calloc( sizeof( struct rewrite_map ), 1 );
68         if ( map == NULL ) {
69                 Debug( LDAP_DEBUG_ANY, "rewrite_xmap_parse:"
70                                 " calloc failed\n%s%s%s", "", "", "" );
71                 return NULL;
72         }
73
74         /*
75          * Experimental passwd map:
76          * replaces the uid with the matching gecos from /etc/passwd file 
77          */
78         if ( strncasecmp(s, "xpasswd", 7 ) == 0 ) {
79                 map->lm_type = REWRITE_MAP_XPWDMAP;
80                 map->lm_name = strdup( "xpasswd" );
81
82                 assert( s[7] == '}' );
83                 *currpos = s + 8;
84
85 #ifdef USE_REWRITE_LDAP_PVT_THREADS
86                 if ( !xpasswd_mutex_init ) {
87                         if ( ldap_pvt_thread_mutex_init( &xpasswd_mutex ) ) {
88                                 free( map );
89                                 return NULL;
90                         }
91                 }
92                 ++xpasswd_mutex_init;
93 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
94
95                 /* Don't really care if fails */
96                 return map;
97         
98         /*
99          * Experimental file map:
100          * looks up key in a `key value' ascii file
101          */
102         } else if ( strncasecmp(s, "xfile", 5 ) == 0 ) {
103                 char *filename;
104                 const char *p;
105                 int l;
106                 int c = 5;
107                 
108                 map->lm_type = REWRITE_MAP_XFILEMAP;
109                 
110                 if ( s[ c ] != '(' ) {
111                         free( map );
112                         return NULL;
113                 }
114
115                 /* Must start with '/' for security concerns */
116                 c++;
117                 if ( s[ c ] != '/' ) {
118                         free( map );
119                         return NULL;
120                 }
121
122                 for ( p = s + c; p[ 0 ] != '\0' && p[ 0 ] != ')'; p++ );
123                 if ( p[ 0 ] != ')' ) {
124                         free( map );
125                         return NULL;
126                 }
127
128                 l = p - s - c;
129                 filename = calloc( sizeof( char ), l + 1 );
130                 AC_MEMCPY( filename, s + c, l );
131                 filename[ l ] = '\0';
132                 
133                 map->lm_args = ( void * )fopen( filename, "r" );
134                 free( filename );
135
136                 if ( map->lm_args == NULL ) {
137                         free( map );
138                         return NULL;
139                 }
140
141                 *currpos = p + 1;
142
143 #ifdef USE_REWRITE_LDAP_PVT_THREADS
144                 if ( ldap_pvt_thread_mutex_init( &map->lm_mutex ) ) {
145                         fclose( ( FILE * )map->lm_args );
146                         free( map );
147                         return NULL;
148                 }
149 #endif /* USE_REWRITE_LDAP_PVT_THREADS */       
150                 
151                 return map;
152
153         /*
154          * Experimental ldap map:
155          * looks up key on the fly (not implemented!)
156          */
157         } else if ( strncasecmp(s, "xldap", 5 ) == 0 ) {
158                 char *p;
159                 char *url;
160                 int l, rc;
161                 int c = 5;
162                 LDAPURLDesc *lud;
163
164                 if ( s[ c ] != '(' ) {
165                         free( map );
166                         return NULL;
167                 }
168                 c++;
169                 
170                 p = strchr( s, '}' );
171                 if ( p == NULL ) {
172                         free( map );
173                         return NULL;
174                 }
175                 p--;
176
177                 *currpos = p + 2;
178         
179                 /*
180                  * Add two bytes for urlencoding of '%s'
181                  */
182                 l = p - s - c;
183                 url = calloc( sizeof( char ), l + 3 );
184                 AC_MEMCPY( url, s + c, l );
185                 url[ l ] = '\0';
186
187                 /*
188                  * Urlencodes the '%s' for ldap_url_parse
189                  */
190                 p = strchr( url, '%' );
191                 if ( p != NULL ) {
192                         AC_MEMCPY( p + 3, p + 1, strlen( p + 1 ) + 1 );
193                         p[ 1 ] = '2';
194                         p[ 2 ] = '5';
195                 }
196
197                 rc =  ldap_url_parse( url, &lud );
198                 free( url );
199
200                 if ( rc != LDAP_SUCCESS ) {
201                         free( map );
202                         return NULL;
203                 }
204                 assert( lud != NULL );
205
206                 map->lm_args = ( void * )lud;
207                 map->lm_type = REWRITE_MAP_XLDAPMAP;
208
209 #ifdef USE_REWRITE_LDAP_PVT_THREADS
210                 if ( ldap_pvt_thread_mutex_init( &map->lm_mutex ) ) {
211                         ldap_free_urldesc( lud );
212                         free( map );
213                         return NULL;
214                 }
215 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
216
217                 return map;
218         
219         /* Unhandled map */
220         }
221         
222         return NULL;
223 }
224
225 /*
226  * Map key -> value resolution
227  * NOTE: these are old-fashion maps; new maps will be parsed on separate
228  * config lines, and referred by name.
229  */
230 int
231 rewrite_xmap_apply(
232                 struct rewrite_info *info,
233                 struct rewrite_op *op,
234                 struct rewrite_map *map,
235                 struct berval *key,
236                 struct berval *val
237 )
238 {
239         int rc = REWRITE_SUCCESS;
240         
241         assert( info != NULL );
242         assert( op != NULL );
243         assert( map != NULL );
244         assert( key != NULL );
245         assert( val != NULL );
246         
247         val->bv_val = NULL;
248         val->bv_len = 0;
249         
250         switch ( map->lm_type ) {
251 #ifdef HAVE_GETPWNAM
252         case REWRITE_MAP_XPWDMAP: {
253                 struct passwd *pwd;
254
255 #ifdef USE_REWRITE_LDAP_PVT_THREADS
256                 ldap_pvt_thread_mutex_lock( &xpasswd_mutex );
257 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
258                 
259                 pwd = getpwnam( key->bv_val );
260                 if ( pwd == NULL ) {
261
262 #ifdef USE_REWRITE_LDAP_PVT_THREADS
263                         ldap_pvt_thread_mutex_unlock( &xpasswd_mutex );
264 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
265
266                         rc = REWRITE_NO_SUCH_OBJECT;
267                         break;
268                 }
269
270 #ifdef HAVE_PW_GECOS
271                 if ( pwd->pw_gecos != NULL && pwd->pw_gecos[0] != '\0' ) {
272                         int l = strlen( pwd->pw_gecos );
273                         
274                         val->bv_val = strdup( pwd->pw_gecos );
275                         if ( val->bv_val == NULL ) {
276
277 #ifdef USE_REWRITE_LDAP_PVT_THREADS
278                                 ldap_pvt_thread_mutex_unlock( &xpasswd_mutex );
279 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
280
281                                 rc = REWRITE_ERR;
282                                 break;
283                         }
284                         val->bv_len = l;
285                 } else
286 #endif /* HAVE_PW_GECOS */
287                 {
288                         val->bv_val = strdup( key->bv_val );
289                         val->bv_len = key->bv_len;
290                 }
291
292 #ifdef USE_REWRITE_LDAP_PVT_THREADS
293                 ldap_pvt_thread_mutex_unlock( &xpasswd_mutex );
294 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
295                         
296                 break;
297         }
298 #endif /* HAVE_GETPWNAM*/
299         
300         case REWRITE_MAP_XFILEMAP: {
301                 char buf[1024];
302                 
303                 if ( map->lm_args == NULL ) {
304                         rc = REWRITE_ERR;
305                         break;
306                 }
307                 
308 #ifdef USE_REWRITE_LDAP_PVT_THREADS
309                 ldap_pvt_thread_mutex_lock( &map->lm_mutex );
310 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
311
312                 rewind( ( FILE * )map->lm_args );
313                 
314                 while ( fgets( buf, sizeof( buf ), ( FILE * )map->lm_args ) ) {
315                         char *p;
316                         int blen;
317                         
318                         blen = strlen( buf );
319                         if ( buf[ blen - 1 ] == '\n' ) {
320                                 buf[ blen - 1 ] = '\0';
321                         }
322                         
323                         p = strtok( buf, " " );
324                         if ( p == NULL ) {
325 #ifdef USE_REWRITE_LDAP_PVT_THREADS
326                                 ldap_pvt_thread_mutex_unlock( &map->lm_mutex );
327 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
328                                 rc = REWRITE_ERR;
329                                 goto rc_return;
330                         }
331                         if ( strcasecmp( p, key->bv_val ) == 0 
332                                         && ( p = strtok( NULL, "" ) ) ) {
333                                 val->bv_val = strdup( p );
334                                 if ( val->bv_val == NULL ) {
335                                         return REWRITE_ERR;
336                                 }
337
338                                 val->bv_len = strlen( p );
339                                 
340 #ifdef USE_REWRITE_LDAP_PVT_THREADS
341                                 ldap_pvt_thread_mutex_unlock( &map->lm_mutex );
342 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
343                                 
344                                 goto rc_return;
345                         }
346                 }
347
348 #ifdef USE_REWRITE_LDAP_PVT_THREADS
349                 ldap_pvt_thread_mutex_unlock( &map->lm_mutex );
350 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
351
352                 rc = REWRITE_ERR;
353                 
354                 break;
355         }
356
357         case REWRITE_MAP_XLDAPMAP: {
358                 LDAP *ld;
359                 char filter[1024];
360                 LDAPMessage *res = NULL, *entry;
361                 LDAPURLDesc *lud = ( LDAPURLDesc * )map->lm_args;
362                 int attrsonly = 0;
363                 char **values;
364
365                 assert( lud != NULL );
366
367                 /*
368                  * No mutex because there is no write on the map data
369                  */
370                 
371                 ld = ldap_init( lud->lud_host, lud->lud_port );
372                 if ( ld == NULL ) {
373                         rc = REWRITE_ERR;
374                         goto rc_return;
375                 }
376
377                 snprintf( filter, sizeof( filter ), lud->lud_filter,
378                                 key->bv_val );
379
380                 if ( strcasecmp( lud->lud_attrs[ 0 ], "dn" ) == 0 ) {
381                         attrsonly = 1;
382                 }
383                 rc = ldap_search_s( ld, lud->lud_dn, lud->lud_scope,
384                                 filter, lud->lud_attrs, attrsonly, &res );
385                 if ( rc != LDAP_SUCCESS ) {
386                         ldap_unbind( ld );
387                         rc = REWRITE_ERR;
388                         goto rc_return;
389                 }
390
391                 if ( ldap_count_entries( ld, res ) != 1 ) {
392                         ldap_unbind( ld );
393                         rc = REWRITE_ERR;
394                         goto rc_return;
395                 }
396
397                 entry = ldap_first_entry( ld, res );
398                 if ( entry == NULL ) {
399                         ldap_msgfree( res );
400                         ldap_unbind( ld );
401                         rc = REWRITE_ERR;
402                         goto rc_return;
403                 }
404                 if ( attrsonly == 1 ) {
405                         val->bv_val = ldap_get_dn( ld, entry );
406                         if ( val->bv_val == NULL ) {
407                                 ldap_msgfree( res );
408                                 ldap_unbind( ld );
409                                 rc = REWRITE_ERR;
410                                 goto rc_return;
411                         }
412                 } else {
413                         values = ldap_get_values( ld, entry,
414                                         lud->lud_attrs[0] );
415                         if ( values == NULL ) {
416                                 ldap_msgfree( res );
417                                 ldap_unbind( ld );
418                                 rc = REWRITE_ERR;
419                                 goto rc_return;
420                         }
421                         val->bv_val = strdup( values[ 0 ] );
422                         ldap_value_free( values );
423                 }
424                 val->bv_len = strlen( val->bv_val );
425
426                 ldap_msgfree( res );
427                 ldap_unbind( ld );
428                 
429                 rc = REWRITE_SUCCESS;
430         }
431         }
432
433 rc_return:;
434         return rc;
435 }
436
437 int
438 rewrite_xmap_destroy(
439                 struct rewrite_map **pmap
440 )
441 {
442         struct rewrite_map *map;
443
444         assert( pmap );
445         assert( *pmap );
446
447         map = *pmap;
448
449         switch ( map->lm_type ) {
450         case REWRITE_MAP_XPWDMAP:
451 #ifdef USE_REWRITE_LDAP_PVT_THREADS
452                 --xpasswd_mutex_init;
453                 if ( !xpasswd_mutex_init ) {
454                         ldap_pvt_thread_mutex_destroy( &xpasswd_mutex );
455                 }
456 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
457
458                 break;
459
460         case REWRITE_MAP_XFILEMAP:
461 #ifdef USE_REWRITE_LDAP_PVT_THREADS
462                 ldap_pvt_thread_mutex_lock( &map->lm_mutex );
463 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
464
465                 if ( map->lm_args ) {
466                         fclose( ( FILE * )map->lm_args );
467                         map->lm_args = NULL;
468                 }
469
470 #ifdef USE_REWRITE_LDAP_PVT_THREADS
471                 ldap_pvt_thread_mutex_unlock( &map->lm_mutex );
472                 ldap_pvt_thread_mutex_destroy( &map->lm_mutex );
473 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
474                 break;
475
476         case REWRITE_MAP_XLDAPMAP:
477 #ifdef USE_REWRITE_LDAP_PVT_THREADS
478                 ldap_pvt_thread_mutex_lock( &map->lm_mutex );
479 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
480
481                 if ( map->lm_args ) {
482                         ldap_free_urldesc( ( LDAPURLDesc * )map->lm_args );
483                         map->lm_args = NULL;
484                 }
485
486 #ifdef USE_REWRITE_LDAP_PVT_THREADS
487                 ldap_pvt_thread_mutex_unlock( &map->lm_mutex );
488                 ldap_pvt_thread_mutex_destroy( &map->lm_mutex );
489 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
490                 break;
491
492         default:
493                 break;
494
495         }
496
497         free( map->lm_name );
498         free( map );
499         *pmap = NULL;
500
501         return 0;
502 }
503