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