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