]> git.sur5r.net Git - openldap/blob - libraries/librewrite/ldapmap.c
From HEAD
[openldap] / libraries / librewrite / ldapmap.c
1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 2000-2004 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 #define LDAP_DEPRECATED 1
23 #include "rewrite-int.h"
24 #include "rewrite-map.h"
25
26 /*
27  * LDAP map data structure
28  */
29 struct ldap_map_data {
30         char                           *lm_url;
31         LDAPURLDesc                    *lm_lud;
32         int                             lm_attrsonly;
33         char                           *lm_binddn;
34         char                           *lm_bindpw;
35
36 #define MAP_LDAP_EVERYTIME              0x00
37 #define MAP_LDAP_NOW                    0x01
38 #define MAP_LDAP_LATER                  0x02
39         int                             lm_when;
40
41         LDAP                           *lm_ld;
42
43 #ifdef USE_REWRITE_LDAP_PVT_THREADS
44         ldap_pvt_thread_mutex_t         lm_mutex;
45 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
46 };
47
48 static void
49 map_ldap_free(
50                 struct ldap_map_data *data
51 )
52 {
53         assert( data != NULL );
54
55         if ( data->lm_url != NULL ) {
56                 free( data->lm_url );
57         }
58
59         if ( data->lm_lud != NULL ) {
60                 ldap_free_urldesc( data->lm_lud );
61         }
62
63         if ( data->lm_binddn != NULL ) {
64                 free( data->lm_binddn );
65         }
66
67         if ( data->lm_bindpw != NULL ) {
68                 free( data->lm_bindpw );
69         }
70
71         if ( data->lm_when != MAP_LDAP_EVERYTIME && data->lm_ld != NULL ) {
72                 ldap_unbind_s( data->lm_ld );
73         }
74
75         free( data );
76 }
77
78 void *
79 map_ldap_parse(
80                 struct rewrite_info *info,
81                 const char *fname,
82                 int lineno,
83                 int argc,
84                 char **argv
85 )
86 {
87         struct ldap_map_data *data;
88         char *p;
89
90         assert( info != NULL );
91         assert( fname != NULL );
92         assert( argv != NULL );
93
94         data = calloc( sizeof( struct ldap_map_data ), 1 );
95         if ( data == NULL ) {
96                 return NULL;
97         }
98
99         if ( argc < 1 ) {
100                 Debug( LDAP_DEBUG_ANY,
101                                 "[%s:%d] ldap map needs URI\n%s",
102                                 fname, lineno, "" );
103                 free( data );
104                 return NULL;
105         }
106
107         data->lm_url = strdup( argv[ 0 ] );
108         if ( data->lm_url == NULL ) {
109                 map_ldap_free( data );
110                 return NULL;
111         }
112         
113         if ( ldap_url_parse( argv[ 0 ], &data->lm_lud ) != REWRITE_SUCCESS ) {
114                 Debug( LDAP_DEBUG_ANY,
115                                 "[%s:%d] illegal URI '%s'\n",
116                                 fname, lineno, argv[ 0 ] );
117                 map_ldap_free( data );
118                 return NULL;
119         }
120
121         p = strchr( data->lm_url, '/' );
122         assert( p[ 1 ] == '/' );
123         if ( ( p = strchr( p + 2, '/' ) ) != NULL ) {
124                 p[ 0 ] = '\0';
125         }
126
127         if ( strcasecmp( data->lm_lud->lud_attrs[ 0 ], "dn" ) == 0 ) {
128                 data->lm_attrsonly = 1;
129         }
130               
131         for ( argc--, argv++; argc > 0; argc--, argv++ ) {
132                 if ( strncasecmp( argv[ 0 ], "binddn=", 7 ) == 0 ) {
133                         char *p = argv[ 0 ] + 7;
134                         int l;
135
136                         if ( p[ 0 ] == '\"' || p [ 0 ] == '\'' ) {
137                                 l = strlen( p ) - 2;
138                                 p++;
139                                 if ( p[ l ] != p[ 0 ] ) {
140                                         map_ldap_free( data );
141                                         return NULL;
142                                 }
143                         } else {
144                                 l = strlen( p );
145                         }
146                         
147                         data->lm_binddn = strdup( p );                  
148                         if ( data->lm_binddn == NULL ) {
149                                 map_ldap_free( data );
150                                 return NULL;
151                         }
152
153                         if ( data->lm_binddn[ l ] == '\"' 
154                                         || data->lm_binddn[ l ] == '\'' ) {
155                                 data->lm_binddn[ l ] = '\0';
156                         }
157                 } else if ( strncasecmp( argv[ 0 ], "bindpw=", 7 ) == 0 ) {
158                         data->lm_bindpw = strdup( argv[ 2 ] + 7 );
159                         if ( data->lm_bindpw == NULL ) {
160                                 map_ldap_free( data );
161                                 return NULL;
162                         }
163                 } else if ( strncasecmp( argv[ 0 ], "bindwhen=", 9 ) == 0 ) {
164                         char *p = argv[ 0 ] + 9;
165
166                         if ( strcasecmp( p, "now" ) == 0 ) {
167                                 int rc;
168                                 
169                                 data->lm_when = MAP_LDAP_NOW;
170                                 
171                                 /*
172                                  * Init LDAP handler ...
173                                  */
174                                 rc = ldap_initialize( &data->lm_ld, data->lm_url );
175                                 if ( rc != LDAP_SUCCESS ) {
176                                         map_ldap_free( data );
177                                         return NULL;
178                                 }
179
180 #ifdef USE_REWRITE_LDAP_PVT_THREADS
181                                 ldap_pvt_thread_mutex_init( &data->lm_mutex );
182 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
183
184                         } else if ( strcasecmp( p, "later" ) == 0 ) {
185                                 data->lm_when = MAP_LDAP_LATER;
186
187 #ifdef USE_REWRITE_LDAP_PVT_THREADS
188                                 ldap_pvt_thread_mutex_init( &data->lm_mutex );
189 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
190
191                         } else if ( strcasecmp( p, "everytime" ) == 0 ) {
192                                 data->lm_when = MAP_LDAP_EVERYTIME;
193                         } else {
194                                 /* ignore ... */
195                         }
196                 }
197         }
198
199         return ( void * )data;
200 }
201
202 int
203 map_ldap_apply(
204                 struct rewrite_builtin_map *map,
205                 const char *filter,
206                 struct berval *val
207
208 )
209 {
210         LDAP *ld;
211         LDAPMessage *res = NULL, *entry;
212         char **values;
213         int rc;
214         struct ldap_map_data *data = ( struct ldap_map_data * )map->lb_private;
215         LDAPURLDesc *lud = data->lm_lud;
216         
217         int first_try = 1;
218
219         assert( map != NULL );
220         assert( map->lb_type == REWRITE_BUILTIN_MAP_LDAP );
221         assert( map->lb_private != NULL );
222         assert( filter != NULL );
223         assert( val != NULL );
224
225         val->bv_val = NULL;
226         val->bv_len = 0;
227
228         if ( data->lm_when == MAP_LDAP_EVERYTIME ) {
229                 rc = ldap_initialize( &ld, data->lm_url );
230
231         } else {
232 #ifdef USE_REWRITE_LDAP_PVT_THREADS
233                 ldap_pvt_thread_mutex_lock( &data->lm_mutex );
234 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
235
236                 rc = LDAP_SUCCESS;
237
238                 if ( data->lm_when == MAP_LDAP_LATER && data->lm_ld == NULL ) {
239                         rc = ldap_initialize( &data->lm_ld, data->lm_url );
240                 }
241                 
242                 ld = data->lm_ld;
243         }
244
245         if ( rc != LDAP_SUCCESS ) {
246                 rc = REWRITE_ERR;
247                 goto rc_return;
248         }
249
250 do_bind:;
251         if ( data->lm_binddn != NULL ) {
252                 rc = ldap_simple_bind_s( ld, data->lm_binddn, data->lm_bindpw );
253                 if ( rc == LDAP_SERVER_DOWN && first_try ) {
254                         first_try = 0;
255                         if ( ldap_initialize( &ld, data->lm_url ) != LDAP_SUCCESS ) {
256                                 rc = REWRITE_ERR;
257                                 goto rc_return;
258                         }
259                         goto do_bind;
260
261                 } else if ( rc != REWRITE_SUCCESS ) {
262                         rc = REWRITE_ERR;
263                         goto rc_return;
264                 }
265         }
266
267         rc = ldap_search_s( ld, lud->lud_dn, lud->lud_scope, ( char * )filter,
268                         lud->lud_attrs, data->lm_attrsonly, &res );
269         if ( rc == LDAP_SERVER_DOWN && first_try ) {
270                 first_try = 0;
271                 if ( ldap_initialize( &ld, data->lm_url ) != LDAP_SUCCESS ) {
272                         rc = REWRITE_ERR;
273                         goto rc_return;
274                 }
275                 goto do_bind;
276
277         } else if ( rc != REWRITE_SUCCESS ) {
278                 rc = REWRITE_ERR;
279                 goto rc_return;
280         }
281
282         if ( ldap_count_entries( ld, res ) != 1 ) {
283                 ldap_msgfree( res );
284                 rc = REWRITE_ERR;
285                 goto rc_return;
286         }
287
288         entry = ldap_first_entry( ld, res );
289         assert( entry != NULL );
290
291         if ( data->lm_attrsonly == 1 ) {
292                 /*
293                  * dn is newly allocated, so there's no need to strdup it
294                  */
295                 val->bv_val = ldap_get_dn( ld, entry );
296
297         } else {
298                 values = ldap_get_values( ld, entry, lud->lud_attrs[ 0 ] );
299                 if ( values == NULL || values[ 0 ] == NULL ) {
300                         if ( values != NULL ) {
301                                 ldap_value_free( values );
302                         }
303                         ldap_msgfree( res );
304                         rc = REWRITE_ERR;
305                         goto rc_return;
306                 }
307                 val->bv_val = strdup( values[ 0 ] );
308                 ldap_value_free( values );
309         }
310         
311         ldap_msgfree( res );
312
313         if ( val->bv_val == NULL ) {
314                 rc = REWRITE_ERR;
315                 goto rc_return;
316         }
317         val->bv_len = strlen( val->bv_val );
318
319 rc_return:;
320         if ( data->lm_when == MAP_LDAP_EVERYTIME ) {
321                 if ( ld != NULL ) {
322                         ldap_unbind_s( ld );
323                 }
324
325         } else {
326                 data->lm_ld = ld;
327 #ifdef USE_REWRITE_LDAP_PVT_THREADS
328                 ldap_pvt_thread_mutex_unlock( &data->lm_mutex );
329 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
330         }
331         
332         return rc;
333 }
334
335 int
336 map_ldap_destroy(
337                 struct rewrite_builtin_map **pmap
338 )
339 {
340         struct ldap_map_data *data;
341
342         assert( pmap );
343         assert( *pmap );
344         
345         data = ( struct ldap_map_data * )(*pmap)->lb_private;
346
347         if ( data->lm_when != MAP_LDAP_EVERYTIME && data->lm_ld != NULL ) {
348                 ldap_unbind_s( data->lm_ld );
349                 data->lm_ld = NULL;
350         }
351
352         if ( data->lm_lud ) {
353                 ldap_free_urldesc( data->lm_lud );
354                 data->lm_lud = NULL;
355         }
356
357         if ( data->lm_url ) {
358                 free( data->lm_url );
359                 data->lm_url = NULL;
360         }
361
362         if ( data->lm_binddn ) {
363                 free( data->lm_binddn );
364                 data->lm_binddn = NULL;
365         }
366
367         if (data->lm_bindpw ) {
368                 memset( data->lm_bindpw, 0, strlen( data->lm_bindpw ) );
369                 free( data->lm_bindpw );
370                 data->lm_bindpw = NULL;
371         }
372         
373         free( data );
374         (*pmap)->lb_private = NULL;
375
376         return 0;
377 }
378