]> git.sur5r.net Git - openldap/blob - libraries/librewrite/xmap.c
Use AC_MEMCPY
[openldap] / libraries / librewrite / xmap.c
1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 2000-2007 The OpenLDAP Foundation.
5  * All rights reserved.
6  *
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.
10  *
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>.
14  */
15 /* ACKNOWLEDGEMENT:
16  * This work was initially developed by Pierangelo Masarati for
17  * inclusion in OpenLDAP Software.
18  */
19
20 #include <portable.h>
21
22 #include <stdio.h>
23
24 #ifdef HAVE_PWD_H
25 #include <pwd.h>
26 #endif
27
28 #define LDAP_DEPRECATED 1
29 #include "rewrite-int.h"
30 #include "rewrite-map.h"
31
32 /*
33  * Global data
34  */
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 */
39
40 /*
41  * Map parsing
42  * NOTE: these are old-fashion maps; new maps will be parsed on separate
43  * config lines, and referred by name.
44  */
45 struct rewrite_map *
46 rewrite_xmap_parse(
47                 struct rewrite_info *info,
48                 const char *s,
49                 const char **currpos
50 )
51 {
52         struct rewrite_map *map;
53
54         assert( info != NULL );
55         assert( s != NULL );
56         assert( currpos != NULL );
57
58         Debug( LDAP_DEBUG_ARGS, "rewrite_xmap_parse: %s\n%s%s",
59                         s, "", "" );
60
61         *currpos = NULL;
62
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;
68         }
69
70         /*
71          * Experimental passwd map:
72          * replaces the uid with the matching gecos from /etc/passwd file 
73          */
74         if ( strncasecmp(s, "xpasswd", 7 ) == 0 ) {
75                 map->lm_type = REWRITE_MAP_XPWDMAP;
76                 map->lm_name = strdup( "xpasswd" );
77
78                 assert( s[7] == '}' );
79                 *currpos = s + 8;
80
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;
86                         }
87                 }
88                 ++xpasswd_mutex_init;
89 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
90
91                 /* Don't really care if fails */
92                 return map;
93         
94         /*
95          * Experimental file map:
96          * looks up key in a `key value' ascii file
97          */
98         } else if ( strncasecmp( s, "xfile", 5 ) == 0 ) {
99                 char *filename;
100                 const char *p;
101                 int l;
102                 int c = 5;
103                 
104                 map->lm_type = REWRITE_MAP_XFILEMAP;
105                 
106                 if ( s[ c ] != '(' ) {
107                         free( map );
108                         return NULL;
109                 }
110
111                 /* Must start with '/' for security concerns */
112                 c++;
113                 if ( s[ c ] != '/' ) {
114                         free( map );
115                         return NULL;
116                 }
117
118                 for ( p = s + c; p[ 0 ] != '\0' && p[ 0 ] != ')'; p++ );
119                 if ( p[ 0 ] != ')' ) {
120                         free( map );
121                         return NULL;
122                 }
123
124                 l = p - s - c;
125                 filename = calloc( sizeof( char ), l + 1 );
126                 AC_MEMCPY( filename, s + c, l );
127                 filename[ l ] = '\0';
128                 
129                 map->lm_args = ( void * )fopen( filename, "r" );
130                 free( filename );
131
132                 if ( map->lm_args == NULL ) {
133                         free( map );
134                         return NULL;
135                 }
136
137                 *currpos = p + 1;
138
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;
144                 }
145 #endif /* USE_REWRITE_LDAP_PVT_THREADS */       
146                 
147                 return map;
148
149         /*
150          * Experimental ldap map:
151          * looks up key on the fly (not implemented!)
152          */
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;
159
160                 if ( s[ c ] != '(' ) {
161                         free( map );
162                         return NULL;
163                 }
164                 c++;
165                 
166                 p = strchr( s, '}' );
167                 if ( p == NULL ) {
168                         free( map );
169                         return NULL;
170                 }
171                 p--;
172
173                 *currpos = p + 2;
174         
175                 /*
176                  * Add two bytes for urlencoding of '%s'
177                  */
178                 l = p - s - c;
179                 url = calloc( sizeof( char ), l + 3 );
180                 AC_MEMCPY( url, s + c, l );
181                 url[ l ] = '\0';
182
183                 /*
184                  * Urlencodes the '%s' for ldap_url_parse
185                  */
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';
191                 }
192
193                 rc =  ldap_url_parse( url, &lud );
194                 free( url );
195
196                 if ( rc != LDAP_SUCCESS ) {
197                         free( map );
198                         return NULL;
199                 }
200                 assert( lud != NULL );
201
202                 map->lm_args = ( void * )lud;
203                 map->lm_type = REWRITE_MAP_XLDAPMAP;
204
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;
210                 }
211 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
212
213                 return map;
214         
215         /* Unhandled map */
216         }
217
218         free( map );
219         return NULL;
220 }
221
222 /*
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.
226  */
227 int
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
234 )
235 {
236         int rc = REWRITE_SUCCESS;
237         
238         assert( info != NULL );
239         assert( op != NULL );
240         assert( map != NULL );
241         assert( key != NULL );
242         assert( val != NULL );
243         
244         val->bv_val = NULL;
245         val->bv_len = 0;
246         
247         switch ( map->lm_type ) {
248 #ifdef HAVE_GETPWNAM
249         case REWRITE_MAP_XPWDMAP: {
250                 struct passwd *pwd;
251
252 #ifdef USE_REWRITE_LDAP_PVT_THREADS
253                 ldap_pvt_thread_mutex_lock( &xpasswd_mutex );
254 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
255                 
256                 pwd = getpwnam( key->bv_val );
257                 if ( pwd == NULL ) {
258
259 #ifdef USE_REWRITE_LDAP_PVT_THREADS
260                         ldap_pvt_thread_mutex_unlock( &xpasswd_mutex );
261 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
262
263                         rc = LDAP_NO_SUCH_OBJECT;
264                         break;
265                 }
266
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 );
270                         
271                         val->bv_val = strdup( pwd->pw_gecos );
272                         if ( val->bv_val == NULL ) {
273
274 #ifdef USE_REWRITE_LDAP_PVT_THREADS
275                                 ldap_pvt_thread_mutex_unlock( &xpasswd_mutex );
276 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
277
278                                 rc = REWRITE_ERR;
279                                 break;
280                         }
281                         val->bv_len = l;
282                 } else
283 #endif /* HAVE_STRUCT_PASSWD_PW_GECOS */
284                 {
285                         val->bv_val = strdup( key->bv_val );
286                         val->bv_len = key->bv_len;
287                 }
288
289 #ifdef USE_REWRITE_LDAP_PVT_THREADS
290                 ldap_pvt_thread_mutex_unlock( &xpasswd_mutex );
291 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
292                         
293                 break;
294         }
295 #endif /* HAVE_GETPWNAM*/
296         
297         case REWRITE_MAP_XFILEMAP: {
298                 char buf[1024];
299                 
300                 if ( map->lm_args == NULL ) {
301                         rc = REWRITE_ERR;
302                         break;
303                 }
304                 
305 #ifdef USE_REWRITE_LDAP_PVT_THREADS
306                 ldap_pvt_thread_mutex_lock( &map->lm_mutex );
307 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
308
309                 rewind( ( FILE * )map->lm_args );
310                 
311                 while ( fgets( buf, sizeof( buf ), ( FILE * )map->lm_args ) ) {
312                         char *p;
313                         int blen;
314                         
315                         blen = strlen( buf );
316                         if ( buf[ blen - 1 ] == '\n' ) {
317                                 buf[ blen - 1 ] = '\0';
318                         }
319                         
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;
327                         }
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;
333                                 }
334
335                                 val->bv_len = strlen( p );
336                                 
337 #ifdef USE_REWRITE_LDAP_PVT_THREADS
338                                 ldap_pvt_thread_mutex_unlock( &map->lm_mutex );
339 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
340                                 
341                                 goto rc_return;
342                         }
343                 }
344
345 #ifdef USE_REWRITE_LDAP_PVT_THREADS
346                 ldap_pvt_thread_mutex_unlock( &map->lm_mutex );
347 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
348
349                 rc = REWRITE_ERR;
350                 
351                 break;
352         }
353
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;
361
362                 assert( lud != NULL );
363
364                 /*
365                  * No mutex because there is no write on the map data
366                  */
367                 
368                 ld = ldap_init( lud->lud_host, lud->lud_port );
369                 if ( ld == NULL ) {
370                         rc = REWRITE_ERR;
371                         goto rc_return;
372                 }
373
374                 snprintf( filter, sizeof( filter ), lud->lud_filter,
375                                 key->bv_val );
376
377                 if ( strcasecmp( lud->lud_attrs[ 0 ], "dn" ) == 0 ) {
378                         attrsonly = 1;
379                 }
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;
386                 }
387
388                 if ( ldap_count_entries( ld, res ) != 1 ) {
389                         ldap_unbind( ld );
390                         rc = REWRITE_ERR;
391                         goto rc_return;
392                 }
393
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;
400                 }
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;
408                         }
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;
417                         }
418                         val->bv_val = strdup( values[ 0 ] );
419                         ldap_value_free( values );
420                 }
421                 val->bv_len = strlen( val->bv_val );
422
423                 ldap_msgfree( res );
424                 ldap_unbind( ld );
425                 
426                 rc = REWRITE_SUCCESS;
427         }
428         }
429
430 rc_return:;
431         return rc;
432 }
433
434 int
435 rewrite_xmap_destroy(
436                 struct rewrite_map **pmap
437 )
438 {
439         struct rewrite_map *map;
440
441         assert( pmap != NULL );
442         assert( *pmap != NULL );
443
444         map = *pmap;
445
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 );
452                 }
453 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
454
455                 break;
456
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 */
461
462                 if ( map->lm_args ) {
463                         fclose( ( FILE * )map->lm_args );
464                         map->lm_args = NULL;
465                 }
466
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;
472
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 */
477
478                 if ( map->lm_args ) {
479                         ldap_free_urldesc( ( LDAPURLDesc * )map->lm_args );
480                         map->lm_args = NULL;
481                 }
482
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;
488
489         default:
490                 break;
491
492         }
493
494         free( map->lm_name );
495         free( map );
496         *pmap = NULL;
497
498         return 0;
499 }
500